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