android-AdvancedRecyclerview
演示地址(需梯子):
https://www.youtube.com/watch?feature=player_embedded&v=S7cSwMArjUQ
今天主要使用这个库来实现RecyclerView
的左右滑动item
和 拖拽排序
Gradle配置
compile ‘com.android.support:recyclerview-v7:22.1.1‘
compile ‘com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.7.1‘
接下来我们就可以使用了
1. 在布局中添加RecyclerView
控件
<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
2. 初始化RecyclerView
//MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private RecyclerView.Adapter mAdapter;
private RecyclerView.Adapter mWrappedAdapter;
private RecyclerViewSwipeManager mRecyclerViewSwipeManager;
private RecyclerViewTouchActionGuardManager mRecyclerViewTouchActionGuardManager;
private RecyclerViewDragDropManager mRecyclerViewDragDropManager;
private List<MyItem> dataList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取RecycleView,创建LayoutManager
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(this);
// touch guard manager 阻止当左右滑动(swipe)item时列表滚动
mRecyclerViewTouchActionGuardManager = new RecyclerViewTouchActionGuardManager();
mRecyclerViewTouchActionGuardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
mRecyclerViewTouchActionGuardManager.setEnabled(true);
// drag & drop manager 拖拽排序的manager
mRecyclerViewDragDropManager = new RecyclerViewDragDropManager();
mRecyclerViewDragDropManager.setDraggingItemShadowDrawable(
(NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z3_xxhdpi));
// swipe manager 滑动item的manager
mRecyclerViewSwipeManager = new RecyclerViewSwipeManager();
//adapter,这里是模拟数据
for(int i=0;i<100;i++){
dataList.add(new MyItem(i,"测试数据"+i));
}
mAdapter = new MyAdapter(dataList);
//封装一下adapter
mWrappedAdapter = mRecyclerViewDragDropManager.createWrappedAdapter(mAdapter); //处理一下mAdapter可以拖拽
mWrappedAdapter = mRecyclerViewSwipeManager.createWrappedAdapter(mWrappedAdapter); //处理一下mAdapter可以滑动删除,注意这里的 -变量
final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
// Change animations are enabled by default since support-v7-recyclerview v22.
// Disable the change animation in order to make turning back animation of swiped item works properly.
animator.setSupportsChangeAnimations(false);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mWrappedAdapter); // 注意设置的是mWrappedAdapter
mRecyclerView.setItemAnimator(animator);
//additional decorations
//noinspection StatementWithEmptyBody
if (supportsViewElevation()) {
// Lollipop or later has native drop shadow feature. ItemShadowDecorator is not required.
} else {
mRecyclerView.addItemDecoration(new ItemShadowDecorator((NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z3_xxhdpi)));
}
mRecyclerView.addItemDecoration(new SimpleListDividerDecorator(getResources().getDrawable(R.drawable.list_divider), true));
// NOTE:
// 初始化的顺序十分重要,这决定了处理Touch事件的优先级
// 优先级: TouchActionGuard > Swipe > DragAndDrop
mRecyclerViewTouchActionGuardManager.attachRecyclerView(mRecyclerView);
mRecyclerViewSwipeManager.attachRecyclerView(mRecyclerView);
mRecyclerViewDragDropManager.attachRecyclerView(mRecyclerView);
}
//判断版本号
private boolean supportsViewElevation() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
}
}
需要注意的问题
1. adapter的处理
2. 需要将需要用到的manager 绑定到recylerView上
3. 最主要的还是Adapter
//MyAdapter
/*
* Created by Hanks
* Copyright (c) 2015 Nashangban. All rights reserved
*
*/
package app.hanks.com.testadvancerecyclerview;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableSwipeableItemViewHolder;
import java.util.List;
/**
* Created by Hanks on 2015/5/24.
*/
public class MyAdapter
extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
implements DraggableItemAdapter<MyAdapter.MyViewHolder>,
SwipeableItemAdapter<MyAdapter.MyViewHolder> {
private final List<MyItem> dataList;
public MyAdapter( List<MyItem> dataList) {
this.dataList = dataList;
//需要设置id
setHasStableIds(true);
}
//需要设置Id
@Override
public long getItemId(int position) {
return dataList.get(position).getId();
}
@Override
public int getItemViewType(int position) {
return dataList.get(position).getViewType();
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.item_list_swipe, parent, false);
return new MyViewHolder(v);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyItem item = dataList.get(position);
holder.textView.setText(item.getContent());
// set background resource (target view ID: container)
final int dragState = holder.getDragStateFlags();
final int swipeState = holder.getSwipeStateFlags();
if (((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_UPDATED) != 0) ||
((swipeState & RecyclerViewSwipeManager.STATE_FLAG_IS_UPDATED) != 0)) {
int bgResId;
if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_ACTIVE) != 0) {
bgResId = R.drawable.bg_item_dragging_active_state;
} else if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_DRAGGING) != 0) {
bgResId = R.drawable.bg_item_dragging_state;
} else if ((swipeState & RecyclerViewSwipeManager.STATE_FLAG_IS_ACTIVE) != 0) {
bgResId = R.drawable.bg_item_swiping_active_state;
} else if ((swipeState & RecyclerViewSwipeManager.STATE_FLAG_SWIPING) != 0) {
bgResId = R.drawable.bg_item_swiping_state;
} else {
bgResId = R.drawable.bg_item_normal_state;
}
holder.container.setBackgroundResource(bgResId);
}
// set swiping properties
holder.setSwipeItemSlideAmount(
item.isPinedToSwipeLeft() ? RecyclerViewSwipeManager.OUTSIDE_OF_THE_WINDOW_LEFT : 0);
}
@Override
public int getItemCount() {
return dataList.size();
}
//交换位置
@Override
public void onMoveItem(int fromPosition, int toPosition) {
Log.d("zyh", "onMoveItem(fromPosition = " + fromPosition + ", toPosition = " + toPosition + ")");
if (fromPosition == toPosition) {
return;
}
moveItem(fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
private void moveItem(int fromPosition, int toPosition) {
if (fromPosition == toPosition) {
return;
}
final MyItem item = dataList.remove(fromPosition);
dataList.add(toPosition, item);
}
@Override
public int onGetSwipeReactionType(MyViewHolder holder, int position, int x, int y) {
if (onCheckCanStartDrag(holder, position, x, y)) {
return RecyclerViewSwipeManager.REACTION_CAN_NOT_SWIPE_BOTH;
} else {
return RecyclerViewSwipeManager.REACTION_CAN_SWIPE_BOTH;
}
}
@Override
public void onSetSwipeBackground(MyViewHolder holder, int position, int type) {
int bgRes = 0;
switch (type) {
case RecyclerViewSwipeManager.DRAWABLE_SWIPE_NEUTRAL_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_neutral;
break;
case RecyclerViewSwipeManager.DRAWABLE_SWIPE_LEFT_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_left; //左边滑动出现的布局,应该算是一个drawable
break;
case RecyclerViewSwipeManager.DRAWABLE_SWIPE_RIGHT_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_right; //右边滑动出现的布局
break;
}
holder.itemView.setBackgroundResource(bgRes);
}
@Override
public int onSwipeItem(MyViewHolder holder, int position, int result) {
switch (result) {
// swipe right
case RecyclerViewSwipeManager.RESULT_SWIPED_RIGHT:
if (dataList.get(position).isPinedToSwipeLeft()) {
// pinned --- back to default position
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_DEFAULT;
} else {
// not pinned --- remove
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_REMOVE_ITEM;
}
// swipe left -- pin
case RecyclerViewSwipeManager.RESULT_SWIPED_LEFT:
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_MOVE_TO_SWIPED_DIRECTION;
// other --- do nothing
case RecyclerViewSwipeManager.RESULT_CANCELED:
default:
return RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_DEFAULT;
}
}
@Override
public void onPerformAfterSwipeReaction(MyViewHolder holder, int position, int result, int reaction) {
final MyItem item = dataList.get(position);
if (reaction == RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_REMOVE_ITEM) {
dataList.remove(position);
notifyItemRemoved(position);
} else if (reaction == RecyclerViewSwipeManager.AFTER_SWIPE_REACTION_MOVE_TO_SWIPED_DIRECTION) {
item.setPinedToSwipeLeft(true);
notifyItemChanged(position);
} else {
item.setPinedToSwipeLeft(false);
}
}
@Override
public boolean onCheckCanStartDrag(MyViewHolder holder, int position, int x, int y) {
// x, y --- relative from the itemView‘s top-left
final View containerView = holder.container;
final View dragHandleView = holder.dragHandle;
final int offsetX = containerView.getLeft() + (int) (ViewCompat.getTranslationX(containerView) + 0.5f);
final int offsetY = containerView.getTop() + (int) (ViewCompat.getTranslationY(containerView) + 0.5f);
return hitTest(dragHandleView, x - offsetX, y - offsetY);
}
@Override
public ItemDraggableRange onGetItemDraggableRange(MyViewHolder holder, int position) {
// no drag-sortable range specified
return null;
}
public static class MyViewHolder extends AbstractDraggableSwipeableItemViewHolder {
private final ViewGroup container;
private final TextView textView;
private final View dragHandle;
public MyViewHolder(View itemView) {
super(itemView);
container = (ViewGroup) itemView.findViewById(R.id.container);
dragHandle = itemView.findViewById(R.id.drag_handle);
textView = (TextView) itemView.findViewById(R.id.text);
}
@Override
public View getSwipeableContainerView() {
return container;
}
}
public static boolean hitTest(View v, int x, int y) {
final int tx = (int) (ViewCompat.getTranslationX(v) + 0.5f);
final int ty = (int) (ViewCompat.getTranslationY(v) + 0.5f);
final int left = v.getLeft() + tx;
final int right = v.getRight() + tx;
final int top = v.getTop() + ty;
final int bottom = v.getBottom() + ty;
return (x >= left) && (x <= right) && (y >= top) && (y <= bottom);
}
}
4. 还没完, item的布局
<!-- item_list_swipe -->
<?xml version="1.0" encoding="utf-8"?>
<!-- NOTE: should use FrameLayout or RelativeLayout for parent of the "@id/container" view (for Android 2.3 compatibility) -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="64dp"
android:minHeight="64dp"
android:background="@drawable/bg_swipe_item_neutral">
<RelativeLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
tools:ignore="UselessParent">
<View
android:id="@+id/drag_handle"
android:layout_width="32dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#20000000"/>
<TextView
android:id="@+id/text"
android:text="sdsad"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/drag_handle"
android:gravity="center"
tools:ignore="RtlHardcoded"/>
</RelativeLayout>
</FrameLayout>
注意上面的布局
Demo: https://github.com/hanks-zyh/RecylerView
library: https://github.com/h6ah4i/android-advancedrecyclerview
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。