Зв’яжіться з Bubble EditText


89

Я намагаюся створити бульбашки контактів, MultiAutoCompleteTextViewподібні до того, як це реалізовано в додатку Google+. Нижче наведено знімок екрана:

Знімок екрана Google+ Створення повідомлення .

Я намагався розширити 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 drawable визначається так:

<?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, я встановив діапазон міхурів так:

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 символами у рядку, символи не видно, а на задньому плані немає овальних малюнків.

Якщо я змінив метод getDrawable () BubbleSpan, щоб використовувати .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 з’явиться, але символи в рядку, що є частиною проміжку, не відображатимуться. Як я можу зробити так, щоб символи в інтервалі відображалися на передньому плані, а тим часом власна фігура, що малюється, відображалася на задньому плані?

Я спробував також використати ImageSpanзамість підкласу, DynamicDrawableSpanале не вдався.



Як ви отримуєте вибрані контактні номери
srihari

github.com/splitwise/TokenAutoComplete може бути корисним для
когось

Відповіді:


55

Дякую @chrish за всю допомогу. Отже, ось як я це зробив:

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
Я виявив, що це спрацювало не на всіх пристроях через проблеми з масштабуванням. Кращий спосіб зробити це - повернути растрове зображення з convertView, а потім використовувати фактичні розміри растрового зображення при встановленні малювальних країв. Наприклад, BitmapDrawable bd = new BitmapDrawable(bitmap); bd.setBounds(0,0,bitmap.getWidth(), bitmap.getHeight()); це працює на всіх пристроях.
dmon

Привіт, можливо, мені доведеться опублікувати це в новому питанні, але я хотів би знати, чи не стикалися ви з проблемами з багаторядковими TextViews. Я запускаю це на Android 3.2 і "іноді", схоже, ширина бульбашки розрахована погано. Як і в тексті, не буде продовження до наступного рядка, а натомість продовження поза TextView. Якщо ви бачили це, будь-які поради?
Йоганн Хільбольд

1
Якщо текст із міхуром ширший, то автозаповнення, ніж міхур, створюється двічі у два рядки. Ви повинні встановити для цього значення textView: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `І я також використовую це (якщо текст занадто великий - у два рядки в міхурі і з ... в кінці): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (false); textView.setMaxLines (2);
SocialError

це працює добре, якщо не вибрати зі спадного списку. Якщо ви хочете встановити деякі заздалегідь визначені значення для редагування тексту, то як я можу обернути цей текст межею n перехресною кнопкою?
Брай

5
як ви додаєте клікер до іншого елемента в текстовому режимі, щоб видалити текст.
Намбі,

21

Ось повне рішення для вас

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

}

Ось повний файл проекту, якщо хтось із вас хоче використовувати Spannble


1
дякую ... ваше рішення працює нормально, але мої проблеми полягають у тому, що коли я натиснув кнопку ДОДАТИ, міхур-текст додається до редагування тексту, але коли я очищаю текст редагування та намагаюся повторно ввести (натисніть кнопку Додати), раніше доданий міхур залишається і додається також новий. і я також видаляю міхур, коли натискаю праворуч хрест.
Govind Rathod

Звернення до першого випуску. Я припускаю, що ви зберегли текст у списку, і не очистили його під час очищення редагування тексту. я не можу бути райтом, це було лише здогадка, оскільки я не знаю, як ви кодуєте.
Кришна Шрешта

Я знаю його стару публікацію, але мені потрібна відповідь на моє запитання .. Я будую те саме додаток, що показано вище ... я використовую MultiAutoCompleteTextView для пропозицій, а потім створюю бульбашки при натисканні на елемент ... бульбашки створюються успішно, але моя проблема в тому, що я не хочу, щоб курсор з'являвся між двома бульбашками ... я використовую космічний маркер для MultiAutoCompleteTextView .. будь-який підказ, як цього досягти
VijayRaj

@chrish Дякую за цей код, я маю одне питання. У мене ситуація, коли у мене вже є деякі значення, і я вставлю їх безпосередньо в текст редагування як тексти, які можна обертати. однак зараз мені просто цікаво, чи можливо поєднати ваш код із проекту, що розгортається, з таким функціоналом. Я хочу мати можливість додавати імена видалення під час запуску, додавання може відбуватися в купі, однак видалення відбувається як зазвичай (по одному) .. дякую
kuldeep

5

Я отримав бібліотеку, яка робить те, що ви шукаєте:

  • За замовчуванням або повністю настроюється (можна навіть використовувати власний макет)
  • Багаторядкова підтримка
  • Клацніть слухач

Подивіться тут

Ось швидкий старт:

Додайте ChipView до свого макета або створіть його програмно:

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

Створіть його зі списком даних, що розширюють абстрактний чіп, і прослуховувач клацань (якщо хочете):

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 відображається так:

За замовчуванням ChipView

Але ви можете налаштувати як завгодно від загального рівня до рівня чіпа:

Загальний ChipView Спеціальний ChipView

Це не MultiAutocomplete, але вам вдається його імітувати (я насправді використовую його так)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.