自定义View---继承ViewGroup动效
前言
在做自定义控件的时候,我们首先要选择的是要继承View还是ViewGroup。本文介绍的是自定义控件继承ViewGroup时进行子View的动效。
1.继承选择
我们通常不是直接继承ViewGroup,因为这样的话我们要自己实现onMeasure(要根据MeasureSpec的模式不同测量自己,获取padding值,测量子View以及利用LayoutParams获取margin值),我们还有自己实现onLayout,需要摆放自己和子View。一般情况下,我们会选取继承轻量级的FrameLayout,利用它的默认实现onMeasure,可选择的是否实现onLayout。选择了要要继承的FrameLayout了,接下来就是实现构造,Android Studio的自定义模板:vc,可以帮我们快速实现自定义控件的构造。
常用方法介绍
CustomView(Context context)
在代码中new出自定义控件时被调用
CustomTitleView(Context context, AttributeSet attrs)
读取xml文件后被调用,最终会调用三个参数的构造
onFinishInflate
此方法执行在当前view在布局文件中的xml结束标签读取完后执行。此时已经添加了子View,但是还没有测量。
onSizeChanged
此方法是onMeasure执行之后执行,因此可获取宽高
ViewDragHelper
触摸事件的解析类(如GestureDecetor),需要我们传递给它触摸事件,该类专门用于在ViewGroup中对子View进行拖拽处理。
ViewDragHelper viewDragHelper = ViewDragHelper.create(this, callback);
public boolean onInterceptTouchEvent(MotionEvent ev) {
//让ViewDragHelper帮助我们判断是否应该拦截
boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);
return result;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//将触摸事件传递给ViewDragHelper来解析
viewDragHelper.processTouchEvent(event);
return true;
}
ViewDragHelper.Callback的回调方法
tryCaptureView
判断要对哪个View进行触摸事件的捕获
getViewHorizontalDragRange
用来判断你是否想强制水平滑动的,如果想强制水平滑动,则返回大于0的任意值
clampViewPositionHorizontal
控制子View在水平方向上的移动
clampViewPositionVertical
控制子View在竖直方向上的移动
onViewPositionChanged
当View位置改变的时候执行,可以获取view移动的距离。
ViewDragHelper只是触摸事件的解析类,在这个方法里需要进行真正的动画效果。
移动View的方法:
通过改变View的scroll的坐标来移动:
scrollTo(x,y);//滚动到指定位置
scrollBy(xOffset,yOffset);//滚动多少距离
通过改变View在父View中的布局的位置:
offsetLeftAndRight(offset);//同时更改view的left和right
offsetTopAndBottom(offset);//同时更改view的top和bottom
layout(l,t,r,b);
ViewCompat.offsetLeftAndRight(view,dx);//让view进行伴随移动
在得到子View拖动的百分比fraction,后我们通常要一些算法计算出中间的动画效果,这里我们通常可以利用FloatEvaluator(数值变化),ArgbEvaluator(颜色变化)
float scale = floatEval.evaluate(fraction,1f,0.8f);
view.setScaleY(scale);
view.setScaleX(scale);
int color = (int) argbEval.evaluate(fraction,Color.BLACK,Color.TRANSPARENT);
getBackground().setColorFilter(color,PorterDuff.Mode.SRC_OVER);
onViewReleased
手指抬起的时候执行,通常在这里可以做一些手指抬起时的缓慢移动的动效.这里可以利用ViewCompat进行动画效果(不用传入时长,会计算出一个最优的动画时间)
dragHelper.smoothSlideViewTo(view,left,top);
ViewCompat.postInvalidateOnAnimation(ViewGroup.this);
同时重写computeScroll方法:
@Override
public void computeScroll() {
super.computeScroll();
if(viewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}