When the soft keyboard appears, it makes my EditText field lose focus

后端 未结 11 1756
名媛妹妹
名媛妹妹 2020-12-07 10:19

I\'ve got a few EditText fields in a ListView. When I tap on one of the EditText fields, the keyboard slides into view (as it should), but the EditText field I tapped loses

相关标签:
11条回答
  • 2020-12-07 10:37

    Add android:windowSoftInputMode="adjustResize" in the activity holding the listview or EditText. This will solve your problem.

    <activity android:name=".MainActivity"
            android:windowSoftInputMode="adjustResize">
    </activity>
    
    0 讨论(0)
  • 2020-12-07 10:38

    Here is how I did it. The onFocusChangeListener() is called several times when you touch a EditText to type text into it. The sequence is:

    1. If focus was on a different view, then that view loses focus
    2. The target gains focus
    3. Soft keyboard pops up.
    4. This causes the target to lose focus
    5. The code detects this situation and calls target.requestFocus()
    6. The leftmost, topmost view gains focus, due to Android nonsense
    7. The leftmost view loses focus, due to requestFocus being called
    8. Target finally gains focus

      //////////////////////////////////////////////////////////////////
      private final int minDelta = 300;           // threshold in ms
      private long focusTime = 0;                 // time of last touch
      private View focusTarget = null;
      
      View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
          @Override
          public void onFocusChange(View view, boolean hasFocus) {
              long t = System.currentTimeMillis();
              long delta = t - focusTime;
              if (hasFocus) {     // gained focus
                  if (delta > minDelta) {
                      focusTime = t;
                      focusTarget = view;
                  }
              }
              else {              // lost focus
                  if (delta <= minDelta  &&  view == focusTarget) {
                      focusTarget.post(new Runnable() {   // reset focus to target
                          public void run() {
                              focusTarget.requestFocus();
                          }
                      });
                  }
              }
          }
      };
      

    The code above works well for the keyboard pop-ups. However, it does not detect the speech-to-text pop-up.

    0 讨论(0)
  • 2020-12-07 10:42

    In AndroidManifest.xml use adjustNothing in the activity that contain the views

    <activity
                android:name=".ActivityName"
                android:windowSoftInputMode="adjustNothing">
    
    0 讨论(0)
  • 2020-12-07 10:43

    Convert to RecyclerView

    I believe that loss of focus on show or hide of the keyboard is not expected behavior and either should have been (or should be) a reported Android issue.

    But too late now, 10 years after OP encountered it!

    In my case, the disadvantage of switching from SOFT_INPUT_ADJUST_RESIZE to SOFT_INPUT_ADJUST_PAN outweighed the advantage of not losing focus.

    Why? ADJUST_RESIZE is the officially preferred approach because ADJUST_PAN blocks part of your view and may prevent scrolling.

    But thanks to an earlier answer to this question I became intensely suspicious of ListView.

    To prove my suspicions I spent a day converting a complex ListView-based editor to RecyclerView.

    I can confirm that soft keyboard state changes no longer affect EditText focus even though I am using ADJUST_RESIZE.

    Seemingly painful I know - but perhaps the final result is nicer than sub-classing or tricky workarounds?

    0 讨论(0)
  • 2020-12-07 10:45

    In my case, this is happening because when the ListView resizes, it re-creates all of the list items (i.e. it calls getView() again for each visible list item).

    Because the EditText is within the layout that I'm returning from getView(), this means that it's a different instance of EditText than the one which had the focus previously. A secondary consequence is that when the soft-keyboard appears or disappears I found that I was losing the contents of the EditText.

    Because I wanted my view to remain fully accessible (i.e. I want it to be resized instead of hidden behind the keyboard window with some parts not accessible), I couldn't use Frank's answer, which otherwise seems like the best approach.

    I solved this by using an OnFocusChangeListener on the EditText to record the timestamp when the focus was lost, and then in getView() when recreating the list item, if the current time is within some threshold from when the focus was lost, call requestFocus() to give it back to the EditText in question.

    You can also grab the text from the previous instance of the EditText at that point and transfer it to the new instance.

    private class MyAdapter<Type> extends ArrayAdapter<String>
        implements OnFocusChangeListener
    {
        private EditText mText;
        private long mTextLostFocusTimestamp;
        private LayoutInflater mLayoutInflater;
    
        public MyAdapter(Context context, int resource, int textResourceId, ArrayList<String> data, LayoutInflater li) {
            super(context, resource, textResourceId, data);
            mLayoutInflater = li;
            mTextLostFocusTimestamp = -1;
        }
    
        private void reclaimFocus(View v, long timestamp) {
            if (timestamp == -1)
                return;
            if ((System.currentTimeMillis() - timestamp) < 250)
                v.requestFocus();
        }
    
        @Override public View getView (int position, View convertView, ViewGroup parent)
        {
            View v = mLayoutInflater.inflate(R.layout.mylayout, parent, false);
    
            EditText newText = (EditText) v.findViewById(R.id.email);
            if (mText != null)
                newText.setText(mText.getText());
            mText = newText;
            mText.setOnFocusChangeListener(this);
            reclaimFocus(mText, mTextLostFocusTimestamp);
    
            return v;
        }
    
        @Override public void onFocusChange(View v, boolean hasFocus) {
            if ((v == mText) && !hasFocus)
                mTextLostFocusTimestamp = System.currentTimeMillis();
        }
    }
    
    0 讨论(0)
  • 2020-12-07 10:47

    This guy had the same problem and more besides. He solved it by using a ScrollView and a LinearLayout instead of a ListView.

    0 讨论(0)
提交回复
热议问题