3

I'm using a List Adapter (extends SimpleCursorAdapter) to populate some data.

I'm calling View.SetOnFocusChangeListener in bindView where i attach the listener to the desired EditText. The problem is that the event is fired 4 times where in the end the EditText loses it's focus, until i click again where the event is fired 3 times and the EditText retains focus.

I think it should only be called once. Is the OnTouch event responsible for this?

Here is my code:

@Override
public void bindView(View view, Context context, Cursor cursor) {       
    view.setId(cursor.getPosition());//Setting the row id to the corresponding cursor row id for easier data manipulation
    super.bindView(view, context, cursor);
    EditText etItemQuantity = (EditText)view.findViewById(R.id.etItemQuantity);
    if(!isNumeric(etItemQuantity.getText().toString())) {
        etItemQuantity.setFocusable(false);
        etItemQuantity.setFocusableInTouchMode(false);
        etItemQuantity.setClickable(false);
    } else {
        etItemQuantity.setFocusable(true);
        etItemQuantity.setFocusableInTouchMode(true);
        etItemQuantity.setClickable(true);
        etItemQuantity.setOnFocusChangeListener(ofcl);
        etItemQuantity.setOnEditorActionListener(oeal);
    }

}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    View view = inflater.inflate(layout, null);
    return view;
}

View.OnFocusChangeListener ofcl = new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!(v instanceof EditText)) {                     
            return;
        }
        EditText tableEt = (EditText)v;

        if(hasFocus) {
            tableEt.setTag(tableEt.getText().toString());
            tableEt.setText("");
        } else {
            if(tableEt.getText().toString().equals("")) {           
                tableEt.setText(tableEt.getTag().toString());
                tableEt.setTag(null);
            }
        }


    }
};
Mitsosp
  • 399
  • 3
  • 17

2 Answers2

1

In my case I had onFocusChange fired twice in API 24.

editText.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
    // ... hasFocus
}

container.setOnTouchListener { v, _ ->
    editText.clearFocus()
    hideKeyboard(editText)
    v.performClick()
    return@setOnTouchListener false
}

I wanted to remove focus from EditText when a user clicks outside of the EditText. But in API 24 editText.clearFocus() fired onFocusChange twice. To set similar behaviour in API 24 and API 30 I added these lines to XML:

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/container"
    ....
    android:focusableInTouchMode="true"
    android:focusable="true">

    <EditText ... />

Instead of XML you can change the code so, but in API 30 there may be new problems:

editText.clearFocus()
hideKeyboard(editText)
v.performClick()
v.requestFocus() // 1.
v.requestFocusFromTouch() // 2.
return@setOnTouchListener false
CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • I added the `android:focusableInTouchMode="true" android:focusable="true"` to my XML and it worked. But why? Why does allowing the root/parent layout to be focusable resolve this problem? – Daniel Aug 11 '23 at 09:11
  • @Daniel, good question. I don't know. Probably two links in my answer can help, but I didn't find an answer there. – CoolMind Aug 11 '23 at 11:01
0

Adding the following line int my activity in the manifest fixed the problem:

        android:windowSoftInputMode="adjustPan"

Not sure why though.

Mitsosp
  • 399
  • 3
  • 17
  • 1
    I guess it is because this flag probably prevents the layout from being fired again, which would result in the editor losing focus and regaining focus. – Amir Uval Nov 17 '14 at 16:11