先来看效果图:
整体思路:
最外层的LinearLayout会监听手指滑动的的距离,当滑动的距离大于“不约”View的二分之一宽度时,LinearLayou将会滑动到“不约”View的宽度。当滑动的距离小于“不约”View的二分之一宽度时,将会滑回初始位置。
xml布局
<?xml version="1.0" encoding="utf-8"?>
<com.yeliang.app02_sliding_item_menu.SlidingItemMenuLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.yeliang.app02_sliding_item_menu.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#f00"
android:gravity="center_vertical"
android:paddingLeft="20dp"
android:text="约吗?帅哥?"
android:textColor="#fff"
android:textSize="28sp" />
<TextView
android:id="@+id/textView"
android:layout_width="100dp"
android:layout_height="80dp"
android:background="#0f0"
android:gravity="center"
android:text="不约"
android:textSize="28sp" />
</com.yeliang.app02_sliding_item_menu.SlidingItemMenuLayout>
java代码
public class SlidingItemMenuLayout extends LinearLayout {
private Scroller mScroller;
private View leftChild;
private View rightChild;
public SlidingItemMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
mScroller = new Scroller(getContext(), null, true);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
leftChild = getChildAt(0);
rightChild = getChildAt(1);
rightChild.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mScroller.startScroll(getScrollX(), getScrollY(), -rightChild.getWidth(), 0);
}
});
}
private float startX;
private float startY;
private float dx;
private float dy;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = ev.getX();
startY = ev.getY();
super.dispatchTouchEvent(ev);
return true;
case MotionEvent.ACTION_MOVE:
dx = ev.getX() - startX;
dy = ev.getY() - startY;
// dx>0右滑 dx<0左滑
if (Math.abs(dx) - Math.abs(dy) > ViewConfiguration.getTouchSlop()) {
if (getScrollX() + (-dx) > rightChild.getWidth() || getScrollX() + (-dx) < 0) {
return true;
}
this.scrollBy((int) -dx, 0);
startX = ev.getX();
startY = ev.getY();
return true;
}
break;
case MotionEvent.ACTION_UP:
//判断此时松手往左滑还是往右滑
int offset = (getScrollX() / (float) rightChild.getWidth()) > 0.5f ? rightChild.getWidth() - getScrollX() : -getScrollX();
mScroller.startScroll(getScrollX(), getScrollY(), offset, 0);
invalidate();
startX = 0;
startY = 0;
dx = 0;
dy = 0;
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
//在开始滑动的过程中,此方法会不断的被调用
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
this.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
super.computeScroll();
}
}