1] 4 digit input boxes without input:
2] 4 digit input boxes with input :
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.
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
Other workaround is to create your own EditText
class and change it when user types
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
WHEN EDIT
FINAL
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With