30

I am simply trying to have an onlick listen on an Edit text inside a TextInputLayout. It works but I need to click on the EditText twice for it to trigger I dont understand why. Here is my code:

xml:

  <android.support.design.widget.TextInputLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

        <EditText
            android:id="@+id/start_date"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="Starting Date*: "
            android:inputType="textPersonName" />
    </android.support.design.widget.TextInputLayout>

Listenner:

   private void setListenners() {
        EditText startDate = (EditText) mView.findViewById(R.id.start_date);
        startDate.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.N)
            @Override
            public void onClick(View v) {
                Calendar mcurrentDate=Calendar.getInstance();
                int mYear = mcurrentDate.get(Calendar.YEAR);
                int mMonth = mcurrentDate.get(Calendar.MONTH);
                int mDay = mcurrentDate.get(Calendar.DAY_OF_MONTH);

                DatePickerDialog mDatePicker=new DatePickerDialog(getActivity(), new DatePickerDialog.OnDateSetListener() {
                    @Override
                    public void onDateSet(DatePicker datePicker, int year, int month, int day) {
                        Log.d("DEBUG", "year: " + year + " month: " + month + " day: " + day);
                    }
                },mYear, mMonth, mDay);
                mDatePicker.show();
            }
        });
    }
0xtuytuy
  • 1,494
  • 6
  • 26
  • 51
  • Consider using a `Fragment` over `Dialog`, since it's very easy to leak a `Dialog`. For example, if the user, having a dialog shown, taps the menu button (hides the app), then Activity gets destroyed by the system, and after that the user starts the app again, this causes _Activity has leaked window_ error. – ivan8m8 Apr 09 '20 at 08:33

2 Answers2

69

Set the attribute android:focusableInTouchMode to false

android:focusableInTouchMode="false"

in your edittext xml code.


Explanation, as from docs, android:focusableInTouchMode is:

Boolean that controls whether a view can take focus while in touch mode. If this is true for a view, that view can gain focus when clicked on, and can keep focus if another view is clicked on that doesn't have this attribute set to true.

and the EditText is true by default.

In other words: the first click will make the edittext to gain focus and second click is the one that triggers the ClickListener. So you should disable gaining focus on touch.

Atef Hares
  • 4,715
  • 3
  • 29
  • 61
  • 1
    @Rémi you're welcome, please consider accepting it as answer for other people who may come through you question. – Atef Hares Feb 26 '17 at 15:04
  • If you long click on the input, you will be able to paste your last copied text, so this is not a full solution. – Nabil Souk Sep 13 '17 at 21:03
  • @NabilSouk your situation is not part of OP's question. if you have a separate question feel free to search on `SO` or post new question if you did not find what you aim for. – Atef Hares Sep 13 '17 at 21:06
  • 1
    @NabilSouk To get the default behaviour you need to add this within the onClickListener: startDate.setFocusableInTouchMode(true); startDate.requestFocus(); – John T Jun 15 '18 at 06:58
6

I found an alternative solution which suited my needs better than the other answer. Basically you set the onClickListener as normal, but you add an OnFocusChangedListener to pick up the first tap (when gaining focus). This only activates in touch mode so doesn't affect keyboard navigation.

You don't need to set any XML attributes related to focus, just use the following code (it's kotlin btw):

    editText.setOnFocusChangeListener { view, isFocused ->
        if (view.isInTouchMode && isFocused) {
            view.performClick()  // picks up first tap
        }
    }
    editText.setOnClickListener {
        showDatePicker() // the actual thing you want to do
    }

This method has the advantage that the view will remain focused (and if you are using a TextInputLayout.OutlinedBox style, it will remain highlighted) even after the DatePicker is dismissed. This does not happen when you set focusableInTouchMode = false.

Once the view is focused, future taps will trigger only the OnClickListener, so it won't be called again by the FocusChangeListener calling performClick(). (I checked this with the debugger on API 29)

machfour
  • 1,929
  • 2
  • 14
  • 21