1 /*
2  * Copyright (C) 2019 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 package com.android.car.apps.common;
17 
18 import android.content.Context;
19 import android.content.res.TypedArray;
20 import android.graphics.Bitmap;
21 import android.graphics.drawable.BitmapDrawable;
22 import android.graphics.drawable.Drawable;
23 import android.util.AttributeSet;
24 import android.util.Size;
25 import android.view.View;
26 
27 import androidx.annotation.Nullable;
28 import androidx.constraintlayout.widget.ConstraintLayout;
29 
30 /**
31  * A View to place a large, blurred image in the background.
32  * Intended for Car's Dialer and Media apps.
33  */
34 public class BackgroundImageView extends ConstraintLayout {
35 
36     private CrossfadeImageView mImageView;
37 
38     /** Configuration (controlled from resources) */
39     private Size mBitmapTargetSize;
40     private float mBitmapBlurPercent;
41 
42     private View mDarkeningScrim;
43 
BackgroundImageView(Context context)44     public BackgroundImageView(Context context) {
45         this(context, null);
46     }
47 
BackgroundImageView(Context context, AttributeSet attrs)48     public BackgroundImageView(Context context, AttributeSet attrs) {
49         this(context, attrs, R.attr.backgroundImageViewStyle);
50     }
51 
BackgroundImageView(Context context, AttributeSet attrs, int defStyle)52     public BackgroundImageView(Context context, AttributeSet attrs, int defStyle) {
53         super(context, attrs, defStyle);
54 
55         inflate(getContext(), R.layout.background_image, this);
56 
57         mImageView = findViewById(R.id.background_image_image);
58         mDarkeningScrim = findViewById(R.id.background_image_darkening_scrim);
59 
60         int size = getResources().getInteger(R.integer.background_bitmap_target_size_px);
61         mBitmapTargetSize = new Size(size, size);
62         mBitmapBlurPercent = getResources().getFloat(R.dimen.background_bitmap_blur_percent);
63 
64         TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
65                 R.styleable.BackgroundImageView, defStyle, 0);
66 
67         try {
68             setImageAdditionalScale(a.getFloat(R.styleable.BackgroundImageView_imageAdditionalScale,
69                     1.05f));
70         } finally {
71             a.recycle();
72         }
73     }
74 
75     /**
76      * @deprecated Use {@link #setBackgroundDrawable} instead, and make sure to only call when the
77      * image is actually different! TODO(b/139387273).
78      * Sets the image to display to a bitmap
79      * @param bitmap The image to show. It will be scaled to the correct size and blurred.
80      * @param showAnimation Whether or not to cross fade to the new image
81      */
82     @Deprecated
setBackgroundImage(@ullable Bitmap bitmap, boolean showAnimation)83     public void setBackgroundImage(@Nullable Bitmap bitmap, boolean showAnimation) {
84         Drawable drawable = (bitmap != null) ? new BitmapDrawable(bitmap) : null;
85         updateBlur(drawable, showAnimation);
86     }
87 
88     /** Sets the drawable that will be displayed blurred by this view. */
setBackgroundDrawable(@ullable Drawable drawable)89     public void setBackgroundDrawable(@Nullable Drawable drawable) {
90         setBackgroundDrawable(drawable, true);
91     }
92 
93     /**
94      * Sets the drawable that will be displayed blurred by this view specifying if animation is
95      * enabled.
96      */
setBackgroundDrawable(@ullable Drawable drawable, boolean showAnimation)97     public void setBackgroundDrawable(@Nullable Drawable drawable, boolean showAnimation) {
98         updateBlur(drawable, showAnimation);
99     }
100 
updateBlur(@ullable Drawable drawable, boolean showAnimation)101     private void updateBlur(@Nullable Drawable drawable, boolean showAnimation) {
102         if (drawable == null) {
103             mImageView.setImageBitmap(null, false);
104             return;
105         }
106 
107         Bitmap src = BitmapUtils.fromDrawable(drawable, mBitmapTargetSize);
108         Bitmap blurred = ImageUtils.blur(getContext(), src, mBitmapTargetSize, mBitmapBlurPercent);
109         mImageView.setImageBitmap(blurred, showAnimation);
110         invalidate();
111         requestLayout();
112     }
113 
114     /** Sets the background to a color */
setBackgroundColor(int color)115     public void setBackgroundColor(int color) {
116         mImageView.setBackgroundColor(color);
117     }
118 
119     /** Dims/undims the background image by 30% */
setDimmed(boolean dim)120     public void setDimmed(boolean dim) {
121         mDarkeningScrim.setVisibility(dim ? View.VISIBLE : View.GONE);
122     }
123 
124     /**
125      * Sets a scale to be applied on top of the scaling that was used to fit the
126      * image to the frame of the view.
127      *
128      * See {@link
129      * com.android.car.apps.common.CropAlignedImageView#setImageAdditionalScale(float)}
130      * for more details.
131      */
setImageAdditionalScale(float scale)132     public void setImageAdditionalScale(float scale) {
133         mImageView.setImageAdditionalScale(scale);
134     }
135 }
136