1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.design.widget; 18 19import android.animation.Animator; 20import android.animation.ObjectAnimator; 21import android.animation.StateListAnimator; 22import android.annotation.TargetApi; 23import android.content.res.ColorStateList; 24import android.graphics.PorterDuff; 25import android.graphics.drawable.Drawable; 26import android.graphics.drawable.LayerDrawable; 27import android.graphics.drawable.RippleDrawable; 28import android.os.Build; 29import android.support.v4.graphics.drawable.DrawableCompat; 30import android.support.v4.view.ViewCompat; 31import android.view.View; 32import android.view.animation.AnimationUtils; 33import android.view.animation.Interpolator; 34 35@TargetApi(Build.VERSION_CODES.LOLLIPOP) 36class FloatingActionButtonLollipop extends FloatingActionButtonHoneycombMr1 { 37 38 private Drawable mShapeDrawable; 39 private RippleDrawable mRippleDrawable; 40 private Drawable mBorderDrawable; 41 42 private Interpolator mInterpolator; 43 44 FloatingActionButtonLollipop(View view, ShadowViewDelegate shadowViewDelegate) { 45 super(view, shadowViewDelegate); 46 47 if (!view.isInEditMode()) { 48 mInterpolator = AnimationUtils.loadInterpolator(mView.getContext(), 49 android.R.interpolator.fast_out_slow_in); 50 } 51 } 52 53 @Override 54 void setBackgroundDrawable(Drawable originalBackground, ColorStateList backgroundTint, 55 PorterDuff.Mode backgroundTintMode, int rippleColor, int borderWidth) { 56 // Now we need to tint the original background with the tint 57 mShapeDrawable = DrawableCompat.wrap(originalBackground.mutate()); 58 DrawableCompat.setTintList(mShapeDrawable, backgroundTint); 59 if (backgroundTintMode != null) { 60 DrawableCompat.setTintMode(mShapeDrawable, backgroundTintMode); 61 } 62 63 final Drawable rippleContent; 64 if (borderWidth > 0) { 65 mBorderDrawable = createBorderDrawable(borderWidth, backgroundTint); 66 rippleContent = new LayerDrawable(new Drawable[]{mBorderDrawable, mShapeDrawable}); 67 } else { 68 mBorderDrawable = null; 69 rippleContent = mShapeDrawable; 70 } 71 72 mRippleDrawable = new RippleDrawable(ColorStateList.valueOf(rippleColor), 73 rippleContent, null); 74 75 mShadowViewDelegate.setBackgroundDrawable(mRippleDrawable); 76 mShadowViewDelegate.setShadowPadding(0, 0, 0, 0); 77 } 78 79 @Override 80 void setBackgroundTintList(ColorStateList tint) { 81 DrawableCompat.setTintList(mShapeDrawable, tint); 82 if (mBorderDrawable != null) { 83 DrawableCompat.setTintList(mBorderDrawable, tint); 84 } 85 } 86 87 @Override 88 void setBackgroundTintMode(PorterDuff.Mode tintMode) { 89 DrawableCompat.setTintMode(mShapeDrawable, tintMode); 90 } 91 92 @Override 93 void setRippleColor(int rippleColor) { 94 mRippleDrawable.setColor(ColorStateList.valueOf(rippleColor)); 95 } 96 97 @Override 98 public void setElevation(float elevation) { 99 ViewCompat.setElevation(mView, elevation); 100 } 101 102 @Override 103 void setPressedTranslationZ(float translationZ) { 104 StateListAnimator stateListAnimator = new StateListAnimator(); 105 106 // Animate translationZ to our value when pressed or focused 107 stateListAnimator.addState(PRESSED_ENABLED_STATE_SET, 108 setupAnimator(ObjectAnimator.ofFloat(mView, "translationZ", translationZ))); 109 stateListAnimator.addState(FOCUSED_ENABLED_STATE_SET, 110 setupAnimator(ObjectAnimator.ofFloat(mView, "translationZ", translationZ))); 111 // Animate translationZ to 0 otherwise 112 stateListAnimator.addState(EMPTY_STATE_SET, 113 setupAnimator(ObjectAnimator.ofFloat(mView, "translationZ", 0f))); 114 115 mView.setStateListAnimator(stateListAnimator); 116 } 117 118 @Override 119 void onDrawableStateChanged(int[] state) { 120 // no-op 121 } 122 123 @Override 124 void jumpDrawableToCurrentState() { 125 // no-op 126 } 127 128 private Animator setupAnimator(Animator animator) { 129 animator.setInterpolator(mInterpolator); 130 return animator; 131 } 132 133 @Override 134 CircularBorderDrawable newCircularDrawable() { 135 return new CircularBorderDrawableLollipop(); 136 } 137} 138