Android自定义SwipeLayout仿QQ侧滑条目 Android自定义SwipeLayout仿QQ侧滑条目
张行之 人气:0Android自定义SwipeLayout仿QQ侧滑条目,供大家参考,具体内容如下
先看动图
看布局文件
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="www.weshared.qqcehua.MainActivity"> <include layout="@layout/swipelayout" /> </RelativeLayout>
swipelayout.xml
<?xml version="1.0" encoding="utf-8"?> <www.weshared.qqcehua.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/swipelayout" android:layout_width="match_parent" android:layout_height="72dp"> <!--0 左边后布局--> <TextView android:id="@+id/back_left_tv_mark" android:layout_width="84dp" android:layout_height="match_parent" android:background="@android:color/holo_blue_dark" android:gravity="center" android:text="Mark" android:textColor="@android:color/white" android:textSize="20sp" /> <!--1 右边后布局--> <LinearLayout android:id="@+id/back_right_ll" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="right" android:orientation="horizontal"> <TextView android:id="@+id/back_right_tv_call" android:layout_width="84dp" android:layout_height="match_parent" android:background="@android:color/holo_orange_dark" android:gravity="center" android:text="Call" android:textColor="@android:color/white" android:textSize="20sp" /> <TextView android:id="@+id/back_right_tv_delete" android:layout_width="84dp" android:layout_height="match_parent" android:background="@android:color/holo_red_dark" android:gravity="center" android:text="Delete" android:textColor="@android:color/white" android:textSize="20sp" /> </LinearLayout> <!--2 前布局 content--> <TextView android:id="@+id/front_tv_content" android:layout_width="match_parent" android:layout_gravity="center" android:gravity="center" android:layout_height="match_parent" android:background="#666666" /> </www.weshared.qqcehua.SwipeLayout>
在MainActivity中
public class MainActivity extends AppCompatActivity { private SwipeLayout mSwipeLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { mSwipeLayout = (SwipeLayout) findViewById(R.id.swipelayout); mSwipeLayout.setOnClickListener(new SwipeLayout.OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { case R.id.back_left_tv_mark: toast("mark"); break; case R.id.front_tv_content: toast("content"); break; case R.id.back_right_tv_call: toast("call"); break; case R.id.back_right_tv_delete: toast("delete"); break; } } }); } public void toast(String message) { Toast toast = Toast.makeText(this, "", Toast.LENGTH_SHORT); if (!TextUtils.isEmpty(message) && toast != null) { toast.setText(message); toast.show(); } } }
自定义SwipeLayout控件
public class SwipeLayout extends FrameLayout { private View mBackLeftView; private ViewGroup mBackRightView; private View mFrontView; private int mWidth; private int mHeight; private int mLeftRange; private int mRightRange; private int status; public final int NORMAL = 0;//关闭状态 public final int LEFT_OPEN = 1;//左边打开状态 public final int RIGHT_OPEN = 2;//右边打开状态 public final int LEFT_OPENING = 3;//左边正打开状态 public final int LEFT_CLOSING = 4;//左边正关闭状态 public final int RIGHT_OPENING = 5;//右边正打开状态 public final int RIGHT_CLOSING = 6;//右边正关闭状态 private ViewDragHelper mViewDrawHelper; private final int V = 300;//限制速度 private OnSwipeListener mOnSwipeListener; private OnClickListener mOnClickListener; private View mBackRightCall; private View mBackRightDelete; private int x; private boolean isClick; private final int DX = 10; public interface OnSwipeListener { void onLeftOpen(SwipeLayout swipeLayout); void onLeftClose(SwipeLayout swipeLayout); void onRightOpen(SwipeLayout swipeLayout); void onRightClose(SwipeLayout swipeLayout); } public interface OnClickListener { void onClick(View view); } public SwipeLayout(Context context) { super(context); init(); } public SwipeLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } private void init() { status = NORMAL;//默认是NORMAL mViewDrawHelper = ViewDragHelper.create(this, callback); } public void setOnSwipeListener(OnSwipeListener mOnSwipeListener) { this.mOnSwipeListener = mOnSwipeListener; } public void setOnClickListener(OnClickListener mOnClickListener) { this.mOnClickListener = mOnClickListener; } private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { /**是否试图拖拽子view*/ @Override public boolean tryCaptureView(View child, int pointerId) { if (child == mBackLeftView) { return false; } return true; } /** 水平方向上的限制*/ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (child == mFrontView) { if (left < -mRightRange) { left = -mRightRange; } else if (left > mLeftRange) { left = mLeftRange; } } else if (child == mBackRightView) { if (left < mWidth - mRightRange) { left = mWidth - mRightRange; } else if (left > mWidth) { left = mWidth; } } return left; } /**这是系统定义的状态*/ @Override public void onViewDragStateChanged(int state) { super.onViewDragStateChanged(state); if (state == ViewDragHelper.STATE_IDLE) {//ViewDrawHelper处于空闲状态 } else if (state == ViewDragHelper.STATE_DRAGGING) {//ViewDrawHelper处于正在拖拽状态 //拖拽状态,可设置滑动事件 } else if (state == ViewDragHelper.STATE_SETTLING) {//ViewDrawHelper处于飞翔状态 //飞翔状态设置,可设置滚动事件 } } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); if (mFrontView == changedView) { mBackRightView.offsetLeftAndRight(dx); } else if (mBackRightView == changedView) { mFrontView.offsetLeftAndRight(dx); } status = updateStatus();//更新控件的状态 invalidate();//重绘界面 } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); int left = mFrontView.getLeft(); if (left < -mRightRange * 0.5f) { if (xvel > V) { normalClose(); } else { rightOpen(); } } else if (left >= -mRightRange * 0.5f && left <= 0) { if (xvel < -V) {//向左滑动 rightOpen();//打开右边前布局 } else { normalClose(); } } else if (left > 0 && left <= mLeftRange * 0.5f) { if (xvel > V) { leftOpen(); } else { normalClose(); } } else if (left > mLeftRange * 0.5f && left <= mLeftRange) { if (xvel < -V) {//向左滑动 normalClose(); } else { leftOpen(); } } } }; public void dispatchClickListener() { //设置点击事件 if (status == LEFT_OPEN) { //mark的点击事件和Content点击事件 if (mOnClickListener != null) { if (x > 0 && x < mLeftRange) { mOnClickListener.onClick(mBackLeftView); } } } else if (status == RIGHT_OPEN) { //call 和 Delete的点击事件 和Content点击事件 if (mOnClickListener != null) { if (x > mWidth - mRightRange && x < mWidth - mRightRange * 0.5f) { mOnClickListener.onClick(mBackRightCall); } else if (x >= mWidth - mRightRange * 0.5f && x <= mWidth) { mOnClickListener.onClick(mBackRightDelete); } } } else if (status == NORMAL) { //content的点击事件 if (mOnClickListener != null) { mOnClickListener.onClick(mFrontView); } } } private int updateStatus() { int left = mFrontView.getLeft(); if (left == -mRightRange) { status = RIGHT_OPEN; } else if (left == 0) { status = NORMAL; } else if (left == mLeftRange) { status = LEFT_OPEN; } return status; } public void leftOpen() { leftOpen(true); } public void leftOpen(boolean isSmooth) { int finalLeft = mLeftRange; int finalTop = 0; if (isSmooth) { if (mViewDrawHelper.smoothSlideViewTo(mFrontView, finalLeft, finalTop)) { ViewCompat.postInvalidateOnAnimation(this); } } else { layoutContent(LEFT_OPEN); } } public void normalClose() { normalClose(true); } public void normalClose(boolean isSmooth) { int finalLeft = 0; int finalTop = 0; if (isSmooth) { if (mViewDrawHelper.smoothSlideViewTo(mFrontView, finalLeft, finalTop)) { ViewCompat.postInvalidateOnAnimation(this); } } else { layoutContent(NORMAL); } } public void rightOpen() { rightOpen(true); } public void rightOpen(boolean isSmooth) { int finalLeft = -mRightRange; int finalTop = 0; if (isSmooth) { if (mViewDrawHelper.smoothSlideViewTo(mFrontView, finalLeft, finalTop)) { ViewCompat.postInvalidateOnAnimation(this); } } else { layoutContent(RIGHT_OPEN); } } @Override public void computeScroll() { super.computeScroll(); if (mViewDrawHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mViewDrawHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { dispatchOnTouchEvent(event);//分发触摸的事件 try { mViewDrawHelper.processTouchEvent(event);//将触摸事件传递给ViewDrawHelper } catch (Exception e) { } return true; } public void dispatchOnTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { x = (int) event.getX(); isClick = true; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { int movex = (int) event.getX(); if (Math.abs(movex - x) > DX) {//防止点击事件,会稍微手指抖动 isClick = false; } } else if (event.getAction() == MotionEvent.ACTION_UP) { if (isClick) { dispatchClickListener(); } } } @Override protected void onFinishInflate() { super.onFinishInflate(); //获取控件中的子控件 mBackLeftView = getChildAt(0); mBackRightView = (ViewGroup) getChildAt(1); mFrontView = getChildAt(2); mBackRightCall = mBackRightView.getChildAt(0); mBackRightDelete = mBackRightView.getChildAt(1); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); mLeftRange = mBackLeftView.getMeasuredWidth(); mRightRange = mBackRightView.getMeasuredWidth(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); //摆放布局 layoutContent(NORMAL); } public void layoutContent(int status) { Rect frontRect = computeFrontRect(status);//根据状态,摆放前布局 mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom); Rect rightBackRect = computeRightBackRect(frontRect);//根据前布局,摆放右边后布局 mBackRightView.layout(rightBackRect.left, rightBackRect.top, rightBackRect.right, rightBackRect.bottom); } public Rect computeFrontRect(int status) { int left = 0; int top = 0; if (status == LEFT_OPEN) { left = mLeftRange; } else if (status == RIGHT_OPEN) { left = -mRightRange; } return new Rect(left, top, left + mWidth, top + mHeight); } public Rect computeRightBackRect(Rect frontRect) { int left = 0; int top = 0; if (frontRect != null) { left = frontRect.right; } return new Rect(left, top, left + mRightRange, top + mHeight); } }
现在控件耦合程度太高,以后慢慢优化,写成一个库。
加载全部内容