android 垂直滚动通知,安卓自定义播报垂直滚动view

1. 连续滚动

原理

通过 view.post(Runnable()) 每次发消息,每次接收消息时 recyclerView.scrollBy(offset)

代码

class AutoScrollRecyView(context: Context, attrs: AttributeSet?) : RecyclerView(context, attrs) {

internal var autoPollTask: AutoPollTask

private var running: Boolean = false //标示是否正在自动轮询

private var canRun: Boolean = false//标示是否可以自动轮询,可在不需要的是否置false

init {

autoPollTask = AutoPollTask(this)

}

internal class AutoPollTask//使用弱引用持有外部类引用->防止内存泄漏

(reference: AutoScrollRecyView) : Runnable {

var y: Int = 0

private val mReference: WeakReference

init {

this.mReference = WeakReference(reference)

}

override fun run() {

val recyclerView = mReference.get()

if (recyclerView != null && recyclerView.running && recyclerView.canRun) {

// y += 1

// if (y % ((recyclerView.context.resources.getDimension(R.dimen.dp_30)).toInt()) == 0) {

// recyclerView.postDelayed(recyclerView.autoPollTask, 2000)

// return

// }

recyclerView.scrollBy(2, 1)

recyclerView.postDelayed(recyclerView.autoPollTask, TIME_AUTO_POLL)

}

}

}

//开启:如果正在运行,先停止->再开启

fun start() {

if (running)

stop()

canRun = true

running = true

postDelayed(autoPollTask, TIME_AUTO_POLL)

}

fun stop() {

running = false

removeCallbacks(autoPollTask)

}

override fun onTouchEvent(e: MotionEvent): Boolean {

when (e.action) {

MotionEvent.ACTION_DOWN -> if (running)

stop()

MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_OUTSIDE -> if (canRun)

start()

}

return super.onTouchEvent(e)

}

companion object {

private val TIME_AUTO_POLL: Long = 16

}

}

2. 每隔2秒滚动一次,每次滚动用时400ms

原理

通过 view.post(Runnable()) 每次发消息,每次接收消息时使用 ValueAnimator 开启动画,动画持续时间为滚动时间,并不是真的进行动画,而是使用其每次的差值,通过与上一次动画差值相减得到当前需要 recyclerView.scrollBy(offset) 的 offset 距离,动画结束继续 view.post(Runnable()) 发送消息

代码

class AutoPullRecy3(context: Context, attrs: AttributeSet?) : RecyclerView(context, attrs) {

internal var autoPollTask: AutoPollTask

private var running: Boolean = false //标示是否正在自动轮询

private var canRun: Boolean = false//标示是否可以自动轮询,可在不需要的是否置false

init {

autoPollTask = AutoPollTask(this)

}

internal class AutoPollTask//使用弱引用持有外部类引用->防止内存泄漏

(reference: AutoPullRecy3) : Runnable {

var y: Int = 0

private val mReference: WeakReference

init {

this.mReference = WeakReference(reference)

}

override fun run() {

val recyclerView = mReference.get()

if (recyclerView != null && recyclerView.running && recyclerView.canRun) {

var offsetHeight = recyclerView.getChildAt(0).height

recyclerView.startMoveAnim(recyclerView, offsetHeight)

}

}

}

fun startMoveAnim(recyView: AutoPullRecy3, offset: Int) {

val animator = ValueAnimator.ofInt(0, offset)

animator.setTarget(recyView)

animator.addUpdateListener(object : ValueAnimator.AnimatorUpdateListener {

private var lastDs: Int = 0

override fun onAnimationUpdate(animation: ValueAnimator) {

val value = animation.animatedValue as Int

Log.e("TAG", "animatedValue=" + value + " lastDs=" + lastDs)

var realScrollYDistance = (value - lastDs)

Log.e("TAG", "realScrollYDistance=" + realScrollYDistance)

recyView.scrollBy(2, realScrollYDistance)

lastDs = value

}

})

animator.addListener(object : AnimatorListenerAdapter() {

override fun onAnimationEnd(animation: Animator) {

super.onAnimationEnd(animation)

recyView.postDelayed(recyView.autoPollTask, TIME_AUTO_POLL) //动画结束时再发一次

}

}

)

animator.setDuration(SCROLL_TIME)

animator.start()

}

//开启:如果正在运行,先停止->再开启

fun start() {

if (running)

stop()

canRun = true

running = true

postDelayed(autoPollTask, TIME_AUTO_POLL)

}

fun stop() {

running = false

removeCallbacks(autoPollTask)

}

override fun onTouchEvent(e: MotionEvent): Boolean {

when (e.action) {

MotionEvent.ACTION_DOWN -> if (running)

stop()

MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_OUTSIDE -> if (canRun)

start()

}

return super.onTouchEvent(e)

}

companion object {

private val TIME_AUTO_POLL: Long = 2000

private val SCROLL_TIME: Long = 400

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值