Search code examples
androidandroid-edittextontouchlistenerandroid-textinputlayoutontouch

One touch on EditText inside TextInputLayout generate two or more events


I have one EditText inside a TextInputLayout:

    <android.support.design.widget.TextInputLayout
    android:id="@+id/inputLayoutDoB"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/stepViewIndicator"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    app:hintTextAppearance="@style/TextAppearance.App.TextInputLayout"
    app:errorTextAppearance="@style/Text.Appearance.App.ErrorText"
    android:textColorHint="@color/colorAccentLight">

    <android.support.v7.widget.AppCompatEditText
        android:id="@+id/inputDoB"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableStart="@drawable/ic_profile_calendar"
        android:drawablePadding="@dimen/form_drawable_margin"
        android:hint="@string/strHintDoB"
        android:textSize="@dimen/input_text"
        android:inputType="date"
        android:textColor="@android:color/white"/>

</android.support.design.widget.TextInputLayout>

My RelativeLayout is designed to prevent disable view autofocus:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/colorAccent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:focusableInTouchMode="true">

Now, I need to manage touch gesture on the above EditText, to popup a simple AlertDialog:

inputDoB = findViewById(R.id.inputDoB);
// *** PREVENT SOFT KEYBOARD APPEARANCE
inputDoB.setInputType(InputType.TYPE_NULL);
inputDoB.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            AlertDialog alertDialog = new 
            AlertDialog.Builder(ProfileActivity_Step1.this).create();
            alertDialog.setTitle("Alert");
            alertDialog.setMessage("Alert message to be shown");
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            alertDialog.show();
            return false;
        }
    });

All seem to work fine, but when I click/touch the EditText, TWO or MORE AlertDialog appear.

Is this behavior related to the EditText container (TextInputLayout)? If yes, how can I address this issue?

Any idea?

Many thanks for your support


Solution

  • The onTouch() method can be called multiple times for what you (as a human) think of as a "single" touch. At the very least, there will be an ACTION_DOWN event followed by either an ACTION_UP or an ACTION_CANCEL event. But if you move your finger at all while it's on the screen, you'll also get ACTION_MOVE events.

    So, change your method to this:

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            AlertDialog alertDialog = new 
            AlertDialog.Builder(ProfileActivity_Step1.this).create();
            alertDialog.setTitle("Alert");
            alertDialog.setMessage("Alert message to be shown");
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            alertDialog.show();
        }
        return false;
    }
    

    Additionally, if you want to truly intercept the touch event (and prevent the hint from sliding up as though the EditText has focus) you should change this to return true instead.