hootsuite / nachos

Material Chips for Android
Other
450 stars 87 forks source link

Max chip text length #56

Open D330 opened 6 years ago

D330 commented 6 years ago

How to set max length for chip?

austin-kwong commented 6 years ago

You can extend DefaultChipTerminatorHandler or implement your own ChipTerminatorHandler and override the findAndHandleChipTerminators handler methods to be more stringent.

So for example, in handleChipifyCurrentToken, nothing occurs unless (tokenStart < tokenEnd). You could add an additional check here to make sure the length is of a certain range. You can further abstract this to set this length with parameters. Similar logic applies to changing terminateAllTokens, and handleChipifyToTerminator

D330 commented 6 years ago

@augudyne thanks. I create custom TokenizerHandler with callback and edit code so:

if (tokenStart < tokenEnd) {
            CharSequence token = text.subSequence(tokenStart, tokenEnd);
            if (controlWordListener == null || controlWordListener.onControl(token.toString())) {
                CharSequence chippedText = tokenizer.terminateToken(token, null);
                textIterator.replace(tokenStart, tokenEnd, chippedText);
                return tokenStart + chippedText.length();
            }
        }

But i want disallow input if length > maxLength... TokenizerHandler check only when inputted terminated symbol.

austin-kwong commented 6 years ago

So here, you will add if (tokenStart < tokenEnd && (tokenEnd - tokenStart < maxLength)).

Note that there are 3 call back methods for creating chips. Add this logic in handleChipifyCurrentToken, terminateAllTokens and handleChipifyToTerminator

D330 commented 6 years ago

@augudyne. Ookay see please i complete this!

public class DefaultChipTerminatorHandler implements ChipTerminatorHandler {

    @Nullable
    private List<Character> mChipTerminators;

    @Nullable
    private OnControlWordListener controlWordListener;

    @Nullable
    private OnControlSymbolListener controlSymbolListener;

    @Override
    public void addChipTerminator(char character) {
        if (mChipTerminators == null) {
            mChipTerminators = new ArrayList<>();
        }

        mChipTerminators.add(character);
    }

    @Override
    public int findAndHandleChipTerminators(@NonNull ChipTokenizer tokenizer, @NonNull Editable text, int start, int end) {
        // If we don't have a tokenizer or any chip terminators, there's nothing to look for
        if (mChipTerminators == null) {
            return -1;
        }

        TextIterator textIterator = new TextIterator(text, start, end);
        int selectionIndex = -1;

        while (textIterator.hasNextCharacter()) {
            char theChar = textIterator.nextCharacter();
            if (isChipTerminator(theChar)) {
                int newSelection = handleChipifyCurrentToken(textIterator, tokenizer);
                if (newSelection != -1) {
                    selectionIndex = newSelection;
                }
            } else {
                Editable editable = textIterator.getText();
                int index = textIterator.getIndex();
                int tokenStart = tokenizer.findTokenStart(editable, index);
                int tokenEnd = tokenizer.findTokenEnd(editable, index);
                if (tokenStart < tokenEnd) {
                    CharSequence word = text.subSequence(tokenStart, tokenEnd);
                    if (controlSymbolListener != null &&
                            !controlSymbolListener.onControl(theChar, word.toString())) {
                        textIterator.deleteCharacter(true);
                    }
                }
            }
        }

        return selectionIndex;
    }

    private int handleChipifyCurrentToken(TextIterator textIterator, ChipTokenizer tokenizer) {
        textIterator.deleteCharacter(true);
        Editable text = textIterator.getText();
        int index = textIterator.getIndex();
        int tokenStart = tokenizer.findTokenStart(text, index);
        int tokenEnd = tokenizer.findTokenEnd(text, index);
        if (tokenStart < tokenEnd) {
            CharSequence token = text.subSequence(tokenStart, tokenEnd);
            if (controlWordListener == null || controlWordListener.onControl(token.toString())) {
                CharSequence chippedText = tokenizer.terminateToken(token, null);
                textIterator.replace(tokenStart, tokenEnd, chippedText);
                return tokenStart + chippedText.length();
            }
        }
        return -1;
    }

    private boolean isChipTerminator(char character) {
        return mChipTerminators != null && mChipTerminators.contains(character);
    }

    public void setControlWordListener(@Nullable OnControlWordListener controlWordListener) {
        this.controlWordListener = controlWordListener;
    }

    public void setControlSymbolListener(@Nullable OnControlSymbolListener controlSymbolListener) {
        this.controlSymbolListener = controlSymbolListener;
    }
}
BimuratMukhtar commented 5 years ago

(tokenStart < tokenEnd && (tokenEnd - tokenStart < maxLength))

Thanks it works, one thing to note that you should call chipInput.setChipTerminatorHandler(YourCustomHandler()) before chipInput.addChipTerminator() (or maybe before all other methods)