TV 纵向焦点居中ScrollView

该文章介绍了一个自定义的Android视图组件TVFocusCenterScrollView,它继承自NestedScrollView,旨在解决在纵向布局中,当选项超过一屏时,保持焦点始终在屏幕中央的问题。通过重写dispatchKeyEvent方法,处理上下按键事件,计算并调整滚动位置,确保被选中的视图焦点位于屏幕中心。
摘要由CSDN通过智能技术生成

适用场景:

纵向,超过1屏,简单但样式不同的单选或多选按钮

例如一个TV设置页面里有几个已知的可选择项纵向排列,需要获取焦点的view一直在屏幕中间,VerticalGridView当然也可以。

用NestedScrollView简单的放几个view进去,然后加点击事件,处理一下焦点居中岂不是更方便。这样就直接往里塞view就可以了。

import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.View
import androidx.core.widget.NestedScrollView
//import com.blankj.utilcode.util.LogUtils

/**
 * 焦点一直居中的纵向scrollview
 */
class TVFocusCenterScrollView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
    NestedScrollView(context, attrs, defStyleAttr) {
    constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, -1)
    constructor(context: Context) : this(context, null)

    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
        if (event?.action == KeyEvent.ACTION_DOWN) {
            when (event.keyCode) {

                KeyEvent.KEYCODE_DPAD_DOWN -> {
                    //获取当前焦点的横纵坐标
                    val currentFocus: View = findFocus()
                    val next = currentFocus.focusSearch(FOCUS_DOWN)
                    next?.let { it ->
                        val location = IntArray(2)
                        it.getLocationInWindow(location)
                        //如果已经超过半屏
                       // LogUtils.e("----d2----" + location[1] + "  " + this.height / 2)
                        if ((location[1] + it.height / 2) > this.height / 2) {
                            val needscroll = location[1] + it.height / 2 - this.height / 2
                          //  LogUtils.e("--------d3------" + needscroll)
                            scrollBy(0, needscroll)
                        }
                        val nextnext = it.focusSearch(FOCUS_DOWN)
                        if (nextnext == null) {
                            scrollTo(0, this.height)
                        }
                    }
                }

                KeyEvent.KEYCODE_DPAD_UP -> {
                    //获取当前焦点的横纵坐标
                    val currentFocus: View = findFocus()
                    val next = currentFocus.focusSearch(FOCUS_UP)

                    next?.let { it ->
                        val location = IntArray(2)
                        it.getLocationInWindow(location)
                        //如果已经超过半屏
                    //    LogUtils.e("----u1----" + location[1] )

                      //  LogUtils.e("----u2----"  + ( location[1] + it.height / 2) + "  " + this.height / 2)
                        if ( location[1] + it.height / 2 < this.height / 2) {
                            val needscroll =  location[1] - this.height / 2
                        //    LogUtils.e("--------u3------" + needscroll)
                            scrollBy(0, needscroll)
                        }
                        val nextnext = it.focusSearch(FOCUS_UP)
                        if (nextnext == null) {
                            scrollTo(0, 0)
                        }
                    }

                }
            }
        }
        return super.dispatchKeyEvent(event)
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值