2012-05-30 11 views
86

Próbuję utworzyć bąbelki kontaktowe w numerze MultiAutoCompleteTextView, podobne do tego, w jaki sposób jest ono zaimplementowane w aplikacji Google+. Poniżej znajduje się zrzut ekranu:Kontakt Bubble EditText

Google+ Compose Post Screenshot .

Starałem się rozszerzyć klasę DynamicDrawableSpan w celu uzyskania spannable rozciągliwej w tle rozpiętości tekstu

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

Gdzie moja oval.xml odkształcalne jest zdefiniowany jako tak:

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

W mojej klasie działalności, która ma MulitAutoCompleteTextView, ustawić rozpiętość bańka tak:

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

Jednak zamiast owalnego kształtu wyświetlanego za pierwszymi 6 znakami w ciągu znaków znaki są niewidoczne, aw tle nie ma rysunków owalnych.

Jeśli mogę zmienić metodę BubbleSpan za getDrawable(), aby użyć .png zamiast kształtu rozciągliwej:

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 Następnie pojawi się jednak w ciąg znaków, które są częścią zakres nie pojawi się. Jak mogę to zrobić, aby znaki w zakresie były wyświetlane na pierwszym planie, a tymczasem niestandardowy ciąg do rysowania zostanie wyświetlony w tle?

Podjęto próbę użycia również ImageSpan zamiast podklasy DynamicDrawableSpan, ale zakończyło się to niepowodzeniem.

+0

możliwe duplikat [Etykiety Android lub pęcherzyków w EditText] (http://stackoverflow.com/questions/8090711/android-labels-or-bubbles-in-edittext) –

+0

Jak wybrane są coraz numery kontaktowe – srihari

+1

everthing jest w porządku, teraz jak obsługiwać kliknięcie obrazu krzyżowego, chcę aby usunąć widok, jeśli użytkownik kliknął ikonę krzyża, proszę o pomoc. – shaby

Odpowiedz

51

Dzięki @chrish za wszelką pomoc.Więc tutaj jest jak to zrobiłem:

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

} 
+12

Stwierdziłem, że to nie działa na wszystkich urządzeniach ze względu na problemy ze skalowaniem. Lepszym sposobem na to jest zwrócenie mapy bitowej z convertView, a następnie użycie rzeczywistych wymiarów bitmapy podczas ustawiania krawędzi do rysowania. Na przykład. 'BitmapDrawable bd = new BitmapDrawable (bitmap); bd.setBounds (0,0, bitmap.getWidth(), bitmapa.getHeight()); ' Działa to we wszystkich urządzeniach. – dmon

+0

Witam, może będę musiał opublikować to w nowym pytaniu, ale chcę wiedzieć, czy napotkałeś problemy z wielowierszowymi widokami tekstowymi. Używam tego w systemie Android 3.2 i "czasami", wygląda na to, że szerokość bańki nie jest dobrze obliczana. Jak w tekście nie będzie kontynuował do następnego wiersza, ale zamiast tego będzie kontynuował poza TextView. Jeśli widziałeś to, jakieś wskazówki? –

+1

Jeśli tekst z bąbelkiem jest szerszy niż autouzupełnianie, to bąbel jest tworzony dwa razy w dwóch wierszach. Shold ustawiono to na textView: textView.setMaxWidth (this.getWidth() - SOME_PADDING); 'I używam tego również (jeśli tekst jest zbyt duży jest w dwóch liniach w bańce i ... na końcu) : textView.setEllipsize (TruncateAt.END); textView.setSingleLine (false); textView.setMaxLines (2); – koso

21

Tutaj jest kompletnym rozwiązaniem dla Ciebie

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

} 

Oto pełna plik projektu, jeśli ktoś z was chce używać Spannble

+1

dzięki ... twoje rozwiązanie działa dobrze, ale moje problemy są po naciśnięciu przycisku ADD bąbelkowy tekst jest dodawany w tekście edycji, ale kiedy wyczyściłem edycję -tekst i próba ponownego wejścia (naciśnij przycisk Dodaj) poprzednio dodany bąbelek pozostanie i nowy zostanie również dodany. a także usuwam bańkę po naciśnięciu prawego znaku krzyża. –

+0

Adresowanie pierwszego wydania. Zgadnij, że zapisałeś tekst na liście i nie wyczyściłeś go podczas usuwania tekstu. Mogę być wright, to tylko domysły, ponieważ nie wiem, jak kodujesz. –

+0

Znam jego stary post, ale potrzebuję odpowiedzi na moje pytanie .. Buduję tę samą aplikację, jak pokazano powyżej .. używaj MultiAutoCompleteTextView do sugestii, a następnie utwórz bąbelki po kliknięciu elementu .. bąble są tworzone pomyślnie ale mój problem polega na tym, że nie chcę, aby kursor pojawił się między dwoma bąbelkami ... Używam tokenizatora przestrzeni dla MultiAutoCompleteTextView..ne wskazówki jak to osiągnąć? – VijayRaj

5

Mam biblioteki, który robi to, co szukasz z:

  • Naruszenia lub w pełni konfigurowalny (można nawet użyć własnego układu)
  • wsparcie
  • wielowierszowego
  • Kliknij słuchacz

Have a look here

Tutaj quickstart:

Dodaj ChipView do układu lub utworzyć go programowo:

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

Init go z listy danych, które rozciągają streszczenie chip i słuchacza kliknięcia (jeśli chcesz):

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

domyślna ChipView staje się w ten sposób:

Default ChipView

Ale można dostosować, jak chcesz od ogólny poziom Chip:

Overall ChipView Custom ChipView

To nie jest MultiAutocomplete ale może uda Ci się go naśladować (ja faktycznie go używać tak)

+0

jesteś moim oszczędzającym życie. wielkie dzięki –