代码分享
分享点Android基础代码吧~
本想找个轮子,轮子没找到,只能自己搞了。
话不多说,直接上代码干货,分享给后面有需要的xdm,直接拿去用。
整体实现不算复杂,就费点时间,已抽离不相干的代码。
实现效果
- 无限循环顺滑滚动
- 触摸停止滚动,抬手n秒后继续滚动
- 实时记录当前可见的视图
- 支持由后台控制滚动频率
- 支持动态插拔
- 数据更新动画
涉及到的Android知识点包括
- 自定义View
- RecyclerView
- Glide
- 动画
- 定时器
- 事件分发机制
- handle机制
- 另外:编程语言是kotlin
- 注意:这里使用到的动画以及Handler需要做好及时取消与清除,避免内存泄漏问题。
核心代码:
- 实现无限:
private var itemCount = Int.MAX_VALUE
override fun getItemCount(): Int {
return if (list.size > 4) itemCount else list.size
}
- 实现顺滑滚动:
this@AutoScrollRecyclerView.scrollBy(scrollDistance,0)
- 实现触摸启停滚动:
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 {
//([email protected] as SpecialScrollChildAdapter).isAutoScroll(false)
}
}
- 统计当前展示的item:
it.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
(it.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition().let {
//业务逻辑代码...
}
}
})
- 动画
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)
[email protected](scrollDistance,0)
if (isOpenTimeHandler) { // 如果允许滚动,则继续发送消息
//([email protected] 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 {
//([email protected] 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 {
}
}
})
}