Skip to content

2.1 Affine Masks

Egor Taflanidi edited this page Jun 4, 2019 · 5 revisions

You may want to switch between mask formats depending on the input. Say, most of your phone numbers have their primary format like this:

+7 ([000]) [000] [00] [00]

But some of them may have an operator code:

+7 ([000]) [000] [00] [00]#[900]

Such that, when user starts to enter an operator code, the format is switched from the former to the latter.

Input                     Current Mask                        Complete

+7 (123) 456 78           +7 ([000]) [000] [00] [00]          False
+7 (123) 456 78 9         +7 ([000]) [000] [00] [00]          False
+7 (123) 456 78 90        +7 ([000]) [000] [00] [00]          True
+7 (123) 456 78 90#3      +7 ([000]) [000] [00] [00]#[900]    False
+7 (123) 456 78 90#33     +7 ([000]) [000] [00] [00]#[900]    True
+7 (123) 456 78 90#333    +7 ([000]) [000] [00] [00]#[900]    True

Put your additional mask formats into the affineFormats property:

val editText = ... 
val listener = MaskedTextChangedListener("+7 ([000]) [000] [00] [00]", editText)
listener.affineFormats = listOf("+7 ([000]) [000] [00] [00]#[900]") 

Or:

final EditText editText = findViewById(R.id.prefix_edit_text);
final List<String> affineFormats = new ArrayList<>();
affineFormats.add("+7 ([000]) [000] [00] [00]#[900]");

final MaskedTextChangedListener listener = new MaskedTextChangedListener(
    "+7 ([000]) [000] [00] [00]", 
    affineFormats,
    AffinityCalculationStrategy.PREFIX,
    true,
    editText,
    null,
    null
);

editText.addTextChangedListener(listener);
editText.setOnFocusChangeListener(listener);
editText.setHint(listener.placeholder());

Affinity calculation strategy

Affinity is an integer number, which represents the similarity between the input and the current mask. Thus, the mask with the highest affinity is picked to format the output.

Affinity calculation strategy is a text field listener property allowing to alter the math behind the affinity calculation.

.WHOLE_STRING

is the default affinity calculation strategy.
With this strategy, affinity equals text length subtracting the count of all added and removed characters.

For example:

format: [00].[00]

input1: 1234
input2: 12.34
input3: 1.234

affinity1 = 4 (symbols) - 1 (missed dot)                       = 3
affinity2 = 5 (symbols)                                        = 5
affinity3 = 5 (symbols) - 1 (superfluous dot) - 1 (missed dot) = 3

.PREFIX

— this configuration works better when your affine formats have distinctive prefixes, e.g. +1 ( and 8 ( in phone numbers.
With this strategy, affinity equals length of the longest common prefix between the input and the output.

For example:

format1: +7 [000] [000]
format2: 8 [000] [000]

input: +7 12 345
affinity1 = 5
affinity2 = 0

input: 8 12 345
affinity1 = 0
affinity2 = 4

.CAPACITY

— this strategy comes in handy when the mask format radically changes depending on the input length.
With this strategy, affinity equals tolerance between the length of the input and the total amount of text current mask can accommodate.

For example:

format1: [000]
format2: [00000]
format3: [0000000]

input          affinity1    affinity2    affinity3
1              -2           -4           -6
12             -1           -3           -5
123            0            -2           -4
1234           Int.min      -1           -3
12345          Int.min      0            -2
123456         Int.min      Int.min      -1

IMPORTANT: Make sure the primary mask format of your text field listener is assigned to the widest available mask format when using this affinity calculation strategy.