FloatingActionButtonImpl.java revision f0aec033caa46d2cdddad020b8748d24f921ad5b
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.content.res.ColorStateList; 20import android.content.res.Resources; 21import android.graphics.Color; 22import android.graphics.PorterDuff; 23import android.graphics.Rect; 24import android.graphics.drawable.Drawable; 25import android.graphics.drawable.GradientDrawable; 26import android.support.annotation.Nullable; 27import android.support.design.R; 28import android.view.ViewTreeObserver; 29import android.view.animation.Interpolator; 30 31abstract class FloatingActionButtonImpl { 32 33 static final Interpolator ANIM_INTERPOLATOR = AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR; 34 static final long PRESSED_ANIM_DURATION = 100; 35 static final long PRESSED_ANIM_DELAY = 100; 36 37 Drawable mShapeDrawable; 38 Drawable mRippleDrawable; 39 CircularBorderDrawable mBorderDrawable; 40 Drawable mContentBackground; 41 42 float mElevation; 43 float mPressedTranslationZ; 44 45 interface InternalVisibilityChangedListener { 46 public void onShown(); 47 public void onHidden(); 48 } 49 50 static final int SHOW_HIDE_ANIM_DURATION = 200; 51 52 static final int[] PRESSED_ENABLED_STATE_SET = {android.R.attr.state_pressed, 53 android.R.attr.state_enabled}; 54 static final int[] FOCUSED_ENABLED_STATE_SET = {android.R.attr.state_focused, 55 android.R.attr.state_enabled}; 56 static final int[] ENABLED_STATE_SET = {android.R.attr.state_enabled}; 57 static final int[] EMPTY_STATE_SET = new int[0]; 58 59 final VisibilityAwareImageButton mView; 60 final ShadowViewDelegate mShadowViewDelegate; 61 62 private final Rect mTmpRect = new Rect(); 63 private ViewTreeObserver.OnPreDrawListener mPreDrawListener; 64 65 FloatingActionButtonImpl(VisibilityAwareImageButton view, 66 ShadowViewDelegate shadowViewDelegate) { 67 mView = view; 68 mShadowViewDelegate = shadowViewDelegate; 69 } 70 71 abstract void setBackgroundDrawable(ColorStateList backgroundTint, 72 PorterDuff.Mode backgroundTintMode, int rippleColor, int borderWidth); 73 74 abstract void setBackgroundTintList(ColorStateList tint); 75 76 abstract void setBackgroundTintMode(PorterDuff.Mode tintMode); 77 78 abstract void setRippleColor(int rippleColor); 79 80 final void setElevation(float elevation) { 81 if (mElevation != elevation) { 82 mElevation = elevation; 83 onElevationsChanged(elevation, mPressedTranslationZ); 84 } 85 } 86 87 abstract float getElevation(); 88 89 final void setPressedTranslationZ(float translationZ) { 90 if (mPressedTranslationZ != translationZ) { 91 mPressedTranslationZ = translationZ; 92 onElevationsChanged(mElevation, translationZ); 93 } 94 } 95 96 abstract void onElevationsChanged(float elevation, float pressedTranslationZ); 97 98 abstract void onDrawableStateChanged(int[] state); 99 100 abstract void jumpDrawableToCurrentState(); 101 102 abstract void hide(@Nullable InternalVisibilityChangedListener listener, boolean fromUser); 103 104 abstract void show(@Nullable InternalVisibilityChangedListener listener, boolean fromUser); 105 106 final Drawable getContentBackground() { 107 return mContentBackground; 108 } 109 110 abstract void onCompatShadowChanged(); 111 112 final void updatePadding() { 113 Rect rect = mTmpRect; 114 getPadding(rect); 115 onPaddingUpdated(rect); 116 mShadowViewDelegate.setShadowPadding(rect.left, rect.top, rect.right, rect.bottom); 117 } 118 119 abstract void getPadding(Rect rect); 120 121 void onPaddingUpdated(Rect padding) {} 122 123 void onAttachedToWindow() { 124 if (requirePreDrawListener()) { 125 ensurePreDrawListener(); 126 mView.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); 127 } 128 } 129 130 void onDetachedFromWindow() { 131 if (mPreDrawListener != null) { 132 mView.getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener); 133 mPreDrawListener = null; 134 } 135 } 136 137 boolean requirePreDrawListener() { 138 return false; 139 } 140 141 CircularBorderDrawable createBorderDrawable(int borderWidth, ColorStateList backgroundTint) { 142 final Resources resources = mView.getResources(); 143 CircularBorderDrawable borderDrawable = newCircularDrawable(); 144 borderDrawable.setGradientColors( 145 resources.getColor(R.color.design_fab_stroke_top_outer_color), 146 resources.getColor(R.color.design_fab_stroke_top_inner_color), 147 resources.getColor(R.color.design_fab_stroke_end_inner_color), 148 resources.getColor(R.color.design_fab_stroke_end_outer_color)); 149 borderDrawable.setBorderWidth(borderWidth); 150 borderDrawable.setBorderTint(backgroundTint); 151 return borderDrawable; 152 } 153 154 CircularBorderDrawable newCircularDrawable() { 155 return new CircularBorderDrawable(); 156 } 157 158 void onPreDraw() { 159 } 160 161 private void ensurePreDrawListener() { 162 if (mPreDrawListener == null) { 163 mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() { 164 @Override 165 public boolean onPreDraw() { 166 FloatingActionButtonImpl.this.onPreDraw(); 167 return true; 168 } 169 }; 170 } 171 } 172 173 GradientDrawable createShapeDrawable() { 174 GradientDrawable d = new GradientDrawable(); 175 d.setShape(GradientDrawable.OVAL); 176 d.setColor(Color.WHITE); 177 return d; 178 } 179} 180