ติดต่อ 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แต่ไม่สำเร็จ


อาจทำซ้ำฉลากหรือฟอง
Peter O.

คุณได้รับหมายเลขติดต่อที่เลือกอย่างไร
srihari

github.com/splitwise/TokenAutoComplete อาจเป็นประโยชน์กับบางคน
john-salib

คำตอบ:


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

สวัสดีฉันอาจต้องโพสต์คำถามนี้ในคำถามใหม่ แต่ต้องการทราบว่าคุณพบปัญหาเกี่ยวกับ TextView แบบหลายบรรทัดหรือไม่ ฉันใช้แอนดรอยด์ 3.2 และ "บางครั้ง" ดูเหมือนว่าความกว้างของฟองจะคำนวณไม่ดี เช่นเดียวกับในข้อความจะไม่อยู่ในบรรทัดถัดไป แต่จะดำเนินการต่อนอก TextView แทน หากคุณได้เห็นสิ่งนี้มีเคล็ดลับอย่างไร
Johann Hilbold

1
หากข้อความที่มีฟองกว้างกว่าการเติมข้อความอัตโนมัติจะถูกสร้างขึ้นสองครั้งในสองแถว คุณ shold ตั้งค่านี้เป็น textView: textView.setMaxWidth (this.getWidth () - SOME_PADDING); `และฉันก็ใช้สิ่งนี้ด้วย (ถ้าข้อความใหญ่เกินไปอยู่ในสองบรรทัดในฟองและ ... ในตอนท้าย): textView.setEllipsize (TruncateAt.END); textView.setSingleLine (เท็จ); textView.setMaxLines (2);
SocialError

วิธีนี้ใช้งานได้ดีเมื่อคุณเลือกจากรายการแบบเลื่อนลง ในกรณีที่คุณต้องการตั้งค่าที่กำหนดไว้ล่วงหน้าเป็นแก้ไขข้อความฉันจะตัดข้อความนั้นด้วยเส้นขอบ n ปุ่มกากบาทได้อย่างไร?
Braj

5
คุณเพิ่ม clicklistener ลงในรายการต่างๆในมุมมองข้อความเพื่อลบข้อความได้อย่างไร
Nambi

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
ขอบคุณ ... วิธีแก้ปัญหาของคุณใช้งานได้ดี แต่ปัญหาของฉันคือเมื่อฉันกดปุ่ม ADD Bubble-text ถูกเพิ่มในข้อความแก้ไข แต่เมื่อฉันล้างข้อความแก้ไขและพยายามป้อนใหม่ (กดปุ่มเพิ่ม) ฟองอากาศที่เพิ่มก่อนหน้านี้ยังคงอยู่และ ใหม่ต่อท้ายด้วย และฉันยังลบฟองเมื่อกดเครื่องหมายกากบาทด้านขวา
Govind Rathod

แก้ไขปัญหาแรกฉันเดาว่าคุณเก็บข้อความไว้ในรายการและคุณไม่ได้ล้างขณะล้างแก้ไขข้อความ ฉันอาจจะไม่เขียนมันเป็นเพียงการคาดเดาเพราะฉันไม่รู้ว่าคุณเขียนโค้ดอย่างไร
Krishna Shrestha

ฉันรู้ว่ามันเป็นโพสต์เก่า แต่ฉันต้องการคำตอบสำหรับคำถามของฉันฉันกำลังสร้างแอพพลิเคชั่นเดียวกันกับที่แสดงด้านบน .. ฉันใช้ MultiAutoCompleteTextView สำหรับคำแนะนำจากนั้นสร้างฟองอากาศเมื่อรายการถูกคลิก .. ฟองถูกสร้างสำเร็จ แต่ ปัญหาของฉันคือฉันไม่ต้องการให้เคอร์เซอร์ปรากฏระหว่างสองฟอง ... ฉันใช้ space tokenizer สำหรับ MultiAutoCompleteTextView .. มีเงื่อนงำวิธีที่จะบรรลุสิ่งนี้ได้อย่างไร ??
VijayRaj

@chrish ขอบคุณสำหรับรหัสนี้ฉันมีคำถามหนึ่งข้อ ฉันมีสถานการณ์ที่ฉันมีค่าบางอย่างอยู่แล้วและฉันจะวางค่าเหล่านี้ลงในข้อความแก้ไขโดยตรงเป็นข้อความที่เป็นภาษาสเปน อย่างไรก็ตามตอนนี้ฉันสงสัยว่าเป็นไปได้ไหมที่จะรวมโค้ดของคุณจากโปรเจ็กต์ spannable กับฟังก์ชันประเภทนี้ อยากได้ความสามารถในการเพิ่มชื่อลบในขณะรันการเพิ่มอาจเกิดขึ้นเป็นกลุ่ม แต่การลบเป็นไปตามปกติ (ทีละรายการ) .. ขอบคุณ
kuldeep

5

ฉันมีห้องสมุดที่ทำสิ่งที่คุณต้องการด้วย:

  • ค่าเริ่มต้นหรือปรับแต่งได้ทั้งหมด (คุณสามารถใช้เค้าโครงของคุณเองได้)
  • การสนับสนุนหลายสาย
  • คลิก Listener

ลองดูที่นี่

การเริ่มต้นอย่างรวดเร็ว:

เพิ่ม 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 แต่คุณสามารถเลียนแบบได้ (ฉันใช้แบบนั้นจริงๆ)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.