2012-07-03 20 views
23

Tôi đã tìm kiếm xung quanh nhưng không thể tìm thấy bất kỳ câu trả lời nào cho điều này. Những gì tôi đang cố gắng thực hiện là EditText tương tự như trường 'Tới' được tìm thấy trong màn hình soạn thảo của ứng dụng gmail ICS.Tạo một EditText tùy chỉnh có tính năng giống như thẻ

Dưới đây là một hình ảnh mô tả những gì tôi muốn: enter image description here

Tôi đang nghĩ đến việc mở rộng EditText và thực hiện riêng lớp tùy chỉnh EditText của tôi nhưng tôi không thực sự chắc chắn làm thế nào để làm điều đó hoặc thậm chí nếu đó là giải pháp tốt nhất . Có suy nghĩ gì không?

+1

Tắt dải, tôi đoán bạn đang nhìn thấy một 'EditText' thông thường, trên' Spannable' chứa các phần tử 'ImageSpan' cho" thẻ ". Tuy nhiên, nếu những phần "x" đó có nghĩa là việc chạm vào thẻ sẽ loại bỏ nó, thì tôi không nghĩ rằng điều đó là có thể với 'ImageSpan'. – CommonsWare

+1

Hmm có vẻ hợp lý nhưng yeah, google đã làm việc (với "x" nhỏ để loại bỏ nó) trên ứng dụng gmail của họ vì vậy tôi khá chắc chắn có một giải pháp đầy đủ ở đâu đó. Hy vọng rằng nó không phải là quá nhiều của một hack –

+0

@ BillX: Tôi có thể biết những gì giải pháp bạn đã quyết định sử dụng? Cảm ơn! – Loc

Trả lời

4

Hm, mất một lúc để tìm câu hỏi tương tự nhưng dù sao, đây là closest answer I found. Tôi biết người khác đã có loại vấn đề này trước đây! Nhờ CommonsWare đã chỉ cho tôi đúng hướng.

4

Tôi không thể tìm thấy giải pháp tốt, vì vậy tôi sẽ xây dựng thư viện của riêng mình để xử lý điều này: TokenAutoComplete. Dưới đây là một ví dụ cơ bản: Mã

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

Layout cho contact_token (bạn sẽ cần phải tìm x drawable của riêng bạn)

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

backgound Mã drawable

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

Person mã đối tượng

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

Mẫu acti vity

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", "[email protected]"), 
       new Person("Margaret Smith", "[email protected]"), 
       new Person("Max Jordan", "[email protected]"), 
       new Person("Meg Peterson", "[email protected]"), 
       new Person("Amanda Johnson", "[email protected]"), 
       new Person("Terry Anderson", "[email protected]") 
     }; 

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

Layout đang

<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> 
+0

Tôi đang ở trong cùng một tình huống BillX. Tôi có thể biết giải pháp của bạn hoạt động với nút x-close không? Cảm ơn. – Loc

+0

@LocHa Bạn có tìm thấy giải pháp nào cho chức năng nút x-close không? –

+0

@SwapnilSonar: Tôi không tìm thấy giải pháp hoàn chỉnh nào. Tôi tạo ra cách riêng của mình để chỉnh sửa thẻ (Không giống như cách thức mà BillX muốn). Bạn có thể tìm hiểu điều gì đó từ kpbird.com/2013/02/android-chips-edittext-token-edittext.html – Loc

5

Phỏng theo giải pháp từ this answer. Tách đầu vào tự động khi chèn dấu phẩy (dấu phân cách có thể được điều chỉnh). Tạo một ImageSpan và một ClickableSpan (các mục có thể được gỡ bỏ bằng cách nhấp vào phần bên phải).

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> 

Điều cuối cùng để thêm được png cho "x-Button". Hoạt động tốt cho đến nay, chỉ có vấn đề là nhấn lâu trên phím xóa không hoạt động (nếu ai đó có ý tưởng về cách hoạt động, hãy bình luận)

+0

Làm việc tốt ở đó, tôi đã tự hỏi tại sao tôi không thể thấy con trỏ nhấp nháy lúc đầu khi tôi thêm cái này. – prateek31

1

Tôi đã tạo một library để giải quyết vấn đề này, cảm thấy tự do để sử dụng nó và đóng góp.

+0

bằng cách sử dụng thư viện đẹp của bạn, bạn có thể plz cho tôi biết, làm thế nào để xóa các thẻ từ phía sau (xóa) báo chí trên một SoftKeyboard? – Dhiren

Các vấn đề liên quan