最近看了《android开发艺术探索》中的几个关于自定义View的章节,感到知识点有点多,而且书上最后自定义View的例子比较初级,于是我就找到一个最近用过的TapBarMenu的源码试着分析,巩固学习成果。
首先在构造器中调用init方法如下:
private void init(AttributeSet attrs) {
setWillNotDraw(false);
setupAttributes(attrs);
setGravity(Gravity.CENTER);
setupAnimators();
setupPaint();
});
}
setupAttrirbutes方法初始化view的各种属性。其中
if (typedArray.hasValue(R.styleable.TapBarMenu_tbm_iconOpened)) {
iconOpenedDrawable = typedArray.getDrawable(R.styleable.TapBarMenu_tbm_iconOpened);
} else {
iconOpenedDrawable = ResourcesCompat.getDrawable(getContext(), R.drawable.icon_animated);
}
意思为如果用户在xml中设置了tbm_iconOpened属性,则加载用户的布局,若没设置,则加载默认的布局icon_animated
setupAnimators方法加载动画所需的ValueAnimator,他通过定义一个ValueAnimator数组,在addUpdateListener的onAnimationUpdate方法实时更新view轮廓尺寸。最后通过AnimatorSet将ValueAnimator组合起来。
setupPaint方法初始化画笔,定义颜色。
其次在onAttachedToWindow方法中调用setupMenuItems方法,setupMenuItems中初始化Menu中的按钮,Menu关闭时,设GOES,打开时,设VISIBLE 。onAttachedToWindow在Draw过程之前调用。
然后是toggle方法,此方法用户用java代码在menu点击时调用,通过state标志值调用open或close.
open与close实现相似,我们以open为例。
public void open() {
state = State.OPENED;
showIcons(true);
animator[LEFT].setFloatValues(button[LEFT], 0);
animator[RIGHT].setFloatValues(button[RIGHT], width);
animator[RADIUS].setFloatValues(button[RADIUS], 0);
animator[TOP].setFloatValues(button[TOP], 0);
animator[BOTTOM].setFloatValues(button[BOTTOM], height);
animatorSet.cancel();
animatorSet.start();
if (iconOpenedDrawable instanceof Animatable) {
((Animatable) iconOpenedDrawable).start();
}
ViewGroup parentView = (ViewGroup) TapBarMenu.this.getParent();
this.animate()
.y(menuAnchor == MENU_ANCHOR_BOTTOM ? parentView.getBottom() - height : 0)
.setDuration(animationDuration)
.setInterpolator(DECELERATE_INTERPOLATOR)
.start();
}
首先设置状态值。然后调用了showIcons方法,此方法通过动画显示menu内部的子view。接着利用ValueAnimator数组开始动画,而后调用iconOpenedDrawable的View动画(定义在res/anim中)。最后调用menu的ViewPropertyAnimator改变menu的大小。
至此TapBarMenu开关动画原理介绍完毕。下一篇我们分析其绘制原理。