最近闲来无事,于是研究了一下qq的左滑删除效果,尝试着实现了一下,先上效果图:
大致思路原理:
- 通过设置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; } @Override public 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文件定义如下:
<?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"> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal"> <TextView android: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> <LinearLayout android:layout_width="180dp" android:layout_height="60dp" android:orientation="horizontal"> <TextView android: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" /> <TextView android: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() { @Override public void onClick(View v) { mInfos.remove(position); notifyDataSetChanged(); mListView.turnToNormal(); } }); holder.tvTop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String temp = mInfos.get(position); mInfos.remove(position); mInfos.add(0, temp); notifyDataSetChanged(); mListView.turnToNormal(); } });
最后还有一个遗留问题,ListView左右滑动的时候上下也会滑动,这个有待探索与改进,也希望大家提提意见,帮我改进!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。
新闻热点
疑难解答