最近做新闻类型的项目,用到了频道管理,点击删除排序,拖动排序。来分享一下

下面上代码:

MainActivity 布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="soexample.umeng.com.myapplication.MainActivity"android:orientation="vertical"><FrameLayout
        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>
</LinearLayout>

MainActivity 中的代码:

/***   频道 增删改查 排序*/
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);showDialog();}private RecyclerView mRecy;private ChannelAdapter adapter;private Dialog dialog;//对话框public void showDialog() {if (dialog == null) {dialog = new Dialog(MainActivity.this, R.style.custom_dialog);dialog.setCanceledOnTouchOutside(true);//获取对话框的窗口,并设置窗口参数Window win = dialog.getWindow();WindowManager.LayoutParams params = new WindowManager.LayoutParams();// 不能写成这样,否则Dialog显示不出来// LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);//对话框窗口的宽和高params.width = WindowManager.LayoutParams.MATCH_PARENT;params.height = WindowManager.LayoutParams.MATCH_PARENT;//对话框窗口显示的位置params.x = 120;params.y = 590;win.setAttributes(params);//设置对话框布局dialog.setContentView(R.layout.activity_channel);mRecy = (RecyclerView)dialog.findViewById(R.id.recy);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);adapter = new ChannelAdapter(MainActivity.this, helper, items, otherItems,dialog);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(MainActivity.this, items.get(position).getName(), Toast.LENGTH_SHORT).show();}});}dialog.show();}/*** 隐藏对话框*/public void dismiss() {//隐藏对话框之前先判断对话框是否存在,以及是否正在显示if (dialog != null && dialog.isShowing()) {dialog.dismiss();}}
}

下面是关键:

适配器:

/*** 拖拽排序 + 增删**/
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;private  OnMyChannelItemC mChannelItemC  ;private Dialog dialog;//对话框private boolean flag=false;private Context context;public ChannelAdapter(Context context, ItemTouchHelper helper, List<ChannelEntity> mMyChannelItems, List<ChannelEntity> mOtherChannelItems,Dialog dialog) {this.mInflater = LayoutInflater.from(context);this.mItemTouchHelper = helper;this.mMyChannelItems = mMyChannelItems;this.mOtherChannelItems = mOtherChannelItems;this.dialog=dialog;this.context=context;}@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;}}/*** 获取频道列表  已选的*/public List<ChannelEntity> getChannnelLst() {return mMyChannelItems;}/*** 获取频道列表  未选的*/public List<ChannelEntity> getChannnelLstother() {return mOtherChannelItems;}View view;@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {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);}}});holder.llback.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//隐藏对话框之前先判断对话框是否存在,以及是否正在显示if (dialog != null && dialog.isShowing()) {dialog.dismiss();/***   如果没有点击完成,默认切换*/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) {//是否需要保存flag = true;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, recyclerView, currentView, targetX, targetY);//                                startAnimation(recyclerView, currentView, targetX, targetY);Log.e(" 已选   1", "/*/*/*******************************");} else {Log.e(" 已选   2", "/*/*/*******************************");moveMyToOther(myHolder, recyclerView, currentView, 0, 0);}//
//                            mChannelItemC.onItemClick(v, position - COUNT_PRE_MY_HEADER, flag);} else { 我的频道之前的header数量  该demo中 即标题部分 为 1   COUNT_PRE_MY_HEADERmChannelItemClickListener.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);}} else//是否需要保存flag = true;int position = myHolder.getAdapterPosition();/*** 处理第一个和第二个不可以拖动*/if (position != 1 && position != 2) {mItemTouchHelper.startDrag(myHolder);}
//                            mChannelItemC.onItemClick(v, position - COUNT_PRE_MY_HEADER, flag);return true;}});myHolder.textView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {int position = myHolder.getAdapterPosition();if (isEditMode) {switch (MotionEventCompat.getActionMasked(event)) {case MotionEvent.ACTION_DOWN:startTime = System.currentTimeMillis();break;case MotionEvent.ACTION_MOVE:if (System.currentTimeMillis() - startTime > SPACE_TIME) {/*** 处理第一个和第二个不可以拖动*/if (position!=1&&position!=2){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) {//是否需要保存flag=true;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);Log.e("1","/*/*/*******************************");} else {moveOtherToMy(otherHolder);Log.e("2","/*/*/*******************************");}startAnimation(recyclerView, currentView, targetX, targetY);} else {Log.e("3","/*/*/*******************************");moveOtherToMy(otherHolder);}
//                        mChannelItemC.onItemClick(v,currentPiosition - COUNT_PRE_MY_HEADER,flag);}});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,RecyclerView recyclerView,View currentView,int targetX,int targetY) {int position = myHolder.getAdapterPosition();int startPosition = position - COUNT_PRE_MY_HEADER;if (startPosition > mMyChannelItems.size() - 1) {return;}else if (startPosition==0||startPosition==1){//  第一个条目和第二个条目不移动}else {// 是否为 编辑 模式if (isEditMode) {ChannelEntity item = mMyChannelItems.get(startPosition);mMyChannelItems.remove(startPosition);mOtherChannelItems.add(0, item);notifyItemMoved(position, mMyChannelItems.size() + COUNT_PRE_OTHER_HEADER);startAnimation( recyclerView, currentView, targetX, targetY);}else {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;}/***   移动过程中更新适配器********************************************************* 处理移动后的数据 ********************************************************************* @param fromPosition* @param toPosition*/@Overridepublic void onItemMove(int fromPosition, int toPosition) {if (toPosition==1||toPosition==2){return;}Log.e("fromPosition",fromPosition+"/****************************");Log.e("toPosition",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);//是否需要保存flag=true;
//        mChannelItemC.onItemClick(view,toPosition - COUNT_PRE_MY_HEADER,flag);}/*** 开启编辑模式   默认第一条和第二条不显示可编辑** @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) {if (i==1||i==2){imgEdit.setVisibility(View.GONE);}else {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;}/***  接口回调*/public interface OnMyChannelItemClickListener {void onItemClick(View v, int position);}public void setOnMyChannelItemClickListener(OnMyChannelItemClickListener listener) {this.mChannelItemClickListener = listener;}public interface OnMyChannelItemC {void onItemClick(View v, int position,boolean a);}public void setOnMyChannelItemC(OnMyChannelItemC listener) {this.mChannelItemC = 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;LinearLayout llback;public MyChannelHeaderViewHolder(View itemView) {super(itemView);tvBtnEdit = (TextView) itemView.findViewById(R.id.tv_btn_edit);llback= (LinearLayout) itemView.findViewById(R.id.ll_back);}}}

上面提供了 排序后获取数据的方法:

/*** 获取频道列表  已选的*/public List<ChannelEntity> getChannnelLst() {return mMyChannelItems;}/*** 获取频道列表  未选的*/public List<ChannelEntity> getChannnelLstother() {return mOtherChannelItems;}

一个关键的帮助类 ItemTouchHelper:

/*** ItemDragHelperCallback**/
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;}
}

好了 关键的代码都贴出来了,想要完成代码看下面

源码在这里

Android 仿今日头条、网易新闻的频道管理相关推荐

  1. Android 仿今日头条频道管理(下)(GridView之间Item的移动和拖拽)

    前言 上篇博客我们说到了今日头条频道管理的操作交互体验,我也介绍了2个GridView之间Item的相互移动.详情请參考:Android 仿今日头条频道管理(上)(GridView之间Item的移动和 ...

  2. 转载 Android仿今日头条详情页实现

    转载自@ice_Anson Android仿今日头条详情页实现 源码地址: Android仿今日头条详情页实现 github源码地址 动态图 最近项目有个需求,需要实现一个和今日头条新闻详情页一样的体 ...

  3. android仿今日头条个人中心页面

    android仿今日头条个人中心页面 效果图 实现步骤: 自定义ScrollView,添加一个反弹的动画 代码: package com.example.administrator.gerenzhon ...

  4. iOS仿今日头条顶部新闻分页

    仿今日头条顶部新闻分页 近日闲来无事总是刷头条,突然发现了一个有趣的现象,如下图: 当你滑动或者点击分页的名字的时候,不管当时那个分页在哪,最后都会被滚动到最中间.我又去翻了其他的资讯类的app,发现 ...

  5. Android 仿今日头条首页标题栏效果

    今天带来的是仿今日头条首页的联动滑动效果,废话不多说,先上效果图: 思路: 做这个我们需要实现的效果有 1.滑动内容区域,标题栏会有变化来显示当前所处的位置. 2.点击标题栏,内容区域也会随着滑动并跳 ...

  6. android 今日头条加载动画,Android 仿今日头条简单的刷新效果实例代码

    点击按钮,先自动进行下拉刷新,也可以手动刷新,刷新完后,最后就多一行数据.有四个选项卡. 前两天导师要求做一个给本科学生预定机房座位的app,出发点来自这里.做着做着遇到很多问题,都解决了.这个效果感 ...

  7. Android 仿今日头条评论时键盘自动弹出的效果

    Android 仿今日头条评论时键盘自动弹出的效果:当点击评论时,弹出对话框,同时弹出软键盘,当点击返回键时,将对话框关闭,不只是关闭软键盘. 效果图: 对这个对话框设置一个style效果: < ...

  8. Android仿今日头条首页的顶部标签栏和底部导航栏

    Android仿今日头条首页的顶部标签栏和底部导航栏 先是底部导航栏TextView+ImageView+Fragment: 效果图: activity_main.xml布局: <?xml ve ...

  9. Android仿今日头条的开源项目

    起因 看到众多大神纷纷有了自己的开源项目,于是自己琢磨着也想做一个开源项目来学习下,因为每次无聊必刷的app就是今日头条,评论简直比内容都精彩,所以我打算仿今日头条来练练手,期间也曾放弃过,也遇到很多 ...

  10. Android仿今日头条开源项目

    起因 看到众多大神纷纷有了自己的开源项目,于是自己琢磨着也想做一个开源项目来学习下,因为每次无聊必刷的app就是今日头条,评论简直比内容都精彩,所以我打算仿今日头条来练练手,期间也曾放弃过,也遇到很多 ...

最新文章

  1. 读书笔记 | 墨菲定律(一)
  2. zephir开发的扩展“wudimei框架”之数据库使用方法
  3. VPN之DSVPN的介绍
  4. Linux磁盘分区了解多少?Linux入门必看
  5. python数据结构与算法之排序
  6. Java程序在命令行的编译运行
  7. 一块电路板从“出生”到“成年”
  8. PHP的Smarty较为完整的笔记
  9. webdriver鼠标上下滑动
  10. python数据按照分组进行频率分布_python实现读取类别频数数据画水平条形图
  11. 2017-2018-1 20155201 20155313 实验一 开发环境的熟悉
  12. 间通过蓝牙模块建立通讯_拥抱蓝牙mesh,幻腾用“互联”深化智能
  13. Oracle 单实例数据库安装和real application clusters数据库安装的区别
  14. python语言是二进制语言吗_在大型项目上,Python 是个烂语言吗?
  15. 新能源车提车、上牌流程
  16. Linux 7 提示 -bash: ifconfig: command not found
  17. mysql sql宽字节注入_sql注入之(宽字节注入篇)
  18. 委托(C# 编程指南)
  19. (转载)基于TDOA声源定位算法仿真–MATLAB仿真
  20. 你的产品适不适合做微信小程序?你需要这篇产品逻辑分析

热门文章

  1. 区块链调研备份8.1
  2. (二十五)各向同性张量(函数)
  3. TortoiseSVN patch 创建并应用补丁
  4. 2411681-87-1,Thalidomide-O-PEG4-t-butyl ester化学式:C28H38N2O11
  5. 数据分析 - 9.MECE法(学习笔记)
  6. OpenGL制作简易地图(二)
  7. [SSM框架]—Mybatis入门
  8. Java 创建带有套接字的简单代理服务器示例
  9. scrapy 简单教程
  10. ESP32编译运行ADF音频库