根据大佬B站的视频,也模仿做了一个侧滑SlideMenuLayout,代码如下
package com.gcj.myapplication.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
import android.widget.TextView;
import com.gcj.myapplication.R;
public class SlideMenuLayout extends ViewGroup implements View.OnClickListener {
private View mContentView;
private View ll_function;
private int functions;
private int functionNum;
private Scroller mScroller;
private float mScaledTouchSlop = 0;
private float mInterceptDownX = 0f;
private float mInterceptDownY = 0f;
private float mDownX = 0f;
private float mDownY = 0f;
private boolean isOpen =false;
private Direction mCurrentDirection = Direction.NONE;
private SlideMenuView.Direction mCurrentDirect = SlideMenuView.Direction.NONE;
private final String TAG = "SlideMenuLayout";
private SlideMenuView.OnFunctionListener mOnFunctionListener=null;
enum Direction{
LEFT,RIGHT,NONE
}
public SlideMenuLayout(Context context) {
this(context,null);
}
public SlideMenuLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SlideMenuLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlideMenuLayout);
functions =a.getInt(R.styleable.SlideMenuLayout_functions,0x30);
functionNum = a.getInt(R.styleable.SlideMenuLayout_functionNum,1);
Log.d("功能值为", String.valueOf(functions));
a.recycle();
init();
}
private void init() {
setClickable(true);
setFocusableInTouchMode(true);
mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mScroller = new Scroller(getContext());
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
mInterceptDownX = ev.getX();
mInterceptDownX = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float endX = getX();
float endY = getY();
// 在水平方向移动的位移
float distanceX = Math.abs(endX - mInterceptDownX);
// 在垂直方向移动的位移
float distanceY = Math.abs(endY - mInterceptDownY);
if (distanceX > mScaledTouchSlop && distanceY < mScaledTouchSlop) {
return true;
}
}
return super.onInterceptTouchEvent(ev);
}
// mDuration 走完的mEditView 5/6宽度所需要的时间
private int mMaxDuration = 800;
private int mMinDuration = 300;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float moveY = event.getY();
// 移动的差值
int dx = (int) (moveX - mDownX);
mCurrentDirection = dx > 0? Direction.RIGHT : Direction.LEFT;
// 判断边界
float resultScrollX = -dx + getScrollX();
if (resultScrollX <= 0){
scrollTo(0,0);
}else if (resultScrollX > ll_function.getMeasuredWidth()){
scrollTo(ll_function.getMeasuredWidth(),0);
}else {
scrollBy(-dx,0);
}
// 把差值使用起来
mDownX = moveX;
mDownY = moveY;
// 在滑动的时候要判断是否开关
checkOpenOrClose();
break;
case MotionEvent.ACTION_UP:
// 处理释放以后,判断是显示还是收缩回去
checkOpenOrClose();
break;
case MotionEvent.ACTION_CANCEL:
mCurrentDirection = Direction.NONE;
break;
}
return true;
}
public boolean isOpen(){
return isOpen;
}
/**
* 检查是否应该打开或关闭
*/
private void checkOpenOrClose() {
// 两个关注点
// 是否已经打开
// 方向
int hasBeenScrollX = getScrollX();
int functionViewWidth = ll_function.getMeasuredWidth();
if (isOpen) {
// 当前状态是打开
if (mCurrentDirection == Direction.RIGHT) {
// 方向向右,如果小于3/4,那么就关闭
// 否则打开
if (hasBeenScrollX <= functionViewWidth * 5 / 6) {
close();
} else {
open();
}
} else if (mCurrentDirection == Direction.LEFT) {
open();
}
} else {
// 当前状态是关闭
if (mCurrentDirection == Direction.LEFT) {
// 向左滑动,判断滑动的距离
if (hasBeenScrollX > functionViewWidth / 6) {
open();
} else {
close();
}
} else if (mCurrentDirection == Direction.RIGHT) {
// 向右滑动
close();
}
}
}
public void open() {
// 显示出来
// scrollTo(mEditView.getMeasuredWidth(), 0)
int dx = ll_function.getMeasuredWidth() - getScrollX();
int duration = (int)(dx / ll_function.getMeasuredWidth() * 5 / 6f) * mMaxDuration;
int absDuration = Math.abs(duration);
if (absDuration < mMinDuration) {
absDuration = mMinDuration;
}
mScroller.startScroll(getScrollX(), 0, dx, 0, absDuration);
isOpen = true;
invalidate();
}
public void close() {
// 隐藏
// scrollTo(0,0)
int dx = -getScrollX();
int duration = (int)(dx / ll_function.getMeasuredWidth() * 5 / 6f) * mMaxDuration;
int absDuration = Math.abs(duration);
if (absDuration < mMinDuration) {
absDuration = mMinDuration;
}
mScroller.startScroll(getScrollX(), 0, dx, 0, absDuration);
isOpen = false;
invalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
int currX = mScroller.getCurrX();
// 滑动到指定位置即可
scrollTo(currX, 0);
invalidate();
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
int childCount = getChildCount();
if (childCount<=1){
Log.e(TAG,"Cannot add multiple children,You can only add one child!");
}
mContentView = getChildAt(0);
ll_function = LayoutInflater.from(getContext()).inflate(R.layout.item_function, this, false);
initEditView();
addView(ll_function);
}
private TextView mRead;
private TextView mTop;
private TextView mDelete;
private void initEditView() {
mRead = ll_function.findViewById(R.id.tv_read);
mTop = ll_function.findViewById(R.id.tv_top);
mDelete = ll_function.findViewById(R.id.tv_delete);
switch (functions){
case 3: //top
mDelete.setVisibility(GONE);
mRead.setVisibility(GONE);
break;
case 48: //delete
mTop.setVisibility(GONE);
mRead.setVisibility(GONE);
break;
case 80: //read
mTop.setVisibility(GONE);
mDelete.setVisibility(GONE);
break;
case 51:
mRead.setVisibility(GONE);
break;
case 83:
mDelete.setVisibility(GONE);
break;
case 112:
mTop.setVisibility(GONE);
default:
}
mRead.setOnClickListener(this);
mTop.setOnClickListener(this);
mDelete.setOnClickListener(this);
}
/**
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
//测量第一个内容控件
//宽度和父控件一样宽,高度情况三种 ,如果指定大小,我们获取它的大小,直接测量
//如果是包容,AT_MOST,如果是match_parent 那就设置大小
LayoutParams contentLayoutParams = mContentView.getLayoutParams();
int contentHeight = contentLayoutParams.height;
int contentHeightMeasureSpace;
if (contentHeight==LayoutParams.MATCH_PARENT){
contentHeightMeasureSpace = MeasureSpec.makeMeasureSpec(heightSize,MeasureSpec.EXACTLY);
}else if (contentHeight == LayoutParams.WRAP_CONTENT){
contentHeightMeasureSpace = MeasureSpec.makeMeasureSpec(heightSize,MeasureSpec.AT_MOST);
}else {
contentHeightMeasureSpace = MeasureSpec.makeMeasureSpec(heightSize,MeasureSpec.EXACTLY);
}
mContentView.measure(widthMeasureSpec,contentHeightMeasureSpace);
//测量后的第一个控件高度 使第二个控件的高度与之一致
int contentMeasuredHeight = mContentView.getMeasuredHeight();
int menu = widthSize*functionNum/4;
ll_function.measure(MeasureSpec.makeMeasureSpec(menu,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(contentMeasuredHeight,MeasureSpec.EXACTLY));
//最后需要测量自己
//宽度为所以子控件总和,高度一样
setMeasuredDimension(widthSize + menu,contentMeasuredHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 摆放内容
int contentRight = mContentView.getMeasuredWidth();
int contentBottom = mContentView.getMeasuredHeight();
mContentView.layout(0, 0, contentRight, contentBottom);
int functionViewRight = contentRight + ll_function.getMeasuredWidth();
int functionViewBottom = ll_function.getMeasuredHeight();
// 摆放编辑部分
ll_function.layout(contentRight, 0, functionViewRight, functionViewBottom);
}
@Override
public void onClick(View view) {
if (mOnFunctionListener==null){
return;
}
close();
if (view==mRead){
mOnFunctionListener.onReadClick();
}else if (view == mTop){
mOnFunctionListener.onTopClick();
}else {
mOnFunctionListener.onDelete();
}
}
public void setOnFunctionClickListener(SlideMenuView.OnFunctionListener listener){
this.mOnFunctionListener = listener;
}
public interface OnFunctionListener{
void onReadClick();
void onTopClick();
void onDelete();
}
}
功能菜单子控件代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="match_parent">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:textSize="18sp"
android:textColor="@color/white"
android:text="已读"
android:id="@+id/tv_read"
android:layout_height="match_parent"
android:background="@color/teal_200"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:textSize="18sp"
android:text="置顶"
android:id="@+id/tv_top"
android:textColor="@color/white"
android:layout_height="match_parent"
android:background="@color/ready_color"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:textSize="18sp"
android:text="删除"
android:id="@+id/tv_delete"
android:textColor="@color/white"
android:layout_height="match_parent"
android:background="@color/red"/>
</LinearLayout>
然后想用recyclerView显示多条数据,用这个侧滑控件作为适配器的item,但是不知道为什么显示不出数据,一片空白。
适配器代码
package com.gcj.myapplication.adapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.gcj.myapplication.R;
import com.gcj.myapplication.activity.TestActivity;
import com.gcj.myapplication.bean.ChildInfo;
import com.gcj.myapplication.view.SlideMenuLayout;
import com.gcj.myapplication.view.SlideMenuView;
import com.gcj.myapplication.view.SlideOperateView;
import java.util.ArrayList;
import java.util.List;
public class ResultAdapter extends RecyclerView.Adapter<ResultAdapter.ViewHolder> {
private Context mContext;
private List<String> contentList=new ArrayList<>();
public ResultAdapter(Context context){
this.mContext=context;
}
public void setResultInfo(List<String> data){
this.contentList =data;
}
@NonNull
@Override
public ResultAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view=View.inflate(mContext, R.layout.item_order_info,null);
//view.setBackgroundColor(Color.RED);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ResultAdapter.ViewHolder holder, @SuppressLint("RecyclerView") final int position) {
if (contentList.size()>0){
holder.tv_content.setText(contentList.get(position));
holder.slide_view.setOnFunctionClickListener(new SlideMenuView.OnFunctionListener() {
@Override
public void onReadClick() {
}
@Override
public void onTopClick() {
}
@Override
public void onDelete() {
contentList.remove(contentList.get(position));
notifyDataSetChanged();
}
});
}
}
@Override
public int getItemCount() {
return contentList.size();
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
SlideMenuLayout slide_view;
TextView tv_content;
public ViewHolder(@NonNull View itemView) {
super(itemView);
slide_view = itemView.findViewById(R.id.slide_view);
tv_content = itemView.findViewById(R.id.tv_content);
}
}
private ItemOnClickListener mItemOnClickListener = null;
public interface ItemOnClickListener{
public void itemOnClickListener(int position);
}
public void setItemOnClickListener(ItemOnClickListener listener){
this.mItemOnClickListener = listener;
}
}

上面是适配器和item的代码
界面调用代码为:


结果却是这样空白一片

还望大佬们赐教一下 感谢感谢
你先这样子,把你的slide去掉先,先学会使用recyclerView显示内容,然后才是去使用那个slideMenuLayout。
使用recyclerView注意几个问题,数据给适配器,适配器给控件,控件要设置布局管理器。这几个看了一下你的代码是有的,就看看是不是你嵌套了slideMenuLayout没能显示的问题。
返回的数量是不是对的,加一些log.