美文网首页
如何在初始化activity的时候使listView获取焦点

如何在初始化activity的时候使listView获取焦点

作者: 里蛰肤 | 来源:发表于2019-05-28 12:21 被阅读0次

    在上一次用RecycleView的时候,鄙渣也遇到了焦点问题。可以看看这里:Fragment中的RecycleView的转场动画与保存焦点

    这两个问题详细描述实际上是一样的,鄙渣需要在Acitivity创建完成后立即指定ListView(RecycleView)中的某一个子item获取焦点。在链接中的那篇文章中提到了 viewTreeObserver 这一工具,但是鄙渣最终并没有采用,而是使用了RecycleView.Adapter中的两个方法—— onAttachedToRecyclerViewonDetachedFromRecyclerView 两个回调。这两个回调即可判断出RecycleView被初始化和被销毁的时间节点,并进行相关操作。

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        thisRecyclerView = recyclerView
    }
    
    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        super.onDetachedFromRecyclerView(recyclerView)
        thisRecyclerView = null
    }
        
    override fun onBindViewHolder(holder: FaqViewHolder, position: Int) {
        ...
        if (position == latestPosition) {
            thisRecyclerView?.smoothScrollToPosition(latestPosition)
            faqItemContainer.requestFocus()
        }
    
        ...
        faqItemContainer.setOnFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                latestPosition = position
            }
        }
    }
    
    companion object {
        var latestPosition = 0
    }
    

    在这次的问题中,遇到了一个棘手的问题,ListView中没有 onAttachedToRecyclerViewonDetachedFromRecyclerView 这两个方法。那么难道又得用 viewTreeObserver 吗?

    当然不!上次使用糟糕体验让鄙渣有了十分难受的回忆。所以这次鄙渣选择另寻新方法。在本文一开始已经点明了主要问题——如何判断Activity已经初始化完成 。在这里鄙渣也找到了两个方法,都是用于判断是否初始化完成的。

    一个方法来源于Android 判断 activity 初始化是否完成 中提到的,使用WindowToken来判断是否初始化完成。不过他的写法稍微有些暴力,大概如下:

    class XXXActivity : Activity(){
        ...
        private var focusHandler: Handler? = null
        ...
        
        class RequestListViewFocusHandler(private val weakReference: WeakReference<XXXActivity>) : Handler() {
            override fun handleMessage(msg: Message?) {
                super.handleMessage(msg)
                val activity = weakReference.get()
                activity?.let {
                    if (it.window.decorView.windowToken != null) {
                        Logger.d("token不为空,请求焦点")
                        it.listViewChangeAndFocus()
                        //这里的listView直接是id,kotlin中封装好了这种操作,不需要findviewbyid了
                        it.listView.setSelection(0)
                    } else {
                        sendEmptyMessageDelayed(REFRESH_FOCUS, 100)
                        Logger.d("token为空")
                    }
                }
            }
        }
        
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            focusHandler = RequestListViewFocusHandler(WeakReference(this))
            (focusHandler as RequestListViewFocusHandler).sendEmptyMessageDelayed(REFRESH_FOCUS,100)
            ...
        }
    }
    

    这种写法确实能够做到刷新焦点,几乎也能做到实时刷新,但是这种不断发消息轮询的策略总归不大优雅。所以在启硕哥的帮助下,我又发现了第二种方式: onWindowFocusChanged

    关于android activity加载完毕事件这篇文章里其实有说这一类问题的原因了,并且给出的解决方法就是 onWindowFocusChanged 。实现代码如下:

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        if (hasFocus){
            listViewChangeAndFocus()
            listView.setSelection(0)
        }
    }
    

    这样一来就简洁优雅了许多,并且不需要再花里胡哨地找其他的方法了。

    相关文章

      网友评论

          本文标题:如何在初始化activity的时候使listView获取焦点

          本文链接:https://www.haomeiwen.com/subject/itgrtctx.html