关于自定义ViewGroup的理解和ViewDraghelper的使用
来源:互联网 发布:哪有软件培训 编辑:程序博客网 时间:2024/05/16 11:41
在layout中创建一个activity_main.xml
<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="vertical"
tools:context=".MainActivity" >
<mc.ViewGroup.MyDragViewGroup
android:id="@+id/myDragViewGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#f00"
android:padding="10dp"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00f"
/>
</mc.ViewGroup.MyDragViewGroup>
</LinearLayout>
新建一个Activity和一个自定义View :MainActivity ,MyDragViewGroup
MainActivity:
MyDragViewGroup代码:
package mc.ViewGroup;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.support.v4.widget.ViewDragHelper.Callback;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
import android.widget.TextView;
public class MyDragViewGroup extends ViewGroup {
TextView redView,yelloView;
ViewDragHelper viewDragHelper;
Scroller scroller;
public MyDragViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);init();
}
public MyDragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);init();
}
public MyDragViewGroup(Context context) {
super(context);init();
}
private void init() {
viewDragHelper=ViewDragHelper.create(this, callback1);scroller=new Scroller(getContext());
}
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();// 习惯:在此方法中获得子ViewredView = (TextView) getChildAt(0);yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);/*Log.i("widthMeasureSpec", "" + widthMeasureSpec);Log.i("heightMeasureSpec", "" + heightMeasureSpec);int Heightsize = MeasureSpec.getSize(heightMeasureSpec);int HeightMode = MeasureSpec.getMode(heightMeasureSpec);int Widthsize = MeasureSpec.getSize(widthMeasureSpec);int WidthMode = MeasureSpec.getMode(widthMeasureSpec);Log.i("Heightsize", "" + Heightsize);Log.i("HeightMode", "" + HeightMode);Log.i("Widthsize", "" + Widthsize);Log.i("WidthMode", "" + WidthMode);int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度Log.i("ParentH", "" + ParentH);// 为子控件测量,定义其宽高int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,MeasureSpec.EXACTLY);int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,MeasureSpec.EXACTLY);redView.measure(W, H);yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));//measureChild(redView,widthMeasureSpec, heightMeasureSpec);//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);for(int i=0;i<getChildCount();i++){measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);}*/measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();int redViewpaddingL=redView.getPaddingLeft();int redViewpaddingR=redView.getPaddingRight();int redViewpaddingB=redView.getPaddingBottom();int redViewTop=redViewpaddingT+0;int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件* child: 当前触摸的子View return: true:就捕获并解析 false:不处理*/@Overridepublic boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}/*** View被捕获时回调* capturedChild:当前被捕获的View*/@Overridepublic void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);Log.i("Callback.onViewCaptured", "被捕捉");
}/*** 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0*/@Overridepublic int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}/*** 获得View的拖拽垂直范围*/@Overridepublic int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}/*** 控制child在水平方向的移动* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx* dx:本次child水平方向移动的距离* return: 表示你真正想让child的left变成的值*/@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}/*** 控制child在垂直方向的移动* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy* dy:本次child垂直方向移动的距离* return: 表示你真正想让child的top变成的值*/@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {/*//限制范围if (top < 0) {top = 0;} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {top = getMeasuredHeight() - child.getMeasuredHeight();}*///伴随动画的限制范围if(child==redView){if(top<0)top=0;if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();}if(child==yelloView){if(top<0+redView.getMeasuredHeight())top=0+redView.getMeasuredHeight();if(top>getMeasuredHeight()-child.getMeasuredHeight())top=getMeasuredHeight()-child.getMeasuredHeight();}return top;}/*** 当child的位置改变的时候执行,一般用来做其他子View的伴随移动* changedView:位置改变的child* left:child当前最新的left* top: child当前最新的top* dx: 本次水平移动的距离* dy: 本次垂直移动的距离*/@Overridepublic void onViewPositionChanged(View changedView, int left, int top,int dx, int dy) {super.onViewPositionChanged(changedView, left, top, dx, dy);for(int i=0;i<getChildCount();i++){if(changedView!=getChildAt(i)){getChildAt(i).layout(getChildAt(i).getLeft()+dx,getChildAt(i).getTop()+dy,getChildAt(i).getRight()+dx,getChildAt(i).getBottom()+dy);}}}/*** 手指抬起的执行该方法,* releasedChild:当前抬起的view* xvel: x方向的移动的速度 正:向右移动, 负:向左移动* yvel: y方向移动的速度*/@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {super.onViewReleased(releasedChild, xvel, yvel);int centerLeft = getMeasuredWidth() / 2- releasedChild.getMeasuredWidth() / 2;if (releasedChild.getLeft() < centerLeft) {// 在左半边,应该向左缓慢移动//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);invalidate();*/} else {// 在右半边,应该向右缓慢移动viewDragHelper.smoothSlideViewTo(releasedChild,getMeasuredWidth() - releasedChild.getMeasuredWidth(),releasedChild.getTop());ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);invalidate();*/}Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public MyDragViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyDragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyDragViewGroup(Context context) {
super(context);
init();
}
private void init() {
viewDragHelper=ViewDragHelper.create(this, callback1);
scroller=new Scroller(getContext());
}
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 习惯:在此方法中获得子View
redView = (TextView) getChildAt(0);
yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public MyDragViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyDragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyDragViewGroup(Context context) {
super(context);
init();
}
private void init() {
viewDragHelper=ViewDragHelper.create(this, callback1);
scroller=new Scroller(getContext());
}
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 习惯:在此方法中获得子View
redView = (TextView) getChildAt(0);
yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
private void init() {
viewDragHelper=ViewDragHelper.create(this, callback1);
scroller=new Scroller(getContext());
}
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 习惯:在此方法中获得子View
redView = (TextView) getChildAt(0);
yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
private void init() {
viewDragHelper=ViewDragHelper.create(this, callback1);
scroller=new Scroller(getContext());
}
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 习惯:在此方法中获得子View
redView = (TextView) getChildAt(0);
yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 习惯:在此方法中获得子View
redView = (TextView) getChildAt(0);
yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 读取完XML后回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// 习惯:在此方法中获得子View
redView = (TextView) getChildAt(0);
yelloView=(TextView) getChildAt(1);
}
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 测量OnMeasure
* (int widthMeasureSpec, int heightMeasureSpec)为父View测量并传过来的,且widthMeasureSpec属于一个MeasureSpec值
* 这样的话,MyDragViewGroup默认大小Size为在父控件中测量所得的值
* 利用setMeasuredDimension(480,300);//可以重新设置MyDragViewGroup的像素px大小
* 利用getHeight()可以获得当前View'的高度 可以利用 ,尽量使用getMeasuredHeight();
* int Heightsize=MeasureSpec.getSize(heightMeasureSpec);
* int HeightMode=MeasureSpec.getMode(heightMeasureSpec); 获得当前VIewGroup的高宽和精确度模式
*
* 注:
* 作为一个ViewGroup,不在onMeasure中为其子控件测量的话,界面是无法显示子控件的,当然测量完成后还需要Layout摆放才可以显示
* 1.用 子View .measure(W, H);//W,H为 子View 的宽高的MeasureSpec值
* 2.measureChild(redView,widthMeasureSpec, heightMeasureSpec);//测量某个子View,widthMeasureSpec为父View的传值
* 3.measureChildren(widthMeasureSpec, heightMeasureSpec);//测量所有的子View
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
Log.i("widthMeasureSpec", "" + widthMeasureSpec);
Log.i("heightMeasureSpec", "" + heightMeasureSpec);
int Heightsize = MeasureSpec.getSize(heightMeasureSpec);
int HeightMode = MeasureSpec.getMode(heightMeasureSpec);
int Widthsize = MeasureSpec.getSize(widthMeasureSpec);
int WidthMode = MeasureSpec.getMode(widthMeasureSpec);
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
Log.i("Heightsize", "" + Heightsize);
Log.i("HeightMode", "" + HeightMode);
Log.i("Widthsize", "" + Widthsize);
Log.i("WidthMode", "" + WidthMode);
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
int ParentH = ((View) this.getParent()).getMeasuredHeight();// 父控件的高度
Log.i("ParentH", "" + ParentH);
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
// 为子控件测量,定义其宽高
int W = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().width,
MeasureSpec.EXACTLY);
int H = MeasureSpec.makeMeasureSpec(redView.getLayoutParams().height,
MeasureSpec.EXACTLY);
redView.measure(W, H);
yelloView.measure(MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(yelloView.getLayoutParams().height,MeasureSpec.EXACTLY));
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
//measureChild(redView,widthMeasureSpec, heightMeasureSpec);
//measureChild(yelloView,widthMeasureSpec, heightMeasureSpec);
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
for(int i=0;i<getChildCount();i++){
measureChild(getChildAt(i),widthMeasureSpec, heightMeasureSpec);
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
}
*/
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
}
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();
int redViewpaddingL=redView.getPaddingLeft();
int redViewpaddingR=redView.getPaddingRight();
int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 摆放onLayout
* 1.尽量使用getMeasuredWidth()而不是getWidth(),因为getMeasuredWidth为你测量所得的数据,而getWidth()为该控件View加载完毕后的数据,没加载之前为0
* 2.摆放时要考虑到padding问题
*
*/
@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int b) {
//摆放效果:让redView摆在横向居中,正下方为yelloView
int redViewpaddingT=redView.getPaddingTop();int redViewpaddingL=redView.getPaddingLeft();int redViewpaddingR=redView.getPaddingRight();int redViewpaddingB=redView.getPaddingBottom();
int redViewTop=redViewpaddingT+0;
int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;
int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
int redViewTop=redViewpaddingT+0;int redViewLeft=getMeasuredWidth()/2-redView.getMeasuredWidth()/2;int redViewRight=redView.getMeasuredWidth()+getMeasuredWidth()/2-redView.getMeasuredWidth()/2;int redViewBootom=redView.getMeasuredHeight()+redViewpaddingB;
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
redView.layout(redViewLeft,redViewTop,redViewRight,redViewBootom);
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;
int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;
int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;
yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
int yelloTop=yelloView.getPaddingTop()+0+redViewBootom;int yelloLeft=getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;int yelloRight=yelloView.getMeasuredWidth()+getMeasuredWidth()/2-yelloView.getMeasuredWidth()/2;int yelloBottom=yelloView.getPaddingBottom()+yelloView.getMeasuredHeight()+redViewBootom;yelloView.layout(yelloLeft, yelloTop, yelloRight, yelloBottom);
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
}
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
//判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
//判断是否拦截事件@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);return Isintercept;}
//将事件交给viewDragHelper处理
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
//将事件交给viewDragHelper处理@Overridepublic boolean onTouchEvent(MotionEvent event) {viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
return true;//消费掉事件
}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
return true;//消费掉事件}
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
private ViewDragHelper.Callback callback1=new Callback() {
/**返回是否捕捉处理子View事件
* child: 当前触摸的子View return: true:就捕获并解析 false:不处理
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child==yelloView||child==redView;
}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**返回是否捕捉处理子View事件* child: 当前触摸的子View return: true:就捕获并解析 false:不处理*/@Overridepublic boolean tryCaptureView(View child, int pointerId) {return child==yelloView||child==redView;}
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* View被捕获时回调
* capturedChild:当前被捕获的View
*/
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
Log.i("Callback.onViewCaptured", "被捕捉");
}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** View被捕获时回调* capturedChild:当前被捕获的View*/@Overridepublic void onViewCaptured(View capturedChild, int activePointerId) {super.onViewCaptured(capturedChild, activePointerId);Log.i("Callback.onViewCaptured", "被捕捉");}
/**
* 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0
*/
@Override
public int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 获取view水平方向的拖拽范围,但是目前不能限制边界,返回的值目前用在手指抬起的时候view缓慢移动的动画世界的计算上面; 最好不要返回0*/@Overridepublic int getViewHorizontalDragRange(View child) {
return getMeasuredWidth()-child.getMeasuredWidth();
}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
return getMeasuredWidth()-child.getMeasuredWidth();}
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 获得View的拖拽垂直范围
*/
@Override
public int getViewVerticalDragRange(View child) {
return getMeasuredHeight()-child.getMeasuredHeight();
}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 获得View的拖拽垂直范围*/@Overridepublic int getViewVerticalDragRange(View child) {return getMeasuredHeight()-child.getMeasuredHeight();}
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 控制child在水平方向的移动
* left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx
* dx:本次child水平方向移动的距离
* return: 表示你真正想让child的left变成的值
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//限制范围
if(left<0)
left=0;
if(left>getMeasuredWidth()-child.getMeasuredWidth())
left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 控制child在水平方向的移动 * left:表示ViewDragHelper认为你想让当前child的left改变的值,left=chile.getLeft()+dx * dx:本次child水平方向移动的距离* return: 表示你真正想让child的left变成的值*/@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {//限制范围if(left<0)left=0;if(left>getMeasuredWidth()-child.getMeasuredWidth())left=getMeasuredWidth()-child.getMeasuredWidth();
return left;
}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
return left;}
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 控制child在垂直方向的移动
* top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy
* dy:本次child垂直方向移动的距离
* return: 表示你真正想让child的top变成的值
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
/* //限制范围
if (top < 0) {
top = 0;
} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {
top = getMeasuredHeight() - child.getMeasuredHeight();
}
*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 控制child在垂直方向的移动 * top:表示ViewDragHelper认为你想让当前child的top改变的值,top=chile.getTop()+dy * dy:本次child垂直方向移动的距离* return: 表示你真正想让child的top变成的值*/@Overridepublic int clampViewPositionVertical(View child, int top, int dy) {/*//限制范围if (top < 0) {top = 0;} else if (top > getMeasuredHeight() - child.getMeasuredHeight()) {top = getMeasuredHeight() - child.getMeasuredHeight();}*/
//伴随动画的限制范围
if(child==redView){
if(top<0)
top=0;
if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();
}
if(child==yelloView){
if(top<0+redView.getMeasuredHeight())
top=0+redView.getMeasuredHeight();
if(top>getMeasuredHeight()-child.getMeasuredHeight())
top=getMeasuredHeight()-child.getMeasuredHeight();
}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
//伴随动画的限制范围if(child==redView){if(top<0)top=0;if(top>getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight())top=getMeasuredHeight()-child.getMeasuredHeight()-yelloView.getMeasuredHeight();}if(child==yelloView){if(top<0+redView.getMeasuredHeight())top=0+redView.getMeasuredHeight();if(top>getMeasuredHeight()-child.getMeasuredHeight())top=getMeasuredHeight()-child.getMeasuredHeight();}
return top;
}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
return top;}
/**
* 当child的位置改变的时候执行,一般用来做其他子View的伴随移动
* changedView:位置改变的child
* left:child当前最新的left
* top: child当前最新的top
* dx: 本次水平移动的距离
* dy: 本次垂直移动的距离
*/
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
for(int i=0;i<getChildCount();i++){
if(changedView!=getChildAt(i)){
getChildAt(i).layout(getChildAt(i).getLeft()+dx,
getChildAt(i).getTop()+dy,
getChildAt(i).getRight()+dx,
getChildAt(i).getBottom()+dy);
}
}
}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 当child的位置改变的时候执行,一般用来做其他子View的伴随移动 * changedView:位置改变的child* left:child当前最新的left * top: child当前最新的top * dx: 本次水平移动的距离 * dy: 本次垂直移动的距离*/@Overridepublic void onViewPositionChanged(View changedView, int left, int top,int dx, int dy) {super.onViewPositionChanged(changedView, left, top, dx, dy);for(int i=0;i<getChildCount();i++){if(changedView!=getChildAt(i)){getChildAt(i).layout(getChildAt(i).getLeft()+dx,getChildAt(i).getTop()+dy,getChildAt(i).getRight()+dx,getChildAt(i).getBottom()+dy);}}}
/**
* 手指抬起的执行该方法,
* releasedChild:当前抬起的view
* xvel: x方向的移动的速度 正:向右移动, 负:向左移动
* yvel: y方向移动的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
int centerLeft = getMeasuredWidth() / 2
- releasedChild.getMeasuredWidth() / 2;
if (releasedChild.getLeft() < centerLeft) {
// 在左半边,应该向左缓慢移动
//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 手指抬起的执行该方法,* releasedChild:当前抬起的view * xvel: x方向的移动的速度 正:向右移动, 负:向左移动* yvel: y方向移动的速度*/@Overridepublic void onViewReleased(View releasedChild, float xvel, float yvel) {super.onViewReleased(releasedChild, xvel, yvel);int centerLeft = getMeasuredWidth() / 2- releasedChild.getMeasuredWidth() / 2;if (releasedChild.getLeft() < centerLeft) {// 在左半边,应该向左缓慢移动//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新整个个布局
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);
invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*scroller.startScroll(releasedChild.getLeft(), releasedChild.getTop(),-releasedChild.getLeft(), 0,1000);invalidate();*/
} else {
// 在右半边,应该向右缓慢移动
viewDragHelper.smoothSlideViewTo(releasedChild,
getMeasuredWidth() - releasedChild.getMeasuredWidth(),
releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
} else {// 在右半边,应该向右缓慢移动viewDragHelper.smoothSlideViewTo(releasedChild,getMeasuredWidth() - releasedChild.getMeasuredWidth(),releasedChild.getTop());ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);
invalidate();*/
}
Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());
}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*scroller.startScroll(0,0, getMeasuredWidth()-releasedChild.getRight(),0,1000);invalidate();*/}Log.i("AAA", “Left:”+releasedChild.getLeft()+" Top:"+releasedChild.getTop()+" getMeasuredWidth() "+releasedChild.getRight());}
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
};
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
public void computeScroll() {if (viewDragHelper.continueSettling(true)) {ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);}
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),0);
invalidate();
Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());
}*/
};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。scrollTo(scroller.getCurrX(),0);invalidate();Log.i("SSS",""+scroller.getCurrX()+" "+scroller.getCurrY());}*/};
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 笔记
* * 一.View移动的相关方法总结:
1.通过改变view在父View的layout位置来移动,但是只能移动指定的View:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);//同时改变left和right
view.offsetTopAndBottom(offset);//同时改变top和bottom
2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View;
scrollTo(x,y);
scrollBy(xOffset,yOffset);
3.通过改变Canvas绘制的位置来移动View的内容:
canvas.drawBitmap(bitmap, left, top, paint)
二.使用ViewDragHelper来处理移动
1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中
2.它主要用于处理ViewGroup中对子View的拖拽处理
3.它是Google在2013年开发者大会提出的
4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的
方式告诉我们;只需要我们指定是否需要移动,移动多少等;
5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 笔记* * 一.View移动的相关方法总结: 1.通过改变view在父View的layout位置来移动,但是只能移动指定的View: view.layout(l,t,r,b);view.offsetLeftAndRight(offset);//同时改变left和rightview.offsetTopAndBottom(offset);//同时改变top和bottom 2.通过改变scrollX和scrollY来移动,但是可以移动所有的子View; scrollTo(x,y);scrollBy(xOffset,yOffset); 3.通过改变Canvas绘制的位置来移动View的内容: canvas.drawBitmap(bitmap, left, top, paint) 二.使用ViewDragHelper来处理移动 1.ViewDragHelper在高版本的v4包(android4.4以上的v4)中 2.它主要用于处理ViewGroup中对子View的拖拽处理 3.它是Google在2013年开发者大会提出的 4.它主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的 方式告诉我们;只需要我们指定是否需要移动,移动多少等; 5.本质是对触摸事件的解析类;
三.getHeight和getMeasuredHeight的区别:
getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值;
getHeight:只有view执行完layout才能获取到值;
四.
在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的
布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
三.getHeight和getMeasuredHeight的区别: getMeasuredHeight:只要view执行完onMeasure方法就能够获取到值; getHeight:只有view执行完layout才能获取到值; 四. 在自定义ViewGroup的时候,如果对子View的测量没有特殊的需求,那么可以继承系统已有的 布局(比如FrameLayout),目的是为了让已有的布局帮我们实行onMeasure;
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
*/
void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
*/void A1(){
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
}
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/**
* 关于Srcoller滑动处理器
* 作用:让控件自动缓慢滑动到目的地
* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]
*
* 1.scroller.startScroll(startX,startY,dx,dy);
* startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动
* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动
* dx 水平方向滑动的距离,正值会使滚动向左滚动
* dy 垂直方向滑动的距离,正值会使滚动向上滚动
* 2.重写 computeScroll() {}函数
* public void computeScroll() {
if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。
scrollTo(scroller.getCurrX(),scroller.getCurrY());
invalidate();//刷新界面
}
};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
/*** 关于Srcoller滑动处理器* 作用:让控件自动缓慢滑动到目的地* 注:是通过ScrollTo()实现,即通过目的坐标滑动,是滑动整个父View,从而改变显示位置。[ScrollBy()则是通过偏移量滑动,也是滑动整个父View]* * 1.scroller.startScroll(startX,startY,dx,dy);*startX 水平方向滚动的偏移值,以像素为单位。正值表明滚动将向左滚动* startY 垂直方向滚动的偏移值,以像素为单位。正值表明滚动将向上滚动* dx 水平方向滑动的距离,正值会使滚动向左滚动*dy 垂直方向滑动的距离,正值会使滚动向上滚动* 2.重写computeScroll() {}函数* public void computeScroll() {if(scroller.computeScrollOffset()){//如果mScroller没有调用startScroll,这里将会返回false。scrollTo(scroller.getCurrX(),scroller.getCurrY());invalidate();//刷新界面}};
*
*其原理:
* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量
* 再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置
* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)
*
* 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处
*/void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
**其原理:* 先通过StartScroll(。。。)获得起始坐标和需要偏移的坐标量*再将偏移量用时间分割,然后得到每个时间间隔搜需要到达的位置* 再通过ScrollTo(..)到达指定位置(由左上角的坐标为原点进行偏移)* * 当偏移的位置超出View的边界大小时,动画结束后会弹回边界处*/
void A2(){}
/**
* 关于ViewDragHelper笔记:
* 用法一:实现View的拖拽移动
* 1.定义一个ViewDragHelper对象
* ViewDragHelper viewDragHelper=ViewDragHelper.create(this, callback1);
* 2.定义回调Callback对象
* private ViewDragHelper.Callback callback1=new Callback() {
* 。。。。。(重写其方法)
* }
* 3.在 onInterceptTouchEvent(MotionEvent ev)中判断是否拦截事件
* //判断是否拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean Isintercept=viewDragHelper.shouldInterceptTouchEvent(ev);
return Isintercept;
}
*
* 4.在onTouchEvent(。。)中给viewDragHelper赋予事件处理
* @Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);//将事件交给viewDragHelp处理
return true;//消费掉事件
}
*
*用法二:实现View的Scroll效果
*1.//内部封装了Srcoller,不需要自己实现,调用smoothSlideViewTo()
viewDragHelper.smoothSlideViewTo(releasedChild, 0,releasedChild.getTop());
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);//刷新真个布局
*2.重写computeScroll()
* public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(MyDragViewGroup.this);
}
};
*/
void A3(){};
}
效果图:
- 关于自定义ViewGroup的理解和ViewDraghelper的使用
- Android开发,自定义ViewGroup的神器,ViewDragHelper
- 安卓开发之ViewDragHelper的使用及自定义可下拉展示内容的ViewGroup
- ViewDragHelper完全解析以及对自定义ViewGroup的作用
- android关于ViewDragHelper的使用
- 自定义ViewGroup的使用
- 自定义ViewGroup神器ViewDragHelper
- 自定义ViewGroup笔记--ViewDragHelper
- 自定义viewgroup中onMeasure 和onlayout的一点理解
- View和ViewGroup的理解
- Android自定义ViewGroup神器-ViewDragHelper
- android 利用ViewDragHelper实现childView可随手指移动的自定义ViewGroup
- ViewDragHelper的使用
- viewdraghelper的使用
- ViewDragHelper API 的使用
- ViewDragHelper的使用介绍
- ViewDragHelper的使用
- ViewDragHelper的使用
- [置顶] Android网络通信Volley框架源码浅析(三)
- Java基本学习:数组--协变性
- ewqfasdfawe
- 1、VS编程初学第一章:文件读写操作
- swift2.0 学习笔记Fifteen
- 关于自定义ViewGroup的理解和ViewDraghelper的使用
- 互联网
- iOS-App提交App Store上线被拒原因
- 【Redis基础】Redis3.0集群问题集锦
- Nodejs学习 2 -- events事件处理EventEmitter
- 工作脚本处理文本shell
- 万物的原理
- 高分辨率手机OOM的问题
- #LRU算法