Contacter Bubble EditText


89

J'essaie de créer des bulles de contact de la même MultiAutoCompleteTextViewmanière que dans l'application Google+. Voici une capture d'écran:

Capture d'écran du message Google+ Compose .

J'ai essayé d'étendre la DynamicDrawableSpanclasse afin d'obtenir un dessin spannable en arrière-plan d'une étendue de texte

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;
  }
}

Où mon dessinable oval.xml est défini comme suit:

<?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>

Dans ma classe d'activité qui a le MulitAutoCompleteTextView, j'ai défini la durée de la bulle comme ceci:

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); 

Cependant, au lieu de la forme ovale qui s'affiche derrière les 6 premiers caractères de la chaîne, les caractères ne sont pas visibles et il n'y a pas d'ovale dessinable en arrière-plan.

Si je change la méthode getDrawable () de BubbleSpan pour utiliser un .png au lieu d'une forme dessinable:

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

Ensuite, le .png apparaîtra mais les caractères de la chaîne qui font partie de la plage n'apparaîtront pas. Comment puis-je faire en sorte que les caractères de la plage soient affichés au premier plan, tandis qu'une forme personnalisée pouvant être dessinée s'affiche en arrière-plan?

J'ai essayé d'utiliser également un ImageSpanau lieu de sous-classer, DynamicDrawableSpanmais sans succès.



Comment vous obtenez les numéros de contact sélectionnés
Srihari

github.com/splitwise/TokenAutoComplete pourrait être utile à certains
john-salib

Réponses:


55

Merci @chrish pour toute l'aide. Alors, voici comment je l'ai fait:

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);

}

13
J'ai trouvé que cela ne fonctionnait pas sur tous les appareils en raison de problèmes de mise à l'échelle. Une meilleure façon de procéder consiste à renvoyer le bitmap à partir de convertView, puis à utiliser les dimensions réelles du bitmap lors de la définition des bords dessinables. Par exemple, BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); cela fonctionne dans tous les appareils.
dmon le

Salut, je devrai peut-être publier cela dans une nouvelle question, mais je voulais savoir si vous rencontriez des problèmes avec TextViews multi-lignes. J'exécute ceci sur Android 3.2 et "parfois", il semble que la largeur de la bulle n'est pas bien calculée. Comme dans le texte, il ne passera pas à la ligne suivante, mais continuera à l'extérieur de TextView. Si vous avez vu cela, des conseils?
Johann Hilbold

1
Si le texte avec bulle est plus large, la saisie semi-automatique que la bulle est créée deux fois sur deux lignes. Vous devez définir ceci sur textView: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `Et je l'utilise également (si le texte est trop grand est en deux lignes dans la bulle et avec ... à la fin): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (false); textView.setMaxLines (2);
SocialError

cela fonctionne très bien lorsque vous sélectionnez dans la liste déroulante. Dans le cas où, si vous voulez définir des valeurs prédéfinies sur edittext, comment puis-je envelopper ce texte avec le bouton de bordure n croix?
Braj

5
comment vous ajoutez l'écouteur de clics aux différents éléments de la vue de texte pour supprimer le texte.
Nambi

21

Voici une solution complète pour vous

//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);

}

Voici le fichier de projet complet, si l'un d'entre vous souhaite utiliser Spannble


1
merci ... votre solution fonctionne bien, mais mon problème est que lorsque j'ai appuyé sur le bouton AJOUTER, le texte-bulle est ajouté dans le texte d'édition, mais lorsque j'efface le texte d'édition et que j'essaie de ré-entrer (appuyez sur le bouton Ajouter), la bulle précédemment ajoutée reste et un nouveau est également ajouté. et je supprime également la bulle lorsque vous appuyez sur le signe transversal droit.
Govind Rathod

Résolution du premier problème, je suppose que vous avez stocké du texte dans la liste et que vous n'avez pas effacé lors de la suppression de Modifier le texte. Je ne peux pas être correct, ce n'était qu'une supposition car je ne sais pas comment vous codez.
Krishna Shrestha

Je sais que c'est un ancien post, mais j'ai besoin de répondre à ma question ... Je construis la même application que celle indiquée ci-dessus ... j'utilise MultiAutoCompleteTextView pour les suggestions, puis crée les bulles lorsque l'on clique sur l'élément ... les bulles sont créées avec succès mais mon problème est que je ne veux pas que le curseur apparaisse entre les deux bulles ... J'utilise le tokenizer d'espace pour MultiAutoCompleteTextView..any indice comment y parvenir ??
VijayRaj

@chrish Merci pour ce code, j'ai quand même une question. J'ai une situation où j'ai déjà des valeurs avec moi, et je vais les coller directement dans le texte d'édition sous forme de textes spannables. cependant, maintenant je me demande simplement qu'il est possible de combiner votre code de projet spannable avec ce type de fonctionnalité. Je veux avoir la possibilité d'ajouter des noms de suppression au moment de l'exécution, l'ajout peut se produire en groupe, mais la suppression est comme d'habitude (un par un) .. merci
kuldeep

5

J'ai une bibliothèque qui fait ce que vous cherchez avec:

  • Par défaut ou entièrement personnalisable (vous pouvez même utiliser votre propre mise en page)
  • Prise en charge multiligne
  • Cliquez sur l'écouteur

Regardez ici

Voici un démarrage rapide:

Ajoutez ChipView à votre mise en page ou créez-le par programme:

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

Lancez-le avec une liste de données qui étendent la puce abstraite et un écouteur de clic (si vous le souhaitez):

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 par défaut est rendu comme ceci:

ChipView par défaut

Mais vous pouvez personnaliser à votre guise du niveau global au niveau de la puce:

ChipView global ChipView personnalisé

Ce n'est pas un MultiAutocomplete mais vous pouvez réussir à l'imiter (je l'utilise en fait comme ça)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.