本文已参与「新人创作礼」活动,一起开启掘金创作之路。
RecycleView功能强大,很简单的几个步骤就能满足我们的开发需求,首先来三个效果
上图是动画,相当于加载数据的时候一个简单的动画效果
上图是拖拽,能够选择一行进行上下拖拽和任意一行进行交换
上图是删除,对不用的选项可以进行删除
下面对以上的效果一一进行讲解
首先是动画效果
创建动画的xml文件item_animation_fall_down.xml,这里面写的是旋转,平移,缩放等一些基本参数的介绍
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<translate
android:fromYDelta="-20%"
android:toYDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<scale
android:fromXScale="105%"
android:fromYScale="105%"
android:toXScale="100%"
android:toYScale="100%"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/decelerate_interpolator"
/>
</set>
再创建动画控制
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:delay="15%"
android:animationOrder="normal" />
加载动画到RecycleView的控件上
int resId = R.anim.layout_animation_fall_down;
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(this, resId);
rv_1.setLayoutAnimation(animation);
其次是左右拖拽的效果
实现接口ItemTouchHelper.Callback,这里面的两个方法分别是移动和侧滑的时候调用
package com.example.administrator.testactivity.custom;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import com.example.administrator.testactivity.imple.ItemTouchMoveListener;
import java.util.Collections;
import java.util.List;
public class MyItemTouchCallBack extends ItemTouchHelper.Callback {
private ItemTouchMoveListener touchlistener;
private List<String> list;
public MyItemTouchCallBack(ItemTouchMoveListener touchlistener, List<String> list) {
this.touchlistener = touchlistener;
this.list = list;
}
//CallBack回调监听时先调用,用来判断当前是什么动作 上下还是左右
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlag = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlag = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
int flag = makeMovementFlags(dragFlag,swipeFlag);
return flag;
}
//当移动的时候回调的拖拽方法
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (viewHolder.getItemViewType()!= target.getItemViewType()){
return false;
}
touchlistener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
//当侧滑的时候调用这个方法
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
touchlistener.onItemRemove(viewHolder.getAdapterPosition());
}
}
调用recycleview自身的相关属性就可以了
//左右删除拖拽的效果
helper = new ItemTouchHelper(new MyItemTouchCallBack(this,names));
helper.attachToRecyclerView(rv_1);
上下拖拽交换的效果
定义接口
public interface NofityItem {
void change_move(int form_position, int toPosition);
void change_remove(int position);
}
public interface ItemTouchMoveListener {
/**
* 当拖拽的时候回调
* @param fromPosition
* @param toPosition
* @return
*/
boolean onItemMove(int fromPosition, int toPosition);
/**
* 当条目被删除的时候回调这个接口
* @param position
* @return
*/
boolean onItemRemove(int position);
}
在拖拽回调里面,只要item存在拖拽就会执行下面的方法,在这里面调用接口的里面的方法,在activity中执行回调
//当移动的时候回调的拖拽方法
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (viewHolder.getItemViewType()!= target.getItemViewType()){
return false;
}
touchlistener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
//当侧滑的时候调用这个方法
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
touchlistener.onItemRemove(viewHolder.getAdapterPosition());
}
activity中接收回调并刷新数据
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(names, fromPosition, toPosition);
adapter.notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public boolean onItemRemove(int position) {
names.remove(position);
adapter.notifyItemRemoved(position);
return true;
}
以上是动画效果和拖拽效果的实现基本思路,源码在这里 源码
RecycleView很多人可能用不习惯,觉得太麻烦了,但是实际上用起来的时候功能非常强大。话不多说开始吧。
ItemDecoration这个是RecycleView分割线
//自定义一个类继承RecyclerView.ItemDecoration
public class CustomDividerItem extends RecyclerView.ItemDecoration
接下来需要实现的是getItemOffsets这个主要的方法
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
//拿到当前RecycleView的布局管理器
final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
//由于每个item都会调用一次这个方法,所以我们需要拿到每个item
final int current = parent.getChildLayoutPosition(view);
//拿到总的item数目
final int lastPosition = state.getItemCount() - 1;
//接下来要做的就是在这个方法里面分割
分割每个 Item
//在上面的方法中我们有一个参数outRect 我们需要仔细的理解这个参数,这个参数是每个item的边框
outRect.set(decoration,decoration,decoration,decoration);
//这个方法有四个参数经过我的测试,可以理解为margin分别是左上右下的margin
源码
package com.example.administrator.testactivity.custom;
import android.content.Context;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
public class CustomDividerItem extends RecyclerView.ItemDecoration{
private int dividerHeight;
private static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL;//处于水平状态
private static final int VERTICAL = LinearLayoutManager.VERTICAL;// 处于垂直状态
private int orientation; //方向
private final int decoration;// 边距大小
public CustomDividerItem(int orientation, int decoration) {
this.orientation = orientation;
this.decoration = decoration;
}
/**
* 这个方法每个item都会调用一次
* @param outRect
* @param view
* @param parent
* @param state
*/
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
final RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
//整个recycleview最后一个item的position, getItemCout数目比实际的item个数多一个
final int lastPosition = state.getItemCount() - 1;
//获取当前需要布局的item
final int current = parent.getChildLayoutPosition(view);
Log.e("0000", "0000---->" + current);
Log.e("0000", "0000state.getItemCount()---->" + state.getItemCount());
Log.e("0000", "0000getTargetScrollPosition---->" + state.getTargetScrollPosition());
Log.e("0000", "0000state---->" + state.toString());
if(current == -1) {
return;
}
if (layoutManager instanceof LinearLayoutManager && !(layoutManager instanceof GridLayoutManager)){
//垂直
if (orientation == LinearLayoutManager.VERTICAL){
outRect.set(decoration,decoration,decoration,decoration);
}else{//水平
if (current == lastPosition){
outRect.set(0,0,0,0);
}else{
outRect.set(0,0,decoration,0);
}
}
}
}
}