使用类似标签的function创build自定义editText

我一直在四处寻找,但找不到任何答案。 我想要实现的是一个EditText,类似于ICS gmail应用程序组成屏幕中的“To”字段。

这是一个描述我想要的图像: 在这里输入图像说明

我想扩展EditText和实现我自己的自定义EditText类,但我不知道如何做到这一点,或者即使这是最好的解决scheme。 有什么想法吗?

Solutions Collecting From Web of "使用类似标签的function创build自定义editText"

嗯,花了一段时间find一个类似的问题,但是,这是我发现的最接近的答案 。 我知道其他人以前有过这样的问题! 感谢CommonsWare为我指出了正确的方向。

我找不到一个好的解决scheme,所以我会build立我自己的库来处理这个: TokenAutoComplete 。 这是一个基本的例子:

 public class ContactsCompletionView extends TokenCompleteTextView { public ContactsCompletionView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected View getViewForObject(Object object) { Person p = (Person)object; LayoutInflater l = (LayoutInflater)getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE); LinearLayout view = (LinearLayout)l.inflate(R.layout.contact_token, (ViewGroup)ContactsCompletionView.this.getParent(), false); ((TextView)view.findViewById(R.id.name)).setText(p.getName()); return view; } @Override protected Object defaultObject(String completionText) { //Stupid simple example of guessing if we have an email or not int index = completionText.indexOf('@'); if (index == -1) { return new Person(completionText, completionText.replace(" ", "") + "@example.com"); } else { return new Person(completionText.substring(0, index), completionText); } } } 

contact_token的布局代码(你需要find你自己的x drawable)

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="@drawable/token_background"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/white" android:textSize="14sp" android:text="Test Me" android:padding="2dp" /> <ImageView android:layout_height="10dp" android:layout_width="10dp" android:src="@drawable/x" android:layout_gravity="center_vertical" android:layout_marginLeft="3dp" android:layout_marginRight="5dp" /> </LinearLayout> 

令牌背景可绘制

 <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#ffafafaf" /> <corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp" android:topRightRadius="5dp" android:bottomRightRadius="5dp" /> </shape> 

人员对象代码

 public class Person implements Serializable { private String name; private String email; public Person(String n, String e) { name = n; email = e; } public String getName() { return name; } public String getEmail() { return email; } @Override public String toString() { return name; } } 

示例活动

 public class TokenActivity extends Activity { ContactsCompletionView completionView; Person[] people; ArrayAdapter<Person> adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); people = new Person[]{ new Person("Marshall Weir", "marshall@example.com"), new Person("Margaret Smith", "margaret@example.com"), new Person("Max Jordan", "max@example.com"), new Person("Meg Peterson", "meg@example.com"), new Person("Amanda Johnson", "amanda@example.com"), new Person("Terry Anderson", "terry@example.com") }; adapter = new ArrayAdapter<Person>(this, android.R.layout.simple_list_item_1, people); completionView = (ContactsCompletionView)findViewById(R.id.searchView); completionView.setAdapter(adapter); completionView.setTokenClickStyle(TokenCompleteTextView.TokenClickStyle.Delete); } } 

布局代码

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.tokenautocomplete.ContactsCompletionView android:id="@+id/searchView" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> 

从这个答案改编的解决scheme。 插入逗号时自动分隔input(可以调整分隔符)。 创build一个ImageSpan和一个ClickableSpan(通过点击右边的部分可以删除条目)。

 public class TagEditText extends EditText { TextWatcher textWatcher; String lastString; String separator = ","; public TagEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setMovementMethod(LinkMovementMethod.getInstance()); textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { String thisString = s.toString(); if (thisString.length() > 0 && !thisString.equals(lastString)) { format(); } } }; addTextChangedListener(textWatcher); } private void format() { SpannableStringBuilder sb = new SpannableStringBuilder(); String fullString = getText().toString(); String[] strings = fullString.split(separator); for (int i = 0; i < strings.length; i++) { String string = strings[i]; sb.append(string); if (fullString.charAt(fullString.length() - 1) != separator.charAt(0) && i == strings.length - 1) { break; } BitmapDrawable bd = (BitmapDrawable) convertViewToDrawable(createTokenView(string)); bd.setBounds(0, 0, bd.getIntrinsicWidth(), bd.getIntrinsicHeight()); int startIdx = sb.length() - (string.length()); int endIdx = sb.length(); sb.setSpan(new ImageSpan(bd), startIdx, endIdx, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); MyClickableSpan myClickableSpan = new MyClickableSpan(startIdx, endIdx); sb.setSpan(myClickableSpan, Math.max(endIdx-2, startIdx), endIdx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); if (i < strings.length - 1) { sb.append(separator); } else if (fullString.charAt(fullString.length() - 1) == separator.charAt(0)) { sb.append(separator); } } lastString = sb.toString(); setText(sb); setSelection(sb.length()); } public View createTokenView(String text) { LinearLayout l = new LinearLayout(getContext()); l.setOrientation(LinearLayout.HORIZONTAL); l.setBackgroundResource(R.drawable.bordered_rectangle_rounded_corners); TextView tv = new TextView(getContext()); l.addView(tv); tv.setText(text); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); ImageView im = new ImageView(getContext()); l.addView(im); im.setImageResource(R.drawable.ic_cross_15dp); im.setScaleType(ImageView.ScaleType.FIT_CENTER); return l; } public Object convertViewToDrawable(View view) { int spec = View.MeasureSpec.makeMeasureSpec(0, View.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(getContext().getResources(), viewBmp); } private class MyClickableSpan extends ClickableSpan{ int startIdx; int endIdx; public MyClickableSpan(int startIdx, int endIdx) { super(); this.startIdx = startIdx; this.endIdx = endIdx; } @Override public void onClick(View widget) { String s = getText().toString(); String s1 = s.substring(0, startIdx); String s2 = s.substring(Math.min(endIdx+1, s.length()-1), s.length() ); TagEditText.this.setText(s1 + s2); } } } 

R.drawable.bordered_rectangle_rounded_corners:

 <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/transparent"/> <stroke android:width="1dp" android:color="#AAAAAA" /> <corners android:radius="100dp" /> <padding android:left="5dp" android:top="5dp" android:right="5dp" android:bottom="5dp" /> </shape> 

最后要添加的是“x-Button”的png。 目前为止工作得很好,唯一的问题是长时间按下delete-key不起作用(如果有人有一个想法如何使它工作,随时发表评论)

我创build了一个库来解决这个问题,随时使用它并贡献。