代码分享:实现自动滚动和无限滚动以及一些细致的交互

代码分享

分享点Android基础代码吧~

本想找个轮子,轮子没找到,只能自己搞了。
话不多说,直接上代码干货,分享给后面有需要的xdm,直接拿去用。
整体实现不算复杂,就费点时间,已抽离不相干的代码。

实现效果

  1. 无限循环顺滑滚动
  2. 触摸停止滚动,抬手n秒后继续滚动
  3. 实时记录当前可见的视图
  4. 支持由后台控制滚动频率
  5. 支持动态插拔
  6. 数据更新动画

涉及到的Android知识点包括

  1. 自定义View
  2. RecyclerView
  3. Glide
  4. 动画
  5. 定时器
  6. 事件分发机制
  7. handle机制
  8. 另外:编程语言是kotlin
  9. 注意:这里使用到的动画以及Handler需要做好及时取消与清除,避免内存泄漏问题。

核心代码:

  1. 实现无限:
private var itemCount = Int.MAX_VALUE
override fun getItemCount(): Int {
    return if (list.size > 4) itemCount else list.size
}
  1. 实现顺滑滚动:
this@AutoScrollRecyclerView.scrollBy(scrollDistance,0)
  1. 实现触摸启停滚动:
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    val action = ev?.action
    if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_OUTSIDE) {
        handleTimeHandler(true)
    } else if (action == MotionEvent.ACTION_DOWN) {
        handleTimeHandler(false)
    }
    return super.dispatchTouchEvent(ev)
}
fun handleTimeHandler(isOpen: Boolean){
    isOpenTimeHandler = isOpen
    mTimeHandler.removeMessages(0)
    if(isOpenTimeHandler){
        mTimeHandler.sendEmptyMessageDelayed(0,2000)
    }else {
        //(this@AutoScrollRecyclerView.adapter as SpecialScrollChildAdapter).isAutoScroll(false)
    }

}
  1. 统计当前展示的item:
it.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        (it.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition().let {
            //业务逻辑代码...
        }
    }
})
  1. 动画
ValueAnimator.ofFloat(0f, 1f).apply {
		duration = animationDuration
		addUpdateListener { animation ->
			val alpha = animation.animatedValue as Float
			view.alpha = alpha
		}
		start()
	}

自定义RecyclerView

class AutoScrollRecyclerView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0
) : RecyclerView(context, attrs, defStyle) {

	private var isOpenTimeHandler: Boolean = true

	val time: Long = 20// 缩短滚动间隔
	val scrollDistance: Int = 10 //单次滚动距离
	//这里也可选择直接使用TimerTask
	private val mTimeHandler : Handler by lazy {
		object : Handler(Looper.getMainLooper()){
			override fun handleMessage(msg: Message) {
				super.handleMessage(msg)
				this@AutoScrollRecyclerView.scrollBy(scrollDistance,0)
				if (isOpenTimeHandler) { // 如果允许滚动,则继续发送消息
					//(this@AutoScrollRecyclerView.adapter as SpecialScrollChildAdapter).isAutoScroll(true)
					mTimeHandler.sendEmptyMessageDelayed(0, time)
				}
			}
		}
	}

	//处理触摸停止滚动逻辑
	override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
		val action = ev?.action
		if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_OUTSIDE) {
			handleTimeHandler(true)
		} else if (action == MotionEvent.ACTION_DOWN) {
			handleTimeHandler(false)
		}
		return super.dispatchTouchEvent(ev)
	}

    override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
        return super.onInterceptTouchEvent(e)
    }

    override fun onTouchEvent(e: MotionEvent): Boolean {
        return super.onTouchEvent(e)
    }

	fun handleTimeHandler(isOpen: Boolean){
		isOpenTimeHandler = isOpen
		mTimeHandler.removeMessages(0)
		if(isOpenTimeHandler){
			mTimeHandler.sendEmptyMessageDelayed(0,2000)
		}else {
			//(this@AutoScrollRecyclerView.adapter as SpecialScrollChildAdapter).isAutoScroll(false)
		}

	}

}

Adapter

class SpecialScrollChildAdapter(private val context: Context, private var list: List<Any>) :
    RecyclerView.Adapter<SpecialScrollChildAdapter.ViewHolder>() {

    private var itemCount = Int.MAX_VALUE

    fun isAutoScroll(isAutoScroll: Boolean) {
        itemCount = if (isAutoScroll) Int.MAX_VALUE else list.size
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.item_new_home_session_scroll_child, parent, false)

        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
		holder.initData(this.list[position % this.list.size])
    }

    override fun getItemCount(): Int {
        return if (list.size > 4) itemCount else list.size
    }


    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun initData(any: Any) {
			itemView.findViewById<ImageView>(R.id.iv_session_scroll_good_img)?.load("url")
			itemView.findViewById<TextView>(R.id.tv_session_scroll_good_price)?.text = "测试:" + any.toString()
        }
    }
}

使用

rv_auto_scroll.let{
    it.layoutManager = LinearLayoutManager(view!!.context, LinearLayoutManager.HORIZONTAL, false)
    it.adapter = SpecialScrollChildAdapter(view.context, mutableListOf<Any>())
    if (it.itemDecorationCount > 0) {
        it.removeItemDecorationAt(0)
    }

    it.addItemDecoration {
        width = 15.dp
        linear {
            drawTop = false
            drawBottom = false
            drawLeft = false
            drawRight = false
        }

    }
    it.postDelayed({
        it.handleTimeHandler(true)
    }, 200)

    it.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            (it.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition().let {
            }
        }
    })
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值