这个Demo是用来练习VIewDragHelper的,也是仿照网上一个大神的代码。我通过他的代码学会的ViewDragHelper,然后仿照效果写的同样的效果。
原文连接:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0911/1680.html
效果图:
主要代码就是一个继承VIewGroup的类。写了注释,就不再解释了。
我写的主要代码如下:
public class YouLayout extends RelativeLayout {
private View topView;
private View bottomView;
private ViewDragHelper mDragHelper;
public YouLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init(context);
}
public YouLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
// TODO Auto-generated constructor stub
}
public YouLayout(Context context) {
super(context);
init(context);
}
private void init(Context context){
mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallBack());
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
topView = getTopView();
bottomView = getBottomView();
}
private View getTopView(){
return getChildAt(0);
}
private View getBottomView(){
return getChildAt(1);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) {
mDragHelper.cancel();
return false;
}
return mDragHelper.shouldInterceptTouchEvent(ev); //将事件传递给ViewDragHelper,让它自己处理是否需要打断。
}
private int downX ;
private int downY ;
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event); //同样是传递事件给ViewdragHelper
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = x ;
downY = y ;
break;
case MotionEvent.ACTION_UP:
int dx = x - downX;
int dy = y - downY;
int slop = mDragHelper.getTouchSlop();
if ((Math.pow(dx, 2) + Math.pow(dy, 2)) < Math.pow(slop, 2)) {
//说明是点击事件
if (mDragOffset == 0 ) {
moveTo(1f);
}else {
moveTo(0);
}
}
break;
}//收拾的放下,抬起的处理,是为了针对点击事件做的处理
return isMyView(topView, x, y) || isMyView(bottomView, x, y); //判断当前的点击事件是在TopView或者是在BottomView上,如果在其上,则返回true
//如果是在TopView上,事件则传递给ViewDragHelper处理,如果是在BottomView上,则自然的传递下去。如果是在其他地方,则返回false,将事件传递下去。
}
@Override
public void computeScroll() {
//这个是为了将事件执行到底
if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
//判断点击事件是否在View上
private boolean isMyView(View view, int x, int y) {
int[] viewLocation = new int[2];
view.getLocationOnScreen(viewLocation);
int[] parentLocation = new int[2];
this.getLocationOnScreen(parentLocation);
int screenX = parentLocation[0] + x;
int screenY = parentLocation[1] + y;
return screenX >= viewLocation[0] && screenX < viewLocation[0] + view.getWidth() && screenY >= viewLocation[1] && screenY < viewLocation[1] + view.getHeight();
}
//移动到指定的位置
boolean moveTo(float slideRatio) {
final int topBound = getPaddingTop();
int y = (int) (topBound + slideRatio * mHeight);
if (mDragHelper.smoothSlideViewTo(topView, topView.getLeft(), y)) {
ViewCompat.postInvalidateOnAnimation(this);
return true;
}
return false;
}
class DragHelperCallBack extends Callback{
/**
* 这个是为了判断力要ViewDragHelper处理的是哪个View,很明显,这里处理的是TopView
*/
@Override
public boolean tryCaptureView(View child, int arg1) {
return child == topView;
}
//时时回调。提供的是TopView时时更改的状态
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
mTop = top;
mDragOffset = (float) top / mHeight;
topView.setPivotX(topView.getWidth());
topView.setPivotY(topView.getHeight());
topView.setScaleX(1 - mDragOffset / 2);
topView.setScaleY(1 - mDragOffset / 2);
bottomView.setAlpha(1 - mDragOffset);
requestLayout();
System.out.println("onviewpositionChhanged");
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
int top = getPaddingTop();
if (yvel > 0 || (yvel == 0 && mDragOffset > 0.5f)) {
top += mHeight;
}
mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);
invalidate();
}
@Override
public int getViewVerticalDragRange(View child) {
return mHeight;
}
/**
* 如果手指是竖向滑动,事件则是在这个方法中处理的
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
int topBound = getPaddingTop();
int bottomBound = getHeight() - topView.getHeight() - topView.getPaddingBottom();
int newTop = Math.min(Math.max(top, topBound), bottomBound);
return newTop;
}
}
/**
* 重新的测量View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0),
resolveSizeAndState(maxHeight, heightMeasureSpec, 0));
}
private int mTop = 0 ;
private int mHeight;
private float mDragOffset;
/**
* 重新的布局子View ,不重新布局也是可以的如果只是简单的移动一个topView的时候。在这个Demo中,需要让BottomView与TopView一起的移送,
* ViewdragHelper不能控制两个View,这里自己布局,然后使得在onViewPositionChanged的方法中,重新调用,重新布局,实现两个VIew的联动
*
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mHeight = getHeight() - topView.getHeight();
topView.layout(0, mTop, r, mTop + topView.getMeasuredHeight());
bottomView.layout(0, mTop + topView.getMeasuredHeight(), r, mTop +b);
}
}
我的github地址:https://github.com/flyme2012
我的博客地址:http://www.cnblogs.com/flyme2012/