Contacto Bubble EditText

89

Estoy intentando crear burbujas de contacto de forma MultiAutoCompleteTextViewsimilar a como se implementa en la aplicación Google+. A continuación se muestra una captura de pantalla:

Captura de pantalla de la publicación de redacción de Google+ .

He intentado extender la DynamicDrawableSpanclase para obtener un dibujable extensible en el fondo de un lapso de texto

public class BubbleSpan extends DynamicDrawableSpan {
  private Context c;

  public BubbleSpan(Context context) {
    super();
    c = context;
  }

  @Override
  public Drawable getDrawable() {
    Resources res = c.getResources();
    Drawable d = res.getDrawable(R.drawable.oval);
    d.setBounds(0, 0, 100, 20);
    return d;
  }
}

Donde mi dibujable oval.xml se define así:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
  <solid android:color="#352765"/>
  <padding android:left="7dp" android:top="7dp"
    android:right="7dp" android:bottom="7dp" />
  <corners android:radius="6dp" />
</shape>

En mi clase de actividad que tiene MulitAutoCompleteTextView, configuro el intervalo de burbujas así:

final Editable e = tv.getEditableText();
final SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append("some sample text");
sb.setSpan(new BubbleSpan(getApplicationContext()), 0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
e.append(sb); 

Sin embargo, en lugar de que la forma ovalada se muestre detrás de los primeros 6 caracteres de la cadena, los caracteres no son visibles y no hay un dibujo ovalado en el fondo.

Si cambio el método getDrawable () de BubbleSpan para usar un .png en lugar de una forma dibujable:

public Drawable getDrawable() {
  Resources res = c.getResources();
  Drawable d = res.getDrawable(android.R.drawable.bottom_bar);
  d.setBounds(0, 0, 100, 20);
  return d;
}

Luego, aparecerá el .png, pero los caracteres de la cadena que son parte del intervalo no aparecerán. ¿Cómo puedo hacer que los caracteres en el intervalo se muestren en primer plano, mientras que un dibujable de forma personalizada se muestra en el fondo?

Intenté usar también un en ImageSpanlugar de subclases DynamicDrawableSpanpero no tuve éxito.

toobsco42
fuente
posible duplicado de etiquetas o burbujas
Peter
Cómo obtener números de contacto seleccionados
srihari
github.com/splitwise/TokenAutoComplete podría ser útil para algunos
john-salib

Respuestas:

55

Gracias @chrish por toda la ayuda. Así que así es como lo hice:

final SpannableStringBuilder sb = new SpannableStringBuilder();
TextView tv = createContactTextView(contactName);
BitmapDrawable bd = (BitmapDrawable) convertViewToDrawable(tv);
bd.setBounds(0, 0, bd.getIntrinsicWidth(),bd.getIntrinsicHeight());

sb.append(contactName + ",");
sb.setSpan(new ImageSpan(bd), sb.length()-(contactName.length()+1), sb.length()-1,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
to_input.setText(sb);

public TextView createContactTextView(String text){
  //creating textview dynamically
  TextView tv = new TextView(this);
  tv.setText(text);
  tv.setTextSize(20);
  tv.setBackgroundResource(R.drawable.oval);
  tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_clear_search_api_holo_light, 0);
  return tv;
}

public static Object convertViewToDrawable(View view) {
  int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
  view.measure(spec, spec);
  view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
  Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
            Bitmap.Config.ARGB_8888);
  Canvas c = new Canvas(b);
  c.translate(-view.getScrollX(), -view.getScrollY());
  view.draw(c);
  view.setDrawingCacheEnabled(true);
  Bitmap cacheBmp = view.getDrawingCache();
  Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
  view.destroyDrawingCache();
  return new BitmapDrawable(viewBmp);

}
toobsco42
fuente
13
Descubrí que esto no funcionaba en todos los dispositivos debido a problemas de escala. Una mejor manera de hacer esto es devolver el mapa de bits de convertView, luego usar las dimensiones reales del mapa de bits al configurar los bordes dibujables. Por ejemplo, BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); eso funciona en todos los dispositivos.
dmon
Hola, es posible que deba publicar esto en una nueva pregunta, pero quería saber si tuvo problemas con TextViews de varias líneas. Estoy ejecutando esto en Android 3.2 y "a veces", parece que el ancho de la burbuja no está bien calculado. Como en el texto, no continuará a la siguiente línea, sino que continuará fuera de TextView. Si has visto esto, ¿algún consejo?
Johann Hilbold
1
Si el texto con burbuja es más ancho que el autocompletado, la burbuja se crea dos veces en dos filas. Debes establecer esto en textView: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `Y también estoy usando esto (si el texto es demasiado grande está en dos líneas en la burbuja y con ... al final): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (falso); textView.setMaxLines (2);
SocialError
esto funciona bien si lo selecciona de la lista desplegable. En caso de que desee establecer algunos valores predefinidos para editar texto, ¿cómo puedo ajustar ese texto con el botón de borde n cruzado?
Braj
5
cómo agrega el oyente de clics a un elemento diferente en la vista de texto para eliminar el texto.
Nambi
21

Aquí hay una solución completa para ti

//creating textview dynamicalyy
TextView textView=new TextView(context);
textview.setText("Lauren amos");
textview.setbackgroundResource(r.color.urovalshape);
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_cross, 0);


BitmapDrawable dd = (BitmapDrawable) SmsUtil.getDrawableFromTExtView(textView);
edittext.settext(addSmily(dd));

//convert image to spannableString
public SpannableStringBuilder addSmily(Drawable dd) {
 dd.setBounds(0, 0, dd.getIntrinsicWidth(),dd.getIntrinsicHeight());
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(":-)");
builder.setSpan(new ImageSpan(dd), builder.length() - ":-)".length(),builder.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

return builder;
}

  //convert view to drawable
  public static Object getDrawableFromTExtView(View view) {

    int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    view.measure(spec, spec);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    Bitmap b = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.translate(-view.getScrollX(), -view.getScrollY());
    view.draw(c);
    view.setDrawingCacheEnabled(true);
    Bitmap cacheBmp = view.getDrawingCache();
    Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
    view.destroyDrawingCache();
    return new BitmapDrawable(viewBmp);

}

Aquí está el archivo del proyecto completo, si alguno de ustedes quiere usar Spannble

Krishna Shrestha
fuente
1
gracias ... su solución funciona bien, pero mi problema es que cuando presioné el botón AGREGAR, el texto de la burbuja se agrega en el texto de edición, pero cuando borro el texto de edición y trato de volver a ingresar (presione el botón Agregar), la burbuja agregada anteriormente queda y también se agrega uno nuevo. Y también elimino la burbuja cuando presiono el signo de cruz del lado derecho.
Govind Rathod
Abordar el primer problema. Supongo que almacenó texto en la lista y no lo borró al borrar Editar texto. Puede que no sea correcto, fue solo una suposición, ya que no sé cómo codifica.
Krishna Shrestha
Sé que es una publicación antigua, pero necesito una respuesta a mi pregunta ... Estoy construyendo la misma aplicación que se muestra arriba ... estoy usando MultiAutoCompleteTextView para las sugerencias y luego creo las burbujas cuando se hace clic en el elemento ... las burbujas se crean correctamente pero mi problema es que no quiero que el cursor aparezca entre las dos burbujas ... Estoy usando el tokenizador de espacio para MultiAutoCompleteTextView ... ¿alguna pista de cómo lograr esto?
VijayRaj
@chrish Gracias por este código, sin embargo, tengo una pregunta. Tengo una situación en la que ya tengo algunos valores conmigo y los pegaré directamente en el texto de edición como textos extensibles. sin embargo, ahora me pregunto si es posible combinar su código de un proyecto spannable con este tipo de funcionalidad. Quiero tener la capacidad de agregar nombres de eliminación en tiempo de ejecución, la adición puede ocurrir en grupo, sin embargo, la eliminación es como de costumbre (uno por uno) .. gracias
kuldeep
5

Tengo una biblioteca que hace lo que estás buscando con:

  • Predeterminado o totalmente personalizable (incluso puede usar su propio diseño)
  • Soporte multilínea
  • Oyente de clic

Echa un vistazo aquí

Aquí un inicio rápido:

Agregue ChipView a su diseño o créelo mediante programación:

<com.plumillonforge.android.chipview.ChipView
    android:id="@+id/chipview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Inícielo con una lista de datos que amplían el Chip abstracto y un oyente de clics (si lo desea):

List<Chip> chipList = new ArrayList<>();
chipList.add(new Tag("Lorem"));
chipList.add(new Tag("Ipsum dolor"));
chipList.add(new Tag("Sit amet"));
chipList.add(new Tag("Consectetur"));
chipList.add(new Tag("adipiscing elit"));
ChipView chipDefault = (ChipView) findViewById(R.id.chipview);
chipDefault.setChipList(chipList);
chipDefault.setOnChipClickListener(new OnChipClickListener() {
        @Override
        public void onChipClick(Chip chip) {
            // Action here !
        }
    });

ChipView predeterminado se representa así:

ChipView predeterminado

Pero puede personalizarlo a su gusto desde el nivel general hasta el nivel de Chip:

ChipView general ChipView personalizado

Este no es un MultiAutocomplete, pero puedes imitarlo (en realidad lo estoy usando así)

Fragua de Plumillon
fuente