RecyclerView 左滑(仿QQ左滑删除)

来源:互联网 发布:为知笔记导出 苹果 编辑:程序博客网 时间:2024/05/07 19:10

一、效果图

这里写图片描述

这里写图片描述

二、实现步骤

1.添加依赖库

(Android/Gradle Scripts/build.gradle(Module:app))

compile 'com.android.support:recyclerview-v7:26.+'/*     版本号与 compile 'com.android.support:appcompat-v7:26.+',此句版本号为26.+      */

2.RecyclerView布局

(activity_main.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="match_parent">    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerview"        android:background="#EEEEEE"        android:scrollbars="vertical"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical"        android:overScrollMode="never" /></RelativeLayout>

3.设置颜色选择器

(orange_background.xml)

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_pressed="true">        <layer-list >            <item >                <shape >                    <solid android:color="#f49405"/>                </shape>            </item>            <item >                <shape >                    <solid android:color="#22000000"/>                </shape>            </item>        </layer-list>    </item>    <item >        <shape >            <solid android:color="#f49405"/>        </shape>    </item></selector>

(app/res/drawable/pink_background.xml)

<?xml version="1.0" encoding="utf-8"?><!--颜色选择器--><selector xmlns:android="http://schemas.android.com/apk/res/android">    <!--按定“删除”按钮时该按钮显示的颜色:红色-->    <item android:state_pressed="true">        <layer-list >            <item >                <shape >                    <solid android:color="#FF0000"/>                </shape>            </item>            <item >                <shape >                    <solid android:color="#22000000"/>                </shape>            </item>        </layer-list>    </item>    <!--“删除”按钮直接看上去的颜色:粉红色-->    <item >        <shape >            <!--solid 实心,即填充-->            <solid android:color="#ff0080"/>        </shape>    </item></selector>

(app/res/drawable/white_background.xml)

<?xml version="1.0" encoding="utf-8"?><!--selector 颜色选择器--><selector xmlns:android="http://schemas.android.com/apk/res/android">    <!-- state_pressed="true/false"点击。true 表示点击状态下使用,false表示非点击状态下使用。-->    <item android:state_pressed="true">        <layer-list >            <item >                <shape >                    <solid android:color="@android:color/white"/>                </shape>            </item>            <item >                <shape >                    <!--solid 实心,即填充-->                    <solid android:color="#22000000"/>                </shape>            </item>        </layer-list>    </item>    <item >        <shape >            <solid android:color="@android:color/white"/>        </shape>    </item></selector>

4.item布局

(layout_item.xml)

<?xml version="1.0" encoding="utf-8"?><!--item布局,自定义View--><com.example.textdemo.LeftSlideView xmlns:android="http://schemas.android.com/apk/res/android"                                              android:layout_width="match_parent"                                              android:layout_height="100dp"                                              android:background="@android:color/white"                                              android:layout_marginBottom="1dp">    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        >        <!--"设置","删除"按钮使用了TextView而不是Button,是因为5.0以上版本使用Button会显示在上层产出错误显示-->        <TextView            android:id="@+id/tv_set"            android:layout_height="106dp"            android:layout_width="80dp"            android:gravity="center"            android:layout_toRightOf="@+id/layout_content"            android:text="设置"            android:textSize="25dp"            android:background="@drawable/orange_background"            android:textColor="#DDFFFFFF"            />        <TextView            android:id="@+id/tv_delete"            android:layout_height="match_parent"            android:layout_width="80dp"            android:gravity="center"            android:layout_toRightOf="@+id/tv_set"            android:text="删 除"            android:textSize="25dp"            android:background="@drawable/pink_background"            android:textColor="#DDFFFFFF"            />        <RelativeLayout            android:id="@+id/layout_content"            android:layout_width="match_parent"            android:layout_height="match_parent">            <TextView                android:id="@+id/text"                android:layout_height="match_parent"                android:layout_width="match_parent"                android:textSize="50dp"                android:textColor="#dde65b05"                android:background="@drawable/white_background"                />        </RelativeLayout>    </RelativeLayout></com.example.textdemo.LeftSlideView>

5.自定义View

(LeftSlideView.java)

/*** 自定义View,继承水平滚动条*/public class LeftSlideView extends HorizontalScrollView {    private TextView mTextView_Set;//设置按钮    private TextView mTextView_Delete;//删除按钮    private int mScrollWidth;//记录滚动条可以滚动的距离    private Boolean once = false;//在onMeasure中只执行一次的判断    private Boolean isOpen = false;//记录按钮菜单是否打开,默认关闭false    private IonSlidingButtonListener mIonSlidingButtonListener;//自定义的接口,用于传达滑动事件等    /**    * 1.构造方法    */    public LeftSlideView(Context context) {        super(context, null);    }    public LeftSlideView(Context context, AttributeSet attrs) {        super(context, attrs, 0);    }    public LeftSlideView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.setOverScrollMode(OVER_SCROLL_NEVER);    }    //2.在onMeasure中先取得作为“设置”、“删除”按钮的TextView    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        if (!once) {            mTextView_Delete = (TextView) findViewById(com.example.textdemo.R.id.tv_delete);            mTextView_Set = (TextView) findViewById(com.example.textdemo.R.id.tv_set);            once = true;        }    }    //3.在onLayout中使Item在每次变更布局大小时回到初始位置,并且获取滚动条的可移动距离    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        if (changed) {            this.scrollTo(0, 0);            //获取水平滚动条可以滑动的范围,即右侧“设置”、“删除”按钮的总宽度            mScrollWidth = mTextView_Delete.getWidth() + mTextView_Set.getWidth();        }    }    //4.滑动监听,按滑动的距离大小控制菜单开关    @Override    public boolean onTouchEvent(MotionEvent ev) {        int action = ev.getAction();        switch (action) {            case MotionEvent.ACTION_DOWN://按下            case MotionEvent.ACTION_MOVE://移动                mIonSlidingButtonListener.onDownOrMove(this);                break;            case MotionEvent.ACTION_UP://松开            case MotionEvent.ACTION_CANCEL:                changeScrollx();                return true;            default:                break;        }        return super.onTouchEvent(ev);    }    /**    * 5.    * @param l    * @param t    * @param oldl    * @param oldt    */    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        //改变view的在x轴方向的位置        mTextView_Set.setTranslationX(1);    }    /**    * 6.按滚动条被拖动距离判断关闭或打开菜单    * getScrollX()                view的左上角相对于母视图的左上角的X轴偏移量    * smoothScrollTo(x, y);        参数:相对于ScrollView左上角的位置来说,你要移动的位置    */    public void changeScrollx() {        if (getScrollX() >= (mScrollWidth / 2)) {            this.smoothScrollTo(mScrollWidth, 0);            isOpen = true;            mIonSlidingButtonListener.onMenuIsOpen(this);        } else {            this.smoothScrollTo(0, 0);            isOpen = false;        }    }    /**    * 7.打开菜单    */    public void openMenu() {        if (isOpen) {            return;        }        this.smoothScrollTo(mScrollWidth, 0);//相对于原来没有滑动的位置x轴方向偏移了mScrollWidth,y轴方向没有变化。        isOpen = true;        mIonSlidingButtonListener.onMenuIsOpen(this);    }    /**    * 8.关闭菜单    */    public void closeMenu() {        if (!isOpen) {            return;        }        this.smoothScrollTo(0, 0);//相对于原来没有滑动的位置,x轴方向、y轴方向都没有变化,即回到原来的位置了。        isOpen = false;    }    /**    * 9.接口定义及注册方法    */    public void setSlidingButtonListener(IonSlidingButtonListener listener) {        mIonSlidingButtonListener = listener;    }    public interface IonSlidingButtonListener {        //该方法在Adapter中实现        void onMenuIsOpen(View view);//判断菜单是否打开        void onDownOrMove(LeftSlideView leftSlideView);//滑动或者点击了Item监听    }}

6.设置内容布局的宽为屏幕宽度的工具类

(Utils.java)

public class Utils {    public static int dp2px(Context context, float dp)    {        return (int ) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());    }    /**    * 获得屏幕宽度    *    * @param context    * @return    */    public static int getScreenWidth(Context context)    {        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE );        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics( outMetrics);        return outMetrics .widthPixels ;    }}

7.适配器Adapter

(Adapter.java)

public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> implements LeftSlideView.IonSlidingButtonListener {    private Context mContext;    private List<String> mDatas = new ArrayList<String>();    private IonSlidingViewClickListener mIDeleteBtnClickListener;    private IonSlidingViewClickListener mISetBtnClickListener;    private LeftSlideView mMenu = null;    public Adapter(Context context) {        mContext = context;        mIDeleteBtnClickListener = (IonSlidingViewClickListener) context;        mISetBtnClickListener = (IonSlidingViewClickListener) context;        for (int i = 0; i < 10; i++) {            mDatas.add(i + "");        }    }    @Override    public int getItemCount() {        return mDatas.size();    }    @Override    public void onBindViewHolder(final MyViewHolder holder, int position) {        holder.textView.setText(mDatas.get(position));        //设置内容布局的宽为屏幕宽度        holder.layout_content.getLayoutParams().width = Utils.getScreenWidth(mContext);        //item正文点击事件        holder.textView.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否有删除菜单打开                if (menuIsOpen()) {                    closeMenu();//关闭菜单                } else {                    int n = holder.getLayoutPosition();                    mIDeleteBtnClickListener.onItemClick(v, n);                }            }        });        //左滑设置点击事件        holder.btn_Set.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View view) {                int n = holder.getLayoutPosition();                mISetBtnClickListener.onSetBtnCilck(view, n);            }        });        //左滑删除点击事件        holder.btn_Delete.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View view) {                int n = holder.getLayoutPosition();                mIDeleteBtnClickListener.onDeleteBtnCilck(view, n);            }        });    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) {        //获取自定义View的布局(加载item布局)        View view = LayoutInflater.from(mContext).inflate(R.layout.layout_item, arg0, false);        MyViewHolder holder = new MyViewHolder(view);        return holder;    }    class MyViewHolder extends RecyclerView.ViewHolder {        public TextView btn_Set;        public TextView btn_Delete;        public TextView textView;        public ViewGroup layout_content;        public MyViewHolder(View itemView) {            super(itemView);            btn_Set = (TextView) itemView.findViewById(R.id.tv_set);            btn_Delete = (TextView) itemView.findViewById(R.id.tv_delete);            textView = (TextView) itemView.findViewById(R.id.text);            layout_content = (ViewGroup) itemView.findViewById(R.id.layout_content);            ((LeftSlideView) itemView).setSlidingButtonListener(Adapter.this);        }    }    /**    * 删除item    * @param position    */    public void removeData(int position) {        mDatas.remove(position);        notifyItemRemoved(position);    }    /**    * 删除菜单打开信息接收    */    @Override    public void onMenuIsOpen(View view) {        mMenu = (LeftSlideView) view;    }    /**    * 滑动或者点击了Item监听    *    * @param leftSlideView    */    @Override    public void onDownOrMove(LeftSlideView leftSlideView) {        if (menuIsOpen()) {            if (mMenu != leftSlideView) {                closeMenu();            }        }    }    /**    * 关闭菜单    */    public void closeMenu() {        mMenu.closeMenu();        mMenu = null;    }    /**    * 判断菜单是否打开    *    * @return    */    public Boolean menuIsOpen() {        if (mMenu != null) {            return true;        }        return false;    }    /**    * 注册接口的方法:点击事件。在Mactivity.java实现这些方法。    */    public interface IonSlidingViewClickListener {        void onItemClick(View view, int position);//点击item正文        void onDeleteBtnCilck(View view, int position);//点击“删除”        void onSetBtnCilck(View view, int position);//点击“设置”    }}

8.MainActivity.java

public class MainActivity extends AppCompatActivity implements Adapter.IonSlidingViewClickListener {    private RecyclerView mRecyclerView;    private Adapter mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(com.example.textdemo.R.layout.activity_main);        mRecyclerView = (RecyclerView) findViewById(com.example.textdemo.R.id.recyclerview);        //设置布局管理器        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));//设置布局管理器        mRecyclerView.setAdapter(mAdapter = new Adapter(this));//设置适配器        mRecyclerView.setItemAnimator(new DefaultItemAnimator());//设置控制Item增删的动画    }    /**    * item正文的点击事件    *    * @param view    * @param position    */    @Override    public void onItemClick(View view, int position) {        //点击item正文的代码逻辑    }    /**    * item的左滑设置    *    * @param view    * @param position    */    @Override    public void onSetBtnCilck(View view, int position) {        //“设置”点击事件的代码逻辑        Toast.makeText(MainActivity.this, "请设置", Toast.LENGTH_LONG).show();    }    /**    * item的左滑删除    *    * @param view    * @param position    */    @Override    public void onDeleteBtnCilck(View view, int position) {        mAdapter.removeData(position);    }}

9.屏蔽多点触控,否则左滑时可以同时左滑多条item。

(app/res/values/styles.xml)

<resources>    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">        <item name="android:windowEnableSplitTouch" >false </item>        <item name="android:splitMotionEvents" >false </item>    </style></resources>
原创粉丝点击