大淘客网站怎么做,推广黄冈软件必备软件,wordpress网站维护插件,嘉兴信息网站之前在实现控件阴影时有提到过#xff0c;阴影效果的实现采用的是Android原生的View的属性#xff0c;拔高Z轴。Z轴会让View产生阴影的效果。
Zelevation translationZ 拔高Z轴可以通过控制elevation和translationZ。 我们之前是通过elevation来单纯的控制Z轴#xff1b;而…之前在实现控件阴影时有提到过阴影效果的实现采用的是Android原生的View的属性拔高Z轴。Z轴会让View产生阴影的效果。
Zelevation translationZ 拔高Z轴可以通过控制elevation和translationZ。 我们之前是通过elevation来单纯的控制Z轴而translateZ除了控制Z轴还可以用来控制动画效果比如我们点击按钮时希望它有一个弹起的效果就是借助这个属性来实现。
StateAnimatorView接口
创建一个通用接口
public interface StateAnimatorView {void setStateAnimator(StateAnimator stateAnimator);StateAnimator getStateAnimator();
}实现接口
ShapeButton 实现 StateAnimatorView接口 // -------------------------------// stateAnimator// -------------------------------private StateAnimator stateAnimator new StateAnimator(this);Overridepublic void setStateAnimator(StateAnimator stateAnimator) {this.stateAnimator stateAnimator;}Overridepublic StateAnimator getStateAnimator() {return stateAnimator;}StateAnimator
StateAnimator是一个管理View状态和相关Animator的类
public class StateAnimator {private final ArrayListTuple mTuples new ArrayList();private Tuple lastMatch null;private Animator runningAnimation null;private WeakReferenceView viewRef;public StateAnimator(View target) {setTarget(target);}private Animator.AnimatorListener mAnimationListener new Animator.AnimatorListener() {Overridepublic void onAnimationStart(Animator animation) {}Overridepublic void onAnimationEnd(Animator animation) {if (runningAnimation animation) {runningAnimation null;}}Overridepublic void onAnimationCancel(Animator animation) {}Overridepublic void onAnimationRepeat(Animator animation) {}};/*** Associates the given Animation with the provided drawable state specs so that it will be run* when the Views drawable state matches the specs.** param specs drawable state specs to match against* param animation The Animation to run when the specs match*/public void addState(int[] specs, Animator animation, Animator.AnimatorListener listener) {Tuple tuple new Tuple(specs, animation, listener);animation.addListener(mAnimationListener);mTuples.add(tuple);}/*** Returns the current {link Animation} which is started because of a state change.** return The currently running Animation or null if no Animation is running*/Animator getRunningAnimation() {return runningAnimation;}View getTarget() {return viewRef null ? null : viewRef.get();}void setTarget(View view) {final View current getTarget();if (current view) {return;}if (current ! null) {clearTarget();}if (view ! null) {viewRef new WeakReference(view);}}private void clearTarget() {viewRef null;lastMatch null;runningAnimation null;}/*** Called by View*/public void setState(int[] state) {Tuple match null;final int count mTuples.size();for (int i 0; i count; i) {final Tuple tuple mTuples.get(i);if (StateSet.stateSetMatches(tuple.mSpecs, state)) {match tuple;break;}}if (match lastMatch) {return;}if (lastMatch ! null) {cancel();}lastMatch match;View view (View) viewRef.get();if (match ! null view ! null view.getVisibility() View.VISIBLE) {start(match);}}private void start(Tuple match) {match.getListener().onAnimationStart(match.animation);runningAnimation match.animation;runningAnimation.start();}private void cancel() {if (runningAnimation ! null runningAnimation.isRunning()) {runningAnimation.cancel();runningAnimation null;}}/*** hide*/ArrayListTuple getTuples() {return mTuples;}static class Tuple {final int[] mSpecs;final Animator animation;private Animator.AnimatorListener listener;private Tuple(int[] specs, Animator Animation, Animator.AnimatorListener listener) {mSpecs specs;animation Animation;this.listener listener;}int[] getSpecs() {return mSpecs;}Animator getAnimation() {return animation;}public Animator.AnimatorListener getListener() {return listener;}}}
在初始化阴影属性的地方初始化StateAnimation:
public static void initElevation(ShadowView view, TypedArray a, int[] ids) {int carbon_elevation ids[0];int carbon_shadowColor ids[1];int carbon_ambientShadowColor ids[2];int carbon_spotShadowColor ids[3];float elevation a.getDimension(carbon_elevation, 0);view.setElevation(elevation);// 初始化StateAnimationif (elevation 0)AnimUtils.setupElevationAnimator(((StateAnimatorView) view).getStateAnimator(), view);ColorStateList shadowColor a.getColorStateList(carbon_shadowColor);view.setElevationShadowColor(shadowColor ! null ? shadowColor.withAlpha(255) : null);if (a.hasValue(carbon_ambientShadowColor)) {ColorStateList ambientShadowColor a.getColorStateList(carbon_ambientShadowColor);view.setOutlineAmbientShadowColor(ambientShadowColor ! null ? ambientShadowColor.withAlpha(255) : null);}if (a.hasValue(carbon_spotShadowColor)) {ColorStateList spotShadowColor a.getColorStateList(carbon_spotShadowColor);view.setOutlineSpotShadowColor(spotShadowColor ! null ? spotShadowColor.withAlpha(255) : null);}}按下按钮和松开按钮的状态和动画是一一对应的 public static void setupElevationAnimator(StateAnimator stateAnimator, final ShadowView view) {// 按下时的状态和动画{final ValueAnimator animator ValueAnimator.ofFloat(0, 0);animator.setDuration(SHORT_ANIMATION_DURATION);animator.setInterpolator(new FastOutSlowInInterpolator());Animator.AnimatorListener animatorListener new AnimatorListenerAdapter() {Overridepublic void onAnimationStart(Animator animation) {float elevationOrTranslationZ getElevationOrTranslationZ(view);animator.setFloatValues(0, elevationOrTranslationZ);}};animator.addUpdateListener(animation - view.setTranslationZ((Float) animation.getAnimatedValue()));stateAnimator.addState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}, animator, animatorListener);}// 松开时的状态和动画{final ValueAnimator animator ValueAnimator.ofFloat(0, 0);animator.setDuration(SHORT_ANIMATION_DURATION);animator.setInterpolator(new FastOutSlowInInterpolator());Animator.AnimatorListener animatorListener new AnimatorListenerAdapter() {Overridepublic void onAnimationStart(Animator animation) {float elevationOrTranslationZ getElevationOrTranslationZ(view);animator.setFloatValues(elevationOrTranslationZ, 0);}};animator.addUpdateListener(animation - view.setTranslationZ((Float) animation.getAnimatedValue()));stateAnimator.addState(new int[]{-android.R.attr.state_pressed, android.R.attr.state_enabled}, animator, animatorListener);}// 松开时的状态和动画{final ValueAnimator animator ValueAnimator.ofFloat(0, 0);animator.setDuration(SHORT_ANIMATION_DURATION);animator.setInterpolator(new FastOutSlowInInterpolator());Animator.AnimatorListener animatorListener new AnimatorListenerAdapter() {Overridepublic void onAnimationStart(Animator animation) {animator.setFloatValues(view.getElevation(), 0);}};animator.addUpdateListener(animation - view.setTranslationZ((Float) animation.getAnimatedValue()));stateAnimator.addState(new int[]{android.R.attr.state_enabled}, animator, animatorListener);}}开始动画
在按下或松开按钮时会回调按钮的drawableStateChanged(): Overrideprotected void drawableStateChanged() {super.drawableStateChanged();if (rippleDrawable ! null rippleDrawable.getStyle() ! RippleDrawable.Style.Background)rippleDrawable.setState(getDrawableState());if (stateAnimator ! null)// 这个方法会执行与状态相对应的动画stateAnimator.setState(getDrawableState());}完整代码可查看 ShapeButton部分