Problem: User should be able to login either by their Phone number or username (something they have set during registration). Both of these values would allow user to sign in. The Edittext field needs to be smart enough to determine what is being entered.So when the user enters a number as the first character, it should automatically add the country code phone number prefix and insert the typed character after the prefix.
This is my layout:
<LinearLayout
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputLayout
android:id="@+id/emaillayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:background="@drawable/login_field"
android:padding="2dp"
android:paddingStart="5dp"
android:visibility="visible">
<AutoCompleteTextView
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:hint="@string/prompt_email"
android:inputType="textEmailAddress"
android:maxLines="1"
android:padding="2dp"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/phlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:background="@drawable/login_field"
android:orientation="horizontal"
android:padding="2dp"
android:paddingStart="5dp"
android:visibility="gone">
<EditText
android:id="@+id/et_ph"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:ems="10"
android:hint="Phone number"
android:inputType="phone" />
</android.support.design.widget.TextInputLayout>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputLayout
android:id="@+id/pwdlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@drawable/login_field"
android:orientation="horizontal"
android:padding="2dp"
android:paddingStart="5dp">
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:hint="@string/prompt_password"
android:imeActionId="6"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:padding="2dp"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<TextView
android:id="@+id/pwdtoggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:text="SHOW"
android:layout_marginRight="16dp"
android:paddingTop="10dp"
/>
</FrameLayout>
<Button
android:id="@+id/email_sign_in_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"
android:layout_marginTop="16dp"
android:background="@drawable/sausage_button"
android:text="@string/action_sign_in"
android:textStyle="bold" />
</LinearLayout>
And this my code in the activity:
emailView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s)
{
if(isNumberOnly(s.toString()))
{
ChangeToPhoneNumber(s.toString());
}
}
});
numberView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s)
{
if(s.length()==0)
{
ChangeToUsername();
}
}
});
}
private void ChangeToPhoneNumber(String s)
{
emaillayout.setVisibility(View.GONE);
phlayout.setVisibility(View.VISIBLE);
numberView.setText("+61" + s);
numberView.setSelection(mPhonenumberView.getText().length());
mPhonenumberView.requestFocus();
}
private void ChangeToUsername()
{
emaillayout.setVisibility(View.VISIBLE);
phlayout.setVisibility(View.GONE);
emailView.setText("");
emailView.requestFocus();
}
public boolean isNumberOnly(String s)
{
return s.matches("-?\\d+(.\\d+)?");
}
So by this implementation I am able to achieve what I wanted. Here are the screenshots:
Although I could achieve the results, I feel calling the text watcher all the time could be a bit of an overhead since I am using two separate views and added two instances of Textwatcher. In what ways can this be made more cleaner and efficient?. In addition I would like to understand how can I make sure the prefix is not erased but change the view to the username field when I press the backspace key on the keyboard?