大致思路原理:
- 通过设置margin实现菜单的显示与隐藏
- 监听onTouchEvent,处理滑动事件
上代码
import android.content.Context;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.MotionEvent;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.LinearLayout;import android.widget.ListView;/** * Created by MooreLi on 2016/8/8. */public class SlideListView extends ListView {private String TAG = getClass().getSimpleName();private int mScreenWidth;private int mDownX;private int mDownY;private int mMenuWidth;private boolean isMenuShow;private boolean isMoving;private int mOperatePosition = -1;private ViewGroup mPointChild;private LinearLayout.LayoutParams mLayoutParams;public SlideListView(Context context) {super(context);getScreenWidth(context);}public SlideListView(Context context, AttributeSet attrs) {super(context, attrs);getScreenWidth(context);}public SlideListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);getScreenWidth(context);}private void getScreenWidth(Context context) {WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm = new DisplayMetrics();manager.getDefaultDisplay().getMetrics(dm);mScreenWidth = dm.widthPixels;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:performActionDown(ev);break;case MotionEvent.ACTION_MOVE:performActionMove(ev);break;case MotionEvent.ACTION_UP:performActionUp();break;}return super.onTouchEvent(ev);}private void performActionDown(MotionEvent ev) {mDownX = (int) ev.getX();mDownY = (int) ev.getY();//如果点击的不是同一个item,则关掉正在显示的菜单int position = pointToPosition(mDownX, mDownY);if (isMenuShow && position != mOperatePosition) {turnToNormal();}mOperatePosition = position;mPointChild = (ViewGroup) getChildAt(position - getFirstVisiblePosition());if (mPointChild != null) {mMenuWidth = mPointChild.getChildAt(1).getLayoutParams().width;mLayoutParams = (LinearLayout.LayoutParams) mPointChild.getChildAt(0).getLayoutParams();mLayoutParams.width = mScreenWidth;setChildLayoutParams();}}private boolean performActionMove(MotionEvent ev) {int nowX = (int) ev.getX();int nowY = (int) ev.getY();//if (isMoving) {//if (Math.abs(nowY - mDownY) > 0) {//Log.e(TAG, "kkkkkkk");//onInterceptTouchEvent(ev);//}//}if (Math.abs(nowX - mDownX) > 0) {//左滑 显示菜单if (nowX < mDownX) {if (isMenuShow) {mLayoutParams.leftMargin = -mMenuWidth;} else {//计算显示的宽度int scroll = (nowX - mDownX);if (-scroll >= mMenuWidth) {scroll = -mMenuWidth;}mLayoutParams.leftMargin = scroll;}}//右滑 如果菜单显示状态,则关闭菜单if (isMenuShow && nowX > mDownX) {int scroll = nowX - mDownX;if (scroll >= mMenuWidth) {scroll = mMenuWidth;}mLayoutParams.leftMargin = scroll - mMenuWidth;}setChildLayoutParams();isMoving = true;return true;}return super.onTouchEvent(ev);}private void performActionUp() {//超过一半时,显示菜单,否则隐藏if (-mLayoutParams.leftMargin >= mMenuWidth / 2) {mLayoutParams.leftMargin = -mMenuWidth;setChildLayoutParams();isMenuShow = true;} else {turnToNormal();}isMoving = false;}private void setChildLayoutParams(){if(mPointChild != null){mPointChild.getChildAt(0).setLayoutParams(mLayoutParams);}}/** * 正常显示 */public void turnToNormal() {mLayoutParams.leftMargin = 0;mOperatePosition = -1;setChildLayoutParams();isMenuShow = false;}}item的布局要注意,因为在自定义view中写死的是获取第一个子布局为显示内容,所以需要将显示的样式写在一个容器中,将菜单写在另一个容器中,两个平行的关系。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FFFFFF"android:orientation="horizontal"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="60dp"android:orientation="horizontal"><TextViewandroid:id="@+id/main_tv_title"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:gravity="center_vertical"android:textSize="18sp" /></LinearLayout><LinearLayoutandroid:layout_width="180dp"android:layout_height="60dp"android:orientation="horizontal"><TextViewandroid:id="@+id/main_tv_delete"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#FF0000"android:gravity="center"android:text="删除"android:textColor="#FFFFFF" /><TextViewandroid:id="@+id/main_tv_top"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="#DFCDBF"android:gravity="center"android:text="置顶"android:textColor="#FFFFFF" /></LinearLayout></LinearLayout>最后就是删除操作与置顶操作,这个就比较简单,给按钮添加点击事件即可。我是在adapter中定义实现,记得操作后要将菜单关掉!
holder.tvTitle.setText(mInfos.get(position));holder.tvDelete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mInfos.remove(position);notifyDataSetChanged();mListView.turnToNormal();}});holder.tvTop.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String temp = mInfos.get(position);mInfos.remove(position);mInfos.add(0, temp);notifyDataSetChanged();mListView.turnToNormal();}});最后还有一个遗留问题,ListView左右滑动的时候上下也会滑动,这个有待探索与改进,也希望大家提提意见,帮我改进!