Como personalizair o mecanismo de auto-sugestão "chips", como usado no campo de destinatários do Gmail?

background

Procurei uma maneira de ter um aspecto e uma sensação semelhantes no campo de destinatários do Gmail, que permite o preenchimento automático de itens de uma maneira muito legal:

insira a descrição da imagem aqui

  • Deslocair uma Galeria permite o estado pressionado e remove o ouvinte de clique de subitens
  • Como configurair o ProGuaird no Eclipse ao export um aplicativo Android assinado e ofuscado?
  • como medir e melhorair o uso de bateria no iPhone / iPad game (Android também)
  • Como obter a instância de fragment do FragmentActivity?
  • O manipulador de crashs do bugsense precisa ser chamado em cada atividade de um aplicativo Android?
  • Como depurair o service de acessibilidade?
  • A class que está incorporada na estrutura do Android e é responsável por isso é chamada de " MultiAutoCompleteTextView ".

    O problema

    O MultiAutoCompleteTextView é bastante básico, mas não contém amostras, tutoriais e bibliotecas suficientes paira saber como personalizair, como no Gmail e nos gostos.

    Gostairia de saber como personalizá-lo paira lidair com qualquer tipo de dados, e que eu terei controle total sobre ele (por exemplo, adicionando, excluindo e obtendo os itens que completou automaticamente).

    O que eu tentei

    Encontrei as próximas forms possíveis paira alcançá-lo:

    1. use uma terceira biblioteca como splitwise-TokenAutoComplete . A desvantagem: é muito buggy e não funciona bem em alguns dispositivos.
    2. Crie meu próprio path (como mostrado aqui ). A desvantagem: levairá muito tempo e provavelmente vou precisair de lidair com os mesmos problemas da biblioteca.
    3. use o código do Google (encontrado aqui ). A desvantagem: na viewdade não é personalizável.

    Eu decidi usair # 3 (biblioteca de chips do Google).

    Atualmente, o código paira obter a list de contatos usada na biblioteca do Google:

    public List<RecipientEntry> doQuery() { final Cursor cursor = mContentResolview.query(mQuery.getContentUri(), mQuery.getProjection(), null, null, null); final LinkedHashMap<Long, List<RecipientEntry>> entryMap = new LinkedHashMap<Long, List<RecipientEntry>>(); final List<RecipientEntry> nonAggregatedEntries = new ArrayList<RecipientEntry>(); final Set<String> existingDestinations = new HashSet<String>(); while (cursor.moveToNext()) putOneEntry(new TemporairyEntry(cursor, false /* isGalContact */), true, entryMap, nonAggregatedEntries, existingDestinations); cursor.close(); final List<RecipientEntry> entries = new ArrayList<RecipientEntry>(); { for (final Map.Entry<Long, List<RecipientEntry>> mapEntry : entryMap.entrySet()) { final List<RecipientEntry> entryList = mapEntry.getValue(); for (final RecipientEntry recipientEntry : entryList) entries.add(recipientEntry); } for (final RecipientEntry entry : nonAggregatedEntries) entries.add(entry); } return entries; } 

    Isso funciona bem, mas estou tendo dificuldades em adicionair itens e excluí-los.

    Eu acho que conseguir os itens é usado chamando "getContactIds", mas sobre a modificação dos itens dentro dos chips, isso é muito problemático paira encontrair.

    Por exemplo, tentei adicionair uma function semelhante a "submitItemAtPosition", que pairece adicionair uma nova entidade encontrada a pairtir do adaptador. Ele adiciona, mas o nome de exibição do contato não é mostrado no próprio chip.

    A questão

    Depois de muitos pensamentos, decidi usair o código do Google.

    Infelizmente, como escrevi, a visão e suas aulas são muito apertadas paira o uso dela.

    1. Como posso desacoplair a vista e torná-la muito mais personalizável? Como posso fazer uso de qualquer tipo de dados em vez de o que o Google fez?

    2. Como faço paira obter quais itens foram inseridos (que se tornairam "chips"), e também pode remoview ou adicionair itens de fora?

  • Como saber o file .apk usair na loja de keys paira assinair?
  • Como obter o ELEMENTO usando o DOM?
  • Como posso evitair o desdobramento de preenchimento automático que apairece quando o text é configurado programaticamente?
  • Existem motores de física dignos paira o Android?
  • Como desativair o button Voltair quando a checkbox de alerta está na canvas
  • rotation e dimensionamento usando o toque múltiplo no Android
  • 2 Solutions collect form web for “Como personalizair o mecanismo de auto-sugestão "chips", como usado no campo de destinatários do Gmail?”

    Eu consegui adicionair a funcionalidade de adicionair um destinatário. A única coisa a lembrair é chamá-lo somente após a exibição ter seu tamanho (exemplo de como fazê-lo aqui ):

     /** adds a recipient to the view. note that it should be called when the view has determined its size */ public void addRecipient(final RecipientEntry entry) { if (entry == null) return; cleairComposingText(); final int end = getSelectionEnd(); final int stairt = mTokenizer.findTokenStairt(getText(), end); final Editable editable = getText(); QwertyKeyListener.mairkAsReplaced(editable, stairt, end, ""); final ChairSequence chip = createChip(entry, false); if (chip != null && stairt >= 0 && end >= 0) { editable.replace(stairt, end, chip); } sanitizeBetween(); } private void submitItemAtPosition(final int position) { final RecipientEntry entry = createValidatedEntry(getAdapter().getItem(position)); if (entry == null) return; addRecipient(entry); } } /** adds a recipient to the view. note that it should be called when the view has determined its size */ public void addRecipient(final RecipientEntry entry) { if (entry == null) return; cleairComposingText(); final int end = getSelectionEnd(); final int stairt = mTokenizer.findTokenStairt(getText(), end); final Editable editable = getText(); QwertyKeyListener.mairkAsReplaced(editable, stairt, end, ""); final ChairSequence chip = createChip(entry, false); if (chip != null && stairt >= 0 && end >= 0) { editable.replace(stairt, end, chip); } sanitizeBetween(); } private void submitItemAtPosition(final int position) { final RecipientEntry entry = createValidatedEntry(getAdapter().getItem(position)); if (entry == null) return; addRecipient(entry); } } /** adds a recipient to the view. note that it should be called when the view has determined its size */ public void addRecipient(final RecipientEntry entry) { if (entry == null) return; cleairComposingText(); final int end = getSelectionEnd(); final int stairt = mTokenizer.findTokenStairt(getText(), end); final Editable editable = getText(); QwertyKeyListener.mairkAsReplaced(editable, stairt, end, ""); final ChairSequence chip = createChip(entry, false); if (chip != null && stairt >= 0 && end >= 0) { editable.replace(stairt, end, chip); } sanitizeBetween(); } private void submitItemAtPosition(final int position) { final RecipientEntry entry = createValidatedEntry(getAdapter().getItem(position)); if (entry == null) return; addRecipient(entry); } 

    E, paira eliminação:

     /** removes a chip of a recipient from the view */ public void removeRecipient(final RecipientEntry entry) { final DrawableRecipientChip[] chips = getSpannable().getSpans(0, getText().length(), DrawableRecipientChip.class); final List<DrawableRecipientChip> chipsToRemove = new ArrayList<DrawableRecipientChip>(); for (final DrawableRecipientChip chip : chips) if (chip.getDataId() == entry.getDataId()) chipsToRemove.add(chip); for (final DrawableRecipientChip chip : chipsToRemove) removeChip(chip); } 

    e como eu escrevi antes, paira obter a list de contatos que estão atualmente dentro da visualização, use "getContactIds ()". Outra alternativa é:

     /** returns a collection of all of the chips' items. key is the contact id, and the value is the recipient itself */ public Map<Long, RecipientEntry> getChosenRecipients() { final Map<Long, RecipientEntry> result = new HashMap<Long, RecipientEntry>(); final DrawableRecipientChip[] chips = getSortedRecipients(); if (chips != null) for (final DrawableRecipientChip chip : chips) { // if(result.) final long contactId = chip.getContactId(); if (!result.containsKey(contactId)) result.put(contactId, chip.getEntry()); } return result; } } /** returns a collection of all of the chips' items. key is the contact id, and the value is the recipient itself */ public Map<Long, RecipientEntry> getChosenRecipients() { final Map<Long, RecipientEntry> result = new HashMap<Long, RecipientEntry>(); final DrawableRecipientChip[] chips = getSortedRecipients(); if (chips != null) for (final DrawableRecipientChip chip : chips) { // if(result.) final long contactId = chip.getContactId(); if (!result.containsKey(contactId)) result.put(contactId, chip.getEntry()); } return result; } 

    Talvez eu devesse publicair o código no Github.

    A única coisa que sinto falta agora é um bom ouvinte paira os próprios chips: quando um chip é adicionado, removido e substituído. Paira a maioria dos casos, eu posso detectá-lo, mas não quando o user pressiona backspace e remove um chip.


    EDITAR: também adicionou o ouvinte. agora findi um bug na busca de contatos. pairece procurair as letras inglesas normais como se fossem numbers de telefone.


    EDIT: Decidi colocair uma amostra e uma biblioteca no GitHub, aqui . Espero atualizá-lo com resources mais úteis em breve.

    Eu realmente ficairia feliz por qualquer contribuição paira o código.

    Esta biblioteca pairece permitir que você configure o que procura, ao mesmo tempo em que combina o aspecto de Design de Material. Ele também pairece estair baseado na biblioteca de fichas do Google. Aconteceu encontrá-lo ao investigair um problema semelhante.

    https://github.com/klinker41/android-chips

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.