Contact Bubble EditText

33,197

Solution 1

Thanks @chrish for all the help. So here is how i did it:

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

}

Solution 2

Here is a complete Solution for you

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

}

Here is the complete project file ,if any of you want to use Spannble

Solution 3

I got a library which does what you're looking for with :

  • Default or fully customizable (you can even use your own layout)
  • Multiline support
  • Click listener

Have a look here

Here a quickstart :

Add ChipView to your layout or create it programmatically :

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

Init it with a list of data which extend abstract Chip and a click listener (if you want) :

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

Default ChipView is rendered like this :

Default ChipView

But you can customise as you like from overall to Chip level :

Overall ChipView Custom ChipView

This isn't a MultiAutocomplete but you can manage to mimic it (I'm actually using it like that)

Share:
33,197
Etienne Lawlor
Author by

Etienne Lawlor

Android Dev Check out the surf report app I'm working on https://pitted.app

Updated on July 18, 2020

Comments

  • Etienne Lawlor
    Etienne Lawlor almost 4 years

    I am trying to create contact bubbles in the MultiAutoCompleteTextView similiar to how it is implemented in the Google+ app. Below is a screen shot:

    Google+ Compose Post Screenshot .

    I have tried to extend the DynamicDrawableSpan class in order to get a spannable drawable in the background of a span of text

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

    Where my oval.xml drawable is defined as so:

    <?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 my Activity class that has the MulitAutoCompleteTextView, I set the bubble span like so:

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

    However, instead of the oval shape displaying behind the first 6 characters in the string, the characters are not visible and there is no oval drawable in the background.

    If i change the BubbleSpan's getDrawable() method to use a .png instead of a shape drawable:

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

    Then the .png will show up but the characters in the string that are a part of the span will not show up. How can I make it so that the characters in the span are displayed in the foreground, meanwhile a custom shape drawable gets displayed in the background?

    I attempted to also use an ImageSpan instead of subclassing DynamicDrawableSpan but was unsuccessful.

  • dmon
    dmon over 11 years
    I found that this didn't work in all devices due to scaling issues. A better way to do this is to return the bitmap from the convertView, then use the actual bitmap's dimensions when setting the drawable edges. E.g. BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); That works in all devices.
  • GovindRathod
    GovindRathod over 11 years
    thanks... your solution works fine but my issues is when i pressed ADD button bubble-text is add in edit-text but when i Clear edit-text and trying to re-enter(press Add button) previously added bubble is remaining and new one is appended too. and i also remove bubble when press right side cross sign.
  • Krishna Shrestha
    Krishna Shrestha over 11 years
    Addressing first issue.i guess you stored text in list and you didn't clear while clearing Edit text. i may nt be wright, it was only a guess as i dont kno how you code.
  • Johann Hilbold
    Johann Hilbold over 11 years
    Hi, I may need to post this in a new question, but wanted to know whether you encountered problems with multi line TextViews. I'm running this on Android 3.2 and "sometimes", it looks like the width of the bubble is not calculated well. As in the text will not continue to the next line, but instead continue outside of the TextView. If you have seen this, any tips?
  • Koso
    Koso about 11 years
    If the text with bubble is wider that autocomplete than the bubble is created twice in two rows. You shold set this to textView: textView.setMaxWidth(this.getWidth() - SOME_PADDING);` And I'am also using this (if text is too large is in two lines in bubble and with ... at the end): textView.setEllipsize(TruncateAt.END); textView.setSingleLine(false); textView.setMaxLines(2);
  • VijayRaj
    VijayRaj over 10 years
    I know its an old post, but i need answer to my question..I am building same application as shown above..i m using MultiAutoCompleteTextView for the suggestions and then create the bubbles when the item is clicked..the bubbles are created successfully but my problem is I don't want the cursor to appear between the two bubbles...I m using space tokenizer for MultiAutoCompleteTextView..any clue how to achieve this??
  • Braj
    Braj over 10 years
    this works fine wn u select from dropdown list. In case, if u want set some predefined values to edittext, then , how can i wrap that text with border n cross button?
  • Nambi
    Nambi over 10 years
    how you add the clicklistener to the different item in the textview to delete the text.
  • kuldeep
    kuldeep over 8 years
    @chrish Thanks for this code, I have one question nevertheless. I have a situation where I have some values already with me, and I will paste them directly into the edit text as spannable texts. however, now I just wonder that is it possible to combine your code from spannable project with this kind of functionality. I want to have an ability to add delete names at run time, adding may happen in bunch, however delete is as usual (one by one) .. thanks