您的位置:首页 > 移动开发 > Android开发

ViewDragHelper 实现侧滑(二)

2015-12-12 16:58 453 查看

1 引言  

android support v4中比较强大的类ViewDragHelper。自定义View(三) switch开关按钮 ViewDragHelper的使用初级 该文章粗略简述了ViewDragHelper的使用。本文进一步升级 使用ViewDragHelper类实现侧滑效果。注这里实现效果类似侧拉删除效果。(如果想实现侧拉删除效果需要自定义回调函数和处理逻辑
  参照本文也可以实现自己的slidebar)

2 布局

   均较为简单 可根据自己的需求更改:
(1)left_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="match_parent"
android:background="#ccc"
>

<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="20dp"
android:text="姓名"
android:textColor="#f03744"
android:textSize="18sp" />
<TextView
android:paddingLeft="20dp"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="学号"
android:textColor="#f03744"
android:textSize="18sp" />
</LinearLayout>
(2)right_view.xml 为编辑按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#4690BD"
>

<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:paddingLeft="20dp"
android:text="删除"
android:textColor="#f03744"
android:textSize="18sp" />
<TextView
android:paddingLeft="20dp"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="编辑"
android:textColor="#f03744"
android:textSize="18sp" />
</LinearLayout>
  (3) 主要布局 activity_main

<LinearLayout 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"
android:orientation="horizontal"
>
<com.example.myswipedemo.MySwipeView
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
>
<include layout="@layout/left_view"
android:id="@+id/lview"
/>
<include layout="@layout/right_view"
android:id="@+id/rview"/>

</com.example.myswipedemo.MySwipeView>

</LinearLayout>
com.example.myswipedemo.MySwipeView为本文自定义的ViewGroup 为简便本文继承RelativeLayout

3 自定义的ViewGroup

public class MySwipeView extends RelativeLayout {
private ViewDragHelper mDragger;
private int mRange;
View mLeftView;  //正常显示的View
View mRightView;//编辑模式下显示的View
private int mRightWidth; //右边View的宽度

public MySwipeView(Context context) {
this(context, null);
}

public MySwipeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public MySwipeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mDragger.shouldInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
mDragger.processTouchEvent(event);
return true;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mLeftView = getChildAt(0);
mRightView =  getChildAt(1);
int left = getMeasuredWidth();//左边此时完全显示 宽度是整个View宽度
//左边View放于左边View的右边 超出屏幕 故不显示
mRightView.layout(left, 0, left + mRightView.getMeasuredWidth(), mRightView.getMeasuredHeight());
mRange = left - mRightView.getMeasuredWidth();
mRightWidth = mRightView.getWidth();
}

@Override
public void computeScroll() {  //ViewCompat.postInvalidateOnAnimation
//不断回调此函数
if (mDragger.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {//初始化ViewDragHelper
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}

@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (child == mLeftView) {  //左侧View  的left 值 最大为0 最小为 -mRightWidth
left = Math.min(0,Math.max(-mRightWidth, left));
}
if (child == mRightView) {//同上
left = Math.min(mLeftView.getWidth()+mRightWidth,Math.max(mLeftView.getWidth()-mRightWidth,left));
}
return left;
}

@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if (xvel > 0) {//显示左边view
mDragger.smoothSlideViewTo(mLeftView,0, 0);
} else if((xvel == 0) && (mLeftView.getLeft() > (-mRightWidth / 3))) {//显示左边view
mDragger.smoothSlideViewTo(mLeftView,0, 0);
}else if((xvel == 0) && (mLeftView.getLeft() <= (-mRightWidth / 3))){
mDragger.smoothSlideViewTo(mLeftView,-mRightWidth, 0);
}else if(xvel <0){
mDragger.smoothSlideViewTo(mLeftView,-mRightWidth, 0);
}
ViewCompat.postInvalidateOnAnimation(MySwipeView.this);;
}

@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
if (changedView == mLeftView) {
mRightView.offsetLeftAndRight(dx);
} else if (changedView == mRightView) {
mLeftView.offsetLeftAndRight(dx);
}
ViewCompat.postInvalidateOnAnimation(MySwipeView.this);;//一定要刷新,不然会没效果
}

@Override
public int getViewHorizontalDragRange(View child) {
return mRange;
}
});
}
}


(1) ViewDragHelper的初始化本文不再赘述。ViewGroup的自定义分别经历如下步骤: a onMeasure在onMeasure中计算childView的测量值以及模式,以及设置自己的宽和高: b onLayout对其所有childView进行定位
c dispatchDraw 本文用不上。 具体参见Android 手把手教您自定义ViewGroup(一) (2)使用getChildAt()获取xml中的子View (3)使用getMeasuredWidth()获取测量后的宽 (4)mRightWidth左边未显示(超出屏幕)的view的宽度 (5)public int clampViewPositionHorizontal(View child, int left, int dx)
为水平拉动后View的left值(为变化后的值)与上一节类似不再赘述。 (6)如下函数为本文重点:View的位置改变的时候
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
if (changedView == mLeftView) {
mRightView.offsetLeftAndRight(dx);
}
ViewCompat.postInvalidateOnAnimation(MySwipeView.this);;//一定要刷新,不然会没效果
该句实现 拉动左边View 将移动距离dx 同时交给右边View (7)public void onViewReleased(View releasedChild, float xvel, float yvel) 实现松开View 弹回或显示右边View
     里面的  mDragger.smoothSlideViewTo(mLeftView,0, 0); 第一个参数是滑动的View 后面两个参数是View最后的left 和top
回调computeScroll()来实现平滑移动。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android ViewDragHelper