6

Android 弧形 RecyclerView 实现(Kotlin)

 1 year ago
source link: https://www.chenwenguan.com/android-arc-recyclerview/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Android 弧形 RecyclerView 实现(Kotlin)

2023年6月12日 | 最近更新于 下午5:11

项目改版需要实现一个圆弧效果的滑动列表,网上没找到很好的开源实现,自己改了一版,给出具体实现步骤和源码,以下是项目实现效果截图。

Android圆弧列表实现

一、实现步骤

要求:当前选中的项要居中显示,总共要显示5个可见列表项,前后要各填充两个空数据,列表要以圆弧效果滚动,滑动停止之后要进行居中校正显示处理。

思路:监听列表滑动事件,在滑动的时候动态计算设置每个列表项距离顶部的距离,在滑动停止之后获取当前第一个可见列表项,平滑滚动到居中位置。

这个只是一个简单的基础数学题,滑动的时候计算设置GF两点的距离值即可,整个RecyclerView列表当做圆的一部分弧形区域。

三角形勾股定理

1. 列表滚动监听

在onScrolled方法中监听滚动,动态计算每个列表项需要距离顶部的值,来实现滑动的时候圆弧滚动效果。在onScrollStateChanged方法中,监听SCROLL_STATE_IDLE状态,进行居中校正。

mRVList?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    var isManualScroll = false
    override fun onScrollStateChanged(@NonNull recyclerView: RecyclerView, newState: Int) {
        super.onScrollStateChanged(recyclerView, newState)
        when (newState) {
            RecyclerView.SCROLL_STATE_IDLE -> {
                if (isManualScroll) {
                    var manager = recyclerView.layoutManager as LinearLayoutManager
                    var firstVisibleItemPosition = manager.findFirstVisibleItemPosition()
                    syncShow(firstVisibleItemPosition)
                }
                isManualScroll = false
            }
            RecyclerView.SCROLL_STATE_DRAGGING -> {
                isManualScroll = true
            }
        }
    }
    override fun onScrolled(@NonNull recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)
        for (i in 0 until recyclerView.childCount) {
            val paddingTop: Int = calculateMargin(recyclerView.getChildAt(i).left)
            recyclerView.getChildAt(i).setPadding(0, paddingTop, 0, 0)
        }
    }
})
private fun calculateMargin(marginLeft: Int): Int {
    val display = resources.displayMetrics
    val widthPixel = display.widthPixels.toDouble()
    val halfItemWidth = mArcAdapter?.dp2px(20f) ?:0
    // 偏离中点距离(AH)
    val offset = Math.abs((widthPixel / 2).minus(marginLeft.plus(halfItemWidth)))
    // 直角三角形一条直角边(OG)
    val height = Math.sqrt(Math.pow(widthPixel * 2, 2.0) - Math.pow(offset, 2.0))
   // 距离顶部的值就是圆弧半径(OH)-直角边(OG)
    val marginTop = widthPixel * 2 - height
    return marginTop.toInt()
}

上面的代码中,列表项宽度设置为40dp,圆弧的半径是屏幕宽度的两倍,参数根据自己实际需求调整即可。

2. 居中校正平滑滚动处理

实现设置LinearSmoothScroller对象,calculateTimeForScrolling设置滚动的时间,单位毫秒,让滚动更平滑。

private fun syncShow(position: Int) {
    mRVList?.smoothSnapToPosition(position)
    mArcAdapter?.firstVisiblePosition = position
    mArcAdapter?.notifyDataSetChanged()
}

fun RecyclerView.smoothSnapToPosition(
    position: Int,
    snapMode: Int = LinearSmoothScroller.SNAP_TO_START
) {
    val smoothScroller = object : LinearSmoothScroller(this.context) {
        override fun getVerticalSnapPreference(): Int = snapMode
        override fun getHorizontalSnapPreference(): Int = snapMode
        override fun calculateTimeForScrolling(dx: Int): Int {
            return 250
        }
    }
    smoothScroller.targetPosition = position
    layoutManager?.startSmoothScroll(smoothScroller)
}

3. 点击列表项设置居中

增加点击列表项的时候的居中校正处理,保证选中项始终显示在中间位置。

object: AdapterView.OnItemClickListener {
    override fun onItemClick(p0: AdapterView<*>?, p1: View?, position: Int, p3: Long) {
        if (position > 1 && position < (mArcAdapter?.list?.size ?:0 - 2)) {
            syncShow(position - 2)
        }
    }
}

RecyclerView并没有setOnItemClickListener接口,需要在ViewHolder中实现

inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
    val mTvTitle: TextView = itemView.findViewById(R.id.mTvTitle)

    init {
        itemView.setOnClickListener(this)
    }

    override fun onClick(view: View?) {
        onItemClickListener?.onItemClick(null, view, getAdapterPosition(), (view?.id ?:0).toLong());
    }
}

二、项目源码

https://github.com/wenguan0927/ArcRecyclerView

扩展阅读:

美图手机音乐Widget动画实现

Android 心率动画自定义控件实现

Android 卡片旋转切换动效实现详解

Android 残影数字动画实现详解

转载请注明出处:陈文管的博客 – Android 弧形RecyclerView实现

博客公众号

微信公众号 扫一扫关注


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK