联系 Bubble EditText

我试图在 MultiAutoCompleteTextView中创建联系人气泡,类似于它在 Google + 应用程序中的实现方式。下面是一张截图:

Google+ Compose Post Screenshot .

我已经尝试扩展 DynamicDrawableSpan类,以便在一段文本的背景中获得可跨区域绘制的内容

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

在这里,我的 oval.xml 绘图工具被定义为:

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

在具有 MulitAutoCompleteTextView的 Activity 类中,我如下设置了泡沫跨度:

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

但是,字符串中前6个字符后面显示的不是椭圆形状,而是字符不可见,背景中也没有可绘制的椭圆形。

如果我将 BubbleSpan 的 getDrawable ()方法改为使用. png 而不是形状绘制:

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

然后。Png 将显示,但字符串中属于 span 的字符将不会显示。如何使跨度中的字符显示在前景中,同时自定义形状绘制显示在背景中?

我也尝试使用 ImageSpan代替子类化 DynamicDrawableSpan,但是没有成功。

33791 次浏览

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

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


}

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)

Material https://material.io/components/chips/android#using-chips

The answers above are deprecated

<com.google.android.material.chip.ChipGroup
android:id="@+id/tags"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>

and then in code:

val chip = Chip(context)
chip.text = text
chip.chipBackgroundColor =
ContextCompat.getColorStateList(
requireContext(),
R.color.color_sky_blue
)
chip.setOnCloseIconClickListener {
//clicking close
}
chip.isCloseIconVisible = true
chip.closeIcon =
ContextCompat.getDrawable(requireContext(), R.drawable.ic_cross_chip)
chip.closeIconTint = ContextCompat.getColorStateList(requireContext(), R.color.colorAzure)
chip.closeIconSize = requireContext().resources.getDimension(R.dimen.dp12)
chip.setTextAppearance(R.style.ChipTextAppearance)
chipGroup.addView(chip)