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

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

这里写图片描述

下面上代码:

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 {


    @Override
    protected 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() {
                @Override
                public 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() {
                @Override
                public 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中 即标题部分 为 1
    private static final int COUNT_PRE_MY_HEADER = 1;
    // 其他频道之前的header数量  该demo中 即标题部分 为 COUNT_PRE_MY_HEADER + 1
    private 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;
    }

    @Override
    public 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;
    @Override
    public 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() {
                    @Override
                    public 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() {
                    @Override
                    public 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() {
                    @Override
                    public 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_HEADER
                            mChannelItemClickListener.onItemClick(v, position - COUNT_PRE_MY_HEADER);
                        }
                    }
                });


                /**
                 *    长按*******************
                 */


                    myHolder.textView.setOnLongClickListener(new View.OnLongClickListener() {
                        @Override
                        public 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() {
                        @Override
                        public 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() {
                    @Override
                    public void onClick(View v) {
                        //是否需要保存
                        flag=true;
                        RecyclerView recyclerView = ((RecyclerView) parent);
                        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
                        int currentPiosition = otherHolder.getAdapterPosition();
                        // 如果RecyclerView滑动到底部,移动的目标位置的y轴 - height
                        View 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.height
                                        int firstVisiblePostion = gridLayoutManager.findFirstVisibleItemPosition();
                                        if (firstVisiblePostion == 0) {
                                            // FirstCompletelyVisibleItemPosition == 0 即 内容不满一屏幕 , targetY值不需要变化
                                            // // FirstCompletelyVisibleItemPosition != 0 即 内容满一屏幕 并且 可滑动 , targetY值 + firstItem.getTop
                                            if (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;
    }

    @Override
    public 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);
            }
        }
    }

    @Override
    public int getItemCount() {
        // 我的频道  标题 + 我的频道.size + 其他频道 标题 + 其他频道.size
        return 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() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                viewGroup.removeView(mirrorView);
                if (currentView.getVisibility() == View.INVISIBLE) {
                    currentView.setVisibility(View.VISIBLE);
                }
            }

            @Override
            public 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() {
            @Override
            public 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
     */
    @Override
    public 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 被选中时
         */
        @Override
        public void onItemSelected() {
            textView.setBackgroundResource(R.drawable.bg_channel_p);
        }

        /**
         * item 取消选中时
         */
        @Override
        public 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 {

    @Override
    public 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.END
        int swipeFlags = 0;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public 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;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

    }

    @Override
    public 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);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        if (viewHolder instanceof OnDragVHListener) {
            OnDragVHListener itemViewHolder = (OnDragVHListener) viewHolder;
            itemViewHolder.onItemFinish();
        }
        super.clearView(recyclerView, viewHolder);
    }

    @Override
    public boolean isLongPressDragEnabled() {
        // 不支持长按拖拽功能 手动控制
        return false;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        // 不支持滑动功能
        return false;
    }
}

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

源码在这里

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
PHP Android仿今日头条是指使用PHP和Android编程语言来开发一个类似今日头条的应用程序。 在这个应用程序中,PHP被用于后端开发,处理数据的存储和管理,以及与数据库的交互。PHP可以使用各种框架和技术来实现这些功能,如Laravel、Symfony或CodeIgniter等。通过PHP,可以实现用户账户的管理、文章的发布和编辑、分类和标签管理功能。 而Android则被用于前端开发,用于创建用户界面和处理用户的交互。Android提供了丰富的界面组件和功能,可以实现今日头条类似新闻列表、详情页、评论等功能。通过Android的网络请求功能,可以与后端的PHP接口进行交互,获取数据并展示给用户。 实现这个仿今日头条的应用程序,需要前后端的协同工作。后端通过PHP处理数据的增删改查功能,并提供API接口给前端调用。前端使用Android开发界面和功能,并通过网络请求获取后端的数据进行展示。 在实现过程中,需要注意数据的安全性和用户体验。合理设计数据库表结构,使用合适的框架和技术来处理数据的验证和过滤,防止恶意攻击和非法访问。同时,需要优化页面加载速度,提供流畅的用户体验。 总结来说,PHP Android仿今日头条的开发涉及到后端数据的管理处理,以及前端用户界面的实现和交互。通过合理的架构和技术选型,能够实现一个功能完善、安全可靠的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值