Android: EditText focus jumps to another inside ScrollView

后端 未结 3 1585
时光取名叫无心
时光取名叫无心 2020-12-20 08:50

I have multiple fragments horizontally adjacent using a ViewPager. Each fragment has a ScrollView that contains a table with many EditText views. When I click on a EditTex

相关标签:
3条回答
  • 2020-12-20 09:27

    I found the problem, it was the lines in the main activity XML: activity_slide_view_pager.xml

        android:focusableInTouchMode="true"
        android:descendantFocusability="beforeDescendants"
    

    This was causing the RelativeLayout to grab focus.

    0 讨论(0)
  • 2020-12-20 09:39

    As an addition to @Cameron Ketcham answer, the best fix of the issue is Creating your own CustomViewpager class that extends from ViewPager and overriding the RequestChildFocus method with null so as to disable the automatic focus behavior.

    Your customeViewPager class will look something like this

    public class CustomeViewPager extends ViewPager {
    
       public CustomeViewPager(Context context) {
          super(context);
       }
    
       public CustomeViewPager(Context context, AttributeSet attrs) {
           super(context, attrs);
       }
    
       @Override
       public void requestChildFocus(View child, View focused) {
           //Do nothing, disables automatic focus behaviour
    
       }
    
    }
    

    You can now use this class in your xml and continue from there.

    0 讨论(0)
  • 2020-12-20 09:51

    Focus is changing to the leftmost fragment because that fragment is the current item of the ViewPager. You might try to use setCurrentItem(item) to set the current item to the other fragment (when the user clicks on it) so the left one doesn't steal focus.

    This is happening because at the end of the populate() function of the ViewPager it will always give focus to a view that is in the current item. You could also fix this issue by copying the ViewPager source and changing this code to allow any fragment which is on the screen to have a child with focus.

    Change this:

    if (hasFocus()) {
        View currentFocused = findFocus();
        ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null;
        if (ii == null || ii.position != mCurItem) {
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                ii = infoForChild(child);
                if (ii != null && ii.position == mCurItem) {
                    if (child.requestFocus(FOCUS_FORWARD)) {
                        break;
                    }
                }
            }
        }
    }
    

    To something like this:

    if (hasFocus()) {
        View currentFocused = findFocus();
        ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null;
        if (ii == null || !infoIsOnScreen(ii)) {
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                ii = infoForChild(child);
                if (ii != null && infoIsOnScreen(ii)) {
                    if (child.requestFocus(FOCUS_FORWARD)) {
                        break;
                    }
                }
            }
        }
    }
    
    public boolean infoIsOnScreen(ItemInfo info) {
        // Code to determine if the view is on the screen using ii.offset etc.
    }
    
    0 讨论(0)
提交回复
热议问题