闲来无事,看了下支付宝App做的应用item效果,很炫,效果如下:
自己实现的效果如下:
gif可能有点卡,但是实现了支付宝效果,
说下思路:下面是实例图(凑合看吧,大概意思是)
开始是打算用ScrollView+RecycleView实现,上面一个RecycleView是存储已经添加的app图标区域,下面做一个linearLayout,动态添加RecycleView,因为下面的项目是多个的,动态获取的,可以实现动态添加项目,但是没有动画效果,因为所有的item不是在一个组件里面实现的,功能是实现了,但是没有动画效果,距离支付宝的效果还有距离,于是换一个思想
,把上面和下面的都放在一个RecycleView里面,就是整个界面只有一个RecycleView,并且把每一类item数据放到一个list中,头部添加的也是单独的list,整个数据全部方法一个bean中,bean中数据是这样的结构:list在存每个item的list
public class AllApplyTable implements Serializable {
private int type;
private String titleName;
private List mList;
有人说,支付宝的不是有title么,这样婶儿的:
good question!确实,recycleView的adapter里面可以通过
getItemViewType()方法返回不同的试图,但是这个地方因为是用的
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 4, LinearLayoutManager.VERTICAL, false);
如果单独的返回不同的试图,界面会出现错乱,title的位置不会单独占用一行,但是GridLayoutManager有个类
GridLayoutManager.SpanSizeLookup,这个类有个重写的方法:
getSpanSize(int positon),这个方法返回的的意思是当前的item占几行,比如当前是title试图,那么就单独占一行,所以根据type返回item占的数量:
@Override
public int getSpanSize(int position) {
int type = mApplyAdapter.getItemViewType(position);
switch (type){
case 0:
return 4;
default:
return 1;
}
}
解决了title单独占一行的问题,注意:title也是一个bean和item一样,不过是某些属性不一样来区分是title还是item
然后还有一个拖动的效果,就是可以左右上下拖动,如果是LinearLayoutManager只可以上下拖动,我们需要继承
ItemTouchHelper.Callback所以ItemDragHelperCallback 类这样:
public class ItemDragHelperCallback extends ItemTouchHelper.Callback {
private OnItemMoveListener mOnItemMoveListener;
private boolean mIsLongPressEnabled;
public void setLongPressEnabled(boolean longPressEnabled) {
mIsLongPressEnabled = longPressEnabled;
}
public interface OnItemMoveListener {
boolean onItemMove(int fromPosition, int toPosition);
}
//相当于 set 设置监听 传入ChannelAdapter中的OnItemMoveListener对象
public ItemDragHelperCallback(OnItemMoveListener onItemMoveListener) {
mOnItemMoveListener = onItemMoveListener;
}
//返回true 允许拖拽
@Override
public boolean isLongPressDragEnabled() {
return mIsLongPressEnabled;
}
//返回可以滑动的方向,比如说允许从右到左侧滑,允许上下拖动等
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int itemViewType = viewHolder.getItemViewType();
if (1!= itemViewType){
return makeMovementFlags(0, 0);
}
//根据recyclerView的布局,进行设置拖拽的方向
int dragFlags = setDragFlags(recyclerView);
//不允许进行滑动
int swipeFlags = 0;
// 获取触摸响应的方向 包含两个 1.拖动dragFlags 2.侧滑删除swipeFlags
return makeMovementFlags(dragFlags, swipeFlags);
}
private int setDragFlags(RecyclerView recyclerView) {
int dragFlags;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager || layoutManager instanceof StaggeredGridLayoutManager) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
} else {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
}
return dragFlags;
}
//当用户拖动一个Item进行上下移动从旧的位置到新的位置的时候会调用该方法,在该方法内,
// 我们可以调用Adapter的notifyItemMoved方法来交换两个ViewHolder的位置,最后返回true,
// 表示被拖动的ViewHolder已经移动到了目的位置。所以,如果要实现拖动交换位置,可以重写该方法(前提是支持上下拖动)
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
//不同Type之间不允许移动
if (viewHolder.getItemViewType() != target.getItemViewType()) {
return false;
}
return mOnItemMoveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setBackgroundColor(Color.WHITE);
//当用户操作完毕某个item并且其动画也结束后会调用该方法,一般我们在该方法内恢复ItemView的初始状态,防止由于复用而产生的显示错乱问题。
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//当用户左右滑动Item达到删除条件时,会调用该方法,一般手指触摸滑动的距离达到RecyclerView宽度的一半时,
// 再松开手指,此时该Item会继续向原先滑动方向滑过去并且调用onSwiped方法进行删除,否则会反向滑回原来的位置。
//如果在onSwiped方法内我们没有进行任何操作,即不删除已经滑过去的Item,那么就会留下空白的地方,
// 因为实际上该ItemView还占据着该位置,只是移出了我们的可视范围内罢了。
}
//拖动选择状态改变回调
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
//从静止状态变为拖拽或者滑动的时候会回调该方法,参数actionState表示当前的状态。
/**
* ACTION_STATE_IDLE:拖拽或删除结束,这时 viewHolder 参数为 null 。
* ACTION_STATE_DRAG:开始拖拽
* ACTION_STATE_SWIPE:开始删除
*/
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
// ItemTouchHelper.ACTION_STATE_IDLE 看看源码解释就能理解了
// 侧滑或者拖动的时候背景设置为灰色
viewHolder.itemView.setBackgroundColor(Color.GRAY);
}
}
}
在Activity里面使用 的时候是:
ApplyAdapter allAdapter = new ApplyAdapter(this, allTablesApply);
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 4, LinearLayoutManager.VERTICAL, false);
mRv_head.setLayoutManager(gridLayoutManager);
mRv_head.setItemAnimator(new MydefaultAnimator());
AdapterColSpanLookup mAdapterColSpanLookup = new AdapterColSpanLookup(allAdapter);
//设置AdapterColSpanLookup返回item和title占的个数
gridLayoutManager.setSpanSizeLookup(mAdapterColSpanLookup);
mRv_head.setAdapter(allAdapter);
ItemDragHelperCallback callback = new ItemDragHelperCallback(allAdapter);
// //是一个工具类,可实现侧滑删除和拖拽移动,完成后数据的刷新(UI更新)由重写的ItemDragHelperCallback完成
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
// //调用ItemTouchHelper的attachToRecyclerView方法建立联系
touchHelper.attachToRecyclerView(mRv_head);
allAdapter.setItemDragHelperCallback(callback);
我们还需要定义下那些可以拖动哪些不能拖动,最近添加的在recycle上面的就是可以拖动的,其他下面的不允许拖动:
在ItemDragHelperCallback类的getMovementFlags里面获取itemViewType值,区分是否是已经添加到头部,如果是添加才可以拖动,否则不能拖动
int itemViewType = viewHolder.getItemViewType();
if (1!= itemViewType){
return makeMovementFlags(0, 0);
}
还有一个需要解决的问题是怎么移动,就是当前点击的时候怎么移动到特定的位置,分为下面移动到上面,我们就直接从下面list中删除对应的bean,我们暂且叫list_1,然后添加到头部list,我们暂且叫:headList,
list_1.remove(bean)
headList.add(bean)
就完成下面的删除,上面的添加,然后,在统一添加到adapte的list中,我们设置的时候有个动画:
mRv_head.setItemAnimator(new MydefaultAnimator());mRv_head是recycleView
MydefaultAnimator时候实现SimpleItemAnimator接口的类,是默认的动画
最后执行上面删除执行:allTablesApply是adapter全部list数据
moveEnd = allTablesApply.indexOf(at);
allAdapter.notifyItemMoved(position, moveEnd);
allAdapter.notifyItemRangeChanged(moveEnd-1,allTablesApply.size());
上面添加执行:
appayTableUser是头部已经添加的数据集合
allAdapter.notifyItemMoved(position, appayTableUser.size() - 1);
allAdapter.notifyItemRangeChanged(0,position+1);
最后实现高仿支付宝APP的添加删除item效果,有问题可以留言。
源码下载:
https://download.csdn.net/download/u012106080/11892097