Liên hệ với Bubble EditText


89

Tôi đang cố gắng tạo bong bóng liên hệ MultiAutoCompleteTextViewtương tự như cách nó được triển khai trong ứng dụng Google+. Dưới đây là ảnh chụp màn hình:

Ảnh chụp màn hình bài đăng soạn thảo trên Google+ .

Tôi đã cố gắng mở rộng DynamicDrawableSpanlớp để có được một bản vẽ có thể kéo dài được trong nền của một khoảng văn bản

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

Trường hợp có thể vẽ oval.xml của tôi được xác định như vậy:

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

Trong lớp Hoạt động của tôi có MulitAutoCompleteTextView, tôi đặt khoảng trống bong bóng như vậy:

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

Tuy nhiên, thay vì hình bầu dục hiển thị phía sau 6 ký tự đầu tiên trong chuỗi, các ký tự không hiển thị và không có hình bầu dục có thể vẽ được ở nền.

Nếu tôi thay đổi phương thức getDrawable () của BubbleSpan để sử dụng .png thay vì một hình dạng có thể vẽ:

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

Sau đó, .png sẽ hiển thị nhưng các ký tự trong chuỗi là một phần của khoảng cách sẽ không hiển thị. Làm thế nào tôi có thể làm cho nó để các ký tự trong khoảng được hiển thị ở nền trước, trong khi một hình dạng tùy chỉnh có thể vẽ được hiển thị ở nền?

Tôi cũng đã cố gắng sử dụng một ImageSpanthay vì phân lớp DynamicDrawableSpannhưng không thành công.



Làm thế nào bạn đang nhận được lựa chọn số liên lạc
srihari

github.com/splitwise/TokenAutoComplete có thể hữu ích đối với một số
john-salib

Câu trả lời:


55

Cảm ơn @chrish cho tất cả sự giúp đỡ. Vì vậy, đây là cách tôi đã làm nó:

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

}

13
Tôi thấy rằng điều này không hoạt động trong tất cả các thiết bị do các vấn đề về tỷ lệ. Cách tốt hơn để làm điều này là trả về bitmap từ convertView, sau đó sử dụng kích thước thực của bitmap khi thiết lập các cạnh có thể vẽ. Ví dụ: BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); Điều đó hoạt động trong tất cả các thiết bị.
dmon

Xin chào, tôi có thể cần phải đăng câu hỏi này trong một câu hỏi mới, nhưng muốn biết liệu bạn có gặp sự cố với TextView nhiều dòng hay không. Tôi đang chạy điều này trên Android 3.2 và "đôi khi", có vẻ như chiều rộng của bong bóng không được tính toán tốt. Như trong văn bản sẽ không tiếp tục đến dòng tiếp theo mà thay vào đó tiếp tục bên ngoài TextView. Nếu bạn đã thấy điều này, bất kỳ lời khuyên?
Johann Hilbold

1
Nếu văn bản có bong bóng rộng hơn thì tự động hoàn tất hơn bong bóng sẽ được tạo hai lần trong hai hàng. Bạn nên đặt cái này thành textView: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `Và tôi cũng đang sử dụng cái này (nếu văn bản quá lớn nằm trong hai dòng trong bong bóng và có ... ở cuối): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (sai); textView.setMaxLines (2);
SocialError,

điều này hoạt động tốt nếu bạn chọn từ danh sách thả xuống. Trong trường hợp, nếu bạn muốn đặt một số giá trị xác định trước cho văn bản chỉnh sửa, thì làm thế nào tôi có thể bọc văn bản đó bằng nút chéo n đường viền?
Braj

5
cách bạn thêm clicklistener vào mục khác nhau trong chế độ xem văn bản để xóa văn bản.
Nambi

21

Đây là một giải pháp hoàn chỉnh cho bạn

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

}

Đây là file dự án hoàn chỉnh, nếu có bạn nào muốn sử dụng Spannble


1
cảm ơn ... giải pháp của bạn hoạt động tốt nhưng vấn đề của tôi là khi tôi nhấn nút THÊM, bong bóng-văn bản được thêm vào văn bản chỉnh sửa nhưng khi tôi Xóa văn bản chỉnh sửa và cố gắng nhập lại (nhấn nút Thêm) bong bóng đã thêm trước đó vẫn còn và cái mới cũng được thêm vào. và tôi cũng loại bỏ bong bóng khi nhấn dấu chéo bên phải.
Govind Rathod

Giải quyết vấn đề đầu tiên. Tôi đoán bạn đã lưu trữ văn bản trong danh sách và bạn đã không xóa khi xóa Chỉnh sửa văn bản. Tôi có thể không hiểu, đó chỉ là phỏng đoán vì tôi không hiểu cách bạn viết mã.
Krishna Shrestha

Tôi biết đó là một bài đăng cũ, nhưng tôi cần câu trả lời cho câu hỏi của mình..Tôi đang xây dựng ứng dụng tương tự như được hiển thị ở trên..tôi sử dụng MultiAutoCompleteTextView cho các đề xuất và sau đó tạo bong bóng khi mục được nhấp vào .. bong bóng được tạo thành công nhưng vấn đề của tôi là tôi không muốn con trỏ xuất hiện giữa hai bong bóng ... Tôi đang sử dụng bộ mở rộng không gian cho MultiAutoCompleteTextView..có manh mối làm thế nào để đạt được điều này ??
VijayRaj

@chrish Cảm ơn vì mã này, tuy nhiên, tôi có một câu hỏi. Tôi có một tình huống mà tôi đã có một số giá trị và tôi sẽ dán chúng trực tiếp vào văn bản chỉnh sửa dưới dạng văn bản có thể mở rộng. tuy nhiên, bây giờ tôi chỉ tự hỏi rằng liệu có thể kết hợp mã của bạn từ dự án có thể mở rộng với loại chức năng này không. Tôi muốn có một khả năng thêm tên xóa tại thời gian chạy, thêm có thể xảy ra trong đám, tuy nhiên delete là như bình thường (từng người một) .. cảm ơn
kuldeep

5

Tôi có một thư viện chứa những gì bạn đang tìm kiếm:

  • Mặc định hoặc hoàn toàn có thể tùy chỉnh (bạn thậm chí có thể sử dụng bố cục của riêng mình)
  • Hỗ trợ đa tuyến
  • Nhấp vào người nghe

Có một cái nhìn ở đây

Đây là một bắt đầu nhanh:

Thêm ChipView vào bố cục của bạn hoặc tạo nó theo lập trình:

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

Kết hợp nó với một danh sách dữ liệu mở rộng Chip trừu tượng và trình nghe nhấp chuột (nếu bạn muốn):

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

ChipView mặc định được hiển thị như thế này:

ChipView mặc định

Nhưng bạn có thể tùy chỉnh theo ý muốn từ cấp độ tổng thể đến cấp độ Chip:

ChipView tổng thể Chế độ xem chip tùy chỉnh

Đây không phải là MultiAutocomplete nhưng bạn có thể quản lý để bắt chước nó (tôi thực sự đang sử dụng nó như vậy)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.