一、效果图
二、实现步骤
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>
来源:CSDN
作者:司城
链接:https://blog.csdn.net/Kate_sicheng/article/details/77601153