前言:
RecyclerView作为Android中最重要的一个系统组件,在用户界面展示时就势必要展示其最好的一面(美观、健壮、优化)。本文将通过设置Animation
来快速地达到设置各种炫酷的动画效果。
一:基本配置
首先先创建一个RecyclerView示例项目。其工程结构如图所示:
Bean.java
,BeanAdapter.java
,MainActivity.java
这三个文件分别代表RecyclerView子项的实体Bean,RecyclerView适配器,主活动。其代码如下:
Bean.java
:
public class Bean {
private int imageViewId;
private String title;
public Bean(){
}
public Bean(int imageViewId, String title){
this.imageViewId = imageViewId;
this.title = title;
}
public void setTitle(String title) {
this.title = title;
}
public void setImageViewId(int imageViewId) {
this.imageViewId = imageViewId;
}
public String getTitle() {
return title;
}
public int getImageViewId() {
return imageViewId;
}
@NonNull
@Override
public String toString() {
return super.toString();
}
}
BeanAdapter.java
:
public class BeanAdapter extends RecyclerView.Adapter <BeanAdapter.ViewHolder> {
private List<Bean> mBeanList;
private Context context;
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public ViewHolder(View view){
super(view);
imageView = (ImageView) view.findViewById(R.id.image_view);
textView = (TextView) view.findViewById(R.id.text_view);
}
}
public BeanAdapter(List<Bean> mBeanList, Context context){
this.mBeanList = mBeanList;
this.context = context;
}
@NonNull
@Override
public BeanAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bean,parent,false);
final ViewHolder holder = new ViewHolder(view);
holder.imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Toast.makeText(context, "Click At: " + position, Toast.LENGTH_SHORT).show();
}
});
holder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Toast.makeText(context, "Click At: " + position, Toast.LENGTH_SHORT).show();
}
});
return holder;
}
@Override
public void onBindViewHolder(@NonNull BeanAdapter.ViewHolder holder, int position) {
Bean bean = mBeanList.get(position);
holder.imageView.setImageResource(bean.getImageViewId());
holder.textView.setText(bean.getTitle());
}
@Override
public int getItemCount() {
return mBeanList.size();
}
}
MainActivity.java
:
public class MainActivity extends AppCompatActivity {
private Button buttonUpdate;
private RecyclerView recyclerView;
private BeanAdapter beanAdapter;
private List<Bean> beanList = new ArrayList<Bean>();
private void initData(){
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
}
private void initRecyclerView(Context context){
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
initData();
beanAdapter = new BeanAdapter(beanList, context);
recyclerView.setAdapter(beanAdapter);
}
private void initView(){
buttonUpdate = (Button) findViewById(R.id.button_update);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initRecyclerView(MainActivity.this);
}
});
}
}
关于布局文件不再赘述。这样,一个示例项目就创建完成。
该示例项目在没有使用动画之前是这样的效果:
可以看到数据是直接展示出来的,没有任何转场动画。
那么此时我们把MainActivity.java
文件修改如下:
public class MainActivity extends AppCompatActivity {
private Button buttonUpdate;
private RecyclerView recyclerView;
private BeanAdapter beanAdapter;
private List<Bean> beanList = new ArrayList<Bean>();
private void initAinm() {
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.my_anim);
LayoutAnimationController layoutAnimationController = new LayoutAnimationController(animation);
layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
layoutAnimationController.setDelay(0.2f);
recyclerView.setLayoutAnimation(layoutAnimationController);
}
private void initData(){
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
beanList.add(new Bean(R.drawable.apple, "Apple"));
beanList.add(new Bean(R.drawable.music, "Apple"));
}
private void initRecyclerView(Context context){
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
initData();
beanAdapter = new BeanAdapter(beanList, context);
recyclerView.setAdapter(beanAdapter);
}
private void initView(){
buttonUpdate = (Button) findViewById(R.id.button_update);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
buttonUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
initRecyclerView(MainActivity.this);
initAinm();
}
});
}
}
注意增添的是一个我们自定义的initAnim()
方法,把这个方法增加进去就行。另外,在如下图所示的内容中,新建了一个anim文件夹,并创建了一个名为my_anim.xml的资源文件。
注意新建的资源文件名要与增加的自定义方法里面Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.my_anim);
第二个参数要对应上。这个资源文件就是我们控制动画的关键。
二:设置出/入动画
在my_anim.xml
资源文件中的代码更改如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromXDelta="100%"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="0" />
</set>
参数说明:
-
android:duration
:动画持续时间,单位毫秒 -
android:fromXDelta
:从X轴何处来,数值为正则从屏幕右边来 -
android:fromYDelta
:从Y轴何处来 -
android:toXDelta
:从X轴何消失 -
android:toYDelta
:从Y轴何消失
效果图:
可以看到该效果是item从屏幕右边出现,至屏幕左边缘停止。
三:设置透明度
修改my_anim.xml
资源文件中的代码更改如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="100"
android:fromAlpha="0"
android:toAlpha="1" />
</set>
参数说明:
-
android:duration
:动画持续时间,单位毫秒 -
android:fromAlpha
:item展现时的透明度,范围0~1 -
android:toAlpha
:item最后的透明度,范围0~1
效果图:
这里由于动画持续时间较短,读者可能看的不太明显。该效果展示的是出现时item透明度为0,最终透明度为1的效果。
四:设置旋转动画
修改my_anim.xml
资源文件中的代码更改如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="180"
android:toDegrees="0"
android:pivotX="100%"
android:pivotY="100%"
android:duration="500"/>
</set>
参数说明:
-
android:fromDegrees
:item展现时的角度,单位度 -
android:toDegrees
:item最终的角度,单位度 -
android:pivotX
:旋转中心 -
android:pivotY
:旋转中心 -
android:duration
:动画持续时间,单位毫秒
效果图:
这里item是从其右下角为旋转轴,旋转90°来达到的效果。
五:设置出/入缩放比例
修改my_anim.xml
资源文件中的代码更改如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1"
android:toYScale="1"
android:duration="500" />
</set>
参数说明:
-
android:pivotX
:item的动画中心轴位置,50%为中心 -
android:pivotY
:item的动画中心轴位置,50%为中心 -
android:fromXScale
:item开始时的尺寸,范围0~1 -
android:fromYScale
:item开始时的尺寸,范围0~1 -
android:toXScale
:item结束时的尺寸,范围0~1 -
android:toYScale
:item结束时的尺寸,范围0~1 -
android:duration
:动画持续时间,单位毫秒
效果图:
可以看到一开始item是从中心位置出现,并且极小(0),然后向四周扩散,最终item尺寸变为1
后记:
上述中各个标签实际上是可以相互叠加的来创造出各种丰富的动画效果。这里提供一些模板以供参考:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%"
android:toYDelta="0%"
android:duration="500" />
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="500"/>
<scale
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0.5"
android:fromYScale="0.5"
android:toXScale="1"
android:toYScale="1"
android:duration="500"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="200%"
android:toYDelta="0%"
android:duration="500" />
<scale
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1"
android:toYScale="1"
android:duration="500" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="200%"
android:toYDelta="0%"
android:duration="500" />
<alpha
android:fromAlpha="0.0"
android:toAlpha="3.0"
android:duration="2500"/>
</set>