Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting an EditBox input into dots after a user inputs a single char?

1] 4 digit input boxes without input:

enter image description here

2] 4 digit input boxes with input :

enter image description here

As the user goes on entering 4-digit pin input box is turned into the dot, if the user wants to delete the last digit pressing back button user input gets deleted with dots again converting to the input box. If the user has middle input incorrect he can't convert dot into input box by touching it he has to traverse back deleting from right-to-left.

I see possible solution having the custom widget with setting views visible/gone based on user input detected via implementing TextWatcher. But does existing EditText widget in Android platform has any style configuration by making use of which I can code in XML to get above-mentioned UI change?

So far for the manual change, I have done following changes ( Code given for one input box this has been used to create group of 4 input boxes) :

XML layout for single input box :

<RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/pin_edit_box"
                    style="@style/pin_edittext_style"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:digits="0123456789"
                    android:focusable="true"
                    android:imeOptions="actionNext"
                    android:inputType="numberPassword" />

                <ImageView
                    android:id="@+id/pin_input_dot"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:minEms="3"
                    android:focusable="false"
                    android:layout_centerInParent="true"
                    android:enabled="false"
                    android:src="@drawable/ic_green_dot"
                    android:visibility="gone" />

            </RelativeLayout>

Text change listener :

pin_edit_box.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
int length = editable.toString().length();
        if (length == 1) {
            pin_edit_box_this.setVisibility(View.INVISIBLE);
            pin_input_dot_this.setVisibility(View.VISIBLE);
                        pin_edit_box_next.requestFocus();
        } else if (length == 0) {
// This part doesn't work as EditText is invisible at this time 
// dot image view is visible
            pin_edit_box_this.setVisibility(View.VISIBLE);
            pin_input_dot_this.setVisibility(View.GONE);
                        pin_edit_box_this_previous.requestFocus();
        }
            }
        });

When trying to detect back or delete button event from

boolean onKeyDown (int keyCode, 
                KeyEvent event) {
}

The event of keyboard KeyEvent.KEYCODE_DEL never gets detected to make views visible/invisible after the back press. Official documentation says will not always work the soft-keyboard events may not always get delivered.

As soft input methods can use multiple and inventive ways of inputting text, there is no guarantee that any key press on a soft keyboard will generate a key event: this is left to the IME's discretion, and in fact sending such events is discouraged.

More details here.

Note: Screenshots above are taken from BHIM application which is for Indian money transactions.

like image 961
Prashant Avatar asked Mar 15 '18 09:03

Prashant


2 Answers

See this PinView Library, it does almost the same as you want.

It's easy to use :

Add the dependencies

dependencies {
   compile 'com.chaos.view:pinview:1.3.0'
}

Instead of EditText create a PinView

<com.chaos.view.PinView
    android:id="@+id/pinView"
    style="@style/PinWidget.PinView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="Hint."
    android:inputType="text"
    android:padding="@dimen/common_padding"
    android:textColor="@color/text_colors"
    android:textSize="18sp"
    android:cursorVisible="true"
    app:cursorColor="@color/line_selected"
    app:cursorWidth="2dp"
    app:itemCount="5"
    app:itemHeight="48dp"
    app:itemRadius="4dp"
    app:itemSpacing="0dp"
    app:itemWidth="36dp"
    app:lineColor="@color/line_colors"
    app:lineWidth="2dp"
    app:viewType="rectangle" />

You should see something like this enter image description here

Other workaround is to create your own EditText class and change it when user types

like image 165
Skizo-ozᴉʞS Avatar answered Nov 13 '22 03:11

Skizo-ozᴉʞS


Try this

        <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">


    <EditText
        android:id="@+id/edt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:layout_weight="1"
        android:background="@drawable/normal"
        android:hint=""
        android:maxLength="1" />

    <EditText
        android:id="@+id/edt2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint=""
        android:layout_margin="5dp"
        android:background="@drawable/normal"
        android:layout_weight="1"
        android:maxLength="1" />

    <EditText
        android:id="@+id/edt3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint=""
        android:layout_margin="5dp"
        android:background="@drawable/normal"
        android:layout_weight="1"
        android:maxLength="1" />

    <EditText
        android:id="@+id/edt4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint=""
        android:layout_margin="5dp"
        android:background="@drawable/normal"
        android:layout_weight="1"
        android:maxLength="1" />

</LinearLayout>

@drawable/norma

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:height="1dp"
        android:gravity="bottom">
        <shape android:shape="rectangle">
            <solid android:color="#0011ff" />
        </shape>
    </item>

</layer-list>

drawable.filled

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:height="1dp">
        <shape android:shape="rectangle">
            <solid android:color="#00001eff" />
        </shape>
    </item>
</layer-list>

ACTIVITY CODE

    import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.widget.EditText;


public class MainActivity extends AppCompatActivity {

    EditText edt1, edt2, edt3, edt4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        edt1 = findViewById(R.id.edt1);
        edt2 = findViewById(R.id.edt2);
        edt3 = findViewById(R.id.edt3);
        edt4 = findViewById(R.id.edt4);

        edt1.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (TextUtils.isEmpty(edt1.getText().toString().trim())) {
                    edt1.setBackgroundResource(R.drawable.normal);
                    edt1.requestFocus();
                    edt1.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt1.setInputType(InputType.TYPE_CLASS_TEXT );
                        }
                    },500);
                } else {
                    edt1.setBackgroundResource(R.drawable.filled);
                    edt1.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.red));

                    edt2.requestFocus();
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt1.setInputType(InputType.TYPE_CLASS_TEXT |
                                    InputType.TYPE_TEXT_VARIATION_PASSWORD);
                        }
                    },500);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });


        edt2.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (TextUtils.isEmpty(edt2.getText().toString().trim())) {
                    edt2.setBackgroundResource(R.drawable.normal);
                    edt2.requestFocus();
                    edt2.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt2.setInputType(InputType.TYPE_CLASS_TEXT );
                        }
                    },500);
                } else {
                    edt2.setBackgroundResource(R.drawable.filled);
                    edt3.requestFocus();
                    edt2.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.red));
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt2.setInputType(InputType.TYPE_CLASS_TEXT |
                                    InputType.TYPE_TEXT_VARIATION_PASSWORD);
                        }
                    },500);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
        edt3.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (TextUtils.isEmpty(edt3.getText().toString().trim())) {
                    edt3.setBackgroundResource(R.drawable.normal);
                    edt3.requestFocus();
                    edt3.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt3.setInputType(InputType.TYPE_CLASS_TEXT );
                        }
                    },500);
                } else {
                    edt3.setBackgroundResource(R.drawable.filled);
                    edt3.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.red));
                    edt4.requestFocus();
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt3.setInputType(InputType.TYPE_CLASS_TEXT |
                                    InputType.TYPE_TEXT_VARIATION_PASSWORD);
                        }
                    },500);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });


        edt4.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (TextUtils.isEmpty(edt4.getText().toString().trim())) {
                    edt4.setBackgroundResource(R.drawable.normal);
                    edt4.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.black));
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt4.setInputType(InputType.TYPE_CLASS_TEXT );
                        }
                    },500);
                } else {
                    edt4.setBackgroundResource(R.drawable.filled);
                    edt4.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.red));
                    edt4.clearFocus();
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            edt4.setInputType(InputType.TYPE_CLASS_TEXT |
                                    InputType.TYPE_TEXT_VARIATION_PASSWORD);
                        }
                    },500);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

    }

}

OUTPUT

NORMAL enter image description here

WHEN EDIT enter image description here

FINAL enter image description here

like image 20
AskNilesh Avatar answered Nov 13 '22 04:11

AskNilesh