Contatta Bubble EditText


89

Sto cercando di creare bolle di contatto in modo MultiAutoCompleteTextViewsimile a come è implementato nell'app Google+. Di seguito è una schermata:

Screenshot di Google+ Compose Post .

Ho cercato di estendere la DynamicDrawableSpanclasse per ottenere un disegnabile spannabile sullo sfondo di un intervallo di testo

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

Dove il mio drawable oval.xml è definito così:

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

Nella mia classe di attività che ha il MulitAutoCompleteTextView, ho impostato l'intervallo di bolle in questo modo:

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

Tuttavia, invece della forma ovale visualizzata dietro i primi 6 caratteri nella stringa, i caratteri non sono visibili e non è tracciabile alcun ovale sullo sfondo.

Se cambio il metodo getDrawable () di BubbleSpan per utilizzare un .png invece di una forma disegnabile:

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

Quindi verrà visualizzato .png ma i caratteri nella stringa che fanno parte dell'intervallo non verranno visualizzati. Come posso fare in modo che i caratteri nell'intervallo siano visualizzati in primo piano, nel frattempo una forma disegnabile personalizzata viene visualizzata sullo sfondo?

Ho tentato di utilizzare anche una ImageSpaninvece di una sottoclasse, DynamicDrawableSpanma senza successo.



Come si ottengono i numeri di contatto selezionati
Srihari

github.com/splitwise/TokenAutoComplete potrebbe essere utile ad alcuni
john-salib

Risposte:


55

Grazie @chrish per tutto l'aiuto. Quindi ecco come l'ho fatto:

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
Ho scoperto che questo non funzionava in tutti i dispositivi a causa di problemi di ridimensionamento. Un modo migliore per farlo è restituire la bitmap dal convertView, quindi utilizzare le dimensioni effettive della bitmap quando si impostano i bordi disegnabili. Ad esempio, BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); funziona su tutti i dispositivi.
dmon

Ciao, potrei aver bisogno di postare questo in una nuova domanda, ma volevo sapere se hai riscontrato problemi con TextView a più righe. Sto eseguendo questo su Android 3.2 e "a volte", sembra che la larghezza della bolla non sia calcolata bene. Come nel testo, non continuerà alla riga successiva, ma continuerà invece al di fuori di TextView. Se l'hai visto, qualche consiglio?
Johann Hilbold

1
Se il testo con la bolla è più largo, il completamento automatico della bolla viene creato due volte su due righe. Devi impostarlo su textView: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `E lo sto usando anche (se il testo è troppo grande è in due righe nel fumetto e con ... alla fine): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (false); textView.setMaxLines (2);
SocialError

funziona bene quando si seleziona dall'elenco a discesa. Nel caso in cui, se vuoi impostare alcuni valori predefiniti su edittext, allora, come posso avvolgere quel testo con il pulsante con il bordo n croce?
Braj

5
come aggiungi il clicklistener al diverso elemento nella visualizzazione testo per eliminare il testo.
Nambi

21

Ecco una soluzione completa per te

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

}

Ecco il file di progetto completo, se qualcuno di voi desidera utilizzare Spannble


1
grazie ... la tua soluzione funziona bene ma i miei problemi sono quando ho premuto il pulsante AGGIUNGI il testo della bolla viene aggiunto nel testo di modifica ma quando cancello il testo di modifica e provo a reinserirlo (premi il pulsante Aggiungi) la bolla aggiunta in precedenza rimane e ne viene aggiunto anche uno nuovo. e rimuovo anche la bolla quando si preme il segno a croce sul lato destro.
Govind Rathod

Risolve il primo problema. Suppongo che tu abbia memorizzato il testo nell'elenco e non l'hai cancellato durante la cancellazione di Modifica testo. Potrei non essere corretto, era solo una supposizione perché non so come si codifica.
Krishna Shrestha

So che è un vecchio post, ma ho bisogno di rispondere alla mia domanda .. Sto costruendo la stessa applicazione mostrata sopra..im usando MultiAutoCompleteTextView per i suggerimenti e quindi creo le bolle quando si fa clic sull'elemento .. le bolle vengono create con successo ma il mio problema è che non voglio che il cursore appaia tra le due bolle ... Sto usando lo space tokenizer per MultiAutoCompleteTextView .. qualche indizio su come ottenere questo?
VijayRaj

@chrish Grazie per questo codice, ho comunque una domanda. Ho una situazione in cui ho già alcuni valori con me e li incollerò direttamente nel testo di modifica come testi spannabili. tuttavia, ora mi chiedo solo che sia possibile combinare il codice del progetto spannabile con questo tipo di funzionalità. Voglio avere la possibilità di aggiungere nomi di eliminazione in fase di esecuzione, l'aggiunta può avvenire in gruppo, tuttavia l'eliminazione è come al solito (uno per uno) .. grazie
kuldeep

5

Ho una libreria che fa quello che stai cercando con:

  • Predefinito o completamente personalizzabile (puoi persino utilizzare il tuo layout)
  • Supporto multilinea
  • Fare clic su listener

Dai un'occhiata qui

Ecco una guida rapida:

Aggiungi ChipView al tuo layout o crealo in modo programmatico:

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

Inizializzalo con un elenco di dati che estendono Chip astratto e un listener di clic (se lo desideri):

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

Il ChipView predefinito viene visualizzato in questo modo:

ChipView predefinito

Ma puoi personalizzare come preferisci dal livello generale al livello Chip:

ChipView generale ChipView personalizzato

Questo non è un MultiAutocomplete ma puoi riuscire a imitarlo (in realtà lo sto usando in questo modo)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.