博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ListView与EditText冲突问题解决
阅读量:6914 次
发布时间:2019-06-27

本文共 3853 字,大约阅读时间需要 12 分钟。

最近项目中碰到一个问题,我们有一个界面是一个全屏的ListViewListView中有一个HeaderViewHeaderView内部包含一个EditText。 

出现的一个问题是,在某些手机上,手动隐藏软键盘之后,此时再点击EditText就无法弹出软键盘了。 就像下面这样

EditText点击弹出软键盘的逻辑在TextViewonTouchEvent里面

@Overridepublic boolean onTouchEvent(MotionEvent event) {     //...     if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()            && mText instanceof Spannable && mLayout != null) {        boolean handled = false;        //...        if (touchIsFinished && (isTextEditable() || textIsSelectable)) {            // Show the IME, except when selecting in read-only text.            final InputMethodManager imm = InputMethodManager.peekInstance();            viewClicked(imm);            if (!textIsSelectable && mEditor.mShowSoftInputOnFocus) {                handled |= imm != null && imm.showSoftInput(this, 0);            }            // The above condition ensures that the mEditor is not null            mEditor.onTouchUpEvent(event);            handled = true;        }        if (handled) {            return true;        }    }    return superResult;}复制代码

onTouchEvent方法里面最终会调用InputMethodManager.showSoftInput来展示软键盘

showSoftInput方法最终会调用到以下方法

public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {    checkFocus();    synchronized (mH) {        if (mServedView != view && (mServedView == null                || !mServedView.checkInputConnectionProxy(view))) {            return false;        }        try {            return mService.showSoftInput(mClient, flags, resultReceiver);        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }}复制代码

调试后发现,在执行该函数的第一个if语句时返回了,原因是mServedView!=view

我们知道view既是EditText,那么mServedView是什么?

答案是ListView。

那么mServedView是在什么时候被设置的呢?

我们再来看看showSoftInput方法中的第一句代码checkFocus

public void checkFocus() {    if (checkFocusNoStartInput(false)) {        startInputInner(InputMethodClient.START_INPUT_REASON_CHECK_FOCUS, null, 0, 0, 0);    }}private boolean checkFocusNoStartInput(boolean forceNewFocus) {    // This is called a lot, so short-circuit before locking.    if (mServedView == mNextServedView && !forceNewFocus) {        return false;    }    final ControlledInputConnectionWrapper ic;    synchronized (mH) {        if (mServedView == mNextServedView && !forceNewFocus) {            return false;        }        //...        ic = mServedInputConnectionWrapper;        mServedView = mNextServedView;        //...    }    if (ic != null) {        ic.finishComposingText();    }    return true;}复制代码

 checkFocus会调用到checkFocusNoStartInput,这里就是mServedView被赋值的地方,而它的值就是mNextServedView。

那么问题来了,mNextServedView又是什么鬼呢?mNextServedView被赋值的地方只有一个就是focusInLocked方法

void focusInLocked(View view) {    //...    mNextServedView = view;    //...}复制代码

那focusInLocked又是在什么时候被调用呢?

经调试发现,在每次Layout过程中都会被调用,而入参就是ListView。

到了这里,问题渐渐明朗,那么如何解决问题呢?

核心方案就是将mServedView设置成我们的EditText,由于在checkFocus中会将mNextServedView的值赋予mServedView,因此只需要设置mNextServedView的值为EditText就好了。

所以,我的解决方案就是。。。。反射

etCard.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(final View v) {        LogicUtil.showSoftInput(v, true);    }});复制代码

首先,我们确保每次点击EditText的时候都手动去展示软键盘,从而创建一个反射的切入点,然后就是。。。

try {        Class cls = Class.forName("android.view.inputmethod.InputMethodManager");        Field f = cls.getDeclaredField("mNextServedView");        f.setAccessible(true);        f.set(manager, view);    } catch (NoSuchFieldException e) {        e.printStackTrace();    } catch (IllegalAccessException e) {        e.printStackTrace();    } catch (ClassNotFoundException e) {        e.printStackTrace();    }}if(manager != null && manager.isActive() && view != null){    manager.showSoftInput(view, 0);}复制代码

在调用InputMethodManager.showSoftInput方法之前通过反射设置它的mNextServedView为EditText。

再来看看效果怎么样

完美。。。。

后记:

我认为该问题的核心其实是焦点问题,但是精力有限,没有就问题继续深入下去。而且解决方案也是简单粗暴的。如果大家有更好的解决方案,欢迎分享!

转载地址:http://jsacl.baihongyu.com/

你可能感兴趣的文章
未清销售订单及预测的所有工序物料需求(按BOM展开.考虑已发料)
查看>>
存储过程优点和缺点
查看>>
2.0、Android Studio编写你的应用
查看>>
面向对象……未完待续
查看>>
ChemDraw加键的两种方法
查看>>
CentOS 5.5升级网卡驱动
查看>>
动手动脑五
查看>>
PHP使用GOEASY实现WEB实时推送
查看>>
MapInfo格式转arggis格式
查看>>
Python学习路线(针对具备一定编程经验者)
查看>>
CentOS 6.2安装VNC Server
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
binlog-rollback.pl 在线恢复update 和delete不加条件误操作sql
查看>>
2015.12.31
查看>>
tcpdump couldn't find user 'tcpdump' 报错备忘
查看>>
nginx日志分割脚本
查看>>
程序员该如何学习和积累
查看>>
linux中RAID详解
查看>>
Win7 CMD大全
查看>>