android listview 第一次打开 无 focus 问题

     在开发android智能TV项目时,遇到一个应用的问题,使用ListView的所有UI在第一次打开时均没有焦点,各种方法试尽,前前后后经历N位工程师均没有解决掉,就这样过了半年,一堆相关问题依然挂在那里...


    后来想到是不是touch mode的问题呢?
    ListView.setSelection->setSelectionFromTop(position, 0);
       public void setSelectionFromTop(int position, int y) {
        if (mAdapter == null) {
            return;
        }


        if (!isInTouchMode()) {
            position = lookForSelectablePosition(position, true);
            if (position >= 0) {
                setNextSelectedPositionInt(position);
            }
        } else {
            mResurrectToPosition = position;
        }


        if (position >= 0) {
            mLayoutMode = LAYOUT_SPECIFIC;
            mSpecificTop = mListPadding.top + y;


            if (mNeedSync) {
                mSyncPosition = position;
                mSyncRowId = mAdapter.getItemId(position);
            }


            if (mPositionScroller != null) {
                mPositionScroller.stop();
            }
            requestLayout();
        }
    }


  可以看到isInTouchMode的判断,继续跟进到View.java
      @ViewDebug.ExportedProperty
    public boolean isInTouchMode() {
        if (mAttachInfo != null) {
            return mAttachInfo.mInTouchMode;
        } else {
            return ViewRootImpl.isInTouchMode();
        }
    }


    继续查看ViewRootImpl.java
        static boolean isInTouchMode() {
        IWindowSession windowSession = WindowManagerGlobal.peekWindowSession();
        if (windowSession != null) {
            try {
                return windowSession.getInTouchMode();
            } catch (RemoteException e) {
            }
        }
        return false;
    }


   找到session.java
       public boolean getInTouchMode() {
        synchronized(mService.mWindowMap) {
            return mService.mInTouchMode;
        }
    }


   最后知道是WindowManagerService.java中通过  setInTouchMode来设置  mInTouchMode,而起动作是在ViewRootImpl.java中通过ensureTouchMode来实作
   public void setInTouchMode(boolean mode) {
        synchronized(mWindowMap) {
            mInTouchMode = mode;
        }
    }
    
        boolean ensureTouchMode(boolean inTouchMode) {
        if (DBG) Log.d("touchmode", "ensureTouchMode(" + inTouchMode + "), current "
                + "touch mode is " + mAttachInfo.mInTouchMode);
        if (mAttachInfo.mInTouchMode == inTouchMode) return false;


        // tell the window manager
        try {
            mWindowSession.setInTouchMode(inTouchMode);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }


        // handle the change
        return ensureTouchModeLocally(inTouchMode);
    }


    
   IR有动作时,KeyCode会分发到View上处理,进而调用 ensureTouchMode 设置系统离开TouchMode,坑爹的手机触摸模式...
   
   
   总结分析:开机后第一无法获取焦点,任意按键后可以获取;开机后android默认是在Touch模式,任意按键后,系统离开TouchMode,所以就恢复正常;
   
   
   解决方法:考虑到TV的特殊性,所以在打开ListView的时候调用 Instramention.setInTouchMode(false);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值