Wenden Sie sich an Bubble EditText

89

Ich versuche, Kontaktblasen zu erstellen, MultiAutoCompleteTextViewähnlich wie sie in der Google+ App implementiert sind. Unten ist ein Screenshot:

Google+ Post-Screenshot verfassen .

Ich habe versucht, die DynamicDrawableSpanKlasse zu erweitern, um eine spannbare Zeichnung im Hintergrund einer Textspanne zu erhalten

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

Wo meine oval.xml drawable wie folgt definiert ist:

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

In meiner Aktivitätsklasse mit dem habe MulitAutoCompleteTextViewich die Blasenspanne wie folgt eingestellt:

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

Anstelle der ovalen Form, die hinter den ersten 6 Zeichen in der Zeichenfolge angezeigt wird, sind die Zeichen jedoch nicht sichtbar und im Hintergrund kann kein Oval gezeichnet werden.

Wenn ich die getDrawable () -Methode von BubbleSpan so ändere, dass anstelle einer zeichnbaren Form eine PNG-Datei verwendet wird:

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

Dann wird die PNG-Datei angezeigt, aber die Zeichen in der Zeichenfolge, die Teil der Spanne sind, werden nicht angezeigt. Wie kann ich dafür sorgen, dass die Zeichen in der Spanne im Vordergrund angezeigt werden, während im Hintergrund eine benutzerdefinierte Form gezeichnet wird?

Ich habe versucht, ImageSpananstelle von auch eine Unterklasse zu verwenden DynamicDrawableSpan, war jedoch nicht erfolgreich.

toobsco42
quelle
mögliches Duplikat von Android Labels oder Bubbles in EditText
Peter O.
Wie Sie ausgewählte Kontaktnummern erhalten
srihari
github.com/splitwise/TokenAutoComplete könnte für einige hilfreich sein
John-Salib

Antworten:

55

Danke @chrish für all die Hilfe. Also hier ist, wie ich es gemacht habe:

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
quelle
13
Ich habe festgestellt, dass dies aufgrund von Skalierungsproblemen nicht auf allen Geräten funktioniert. Eine bessere Möglichkeit, dies zu tun, besteht darin, die Bitmap aus der convertView zurückzugeben und dann beim Festlegen der zeichnbaren Kanten die tatsächlichen Bitmap-Abmessungen zu verwenden. ZB BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); Das funktioniert auf allen Geräten.
dmon
Hallo, ich muss dies möglicherweise in einer neuen Frage posten, wollte aber wissen, ob Sie Probleme mit mehrzeiligen TextViews haben. Ich verwende dies auf Android 3.2 und "manchmal" sieht es so aus, als ob die Breite der Blase nicht gut berechnet ist. Wie im Text wird nicht mit der nächsten Zeile fortgefahren, sondern außerhalb der Textansicht. Wenn Sie dies gesehen haben, irgendwelche Tipps?
Johann Hilbold
1
Wenn der Text mit der Blase breiter ist als die automatische Vervollständigung, wird die Blase zweimal in zwei Zeilen erstellt. Sie sollten dies auf textView setzen: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `Und ich verwende dies auch (wenn der Text zu groß ist, steht er in zwei Zeilen in Blase und mit ... am Ende): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (false); textView.setMaxLines (2);
SocialError
Dies funktioniert einwandfrei, wenn Sie aus der Dropdown-Liste auswählen. Wenn Sie einige vordefinierte Werte auf edittext setzen möchten, wie kann ich diesen Text dann mit dem Rand und der Kreuztaste umbrechen?
Braj
5
wie Sie den Clicklistener zu den verschiedenen Elementen in der Textansicht hinzufügen, um den Text zu löschen.
Nambi
21

Hier ist eine Komplettlösung für Sie

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

}

Hier ist die vollständige Projektdatei, falls einer von Ihnen Spannble verwenden möchte

Krishna Shrestha
quelle
1
danke ... Ihre Lösung funktioniert einwandfrei, aber meine Probleme sind, wenn ich auf die Schaltfläche HINZUFÜGEN geklickt habe neue wird ebenfalls angehängt. und ich entferne auch Blase, wenn ich rechtes Kreuzzeichen drücke.
Govind Rathod
Adressierung des ersten Problems. Ich vermute, Sie haben Text in der Liste gespeichert und beim Löschen von Text bearbeiten nicht gelöscht. Ich kann nicht Wright sein, es war nur eine Vermutung, da ich nicht weiß, wie Sie codieren.
Krishna Shrestha
Ich weiß, dass es ein alter Beitrag ist, aber ich brauche eine Antwort auf meine Frage. Ich erstelle dieselbe Anwendung wie oben gezeigt. Ich verwende MultiAutoCompleteTextView für die Vorschläge und erstelle dann die Blasen, wenn auf das Element geklickt wird. Die Blasen werden aber erfolgreich erstellt Mein Problem ist, dass ich nicht möchte, dass der Cursor zwischen den beiden Blasen erscheint. Ich verwende den Space Tokenizer für MultiAutoCompleteTextView. Gibt es einen Hinweis, wie dies erreicht werden kann?
VijayRaj
@chrish Danke für diesen Code, ich habe trotzdem eine Frage. Ich habe eine Situation, in der ich bereits einige Werte bei mir habe, und ich werde sie als spannbare Texte direkt in den Bearbeitungstext einfügen. Jetzt frage ich mich jedoch nur, ob es möglich ist, Ihren Code aus einem spannbaren Projekt mit dieser Art von Funktionalität zu kombinieren. Ich möchte die Möglichkeit haben, Löschnamen zur Laufzeit hinzuzufügen. Das Hinzufügen kann in großen Mengen erfolgen, das Löschen erfolgt jedoch wie gewohnt (nacheinander). Danke
Kuldeep
5

Ich habe eine Bibliothek, die das macht, wonach Sie suchen:

  • Standard oder vollständig anpassbar (Sie können sogar Ihr eigenes Layout verwenden)
  • Mehrzeilige Unterstützung
  • Klicken Sie auf Listener

Schauen Sie hier

Hier ein Schnellstart:

Fügen Sie Ihrem Layout ChipView hinzu oder erstellen Sie es programmgesteuert:

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

Initiieren Sie es mit einer Liste von Daten, die den abstrakten Chip erweitern, und einem Klick-Listener (wenn Sie möchten):

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

Die Standard-ChipView wird folgendermaßen gerendert:

Standard-ChipView

Sie können jedoch von der Gesamt- bis zur Chip-Ebene beliebig anpassen:

Insgesamt ChipView Benutzerdefinierte ChipView

Dies ist kein MultiAutocomplete, aber Sie können es nachahmen (ich benutze es tatsächlich so).

Plumillon Forge
quelle