1fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson/* 2fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * Copyright (C) 2015 The Android Open Source Project 3fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * 4fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * Licensed under the Apache License, Version 2.0 (the "License"); 5fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * you may not use this file except in compliance with the License. 6fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * You may obtain a copy of the License at 7fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * 8fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * http://www.apache.org/licenses/LICENSE-2.0 9fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * 10fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * Unless required by applicable law or agreed to in writing, software 11fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * distributed under the License is distributed on an "AS IS" BASIS, 12fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * See the License for the specific language governing permissions and 14fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * limitations under the License. 15fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson */ 16fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonpackage com.android.launcher3.allapps; 17fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 18fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.animation.ObjectAnimator; 19fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.content.Context; 20fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.content.res.Resources; 21fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.graphics.Canvas; 22fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.graphics.ColorFilter; 23fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.graphics.PixelFormat; 24fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.graphics.Rect; 25fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.graphics.drawable.Drawable; 265931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyalimport android.view.ContextThemeWrapper; 27fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport android.view.Gravity; 28260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal 292d89ea84530559e2002a3a4009a50bac1e568507Jon Mirandaimport com.android.launcher3.LauncherAnimUtils; 30fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winsonimport com.android.launcher3.R; 315931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyalimport com.android.launcher3.util.Themes; 32fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 33fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson/** 34260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal * This is a custom composite drawable that has a fixed virtual size and dynamically lays out its 35260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal * children images relatively within its bounds. This way, we can reduce the memory usage of a 36260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal * single, large sparsely populated image. 37fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson */ 38260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyalpublic class AllAppsBackgroundDrawable extends Drawable { 39fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 40fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson /** 415931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal * A helper class to position and orient a drawable to be drawn. 42fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson */ 43260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal protected static class TransformedImageDrawable { 44260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal private Drawable mImage; 45260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal private float mXPercent; 46260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal private float mYPercent; 47260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal private int mGravity; 48260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal private int mAlpha; 49fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 50260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal /** 51260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal * @param gravity If one of the Gravity center values, the x and y offset will take the width 52260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal * and height of the image into account to center the image to the offset. 53260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal */ 545931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal public TransformedImageDrawable(Context context, int resourceId, float xPct, float yPct, 55260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal int gravity) { 565931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mImage = context.getDrawable(resourceId); 57260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mXPercent = xPct; 58260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mYPercent = yPct; 59260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mGravity = gravity; 60260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 61fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 62260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal public void setAlpha(int alpha) { 63260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mImage.setAlpha(alpha); 64260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mAlpha = alpha; 65260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 66fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 67260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal public int getAlpha() { 68260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal return mAlpha; 69fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 70260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal 71260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal public void updateBounds(Rect bounds) { 72260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal int width = mImage.getIntrinsicWidth(); 73260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal int height = mImage.getIntrinsicHeight(); 74260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal int left = bounds.left + (int) (mXPercent * bounds.width()); 75260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal int top = bounds.top + (int) (mYPercent * bounds.height()); 76260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal if ((mGravity & Gravity.CENTER_HORIZONTAL) == Gravity.CENTER_HORIZONTAL) { 77260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal left -= (width / 2); 78260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 79260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal if ((mGravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL) { 80260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal top -= (height / 2); 81260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 82260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mImage.setBounds(left, top, left + width, top + height); 83fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 84fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 85260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal public void draw(Canvas canvas) { 86260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal mImage.draw(canvas); 87260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 88fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 89260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal public Rect getBounds() { 90260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal return mImage.getBounds(); 91260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 92260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal } 93fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 94260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal protected final TransformedImageDrawable mHand; 95260b07fa86865481ab3e1c6d4fec3ef52ba0a621Sunny Goyal protected final TransformedImageDrawable[] mIcons; 96fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson private final int mWidth; 97fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson private final int mHeight; 98fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 99fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson private ObjectAnimator mBackgroundAnim; 100fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 101fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public AllAppsBackgroundDrawable(Context context) { 102fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson Resources res = context.getResources(); 1035931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mWidth = res.getDimensionPixelSize(R.dimen.all_apps_background_canvas_width); 1045931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mHeight = res.getDimensionPixelSize(R.dimen.all_apps_background_canvas_height); 1055931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal 1065931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal context = new ContextThemeWrapper(context, 1075931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal Themes.getAttrBoolean(context, R.attr.isMainColorDark) 1085931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal ? R.style.AllAppsEmptySearchBackground_Dark 1095931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal : R.style.AllAppsEmptySearchBackground); 1105931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mHand = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_hand, 11157b4006d523d9522dc20a3170c1df73907687d21Sunny Goyal 0.575f, 0.f, Gravity.CENTER_HORIZONTAL); 112fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mIcons = new TransformedImageDrawable[4]; 1135931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mIcons[0] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_1, 114fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 0.375f, 0, Gravity.CENTER_HORIZONTAL); 1155931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mIcons[1] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_2, 11657b4006d523d9522dc20a3170c1df73907687d21Sunny Goyal 0.3125f, 0.2f, Gravity.CENTER_HORIZONTAL); 1175931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mIcons[2] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_3, 11857b4006d523d9522dc20a3170c1df73907687d21Sunny Goyal 0.475f, 0.26f, Gravity.CENTER_HORIZONTAL); 1195931ca04155a7fcdfc1dc0665011a44101afda5fSunny Goyal mIcons[3] = new TransformedImageDrawable(context, R.drawable.ic_all_apps_bg_icon_4, 120fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 0.7f, 0.125f, Gravity.CENTER_HORIZONTAL); 121fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 122fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 123fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson /** 124fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * Animates the background alpha. 125fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson */ 126fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public void animateBgAlpha(float finalAlpha, int duration) { 127fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson int finalAlphaI = (int) (finalAlpha * 255f); 128fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson if (getAlpha() != finalAlphaI) { 129fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mBackgroundAnim = cancelAnimator(mBackgroundAnim); 1302d89ea84530559e2002a3a4009a50bac1e568507Jon Miranda mBackgroundAnim = ObjectAnimator.ofInt(this, LauncherAnimUtils.DRAWABLE_ALPHA, 1312d89ea84530559e2002a3a4009a50bac1e568507Jon Miranda finalAlphaI); 132fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mBackgroundAnim.setDuration(duration); 133fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mBackgroundAnim.start(); 134fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 135fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 136fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 137fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson /** 138fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson * Sets the background alpha immediately. 139fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson */ 140fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public void setBgAlpha(float finalAlpha) { 141fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson int finalAlphaI = (int) (finalAlpha * 255f); 142fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson if (getAlpha() != finalAlphaI) { 143fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mBackgroundAnim = cancelAnimator(mBackgroundAnim); 144fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson setAlpha(finalAlphaI); 145fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 146fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 147fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 148fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 149fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public int getIntrinsicWidth() { 150fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson return mWidth; 151fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 152fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 153fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 154fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public int getIntrinsicHeight() { 155fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson return mHeight; 156fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 157fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 158fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 159fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public void draw(Canvas canvas) { 160fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mHand.draw(canvas); 161fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson for (int i = 0; i < mIcons.length; i++) { 162fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mIcons[i].draw(canvas); 163fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 164fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 165fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 166fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 167fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson protected void onBoundsChange(Rect bounds) { 168fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson super.onBoundsChange(bounds); 169fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mHand.updateBounds(bounds); 170fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson for (int i = 0; i < mIcons.length; i++) { 171fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mIcons[i].updateBounds(bounds); 172fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 173fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson invalidateSelf(); 174fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 175fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 176fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 177fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public void setAlpha(int alpha) { 178fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mHand.setAlpha(alpha); 179fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson for (int i = 0; i < mIcons.length; i++) { 180fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson mIcons[i].setAlpha(alpha); 181fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 182fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson invalidateSelf(); 183fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 184fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 185fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 186fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public int getAlpha() { 187fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson return mHand.getAlpha(); 188fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 189fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 190fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 191fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public void setColorFilter(ColorFilter colorFilter) { 192fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson // Do nothing 193fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 194fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 195fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson @Override 196fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson public int getOpacity() { 197fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson return PixelFormat.TRANSLUCENT; 198fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 199fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson 200fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson private ObjectAnimator cancelAnimator(ObjectAnimator animator) { 201fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson if (animator != null) { 202fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson animator.cancel(); 203fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 204fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson return null; 205fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson } 206fee206f2419a0ffa90abf4f9f3f9e0b6d0b74906Winson} 207