Android添加item动画,RecyclerView基础篇-Item添加动画

4c1eb409bc0e

Android_Banner.jpg

简介

本节中我们介绍下给RecyclerView中的Item添加动画。

添加的动画,分为,在打开列表时有Item的展示动画,当滑动的时候没有动画

和打开列表滑动时有动画两种

实现过程

实现一个列表

效果如下

4c1eb409bc0e

Screenshot_2020-09-01-17-03-35-349_com.dashingqi.module.recyclerview.png

接下来我们就要操作这个列表中的Item,让其产生动画

布局的实现代码

main_activity.xml 的布局文件

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools">

name="viewModel"

type="com.dashingqi.module.recyclerview.RvAnimationViewModel" />

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".RvAnimationActivity">

android:id="@+id/animRv"

android:layout_width="match_parent"

android:layout_height="match_parent"

app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

MainActivity.kt中的代码

lass RvAnimationActivity : AppCompatActivity() {

private val animationDownToUp by lazy {

AnimationUtils.loadAnimation(this, R.anim.item_anim_down_to_up)

}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

val dataBinding = DataBindingUtil.setContentView(

this,

R.layout.activity_rv_animation

)

//获取到ViewModel的实例

val viewModel = ViewModelProvider(this)[RvAnimationViewModel::class.java]

//绑定ViewModel

dataBinding.viewModel = viewModel

//设置适配器

var adapter = RvAnimationAdapter(viewModel.items, animRv)

animRv.adapter = adapter

// 为Rv中的Item添加装饰器

animRv.addItemDecoration(object : RecyclerView.ItemDecoration() {

override fun getItemOffsets(

outRect: Rect,

view: View,

parent: RecyclerView,

state: RecyclerView.State

) {

val childPosition = parent.getChildAdapterPosition(view)

if (childPosition != 0) {

outRect.top = DensityUtils.dip2pxInt(parent.context, 16f)

}

}

})

}

}

ViewModel中的代码

class RvAnimationViewModel : ViewModel() {

val items = ObservableArrayList()

val itemBinding = ItemBinding.of(BR.item, R.layout.item_anim_view)

init {

for (index in 0 until 80) {

items.add("Item${index}")

}

}

}

Adapter中的代码

class RvAnimationAdapter(var datas: ArrayList, var recyclerView: RecyclerView) :

RecyclerView.Adapter() {

class MyViewHolder(var dataBinding: ItemAnimViewBinding) :

RecyclerView.ViewHolder(dataBinding.root) {

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

val dataBinding = DataBindingUtil.inflate(

LayoutInflater.from(parent.context),

R.layout.item_anim_view,

parent,

false

)

return MyViewHolder(dataBinding)

}

override fun getItemCount(): Int {

return datas.size

}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {

val itemDataBinding = holder.dataBinding as ItemAnimViewBinding

itemDataBinding.item = datas[position]

itemDataBinding.executePendingBindings()

}

}

item的布局文件

xmlns:app="http://schemas.android.com/apk/res-auto">

name="item"

type="String" />

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:layout_width="match_parent"

android:layout_height="240dp"

android:background="@android:color/holo_red_dark"

android:text="@{item}"

android:gravity="center"

android:textColor="#ffffff"

android:textSize="20sp"

android:textStyle="bold"

app:layout_constraintTop_toTopOf="parent" />

实现进入列表时的动画

实现效果如下

4c1eb409bc0e

list_start.gif

该动画是从右侧平移到屏幕中,所以我们的平移动画的X轴的起点从 100%开始,终止点为0 ,y不变

android:duration="500">

android:fromXDelta="100%p"

android:fromYDelta="0"

android:toXDelta="0"

android:toYDelta="0" />

android:fromAlpha="0"

android:toAlpha="100" />

接着借助LayoutAnimationController 给 RV的layoutAnimation设置动画数据

val viewModel = ViewModelProvider(this)[RvAnimationViewModel::class.java]

dataBinding.viewModel = viewModel

var adapter = RvAnimationAdapter(viewModel.items, animRv)

animRv.adapter = adapter

var animation = AnimationUtils.loadAnimation(this, R.anim.item_anim_translate)

val layoutAnimationController = LayoutAnimationController(animation)

//设置顺序

layoutAnimationController.order = LayoutAnimationController.ORDER_NORMAL

animRv.layoutAnimation = layoutAnimationController

滑动的时候带有动画

效果如下

4c1eb409bc0e

list_scroll.gif

上图中的效果,是在ItemView可见的时候执行动画,我们的切入点也就是这个时机,正好Adapter中有提供一个方法onViewAttachedToWindow()

onViewAttachedToWindow() 是当Adapter创建好的View依附在Window的时候调用的,所以这个方法是一个时机,在这个方法中,为每一个ItemView设置动画。

同时我们还需要为Rv设置滑动的监听事件,来记录滑动的方向,这样在onViewAttachedToWindow()方法中设置不同的动画

所以Adapter中的代码变更如下

class RvAnimationAdapter(var datas: ArrayList, var recyclerView: RecyclerView) :

RecyclerView.Adapter() {

/**

* 用来记录当前是向上滑动的

*/

var isScrollUp = false

/**

* 用来记录当前是向下滑动的

*/

var isScrollDown = false

/**

* 动画

*/

private val animation by lazy {

AnimationUtils.loadAnimation(recyclerView.context, R.anim.item_anim_translate)

}

private val animationUpToDown by lazy {

AnimationUtils.loadAnimation(recyclerView.context, R.anim.item_anim_up_to_down)

}

private val animationDownToUp by lazy {

AnimationUtils.loadAnimation(recyclerView.context, R.anim.item_anim_down_to_up)

}

init {

//为RV添加滑动事件的监听

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {

super.onScrollStateChanged(recyclerView, newState)

}

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {

super.onScrolled(recyclerView, dx, dy)

isScrollUp = dy > 0

isScrollDown = dy < 0

}

})

}

class MyViewHolder(var dataBinding: ItemAnimViewBinding) :

RecyclerView.ViewHolder(dataBinding.root) {

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

val dataBinding = DataBindingUtil.inflate(

LayoutInflater.from(parent.context),

R.layout.item_anim_view,

parent,

false

)

return MyViewHolder(dataBinding)

}

override fun getItemCount(): Int {

return datas.size

}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {

val itemDataBinding = holder.dataBinding as ItemAnimViewBinding

itemDataBinding.item = datas[position]

itemDataBinding.executePendingBindings()

}

/**

* 当创建好的View依附到Window上时回调的

*/

override fun onViewAttachedToWindow(holder: MyViewHolder) {

super.onViewAttachedToWindow(holder)

for (index in 0 until recyclerView.childCount) {

//获取到Item

val itemView = recyclerView.getChildAt(index)

//清除每一个Item上的动画

itemView?.clearAnimation()

}

// 当向上滑动的时候

if (isScrollUp) {

holder.itemView.startAnimation(animationDownToUp)

}

//当向下滑动的时候

if (isScrollDown) {

holder.itemView.startAnimation(animationUpToDown)

}

}

}

对应的动画文件

android:duration="200">

android:fromYDelta="100%"

android:toYDelta="0" />

android:fromAlpha="0"

android:toAlpha="1" />

android:duration="200"

>

android:fromYDelta="-100%"

android:toYDelta="0" />

android:fromAlpha="0"

android:toAlpha="1" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值