RecyclerView ItemTouchHelper
生活随笔
收集整理的這篇文章主要介紹了
RecyclerView ItemTouchHelper
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文鏈接:http://blog.csdn.net/tyk0910/article/details/51460808
<?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"><LinearLayout android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextView android:id="@+id/txt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:text="切換欄目"android:textSize="15dp"/><View android:layout_width="match_parent"android:layout_height="1dp"android:background="@color/black"/><ScrollView android:layout_width="match_parent"android:layout_height="match_parent"android:scrollbars="none"><LinearLayout android:id="@+id/tbs_ll"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><android.support.v7.widget.RecyclerView android:id="@+id/chose_recycle"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:layout_marginTop="15dp"android:layout_weight="1"/><LinearLayout android:id="@+id/my_ll"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/chose_recycle"android:layout_centerVertical="true"android:background="@color/font_text"><TextView android:id="@+id/second_txt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:text="點擊添加更多欄目"android:textSize="15dp"/></LinearLayout><android.support.v7.widget.RecyclerView android:id="@+id/all_recycle"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/my_ll"android:layout_marginLeft="15dp"android:layout_marginTop="10dp"/></LinearLayout></ScrollView></LinearLayout> </LinearLayout> public interface onMoveAndSwipedListener {boolean onItemMove(int fromPosition , int toPosition);void onItemDismiss(int position); } public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {private onMoveAndSwipedListener mAdapter;public SimpleItemTouchHelperCallback(onMoveAndSwipedListener listener) {mAdapter = listener;}/*** 這個方法是用來設置我們拖動的方向以及側滑的方向的*/@Overridepublic int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {//如果是ListView樣式的RecyclerView//設置拖拽方向為上下final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;//設置側滑方向為從左到右和從右到左都可以final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;//將方向參數設置進去return makeMovementFlags(dragFlags, swipeFlags);}/*** 當我們拖動item時會回調此方法*/@Overridepublic boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {//如果兩個item不是一個類型的,我們讓他不可以拖拽if (viewHolder.getItemViewType() != target.getItemViewType()) {return false;}//回調adapter中的onItemMove方法mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());return true;}/*** 當我們側滑item時會回調此方法*/@Overridepublic void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {mAdapter.onItemDismiss(viewHolder.getAdapterPosition());}} public class WangYiActivity extends AppCompatActivity implements AllTabsAdapter.onAllTabsListener {public static List<String> choseTabs = new ArrayList<>();public static List<String> allTabs = new ArrayList<>();private RecyclerView choseRecycle, allRecycle;private ChoseTabsAdapter choseAdapter;private AllTabsAdapter allAdapter;private LinearLayout linearLayout;private ItemTouchHelper mItemTouchHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_wang_yi);initviews();initdatas();}private void initdatas() {choseTabs.add("頭條");choseTabs.add("科技");choseTabs.add("熱點");choseTabs.add("政務");choseTabs.add("移動互聯");choseTabs.add("軍事");choseTabs.add("歷史");choseTabs.add("社會");choseTabs.add("財經");choseTabs.add("娛樂");allTabs.add("體育");allTabs.add("時尚");allTabs.add("房產");allTabs.add("論壇");allTabs.add("博客");allTabs.add("健康");allTabs.add("輕松一刻");allTabs.add("直播");allTabs.add("段子");allTabs.add("彩票");allTabs.add("直播");allTabs.add("段子");allTabs.add("彩票");allTabs.add("直播");allTabs.add("段子");allTabs.add("彩票");allTabs.add("輕松一刻");allTabs.add("直播");allTabs.add("段子");allTabs.add("彩票");allTabs.add("直播");allTabs.add("段子");allTabs.add("彩票");allTabs.add("直播");allTabs.add("段子");allTabs.add("彩票");}private void initviews() {choseTabs.clear();allTabs.clear();linearLayout = (LinearLayout) findViewById(R.id.tbs_ll);choseRecycle = (RecyclerView) findViewById(R.id.chose_recycle);allRecycle = (RecyclerView) findViewById(R.id.all_recycle);choseAdapter = new ChoseTabsAdapter(this);allAdapter = new AllTabsAdapter(this);allAdapter.setListener(this);choseRecycle.setLayoutManager(new GridLayoutManager(this, 4));allRecycle.setLayoutManager(new GridLayoutManager(this, 4));choseRecycle.addItemDecoration(new SpaceItemDecoration(15));allRecycle.addItemDecoration(new SpaceItemDecoration(15));choseRecycle.setAdapter(choseAdapter);allRecycle.setAdapter(allAdapter);//關聯ItemTouchHelper和RecyclerViewItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(choseAdapter);mItemTouchHelper = new ItemTouchHelper(callback);mItemTouchHelper.attachToRecyclerView(choseRecycle);}@TargetApi(Build.VERSION_CODES.JELLY_BEAN)@Overridepublic void allTabsItemClick(final View view, final int position) {final PathMeasure mPathMeasure;final float[] mCurrentPosition = new float[2];int parentLoc[] = new int[2];linearLayout.getLocationInWindow(parentLoc);int startLoc[] = new int[2];view.getLocationInWindow(startLoc);final View startView = view;startView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));// RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(view.getWidth(), view.getHeight());Log.e("tag", startView.getWidth() + "#" + startView.getHeight());allRecycle.removeView(view);linearLayout.addView(startView);// ImageView imageView = new ImageView(this);// imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));// imageView.setImageResource(R.drawable.location_located);// linearLayout.addView(imageView);final View endView;float toX, toY;int endLoc[] = new int[2];//進行判斷int i = choseTabs.size();if (i == 0) {toX = view.getWidth();toY = view.getHeight();} else if (i % 4 == 0) {endView = choseRecycle.getChildAt(i - 4);endView.getLocationInWindow(endLoc);toX = endLoc[0] - parentLoc[0];toY = endLoc[1] + view.getHeight() - parentLoc[1];} else {endView = choseRecycle.getChildAt(i - 1);endView.getLocationInWindow(endLoc);toX = endLoc[0] + view.getWidth() - parentLoc[0];toY = endLoc[1] - parentLoc[1];}float startX = startLoc[0] - parentLoc[0];float startY = startLoc[1] - parentLoc[1];Path path = new Path();path.moveTo(startX, startY);path.lineTo(toX, toY);mPathMeasure = new PathMeasure(path, false);//屬性動畫實現ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());valueAnimator.setDuration(500);// 勻速插值器valueAnimator.setInterpolator(new LinearInterpolator());valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float value = (Float) animation.getAnimatedValue();// 獲取當前點坐標封裝到mCurrentPositionmPathMeasure.getPosTan(value, mCurrentPosition, null);startView.setTranslationX(mCurrentPosition[0]);startView.setTranslationY(mCurrentPosition[1]);Log.e("tag", mCurrentPosition[0] + "@" + mCurrentPosition[1]);}});valueAnimator.start();valueAnimator.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {//默認recyclerviewe的動畫allRecycle.setItemAnimator(new DefaultItemAnimator());choseRecycle.setItemAnimator(new DefaultItemAnimator());choseTabs.add(choseTabs.size(), allTabs.get(position));allTabs.remove(position);//先更新數據allAdapter.notifyDataSetChanged();choseAdapter.notifyDataSetChanged();//再更新動畫allAdapter.notifyItemRemoved(position);choseAdapter.notifyItemInserted(choseTabs.size());linearLayout.removeView(startView);}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}});}}原文鏈接:http://www.jianshu.com/p/d30fd8da4eac
使用ItemTouchHelper高效地實現 今日頭條 、網易新聞 的頻道排序、移動
/*** ItemDragHelperCallback* Created by YoKeyword on 15/12/29.*/ public class ItemDragHelperCallback extends ItemTouchHelper.Callback {@Overridepublic int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {int dragFlags;RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();if (manager instanceof GridLayoutManager || manager instanceof StaggeredGridLayoutManager) {dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;} else {dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;}// 如果想支持滑動(刪除)操作, swipeFlags = ItemTouchHelper.START | ItemTouchHelper.ENDint swipeFlags = 0;return makeMovementFlags(dragFlags, swipeFlags);}@Overridepublic boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {// 不同Type之間不可移動if (viewHolder.getItemViewType() != target.getItemViewType()) {return false;}if (recyclerView.getAdapter() instanceof OnItemMoveListener) {OnItemMoveListener listener = ((OnItemMoveListener) recyclerView.getAdapter());listener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());}return true;}@Overridepublic void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {}@Overridepublic void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {// 不在閑置狀態if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {if (viewHolder instanceof OnDragVHListener) {OnDragVHListener itemViewHolder = (OnDragVHListener) viewHolder;itemViewHolder.onItemSelected();}}super.onSelectedChanged(viewHolder, actionState);}@Overridepublic void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {if (viewHolder instanceof OnDragVHListener) {OnDragVHListener itemViewHolder = (OnDragVHListener) viewHolder;itemViewHolder.onItemFinish();}super.clearView(recyclerView, viewHolder);}@Overridepublic boolean isLongPressDragEnabled() {// 不支持長按拖拽功能 手動控制return false;}@Overridepublic boolean isItemViewSwipeEnabled() {// 不支持滑動功能return false;} } /*** ViewHolder 被選中 以及 拖拽釋放 觸發監聽器* Created by YoKeyword on 15/12/29.*/ public interface OnDragVHListener {/*** Item被選中時觸發*/void onItemSelected();/*** Item在拖拽結束/滑動結束后觸發*/void onItemFinish(); } /*** Item移動后 觸發* Created by YoKeyword on 15/12/28.*/ public interface OnItemMoveListener {void onItemMove(int fromPosition, int toPosition); } /*** 頻道 增刪改查 排序* Created by YoKeyword on 15/12/29.*/ public class ChannelActivity extends AppCompatActivity {private RecyclerView mRecy;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_demo);mRecy = (RecyclerView) findViewById(R.id.recy);init();}private void init() {final List<ChannelEntity> items = new ArrayList<>();for (int i = 0; i < 18; i++) {ChannelEntity entity = new ChannelEntity();entity.setName("頻道" + i);items.add(entity);}final List<ChannelEntity> otherItems = new ArrayList<>();for (int i = 0; i < 20; i++) {ChannelEntity entity = new ChannelEntity();entity.setName("其他" + i);otherItems.add(entity);}GridLayoutManager manager = new GridLayoutManager(this, 4);mRecy.setLayoutManager(manager);ItemDragHelperCallback callback = new ItemDragHelperCallback();final ItemTouchHelper helper = new ItemTouchHelper(callback);helper.attachToRecyclerView(mRecy);final ChannelAdapter adapter = new ChannelAdapter(this, helper, items, otherItems);manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {int viewType = adapter.getItemViewType(position);return viewType == ChannelAdapter.TYPE_MY || viewType == ChannelAdapter.TYPE_OTHER ? 1 : 4;}});mRecy.setAdapter(adapter);adapter.setOnMyChannelItemClickListener(new ChannelAdapter.OnMyChannelItemClickListener() {@Overridepublic void onItemClick(View v, int position) {Toast.makeText(ChannelActivity.this, items.get(position).getName(), Toast.LENGTH_SHORT).show();}});} } /*** 拖拽排序 + 增刪* Created by YoKeyword on 15/12/28.*/ public class ChannelAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnItemMoveListener {// 我的頻道 標題部分public static final int TYPE_MY_CHANNEL_HEADER = 0;// 我的頻道public static final int TYPE_MY = 1;// 其他頻道 標題部分public static final int TYPE_OTHER_CHANNEL_HEADER = 2;// 其他頻道public static final int TYPE_OTHER = 3;// 我的頻道之前的header數量 該demo中 即標題部分 為 1private static final int COUNT_PRE_MY_HEADER = 1;// 其他頻道之前的header數量 該demo中 即標題部分 為 COUNT_PRE_MY_HEADER + 1private static final int COUNT_PRE_OTHER_HEADER = COUNT_PRE_MY_HEADER + 1;private static final long ANIM_TIME = 360L;// touch 點擊開始時間private long startTime;// touch 間隔時間 用于分辨是否是 "點擊"private static final long SPACE_TIME = 100;private LayoutInflater mInflater;private ItemTouchHelper mItemTouchHelper;// 是否為 編輯 模式private boolean isEditMode;private List<ChannelEntity> mMyChannelItems, mOtherChannelItems;// 我的頻道點擊事件private OnMyChannelItemClickListener mChannelItemClickListener;public ChannelAdapter(Context context, ItemTouchHelper helper, List<ChannelEntity> mMyChannelItems, List<ChannelEntity> mOtherChannelItems) {this.mInflater = LayoutInflater.from(context);this.mItemTouchHelper = helper;this.mMyChannelItems = mMyChannelItems;this.mOtherChannelItems = mOtherChannelItems;}@Overridepublic int getItemViewType(int position) {if (position == 0) { // 我的頻道 標題部分return TYPE_MY_CHANNEL_HEADER;} else if (position == mMyChannelItems.size() + 1) { // 其他頻道 標題部分return TYPE_OTHER_CHANNEL_HEADER;} else if (position > 0 && position < mMyChannelItems.size() + 1) {return TYPE_MY;} else {return TYPE_OTHER;}}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {final View view;switch (viewType) {case TYPE_MY_CHANNEL_HEADER:view = mInflater.inflate(R.layout.item_my_channel_header, parent, false);final MyChannelHeaderViewHolder holder = new MyChannelHeaderViewHolder(view);holder.tvBtnEdit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (!isEditMode) {startEditMode((RecyclerView) parent);holder.tvBtnEdit.setText(R.string.finish);} else {cancelEditMode((RecyclerView) parent);holder.tvBtnEdit.setText(R.string.edit);}}});return holder;case TYPE_MY:view = mInflater.inflate(R.layout.item_my, parent, false);final MyViewHolder myHolder = new MyViewHolder(view);myHolder.textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(final View v) {int position = myHolder.getAdapterPosition();if (isEditMode) {RecyclerView recyclerView = ((RecyclerView) parent);View targetView = recyclerView.getLayoutManager().findViewByPosition(mMyChannelItems.size() + COUNT_PRE_OTHER_HEADER);View currentView = recyclerView.getLayoutManager().findViewByPosition(position);// 如果targetView不在屏幕內,則indexOfChild為-1 此時不需要添加動畫,因為此時notifyItemMoved自帶一個向目標移動的動畫// 如果在屏幕內,則添加一個位移動畫if (recyclerView.indexOfChild(targetView) >= 0) {int targetX, targetY;RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();int spanCount = ((GridLayoutManager) manager).getSpanCount();// 移動后 高度將變化 (我的頻道Grid 最后一個item在新的一行第一個)if ((mMyChannelItems.size() - COUNT_PRE_MY_HEADER) % spanCount == 0) {View preTargetView = recyclerView.getLayoutManager().findViewByPosition(mMyChannelItems.size() + COUNT_PRE_OTHER_HEADER - 1);targetX = preTargetView.getLeft();targetY = preTargetView.getTop();} else {targetX = targetView.getLeft();targetY = targetView.getTop();}moveMyToOther(myHolder);startAnimation(recyclerView, currentView, targetX, targetY);} else {moveMyToOther(myHolder);}} else {mChannelItemClickListener.onItemClick(v, position - COUNT_PRE_MY_HEADER);}}});myHolder.textView.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(final View v) {if (!isEditMode) {RecyclerView recyclerView = ((RecyclerView) parent);startEditMode(recyclerView);// header 按鈕文字 改成 "完成"View view = recyclerView.getChildAt(0);if (view == recyclerView.getLayoutManager().findViewByPosition(0)) {TextView tvBtnEdit = (TextView) view.findViewById(R.id.tv_btn_edit);tvBtnEdit.setText(R.string.finish);}}mItemTouchHelper.startDrag(myHolder);return true;}});myHolder.textView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (isEditMode) {switch (MotionEventCompat.getActionMasked(event)) {case MotionEvent.ACTION_DOWN:startTime = System.currentTimeMillis();break;case MotionEvent.ACTION_MOVE:if (System.currentTimeMillis() - startTime > SPACE_TIME) {mItemTouchHelper.startDrag(myHolder);}break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:startTime = 0;break;}}return false;}});return myHolder;case TYPE_OTHER_CHANNEL_HEADER:view = mInflater.inflate(R.layout.item_other_channel_header, parent, false);return new RecyclerView.ViewHolder(view) {};case TYPE_OTHER:view = mInflater.inflate(R.layout.item_other, parent, false);final OtherViewHolder otherHolder = new OtherViewHolder(view);otherHolder.textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {RecyclerView recyclerView = ((RecyclerView) parent);RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();int currentPiosition = otherHolder.getAdapterPosition();// 如果RecyclerView滑動到底部,移動的目標位置的y軸 - heightView currentView = manager.findViewByPosition(currentPiosition);// 目標位置的前一個item 即當前MyChannel的最后一個View preTargetView = manager.findViewByPosition(mMyChannelItems.size() - 1 + COUNT_PRE_MY_HEADER);// 如果targetView不在屏幕內,則為-1 此時不需要添加動畫,因為此時notifyItemMoved自帶一個向目標移動的動畫// 如果在屏幕內,則添加一個位移動畫if (recyclerView.indexOfChild(preTargetView) >= 0) {int targetX = preTargetView.getLeft();int targetY = preTargetView.getTop();int targetPosition = mMyChannelItems.size() - 1 + COUNT_PRE_OTHER_HEADER;GridLayoutManager gridLayoutManager = ((GridLayoutManager) manager);int spanCount = gridLayoutManager.getSpanCount();// target 在最后一行第一個if ((targetPosition - COUNT_PRE_MY_HEADER) % spanCount == 0) {View targetView = manager.findViewByPosition(targetPosition);targetX = targetView.getLeft();targetY = targetView.getTop();} else {targetX += preTargetView.getWidth();// 最后一個item可見if (gridLayoutManager.findLastVisibleItemPosition() == getItemCount() - 1) {// 最后的item在最后一行第一個位置if ((getItemCount() - 1 - mMyChannelItems.size() - COUNT_PRE_OTHER_HEADER) % spanCount == 0) {// RecyclerView實際高度 > 屏幕高度 && RecyclerView實際高度 < 屏幕高度 + item.heightint firstVisiblePostion = gridLayoutManager.findFirstVisibleItemPosition();if (firstVisiblePostion == 0) {// FirstCompletelyVisibleItemPosition == 0 即 內容不滿一屏幕 , targetY值不需要變化// // FirstCompletelyVisibleItemPosition != 0 即 內容滿一屏幕 并且 可滑動 , targetY值 + firstItem.getTopif (gridLayoutManager.findFirstCompletelyVisibleItemPosition() != 0) {int offset = (-recyclerView.getChildAt(0).getTop()) - recyclerView.getPaddingTop();targetY += offset;}} else { // 在這種情況下 并且 RecyclerView高度變化時(即可見第一個item的 position != 0),// 移動后, targetY值 + 一個item的高度targetY += preTargetView.getHeight();}}} else {System.out.println("current--No");}}// 如果當前位置是otherChannel可見的最后一個// 并且 當前位置不在grid的第一個位置// 并且 目標位置不在grid的第一個位置// 則 需要延遲250秒 notifyItemMove , 這是因為這種情況 , 并不觸發ItemAnimator , 會直接刷新界面// 導致我們的位移動畫剛開始,就已經notify完畢,引起不同步問題if (currentPiosition == gridLayoutManager.findLastVisibleItemPosition()&& (currentPiosition - mMyChannelItems.size() - COUNT_PRE_OTHER_HEADER) % spanCount != 0&& (targetPosition - COUNT_PRE_MY_HEADER) % spanCount != 0) {moveOtherToMyWithDelay(otherHolder);} else {moveOtherToMy(otherHolder);}startAnimation(recyclerView, currentView, targetX, targetY);} else {moveOtherToMy(otherHolder);}}});return otherHolder;}return null;}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {if (holder instanceof MyViewHolder) {MyViewHolder myHolder = (MyViewHolder) holder;myHolder.textView.setText(mMyChannelItems.get(position - COUNT_PRE_MY_HEADER).getName());if (isEditMode) {myHolder.imgEdit.setVisibility(View.VISIBLE);} else {myHolder.imgEdit.setVisibility(View.INVISIBLE);}} else if (holder instanceof OtherViewHolder) {((OtherViewHolder) holder).textView.setText(mOtherChannelItems.get(position - mMyChannelItems.size() - COUNT_PRE_OTHER_HEADER).getName());} else if (holder instanceof MyChannelHeaderViewHolder) {MyChannelHeaderViewHolder headerHolder = (MyChannelHeaderViewHolder) holder;if (isEditMode) {headerHolder.tvBtnEdit.setText(R.string.finish);} else {headerHolder.tvBtnEdit.setText(R.string.edit);}}}@Overridepublic int getItemCount() {// 我的頻道 標題 + 我的頻道.size + 其他頻道 標題 + 其他頻道.sizereturn mMyChannelItems.size() + mOtherChannelItems.size() + COUNT_PRE_OTHER_HEADER;}/*** 開始增刪動畫*/private void startAnimation(RecyclerView recyclerView, final View currentView, float targetX, float targetY) {final ViewGroup viewGroup = (ViewGroup) recyclerView.getParent();final ImageView mirrorView = addMirrorView(viewGroup, recyclerView, currentView);Animation animation = getTranslateAnimator(targetX - currentView.getLeft(), targetY - currentView.getTop());currentView.setVisibility(View.INVISIBLE);mirrorView.startAnimation(animation);animation.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {viewGroup.removeView(mirrorView);if (currentView.getVisibility() == View.INVISIBLE) {currentView.setVisibility(View.VISIBLE);}}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/*** 我的頻道 移動到 其他頻道** @param myHolder*/private void moveMyToOther(MyViewHolder myHolder) {int position = myHolder.getAdapterPosition();int startPosition = position - COUNT_PRE_MY_HEADER;if (startPosition > mMyChannelItems.size() - 1) {return;}ChannelEntity item = mMyChannelItems.get(startPosition);mMyChannelItems.remove(startPosition);mOtherChannelItems.add(0, item);notifyItemMoved(position, mMyChannelItems.size() + COUNT_PRE_OTHER_HEADER);}/*** 其他頻道 移動到 我的頻道** @param otherHolder*/private void moveOtherToMy(OtherViewHolder otherHolder) {int position = processItemRemoveAdd(otherHolder);if (position == -1) {return;}notifyItemMoved(position, mMyChannelItems.size() - 1 + COUNT_PRE_MY_HEADER);}/*** 其他頻道 移動到 我的頻道 伴隨延遲** @param otherHolder*/private void moveOtherToMyWithDelay(OtherViewHolder otherHolder) {final int position = processItemRemoveAdd(otherHolder);if (position == -1) {return;}delayHandler.postDelayed(new Runnable() {@Overridepublic void run() {notifyItemMoved(position, mMyChannelItems.size() - 1 + COUNT_PRE_MY_HEADER);}}, ANIM_TIME);}private Handler delayHandler = new Handler();private int processItemRemoveAdd(OtherViewHolder otherHolder) {int position = otherHolder.getAdapterPosition();int startPosition = position - mMyChannelItems.size() - COUNT_PRE_OTHER_HEADER;if (startPosition > mOtherChannelItems.size() - 1) {return -1;}ChannelEntity item = mOtherChannelItems.get(startPosition);mOtherChannelItems.remove(startPosition);mMyChannelItems.add(item);return position;}/*** 添加需要移動的 鏡像View*/private ImageView addMirrorView(ViewGroup parent, RecyclerView recyclerView, View view) {/*** 我們要獲取cache首先要通過setDrawingCacheEnable方法開啟cache,然后再調用getDrawingCache方法就可以獲得view的cache圖片了。buildDrawingCache方法可以不用調用,因為調用getDrawingCache方法時,若果cache沒有建立,系統會自動調用buildDrawingCache方法生成cache。若想更新cache, 必須要調用destoryDrawingCache方法把舊的cache銷毀,才能建立新的。當調用setDrawingCacheEnabled方法設置為false, 系統也會自動把原來的cache銷毀。*/view.destroyDrawingCache();view.setDrawingCacheEnabled(true);final ImageView mirrorView = new ImageView(recyclerView.getContext());Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());mirrorView.setImageBitmap(bitmap);view.setDrawingCacheEnabled(false);int[] locations = new int[2];view.getLocationOnScreen(locations);int[] parenLocations = new int[2];recyclerView.getLocationOnScreen(parenLocations);FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(bitmap.getWidth(), bitmap.getHeight());params.setMargins(locations[0], locations[1] - parenLocations[1], 0, 0);parent.addView(mirrorView, params);return mirrorView;}@Overridepublic void onItemMove(int fromPosition, int toPosition) {ChannelEntity item = mMyChannelItems.get(fromPosition - COUNT_PRE_MY_HEADER);mMyChannelItems.remove(fromPosition - COUNT_PRE_MY_HEADER);mMyChannelItems.add(toPosition - COUNT_PRE_MY_HEADER, item);notifyItemMoved(fromPosition, toPosition);}/*** 開啟編輯模式** @param parent*/private void startEditMode(RecyclerView parent) {isEditMode = true;int visibleChildCount = parent.getChildCount();for (int i = 0; i < visibleChildCount; i++) {View view = parent.getChildAt(i);ImageView imgEdit = (ImageView) view.findViewById(R.id.img_edit);if (imgEdit != null) {imgEdit.setVisibility(View.VISIBLE);}}}/*** 完成編輯模式** @param parent*/private void cancelEditMode(RecyclerView parent) {isEditMode = false;int visibleChildCount = parent.getChildCount();for (int i = 0; i < visibleChildCount; i++) {View view = parent.getChildAt(i);ImageView imgEdit = (ImageView) view.findViewById(R.id.img_edit);if (imgEdit != null) {imgEdit.setVisibility(View.INVISIBLE);}}}/*** 獲取位移動畫*/private TranslateAnimation getTranslateAnimator(float targetX, float targetY) {TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,Animation.ABSOLUTE, targetX,Animation.RELATIVE_TO_SELF, 0f,Animation.ABSOLUTE, targetY);// RecyclerView默認移動動畫250ms 這里設置360ms 是為了防止在位移動畫結束后 remove(view)過早 導致閃爍translateAnimation.setDuration(ANIM_TIME);translateAnimation.setFillAfter(true);return translateAnimation;}interface OnMyChannelItemClickListener {void onItemClick(View v, int position);}public void setOnMyChannelItemClickListener(OnMyChannelItemClickListener listener) {this.mChannelItemClickListener = listener;}/*** 我的頻道*/class MyViewHolder extends RecyclerView.ViewHolder implements OnDragVHListener {private TextView textView;private ImageView imgEdit;public MyViewHolder(View itemView) {super(itemView);textView = (TextView) itemView.findViewById(R.id.tv);imgEdit = (ImageView) itemView.findViewById(R.id.img_edit);}/*** item 被選中時*/@Overridepublic void onItemSelected() {textView.setBackgroundResource(R.drawable.bg_channel_p);}/*** item 取消選中時*/@Overridepublic void onItemFinish() {textView.setBackgroundResource(R.drawable.bg_channel);}}/*** 其他頻道*/class OtherViewHolder extends RecyclerView.ViewHolder {private TextView textView;public OtherViewHolder(View itemView) {super(itemView);textView = (TextView) itemView.findViewById(R.id.tv);}}/*** 我的頻道 標題部分*/class MyChannelHeaderViewHolder extends RecyclerView.ViewHolder {private TextView tvBtnEdit;public MyChannelHeaderViewHolder(View itemView) {super(itemView);tvBtnEdit = (TextView) itemView.findViewById(R.id.tv_btn_edit);}} } /*** 頻道實體類* Created by YoKeyword on 15/12/29.*/ public class ChannelEntity {private long id;private String name;public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;} }item_my_channel_header.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="48dp"><TextView android:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="16dp"android:text="@string/my_cahnnel"android:textSize="16sp"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@id/tv"android:layout_marginLeft="16dp"android:layout_toRightOf="@id/tv"android:text="@string/tip_drag"android:textColor="@color/tip"android:textSize="12sp"/><TextView android:id="@+id/tv_btn_edit"android:layout_width="56dp"android:layout_height="30dp"android:layout_centerVertical="true"android:layout_alignParentRight="true"android:layout_marginRight="8dp"android:gravity="center"android:textSize="13sp"android:background="@drawable/bg_btn"android:textColor="@color/red_500"android:text="@string/edit"/><View android:layout_width="match_parent"android:layout_height="0.3dp"android:layout_alignParentBottom="true"android:background="@color/tip"/> </RelativeLayout>item_other_channel_header.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="48dp"><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/other_channel"android:layout_centerVertical="true"android:layout_marginLeft="16dp"android:textSize="16sp"/><View android:layout_width="match_parent"android:layout_height="0.3dp"android:layout_alignParentBottom="true"android:background="@color/tip"/> </RelativeLayout>item_my.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"><TextView android:id="@+id/tv"android:layout_width="match_parent"android:layout_height="36dp"android:layout_margin="8dp"android:background="@drawable/bg_channel"android:foreground="?attr/selectableItemBackground"android:layout_centerInParent="true"android:gravity="center"/><ImageView android:id="@+id/img_edit"android:layout_alignParentRight="true"android:layout_width="16dp"android:layout_height="16dp"android:src="@mipmap/ic_channel_edit"/></RelativeLayout>item_other.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"><TextView android:id="@+id/tv"android:layout_width="match_parent"android:layout_height="36dp"android:layout_margin="8dp"android:background="@drawable/bg_channel"android:foreground="?attr/selectableItemBackground"android:layout_centerInParent="true"android:gravity="center"/><ImageView android:id="@+id/img_edit"android:layout_alignParentRight="true"android:layout_width="16dp"android:visibility="invisible"android:layout_height="16dp"/></RelativeLayout>activity_demo.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v7.widget.RecyclerView android:id="@+id/recy"android:padding="8dp"android:clipChildren="false"android:clipToPadding="false"android:layout_width="match_parent"android:layout_height="match_parent"/> </FrameLayout>新聞閱讀器頻道管理
總結
以上是生活随笔為你收集整理的RecyclerView ItemTouchHelper的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android:clipToPaddin
- 下一篇: ViewPager刷新问题详解