diff options
Diffstat (limited to 'library/main/src/com/android/setupwizardlib/view/Illustration.java')
-rw-r--r-- | library/main/src/com/android/setupwizardlib/view/Illustration.java | 341 |
1 files changed, 173 insertions, 168 deletions
diff --git a/library/main/src/com/android/setupwizardlib/view/Illustration.java b/library/main/src/com/android/setupwizardlib/view/Illustration.java index c6968f8..e9cd4b5 100644 --- a/library/main/src/com/android/setupwizardlib/view/Illustration.java +++ b/library/main/src/com/android/setupwizardlib/view/Illustration.java @@ -30,7 +30,6 @@ import android.util.LayoutDirection; import android.view.Gravity; import android.view.ViewOutlineProvider; import android.widget.FrameLayout; - import com.android.setupwizardlib.R; /** @@ -39,184 +38,190 @@ import com.android.setupwizardlib.R; * drawable to fit the width of the view and fills the rest with the background. * * <p>If an aspect ratio is set, then the aspect ratio of the source drawable is maintained. - * Otherwise the the aspect ratio will be ignored, only increasing the width of the illustration. + * Otherwise the aspect ratio will be ignored, only increasing the width of the illustration. */ public class Illustration extends FrameLayout { - // Size of the baseline grid in pixels - private float mBaselineGridSize; - private Drawable mBackground; - private Drawable mIllustration; - private final Rect mViewBounds = new Rect(); - private final Rect mIllustrationBounds = new Rect(); - private float mScale = 1.0f; - private float mAspectRatio = 0.0f; - - public Illustration(Context context) { - super(context); - init(null, 0); - } - - public Illustration(Context context, AttributeSet attrs) { - super(context, attrs); - init(attrs, 0); + // Size of the baseline grid in pixels + private float baselineGridSize; + private Drawable background; + private Drawable illustration; + private final Rect viewBounds = new Rect(); + private final Rect illustrationBounds = new Rect(); + private float scale = 1.0f; + private float aspectRatio = 0.0f; + + public Illustration(Context context) { + super(context); + init(null, 0); + } + + public Illustration(Context context, AttributeSet attrs) { + super(context, attrs); + init(attrs, 0); + } + + @TargetApi(VERSION_CODES.HONEYCOMB) + public Illustration(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs, defStyleAttr); + } + + // All the constructors delegate to this init method. The 3-argument constructor is not + // available in FrameLayout before v11, so call super with the exact same arguments. + private void init(AttributeSet attrs, int defStyleAttr) { + if (attrs != null) { + TypedArray a = + getContext().obtainStyledAttributes(attrs, R.styleable.SuwIllustration, defStyleAttr, 0); + aspectRatio = a.getFloat(R.styleable.SuwIllustration_suwAspectRatio, 0.0f); + a.recycle(); } - - @TargetApi(VERSION_CODES.HONEYCOMB) - public Illustration(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(attrs, defStyleAttr); + // Number of pixels of the 8dp baseline grid as defined in material design specs + baselineGridSize = getResources().getDisplayMetrics().density * 8; + setWillNotDraw(false); + } + + /** + * The background will be drawn to fill up the rest of the view. It will also be scaled by the + * same amount as the foreground so their textures look the same. + */ + // Override the deprecated setBackgroundDrawable method to support API < 16. View.setBackground + // forwards to setBackgroundDrawable in the framework implementation. + @SuppressWarnings("deprecation") + @Override + public void setBackgroundDrawable(Drawable background) { + if (background == this.background) { + return; } - - // All the constructors delegate to this init method. The 3-argument constructor is not - // available in FrameLayout before v11, so call super with the exact same arguments. - private void init(AttributeSet attrs, int defStyleAttr) { - if (attrs != null) { - TypedArray a = getContext().obtainStyledAttributes(attrs, - R.styleable.SuwIllustration, defStyleAttr, 0); - mAspectRatio = a.getFloat(R.styleable.SuwIllustration_suwAspectRatio, 0.0f); - a.recycle(); - } - // Number of pixels of the 8dp baseline grid as defined in material design specs - mBaselineGridSize = getResources().getDisplayMetrics().density * 8; - setWillNotDraw(false); - } - - /** - * The background will be drawn to fill up the rest of the view. It will also be scaled by the - * same amount as the foreground so their textures look the same. - */ - // Override the deprecated setBackgroundDrawable method to support API < 16. View.setBackground - // forwards to setBackgroundDrawable in the framework implementation. - @SuppressWarnings("deprecation") - @Override - public void setBackgroundDrawable(Drawable background) { - if (background == mBackground) { - return; - } - mBackground = background; - invalidate(); - requestLayout(); + this.background = background; + invalidate(); + requestLayout(); + } + + /** + * Sets the drawable used as the illustration. The drawable is expected to have intrinsic width + * and height defined and will be scaled to fit the width of the view. + */ + public void setIllustration(Drawable illustration) { + if (illustration == this.illustration) { + return; } - - /** - * Sets the drawable used as the illustration. The drawable is expected to have intrinsic - * width and height defined and will be scaled to fit the width of the view. - */ - public void setIllustration(Drawable illustration) { - if (illustration == mIllustration) { - return; - } - mIllustration = illustration; - invalidate(); - requestLayout(); + this.illustration = illustration; + invalidate(); + requestLayout(); + } + + /** + * Set the aspect ratio reserved for the illustration. This overrides the top padding of the view + * according to the width of this view and the aspect ratio. Children views will start being laid + * out below this aspect ratio. + * + * @param aspectRatio A float value specifying the aspect ratio (= width / height). 0 to not + * override the top padding. + */ + public void setAspectRatio(float aspectRatio) { + this.aspectRatio = aspectRatio; + invalidate(); + requestLayout(); + } + + @Override + @Deprecated + public void setForeground(Drawable d) { + setIllustration(d); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (aspectRatio != 0.0f) { + int parentWidth = MeasureSpec.getSize(widthMeasureSpec); + int illustrationHeight = (int) (parentWidth / aspectRatio); + illustrationHeight = (int) (illustrationHeight - (illustrationHeight % baselineGridSize)); + setPadding(0, illustrationHeight, 0, 0); } - - /** - * Set the aspect ratio reserved for the illustration. This overrides the top padding of the - * view according to the width of this view and the aspect ratio. Children views will start - * being laid out below this aspect ratio. - * - * @param aspectRatio A float value specifying the aspect ratio (= width / height). 0 to not - * override the top padding. - */ - public void setAspectRatio(float aspectRatio) { - mAspectRatio = aspectRatio; - invalidate(); - requestLayout(); + if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + //noinspection AndroidLintInlinedApi + setOutlineProvider(ViewOutlineProvider.BOUNDS); } - - @Override - @Deprecated - public void setForeground(Drawable d) { - setIllustration(d); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final int layoutWidth = right - left; + final int layoutHeight = bottom - top; + if (illustration != null) { + int intrinsicWidth = illustration.getIntrinsicWidth(); + int intrinsicHeight = illustration.getIntrinsicHeight(); + + viewBounds.set(0, 0, layoutWidth, layoutHeight); + if (aspectRatio != 0f) { + scale = layoutWidth / (float) intrinsicWidth; + intrinsicWidth = layoutWidth; + intrinsicHeight = (int) (intrinsicHeight * scale); + } + Gravity.apply( + Gravity.FILL_HORIZONTAL | Gravity.TOP, + intrinsicWidth, + intrinsicHeight, + viewBounds, + illustrationBounds); + illustration.setBounds(illustrationBounds); } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mAspectRatio != 0.0f) { - int parentWidth = MeasureSpec.getSize(widthMeasureSpec); - int illustrationHeight = (int) (parentWidth / mAspectRatio); - illustrationHeight = - (int) (illustrationHeight - (illustrationHeight % mBaselineGridSize)); - setPadding(0, illustrationHeight, 0, 0); - } - if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { - //noinspection AndroidLintInlinedApi - setOutlineProvider(ViewOutlineProvider.BOUNDS); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (background != null) { + // Scale the background bounds by the same scale to compensate for the scale done to the + // canvas in onDraw. + background.setBounds( + 0, + 0, + (int) Math.ceil(layoutWidth / scale), + (int) Math.ceil((layoutHeight - illustrationBounds.height()) / scale)); } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - final int layoutWidth = right - left; - final int layoutHeight = bottom - top; - if (mIllustration != null) { - int intrinsicWidth = mIllustration.getIntrinsicWidth(); - int intrinsicHeight = mIllustration.getIntrinsicHeight(); - - mViewBounds.set(0, 0, layoutWidth, layoutHeight); - if (mAspectRatio != 0f) { - mScale = layoutWidth / (float) intrinsicWidth; - intrinsicWidth = layoutWidth; - intrinsicHeight = (int) (intrinsicHeight * mScale); - } - Gravity.apply(Gravity.FILL_HORIZONTAL | Gravity.TOP, intrinsicWidth, - intrinsicHeight, mViewBounds, mIllustrationBounds); - mIllustration.setBounds(mIllustrationBounds); - } - if (mBackground != null) { - // Scale the background bounds by the same scale to compensate for the scale done to the - // canvas in onDraw. - mBackground.setBounds(0, 0, (int) Math.ceil(layoutWidth / mScale), - (int) Math.ceil((layoutHeight - mIllustrationBounds.height()) / mScale)); - } - super.onLayout(changed, left, top, right, bottom); + super.onLayout(changed, left, top, right, bottom); + } + + @Override + public void onDraw(Canvas canvas) { + if (background != null) { + // Draw the background filling parts not covered by the illustration + canvas.save(); + canvas.translate(0, illustrationBounds.height()); + // Scale the background so its size matches the foreground + canvas.scale(scale, scale, 0, 0); + if (VERSION.SDK_INT > VERSION_CODES.JELLY_BEAN_MR1 + && shouldMirrorDrawable(background, getLayoutDirection())) { + // Flip the illustration for RTL layouts + canvas.scale(-1, 1); + canvas.translate(-background.getBounds().width(), 0); + } + background.draw(canvas); + canvas.restore(); } - - @Override - public void onDraw(Canvas canvas) { - if (mBackground != null) { - // Draw the background filling parts not covered by the illustration - canvas.save(); - canvas.translate(0, mIllustrationBounds.height()); - // Scale the background so its size matches the foreground - canvas.scale(mScale, mScale, 0, 0); - if (VERSION.SDK_INT > VERSION_CODES.JELLY_BEAN_MR1 && - shouldMirrorDrawable(mBackground, getLayoutDirection())) { - // Flip the illustration for RTL layouts - canvas.scale(-1, 1); - canvas.translate(-mBackground.getBounds().width(), 0); - } - mBackground.draw(canvas); - canvas.restore(); - } - if (mIllustration != null) { - canvas.save(); - if (VERSION.SDK_INT > VERSION_CODES.JELLY_BEAN_MR1 && - shouldMirrorDrawable(mIllustration, getLayoutDirection())) { - // Flip the illustration for RTL layouts - canvas.scale(-1, 1); - canvas.translate(-mIllustrationBounds.width(), 0); - } - // Draw the illustration - mIllustration.draw(canvas); - canvas.restore(); - } - super.onDraw(canvas); + if (illustration != null) { + canvas.save(); + if (VERSION.SDK_INT > VERSION_CODES.JELLY_BEAN_MR1 + && shouldMirrorDrawable(illustration, getLayoutDirection())) { + // Flip the illustration for RTL layouts + canvas.scale(-1, 1); + canvas.translate(-illustrationBounds.width(), 0); + } + // Draw the illustration + illustration.draw(canvas); + canvas.restore(); } - - private boolean shouldMirrorDrawable(Drawable drawable, int layoutDirection) { - if (layoutDirection == LayoutDirection.RTL) { - if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { - return drawable.isAutoMirrored(); - } else if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) { - final int flags = getContext().getApplicationInfo().flags; - //noinspection AndroidLintInlinedApi - return (flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0; - } - } - return false; + super.onDraw(canvas); + } + + private boolean shouldMirrorDrawable(Drawable drawable, int layoutDirection) { + if (layoutDirection == LayoutDirection.RTL) { + if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { + return drawable.isAutoMirrored(); + } else if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) { + final int flags = getContext().getApplicationInfo().flags; + //noinspection AndroidLintInlinedApi + return (flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0; + } } + return false; + } } |