Android N(7.0) 在ListView里显示EditText时软键盘弹出时会自动切换到全键盘的问题?

Android N(7.0) 在ListView里显示EditText时软键盘弹出时会自动切换到全键盘的问题?

问题症状描述

  1. Activity 在AndroidManifest.xml里设置android:windowSoftInputMode="adjustPan"
  2. 在ListView里绘制Item
  3. Item控件为EditText
  4. EditText设置InputType为Number
  5. 当在Android 7.0系统上,点击EditText时,弹出的软键盘为“数字”输入模式,但是瞬间就会切换到“全键盘”模式。

    在7.0之前的系统,都没有出现这种问题。

尝试性解决方案(风险未评估)

/**
 * 尝试性修复了在ListView里显示EditText InputType为 其它非text 类型时,弹出的软键盘会从数字键盘自动切换为 英文全键盘 的问题。
 */
class ListViewEx2 extends ListView
{
public ListViewEx2(final Context context)
{
    super(context);
}

public ListViewEx2(final Context context, final AttributeSet attrs)
{
    super(context, attrs);
}

public ListViewEx2(final Context context, final AttributeSet attrs, final int defStyleAttr)
{
    super(context, attrs, defStyleAttr);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ListViewEx2(final Context context, final AttributeSet attrs, final int defStyleAttr, final int defStyleRes)
{
    super(context, attrs, defStyleAttr, defStyleRes);
}

@Override
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b)
{
    //XXX:经过初步测试,只有在Android 7.0平台以上的系统才会出现软键盘自动切换的问题。
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && changed)
        super.onLayout(changed, l, t, r, b);
    else
        super.onLayout(changed, l, t, r, b);
}
}

ListView.java 源码对比

Android 版本名称: Nougat API Level: 24 ListView.java 在线查看

Android 7.0 部分可疑的改动过的源码

private class FocusSelector implements Runnable {
    // the selector is waiting to set selection on the list view
    private static final int STATE_SET_SELECTION = 1;
    // the selector set the selection on the list view, waiting for a layoutChildren pass
    private static final int STATE_WAIT_FOR_LAYOUT = 2;
    // the selector's selection has been honored and it is waiting to request focus on the
    // target child.
    private static final int STATE_REQUEST_FOCUS = 3;

    public void run() {
        if (mAction == STATE_SET_SELECTION) {
            setSelectionFromTop(mPosition, mPositionTop);
            mAction = STATE_WAIT_FOR_LAYOUT;
        } else if (mAction == STATE_REQUEST_FOCUS) {
            final int childIndex = mPosition - mFirstPosition;
            final View child = getChildAt(childIndex);
            if (child != null) {
                child.requestFocus();
            }
            mAction = -1;
        }
    }
    }
}

Android 版本名称: Marshmallow API Level: 23 ListView.java 在线查看

Android 6.0 部分可疑的改动过的对应旧版本源码

private class FocusSelector implements Runnable {       
    public void run() {
        setSelectionFromTop(mPosition, mPositionTop);
    }
    }

参考资料

posted @ 2017-10-25 17:52  Asion Tang  阅读(...)  评论(...编辑  收藏