diff --git a/proguard.flags b/proguard.flags index 6cbab08e2c..2ad9cacf21 100644 --- a/proguard.flags +++ b/proguard.flags @@ -82,6 +82,10 @@ *; } +-keep class com.android.launcher3.graphics.ShadowDrawable { + public (...); +} + # Proguard will strip methods required for talkback to properly scroll to # next row when focus is on the last item of last row when using a RecyclerView # Keep optimized and shrunk proguard to prevent issues like this when using diff --git a/res/drawable-hdpi/ic_info_launcher.png b/res/drawable-hdpi/ic_info_launcher.png deleted file mode 100644 index 11162e1e78..0000000000 Binary files a/res/drawable-hdpi/ic_info_launcher.png and /dev/null differ diff --git a/res/drawable-hdpi/ic_remove_launcher.png b/res/drawable-hdpi/ic_remove_launcher.png deleted file mode 100644 index ad2b9af249..0000000000 Binary files a/res/drawable-hdpi/ic_remove_launcher.png and /dev/null differ diff --git a/res/drawable-hdpi/ic_uninstall_launcher.png b/res/drawable-hdpi/ic_uninstall_launcher.png deleted file mode 100644 index 426683c6de..0000000000 Binary files a/res/drawable-hdpi/ic_uninstall_launcher.png and /dev/null differ diff --git a/res/drawable-mdpi/ic_info_launcher.png b/res/drawable-mdpi/ic_info_launcher.png deleted file mode 100644 index 6fbe5e3958..0000000000 Binary files a/res/drawable-mdpi/ic_info_launcher.png and /dev/null differ diff --git a/res/drawable-mdpi/ic_remove_launcher.png b/res/drawable-mdpi/ic_remove_launcher.png deleted file mode 100644 index 2bb281d599..0000000000 Binary files a/res/drawable-mdpi/ic_remove_launcher.png and /dev/null differ diff --git a/res/drawable-mdpi/ic_uninstall_launcher.png b/res/drawable-mdpi/ic_uninstall_launcher.png deleted file mode 100644 index bfcbc6dfa2..0000000000 Binary files a/res/drawable-mdpi/ic_uninstall_launcher.png and /dev/null differ diff --git a/res/drawable-v24/ic_info_shadow.xml b/res/drawable-v24/ic_info_shadow.xml new file mode 100644 index 0000000000..9bd7e16d0b --- /dev/null +++ b/res/drawable-v24/ic_info_shadow.xml @@ -0,0 +1,18 @@ + + + diff --git a/res/drawable-v24/ic_remove_shadow.xml b/res/drawable-v24/ic_remove_shadow.xml new file mode 100644 index 0000000000..16a630e5fa --- /dev/null +++ b/res/drawable-v24/ic_remove_shadow.xml @@ -0,0 +1,18 @@ + + + diff --git a/res/drawable-v24/ic_uninstall_shadow.xml b/res/drawable-v24/ic_uninstall_shadow.xml new file mode 100644 index 0000000000..2532157abc --- /dev/null +++ b/res/drawable-v24/ic_uninstall_shadow.xml @@ -0,0 +1,18 @@ + + + diff --git a/res/drawable-xhdpi/ic_info_launcher.png b/res/drawable-xhdpi/ic_info_launcher.png deleted file mode 100644 index 041f2b3c0c..0000000000 Binary files a/res/drawable-xhdpi/ic_info_launcher.png and /dev/null differ diff --git a/res/drawable-xhdpi/ic_remove_launcher.png b/res/drawable-xhdpi/ic_remove_launcher.png deleted file mode 100644 index ff94eb8e90..0000000000 Binary files a/res/drawable-xhdpi/ic_remove_launcher.png and /dev/null differ diff --git a/res/drawable-xhdpi/ic_uninstall_launcher.png b/res/drawable-xhdpi/ic_uninstall_launcher.png deleted file mode 100644 index 2c7ab56e95..0000000000 Binary files a/res/drawable-xhdpi/ic_uninstall_launcher.png and /dev/null differ diff --git a/res/drawable-xxhdpi/ic_info_launcher.png b/res/drawable-xxhdpi/ic_info_launcher.png deleted file mode 100644 index 8e602da02c..0000000000 Binary files a/res/drawable-xxhdpi/ic_info_launcher.png and /dev/null differ diff --git a/res/drawable-xxhdpi/ic_remove_launcher.png b/res/drawable-xxhdpi/ic_remove_launcher.png deleted file mode 100644 index 78ca0804c5..0000000000 Binary files a/res/drawable-xxhdpi/ic_remove_launcher.png and /dev/null differ diff --git a/res/drawable-xxhdpi/ic_uninstall_launcher.png b/res/drawable-xxhdpi/ic_uninstall_launcher.png deleted file mode 100644 index 43aba6ec09..0000000000 Binary files a/res/drawable-xxhdpi/ic_uninstall_launcher.png and /dev/null differ diff --git a/res/drawable-xxxhdpi/ic_info_launcher.png b/res/drawable-xxxhdpi/ic_info_launcher.png deleted file mode 100644 index 3540de1a16..0000000000 Binary files a/res/drawable-xxxhdpi/ic_info_launcher.png and /dev/null differ diff --git a/res/drawable-xxxhdpi/ic_remove_launcher.png b/res/drawable-xxxhdpi/ic_remove_launcher.png deleted file mode 100644 index 418d81ad6a..0000000000 Binary files a/res/drawable-xxxhdpi/ic_remove_launcher.png and /dev/null differ diff --git a/res/drawable-xxxhdpi/ic_uninstall_launcher.png b/res/drawable-xxxhdpi/ic_uninstall_launcher.png deleted file mode 100644 index 724437a2a5..0000000000 Binary files a/res/drawable-xxxhdpi/ic_uninstall_launcher.png and /dev/null differ diff --git a/res/drawable/ic_info_no_shadow.xml b/res/drawable/ic_info_no_shadow.xml index 5f145c9f1a..91a3a565ab 100644 --- a/res/drawable/ic_info_no_shadow.xml +++ b/res/drawable/ic_info_no_shadow.xml @@ -17,8 +17,9 @@ android:width="24dp" android:height="24dp" android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportHeight="24.0" + android:tint="?android:attr/textColorPrimary" > diff --git a/res/drawable/ic_remove_no_shadow.xml b/res/drawable/ic_remove_no_shadow.xml new file mode 100644 index 0000000000..ef538a6111 --- /dev/null +++ b/res/drawable/ic_remove_no_shadow.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/drawable/ic_uninstall_no_shadow.xml b/res/drawable/ic_uninstall_no_shadow.xml new file mode 100644 index 0000000000..5bab4222eb --- /dev/null +++ b/res/drawable/ic_uninstall_no_shadow.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/layout/drop_target_bar_horz.xml b/res/layout/drop_target_bar_horz.xml index fcbb54e397..ed18192c5b 100644 --- a/res/layout/drop_target_bar_horz.xml +++ b/res/layout/drop_target_bar_horz.xml @@ -20,6 +20,7 @@ android:theme="@style/HomeScreenElementTheme" android:layout_width="match_parent" android:layout_height="@dimen/dynamic_grid_drop_target_size" + android:visibility="invisible" android:layout_gravity="center_horizontal|top" android:focusable="false"> diff --git a/res/layout/drop_target_bar_vert.xml b/res/layout/drop_target_bar_vert.xml index 54d9dfe3af..e2a65d4a55 100644 --- a/res/layout/drop_target_bar_vert.xml +++ b/res/layout/drop_target_bar_vert.xml @@ -21,6 +21,7 @@ android:orientation="vertical" android:layout_height="match_parent" android:layout_gravity="left" + android:visibility="invisible" android:focusable="false" android:paddingTop="@dimen/vert_drop_target_vertical_gap" > diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 18f409f343..18759f817c 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -16,7 +16,7 @@ */ --> - + @@ -111,4 +111,8 @@ + + + + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 75618b894b..7dd9e5315f 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -146,6 +146,7 @@ 2dp 4dp 2dp + 2dp 8dp diff --git a/res/values/drawables.xml b/res/values/drawables.xml new file mode 100644 index 0000000000..fea17b1530 --- /dev/null +++ b/res/values/drawables.xml @@ -0,0 +1,20 @@ + + + + @drawable/ic_info_no_shadow + @drawable/ic_remove_no_shadow + @drawable/ic_uninstall_no_shadow + \ No newline at end of file diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index 9097ed23d7..975675a6fc 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -40,7 +40,7 @@ public class DeleteDropTarget extends ButtonDropTarget { // Get the hover color mHoverColor = getResources().getColor(R.color.delete_target_hover_tint); - setDrawable(R.drawable.ic_remove_launcher); + setDrawable(R.drawable.ic_remove_shadow); } @Override diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java index 2f61a01ed7..7b3bded174 100644 --- a/src/com/android/launcher3/InfoDropTarget.java +++ b/src/com/android/launcher3/InfoDropTarget.java @@ -40,12 +40,10 @@ public class InfoDropTarget extends UninstallDropTarget { } @Override - protected void onFinishInflate() { - super.onFinishInflate(); + protected void setupUi() { // Get the hover color mHoverColor = Themes.getColorAccent(getContext()); - - setDrawable(R.drawable.ic_info_launcher); + setDrawable(R.drawable.ic_info_shadow); } @Override diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java index 0fac29f30a..45c14d6bba 100644 --- a/src/com/android/launcher3/UninstallDropTarget.java +++ b/src/com/android/launcher3/UninstallDropTarget.java @@ -28,10 +28,13 @@ public class UninstallDropTarget extends ButtonDropTarget { @Override protected void onFinishInflate() { super.onFinishInflate(); + setupUi(); + } + + protected void setupUi() { // Get the hover color mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint); - - setDrawable(R.drawable.ic_uninstall_launcher); + setDrawable(R.drawable.ic_uninstall_shadow); } @Override diff --git a/src/com/android/launcher3/graphics/ShadowDrawable.java b/src/com/android/launcher3/graphics/ShadowDrawable.java new file mode 100644 index 0000000000..5e76649ca3 --- /dev/null +++ b/src/com/android/launcher3/graphics/ShadowDrawable.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.graphics; + +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; + +import com.android.launcher3.R; +import com.android.launcher3.Utilities; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * A drawable which adds shadow around a child drawable. + */ +public class ShadowDrawable extends Drawable { + + private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + + private final ShadowDrawableState mState; + + public ShadowDrawable() { + this(new ShadowDrawableState()); + } + + private ShadowDrawable(ShadowDrawableState state) { + mState = state; + } + + @Override + public void draw(Canvas canvas) { + Rect bounds = getBounds(); + if (bounds.isEmpty()) { + return; + } + if (mState.mLastDrawnBitmap == null) { + regenerateBitmapCache(); + } + canvas.drawBitmap(mState.mLastDrawnBitmap, null, bounds, mPaint); + } + + @Override + public void setAlpha(int alpha) { + mPaint.setAlpha(alpha); + invalidateSelf(); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + mPaint.setColorFilter(colorFilter); + invalidateSelf(); + } + + @Override + public ConstantState getConstantState() { + return mState; + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public int getIntrinsicHeight() { + return mState.mIntrinsicHeight; + } + + @Override + public int getIntrinsicWidth() { + return mState.mIntrinsicWidth; + } + + /** + * Sets the color for the generated shadow + */ + public void setShadowColor(int color) { + if (mState.mShadowColor != color) { + mState.mShadowColor = color; + mState.mLastDrawnBitmap = null; + invalidateSelf(); + } + } + + private void regenerateBitmapCache() { + Bitmap bitmap = Bitmap.createBitmap(mState.mIntrinsicWidth, mState.mIntrinsicHeight, + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + + // Call mutate, so that the pixel allocation by the underlying vector drawable is cleared. + Drawable d = mState.mChildState.newDrawable().mutate(); + d.setBounds(mState.mShadowSize, mState.mShadowSize, + mState.mIntrinsicWidth - mState.mShadowSize, + mState.mIntrinsicHeight - mState.mShadowSize); + d.draw(canvas); + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + paint.setMaskFilter(new BlurMaskFilter(mState.mShadowSize, BlurMaskFilter.Blur.NORMAL)); + int[] offset = new int[2]; + Bitmap shadow = bitmap.extractAlpha(paint, offset); + + paint.setMaskFilter(null); + paint.setColor(mState.mShadowColor); + bitmap.eraseColor(Color.TRANSPARENT); + canvas.drawBitmap(shadow, offset[0], offset[1], paint); + d.draw(canvas); + + if (Utilities.isAtLeastO()) { + bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false); + } + mState.mLastDrawnBitmap = bitmap; + } + + @Override + public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, + Resources.Theme theme) throws XmlPullParserException, IOException { + super.inflate(r, parser, attrs, theme); + + final TypedArray a = theme == null + ? r.obtainAttributes(attrs, R.styleable.ShadowDrawable) + : theme.obtainStyledAttributes(attrs, R.styleable.ShadowDrawable, 0, 0); + + try { + Drawable d = a.getDrawable(R.styleable.ShadowDrawable_android_src); + if (d == null) { + throw new XmlPullParserException("missing src attribute"); + } + mState.mShadowColor = a.getColor( + R.styleable.ShadowDrawable_android_shadowColor, Color.BLACK); + mState.mShadowSize = r.getDimensionPixelSize(R.dimen.drawable_shadow_size); + + mState.mIntrinsicHeight = d.getIntrinsicHeight() + 2 * mState.mShadowSize; + mState.mIntrinsicWidth = d.getIntrinsicWidth() + 2 * mState.mShadowSize; + mState.mChangingConfigurations = d.getChangingConfigurations(); + + mState.mChildState = d.getConstantState(); + } finally { + a.recycle(); + } + } + + private static class ShadowDrawableState extends ConstantState { + + int mChangingConfigurations; + int mIntrinsicWidth; + int mIntrinsicHeight; + + int mShadowColor; + int mShadowSize; + + Bitmap mLastDrawnBitmap; + ConstantState mChildState; + + @Override + public Drawable newDrawable() { + return new ShadowDrawable(this); + } + + @Override + public int getChangingConfigurations() { + return mChangingConfigurations; + } + } +}