网上有很多关于侧面滑动菜单的代码和文章,有的包含了很多功能,有的比较简单但是用起来有很多限制,修改起来比较坑多。
这里我写了一个最简版的侧面滑动功能,实现了主要的左滑菜单功能。
效果图
一、添加自定义属性:
在values 中创建 attrs.xml 文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyRecyclerViewItem">
<attr name="left_width" format="integer"/>
<attr name="right_width" format="integer"/>
<attr name="move_range" format="integer"/>
</declare-styleable>
</resources>
二、列表item 模板
im_test_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.chenxing.searchjob.sdk.view.MyRecyclerViewItem xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scroll_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
app:move_range="20"
app:right_width="200">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="20dp">
<LinearLayout
android:id="@+id/content_layout"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--内容区域放置布局-->
<TextView
android:id="@+id/show"
android:layout_width="1000dp"
android:layout_height="200dp"
android:background="@color/colorPrimaryDark"
android:gravity="center_vertical"
android:text="点击试试"
android:textColor="#ffffff"
android:textSize="18sp"
android:textStyle="bold" />
<!--内容区域放置布局结束-->
</LinearLayout>
<LinearLayout
android:id="@+id/rightLayout"
android:layout_width="140dp"
android:layout_height="match_parent"
android:layout_alignTop="@id/content_layout"
android:layout_alignBottom="@id/content_layout"
android:layout_toEndOf="@id/content_layout"
android:background="@color/colorAccent"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="2">
<!--自定义侧边菜单布局-->
<TextView
android:id="@+id/click"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="删除"
android:textColor="#ffffff"
android:textSize="26sp" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="修改"
android:textColor="#ff839dff"
android:textSize="26sp" />
<!--自定义侧边菜单布局结束-->
</LinearLayout>
</RelativeLayout>
</com.chenxing.searchjob.sdk.view.MyRecyclerViewItem>
三、自定义控件核心代码:
MyRecyclerViewItem.java
package com.chenxing.searchjob.sdk.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import io.rong.imkit.R;
public class MyRecyclerViewItem extends HorizontalScrollView {
public MyRecyclerViewItem(Context context) {
super(context);
init(context,null);
}
public MyRecyclerViewItem(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MyRecyclerViewItem(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
public static final String TAG=MyRecyclerViewItem.class.getSimpleName();
private boolean isLeft = true;//默认左边
private int rightLayoutWidth;
private int leftLayoutWidth;
private int range;
public void setRightLayoutWidth(int rightLayoutWidth) {
this.rightLayoutWidth = rightLayoutWidth;
}
public void setLeftLayoutWidth(int leftLayoutWidth) {
this.leftLayoutWidth = leftLayoutWidth;
}
public void setRange(int range) {
this.range = range;
}
private void init(Context context, AttributeSet attrs) {
leftLayoutWidth = getScreenSize(getContext()).widthPixels;// recyclerview 宽度
rightLayoutWidth = dp2px(getContext(),200);// 右边布局的宽度
range = dp2px(getContext(), 30);// 移动多少开始切换阈值
if (attrs!=null){
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyRecyclerViewItem);
int indexCount = typedArray.getIndexCount();
for (int i = 0; i < indexCount; i++) {
int index = typedArray.getIndex(i);
if (index==R.styleable.MyRecyclerViewItem_left_width){
leftLayoutWidth = typedArray.getInteger(index, 0)==0? leftLayoutWidth : dp2px(context, typedArray.getInteger(index, 0));
}
if (index==R.styleable.MyRecyclerViewItem_right_width){
rightLayoutWidth = typedArray.getInteger(index, 0)==0? rightLayoutWidth : dp2px(context, typedArray.getInteger(index, 0));
}
if (index==R.styleable.MyRecyclerViewItem_move_range){
range = typedArray.getInteger(index, 0)==0? range : dp2px(context, typedArray.getInteger(index, 0));
}
}
typedArray.recycle();
}
}
//适配器 bind 方法中调用
public void apply() {
isLeft = true;
changeLayout();
scrollTo(0, 0);
}
private void changeLayout() {
try {
ViewGroup mainLayout= (ViewGroup) getChildAt(0);
ViewGroup left= (ViewGroup) mainLayout.getChildAt(0);
ViewGroup right= (ViewGroup) mainLayout.getChildAt(1);
if (left.getMeasuredWidth()== leftLayoutWidth && right.getMeasuredWidth()==rightLayoutWidth){
Log.i(TAG, "changeLayout: no change");
return;
}
ViewGroup.LayoutParams layoutParams = left.getLayoutParams();
layoutParams.width = leftLayoutWidth;
left.setLayoutParams(layoutParams);
ViewGroup.LayoutParams layoutParams2 = right.getLayoutParams();
layoutParams2.width = rightLayoutWidth;
left.setLayoutParams(layoutParams);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DisplayMetrics getScreenSize(Context context){
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
return dm;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
Log.i(getClass().getSimpleName(), "down");
return true;
}
if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) {
Log.i(getClass().getSimpleName(), "up");
if (isLeft) {
if (getScrollX() > range) {
isLeft = false;
smoothScrollTo(rightLayoutWidth, 0);
} else {
smoothScrollTo(0, 0);
}
} else {
if (getScrollX() < (rightLayoutWidth - range)) {
isLeft = true;
smoothScrollTo(0, 0);
} else {
smoothScrollTo(rightLayoutWidth, 0);
}
}
return true;
}
Log.i(getClass().getSimpleName(), "end");
return super.onTouchEvent(ev);
}
public static int dp2px(Context context,float dpValue) {
DisplayMetrics scale = context.getResources().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, scale);
}
}
四、调用测试
布局内容:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/insertLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
java代码:
package com.chenxing.searchjob.sdk.view;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.chenxing.searchjob.sdk.base.activity.COMBaseActivity;
import io.rong.imkit.R;
public class TestClass extends COMBaseActivity {
private String TAG = "IMListView";
private RecyclerView recycler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.im_test_class);
recycler=findViewById(R.id.recycler);
recycler.setLayoutManager(new LinearLayoutManager(this));
recycler.setAdapter(new MyApr());
}
public static class VH extends RecyclerView.ViewHolder{
public TextView show;
public TextView click;
public MyRecyclerViewItem recyclerViewItem;
public VH(View itemView) {
super(itemView);
recyclerViewItem=itemView.findViewById(R.id.scroll_item);
show=itemView.findViewById(R.id.show);
click=itemView.findViewById(R.id.click);
}
}
public static class MyApr extends RecyclerView.Adapter<VH>{
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
return new VH(LayoutInflater.from(parent.getContext()).inflate(R.layout.im_test_item, parent, false));
}
@Override
public void onBindViewHolder(final VH holder, final int position) {
//恢复状态
holder.recyclerViewItem.apply();
holder.show.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(holder.itemView.getContext(), "编号:"+position, Toast.LENGTH_LONG).show();
}
});
holder.click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(holder.itemView.getContext(), "删除:"+position, Toast.LENGTH_LONG).show();
}
});
}
@Override
public int getItemCount() {
return 10;
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
}
最简单侧滑菜单,因为他思路很容易理解,方便自己扩展调整,尤其布局调整很简单。
老鸟一看代码都不用我解释了。
对于新手这边解释一下;
主要是自定了item 的布局布局结构使用了HorizontalScrollView作为根节点;
每次bind时候计算一次尺寸进行布局,所以要调用apply 方法。
实现了touch处理事件,通过判断手指抬起的时候来处理滑动逻辑。
非常精简,RecyclerView 使用没有任何限制。
看完上面的左滑动 那么如果理解 右滑动菜单也是没有问题了!
如果对你有帮助请点点zan o