加载RecycleView时为itemView添加一些过渡动画(一)
来源:互联网 发布:python数组减1 编辑:程序博客网 时间:2024/05/16 09:38
参考:实现Instagram的Material Design概念设计
效果图如下:
采用什么方式实现该种动画效果?
Android动画可以分为三类:帧动画(Frame Animation)、补间动画(Tween Animation)、属性动画(Property Animation)。我们主要这里用到了补间动画的Alpha(透明度)和Translate(位移)属性。
在哪里为Item项添加动画?
由于我们是为RecyclerView的Item视图绘制动画效果,所以我们在自定义的MyAdapter(继承了RecyclerView.Adapter)的onBindViewHolder(…)方法里为Item项开启动画。
分析动画效果的组成
仔细观察动画效果,我们可以看到动画效果由两部分组成:
- Item项从无到有:这个我们利用补间动画的Alpha(透明度)属性完成
- Item项慢慢从下往上浮现:利用补间动画的Translate(位移)属性完成
具体的动画方法代码
private void runEnterAnimation(View view, int position) { if (animationsLocked) return; //animationsLocked是布尔类型变量,一开始为false //确保仅屏幕一开始能够容纳显示的item项才开启动画 if (position > lastAnimatedPosition) {//lastAnimatedPosition是int类型变量,默认-1, //这两行代码确保了recyclerview滚动式回收利用视图时不会出现不连续效果 lastAnimatedPosition = position; view.setTranslationY(500); //Item项一开始相对于原始位置下方500距离 view.setAlpha(0.f); //item项一开始完全透明 //每个item项两个动画,从透明到不透明,从下方移动到原始位置 view.animate() .translationY(0).alpha(1.f) //设置最终效果为完全不透明 //并且在原来的位置 .setStartDelay(delayEnterAnimation ? 20 * (position) : 0)//根据item的位置设置延迟时间 //达到依次动画一个接一个进行的效果 .setInterpolator(new DecelerateInterpolator(0.5f)) //设置动画位移先快后慢的效果 .setDuration(700) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animationsLocked = true; //确保仅屏幕一开始能够显示的item项才开启动画 //也就是说屏幕下方还没有显示的item项滑动时是没有动画效果 } }) .start(); } }
下面给出完整实现代码
- 界面主布局activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/contentRoot" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="16dp" android:orientation="vertical" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/rcv" android:layout_width="match_parent" android:layout_weight="1" android:layout_height="0dp" /> <LinearLayout android:layout_marginTop="2dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/edit" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/send" android:text="发送" android:textColor="#ffffff" android:background="#02c754" android:layout_width="72dp" android:layout_height="46dp" android:layout_marginBottom="2dp" android:layout_marginRight="6dp" android:layout_marginLeft="8dp" /> </LinearLayout> </LinearLayout>
- RecyclerView的Item项布局item_view.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingBottom="8dp" android:paddingTop="8dp"> <ImageView android:id="@+id/ivUser" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:src="@drawable/icon3" /> <TextView android:id="@+id/tvComment" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginRight="16dp" android:layout_weight="1" android:text="Lorem ipsum dolor sit amet。" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_gravity="bottom" android:layout_marginBottom="2dp" android:layout_marginLeft="88dp" android:background="#cccccc" /> </FrameLayout>
- MainActivity.java
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.EditText; import java.util.ArrayList; import butterknife.ButterKnife; import butterknife.BindView; public class MainActivity extends AppCompatActivity { @BindView(R.id.rcv) RecyclerView rcy; @BindView(R.id.edit) EditText editText; @BindView(R.id.contentRoot) LinearLayout contentRoot; private ArrayList<String> mDataSet; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); initDate(); initRcy(); } private void initRcy() { rcy.setLayoutManager(new LinearLayoutManager(this)); rcy.setAdapter(new MyAdapter(this,mDataSet)); } private void initDate() { mDataSet=new ArrayList<String>(); mDataSet.add("要想实现这个动画效果,必须考虑到取消原本的重绘回调机制。"); mDataSet.add("item项首先是不透明,并且在原来位置的下方100处,然后慢慢变回透明,并且同时回到原来的位置"); mDataSet.add("底部的输入评论视图首先在原来的位置下方100处,item动画完成后重新回到原来的位置"); mDataSet.add("要想实现这个动画效果,必须考虑到取消原本的重绘回调机制。"); mDataSet.add("item项首先是不透明,并且在原来位置的下方100处,然后慢慢变回透明,并且同时回到原来的位置"); mDataSet.add("底部的输入评论视图首先在原来的位置下方100处,item动画完成后重新回到原来的位置"); mDataSet.add("要想实现这个动画效果,必须考虑到取消原本的重绘回调机制。"); mDataSet.add("item项首先是不透明,并且在原来位置的下方100处,然后慢慢变回透明,并且同时回到原来的位置"); mDataSet.add("底部的输入评论视图首先在原来的位置下方100处,item动画完成后重新回到原来的位置"); mDataSet.add("要想实现这个动画效果,必须考虑到取消原本的重绘回调机制。"); mDataSet.add("item项首先是不透明,并且在原来位置的下方100处,然后慢慢变回透明,并且同时回到原来的位置"); mDataSet.add("底部的输入评论视图首先在原来的位置下方100处,item动画完成后重新回到原来的位置"); } }
- RecyclerView的适配器代码MyAdapter.java
import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; import butterknife.ButterKnife; import butterknife.BindView; /** * Created by yang on 16-4-18. */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private Context mContext; private ArrayList<String> mDataSet; private int lastAnimatedPosition=-1; private boolean animationsLocked = false; private boolean delayEnterAnimation = true; private int itemCount=0; public void setmDataSet(ArrayList<String> mDataSet) { this.mDataSet = mDataSet; } public MyAdapter(Context mContext, ArrayList<String> mDataSet) { this.mContext = mContext; this.mDataSet = mDataSet; } public MyAdapter(Context mContext) { this.mContext = mContext; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder viewHolder = new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_view, parent, false)); return viewHolder; } private void runEnterAnimation(View view, int position) { if (animationsLocked) return; //animationsLocked是布尔类型变量,一开始为false //确保仅屏幕一开始能够容纳显示的item项才开启动画 if (position > lastAnimatedPosition) {//lastAnimatedPosition是int类型变量,默认-1, //这两行代码确保了recyclerview滚动式回收利用视图时不会出现不连续效果 lastAnimatedPosition = position; view.setTranslationY(500); //Item项一开始相对于原始位置下方500距离 view.setAlpha(0.f); //item项一开始完全透明 //每个item项两个动画,从透明到不透明,从下方移动到原始位置 view.animate() .translationY(0).alpha(1.f) //设置最终效果为完全不透明 //并且在原来的位置 .setStartDelay(delayEnterAnimation ? 20 * (position) : 0)//根据item的位置设置延迟时间 //达到依次动画一个接一个进行的效果 .setInterpolator(new DecelerateInterpolator(0.5f)) //设置动画位移先快后慢的效果 .setDuration(700) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animationsLocked = true; //确保仅屏幕一开始能够显示的item项才开启动画 //也就是说屏幕下方还没有显示的item项滑动时是没有动画效果 } }) .start(); } } @Override public void onBindViewHolder(MyViewHolder holder, int position) { runEnterAnimation(holder.itemView,position); if(position%2==0){ holder.ivUser.setImageResource(R.drawable.icon2); }else if(position%3==0){ holder.ivUser.setImageResource(R.drawable.icon3); }else{ holder.ivUser.setImageResource(R.drawable.icon1); } holder.tvComment.setText(mDataSet.get(position)); } @Override public int getItemCount() { return mDataSet.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.tvComment) TextView tvComment; @BindView(R.id.ivUser) ImageView ivUser; public MyViewHolder(View itemView) { super(itemView); ButterKnife.bind(this,itemView); } } }
这样子最终效果就出来了,如果有错误的地方请指出。
PS:
该动画效果仅在首次显示RecyclerView时显示,如果有刷新等操作需要重新显示动画效果时,可以考虑重新恢复animationsLoacked和LastAnimatedPosition的值为false
和-1
。
阅读全文
0 0
- 加载RecycleView时为itemVIew添加一些过渡动画(一)
- 加载RecycleView时为itemView添加一些过渡动画(一)
- ExtJs4问题笔记(一) 为treePanel 添加加载动画
- RecycleView添加动画
- recycleview 的 ItemView常用验证
- RecycleView 添加底部加载更多
- 仿ListView源码添加ReCycleView头部和底部ItemView的功能
- RecycleView添加分割线(ItemDecoration)以及交互动画效果
- 为RecycleView添加ContextMenu支持
- 基于material design的过渡加载动画
- 动态添加布局增添动画过渡效果
- 一句代码搞定 RecycleView 侧滑菜单、添加头部底部、加载更多
- 一句代码搞定 RecycleView 侧滑菜单、添加头部底部、加载更多
- unity加载下一场景时显示过渡画面
- RecycleView原生添加上拉加载
- 动画(过渡动画、关键帧动画)
- height为auto,css3过渡动画问题
- RecyclerView 动画 (添加、删除动画 以及 加载item 时的动画)
- 【BZOJ5119】【CTT2017】生成树计数 DP 分治FFT 斯特林数
- 签名文件keystore常见操作
- table 表格
- 设计模式(十二)------23种设计模式(5):原型模式
- axure rp8.1 注册码
- 加载RecycleView时为itemView添加一些过渡动画(一)
- ubuntu通过apt-get安装jdk8
- reactNative 商品分类效果
- loj6011「网络流 24 题」运输问题(费用流)
- java 文件夹复制到另一个文件夹中
- python数据类型
- php运行超时
- RT-Thread在STM32F103C8T6上面的使用——使用msh
- 本人为初学者,留下一点自己的知识