How to customize the “chips” auto-suggesting mechanism, as used on Gmail's recipients field?

后端 未结 2 1841
时光说笑
时光说笑 2021-02-08 01:20

Background

I\'ve searched for a way to have a similar look & feel to the Gmail receipients field, which allows auto-filling of items in a really cool way:

相关标签:
2条回答
  • 2021-02-08 01:24

    I've succeeded adding the functionality of adding a recipient. The only thing to remember is to call it only after the view got its size (example of how to do it here) :

    /** 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;
        clearComposingText();
    
        final int end = getSelectionEnd();
        final int start = mTokenizer.findTokenStart(getText(), end);
    
        final Editable editable = getText();
        QwertyKeyListener.markAsReplaced(editable, start, end, "");
        final CharSequence chip = createChip(entry, false);
        if (chip != null && start >= 0 && end >= 0) {
            editable.replace(start, end, chip);
        }
        sanitizeBetween();
    }
    
    private void submitItemAtPosition(final int position) {
        final RecipientEntry entry = createValidatedEntry(getAdapter().getItem(position));
        if (entry == null)
            return;
        addRecipient(entry);
    }
    

    And, for deletion:

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

    and as I've written before, for getting the list of contactIds that are currently inside the view, use "getContactIds()" . Another alternative is:

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

    Maybe I should post the code on Github.

    The only thing I miss now is a good listener to the chips themselves : when a chip is added, removed and replaced. for most of the cases I can detect it, but not when the user presses backspace and removes a chip.


    EDIT: also added the listener. now I've found a bug in searching of contacts. it seems to search the normal English letters as if they were phone numbers.


    EDIT: I've decided to put a sample and a library on GitHub, here . Hope to update it with more useful features soon.

    I would really be happy for any contribution to the code.

    0 讨论(0)
  • 2021-02-08 01:24

    This library seems to allow you to configure what it searches for while also matching the Material Design look. It also seems to be based off of Google's chip library. I happened to find it when investigating a similar problem.

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

    0 讨论(0)
提交回复
热议问题