看到标题,很多人也许会问:引入了 自适应图标规范 后,在 Android 8.0 上我们已经可以通过一些第三方 Launcher(比如 Lawnchair、Nova 等等)来修改图标形状。

为什么还要多此一举?

因为通过 Launcher 修改图标形状的效果并不完美。仔细观察,无论我们在哪个 Launcher 中修改图标遮罩为何种形状,多任务卡片、已安装的应用列表、第三方应用所能够读取的应用图标,都依然是圆角矩形

android设置圆形图标 安卓图标圆形变方形_android设置圆形图标

任务卡片左上角的图标默认为圆角矩形

也就是 Nexus 用户在升级到 Android 8.0 后在默认的 Google Now Launcher 上所看到的那样:

android设置圆形图标 安卓图标圆形变方形_android设置圆形图标_02

Nexus 用户觉得亲切吗?

作为一个习惯了 Pixel 圆形图标、想要最大程度上贴近原生体验的强迫症和完美主义者,上面的情况简直不能忍。

那么如何改变这种图标不统一的状况呢?

在 上一篇教程中 我们提到,在 Android 7.x 中,我们可以通过反编译 framework-res.apk、将其中 config_useRoundIcon 的值由 false 修改为 true 来强制启用圆形图标规范。

在 Android 8.0 中,config_useRoundIcon 这个标签虽然还在,但由于自适应图标特性的引入、系统级主题引擎等因素,它已不足以控制全局图标遮罩。

因此我们需要额外修改位于 string 当中的 config_icon_mask

需要用到的工具和具体操作如下:

  • 已 root 的 Android 8.0 设备
  • MT 文件管理器 2.0

 

android设置圆形图标 安卓图标圆形变方形_android_03

MT管理器2.0

首先,参考 @Clyde 的教程,使用 MT 文件管理器定位至 /system/framework 目录,找到 framework-res.apk 这个文件并将其复制到内部储存备用;

android设置圆形图标 安卓图标圆形变方形_android_04

点击备用的 framework-res.apk 文件,选择「查看」,在打开的界面定位至 resources.arsc 文件并打开;

在 resources.arsc 的目录中定位至 android -> bool -> bool 标签,找到 config_useRoundIcon 一项,将其数值从 false 修改为 true

这里不修改的话cts会提示:

android设置圆形图标 安卓图标圆形变方形_ico_05

同样在 resources.arsc 的目录中,定位至 android -> string -> string 标签,找到 config_icon_mask 一项;

android设置圆形图标 安卓图标圆形变方形_ico_06

可以看到,config_icon_mask 的数值非常复杂,而非 Pixel 设备上全局强制开启的圆角矩形图标遮罩就是由这串字符控制的:

M50,0L92,0C96.42,0 100,4.58 100 8L100,92C100, 96.42 96.42 100 92 100L8 100C4.58, 100 0 96.42 0 92L0 8 C 0 4.42 4.42 0 8 0L50 0Z

我们需要将这段代码精确地、一字不漏地修改为 Pixel 设备中的圆形图标遮罩代码:

M50 0C77.6 0 100 22.4 100 50C100 77.6 77.6 100 50 100C22.4 100 0 77.6 0 50C0 22.4 22.4 0 50 0Z

android设置圆形图标 安卓图标圆形变方形_android_07

这就是开启全局圆形图标遮罩的魔法了!

完成以上两部分修改后,保存并退出编辑。用于开启圆形图标规范的 framework-res.apk 文件就已经修改好了。

接下来我们要做的就是将修改后的 framework-res.apk 替换回去,这里建议大家先将它拷贝至 /system 目录下,修改权限为「rw-r--r--」,然后再移动至 /system/framework 文件夹中进行替换。

android设置圆形图标 安卓图标圆形变方形_android_08

权限设置示意图

替换后重启手机就能看见效果了,这样修改后,无论是多任务卡片上的小图标还是已安装应用列表中的应用图标,都会启用 Pixel 设备上的原型图标遮罩;如果你在启动其中应用圆形图标,整个系统在图标部分就会非常和谐统一。

android设置圆形图标 安卓图标圆形变方形_ico_09

修改前/修改后

当然,如果你喜欢其它形状的图标遮罩,也可以按照本文的方法进行修改。前提是——你得知道这种图标遮罩所对应的字符串。

-----------------------------------------------------------------------------------------------------------------如果需要方形圆角-------------------------------------------

launcher3的修改

diff --git a/src/com/android/launcher3/graphics/IconShape.java b/src/com/android/launcher3/graphics/IconShape.java
index 4369385..edeb5c8 100644
--- a/src/com/android/launcher3/graphics/IconShape.java
+++ b/src/com/android/launcher3/graphics/IconShape.java
@@ -404,7 +404,7 @@ public abstract class IconShape {
 
     private static List<IconShape> getAllShapes(Context context) {
         ArrayList<IconShape> result = new ArrayList<>();
-        try (XmlResourceParser parser = context.getResources().getXml(R.xml.folder_shapes)) {
+        try (XmlResourceParser parser = context.getResources().getXml(R.xml.folder_shapes_round)) {
 
             // Find the root tag
             int type;

frameworks/libs/systemui / iconloaderlib修改

diff --git a/iconloaderlib/res/values/dimens.xml b/iconloaderlib/res/values/dimens.xml
index e8c0c44..f51af34 100644
--- a/iconloaderlib/res/values/dimens.xml
+++ b/iconloaderlib/res/values/dimens.xml
@@ -16,4 +16,10 @@
 
 <resources>
     <dimen name="profile_badge_size">24dp</dimen>
+	<dimen name="bottom_sheet_edu_padding">10dp</dimen>
+	<dimen name="left_side_coordinate">8dp</dimen>
+    <dimen name="top_side_coordinate">8dp</dimen>
+    <dimen name="right_side_coordinate">8dp</dimen>
+    <dimen name="bottom_side_coordinate">8dp</dimen>
+	<dimen name="icon_round_rect_radius">12dp</dimen>
 </resources>
diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
index 31a923e..975593d 100644
--- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
+++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java
@@ -12,7 +12,10 @@ import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.AdaptiveIconDrawable;
@@ -330,7 +333,28 @@ public class BaseIconFactory implements AutoCloseable {
         }
         icon.setBounds(mOldBounds);
         mCanvas.setBitmap(null);
-        return bitmap;
+        return getRoundedBitmap(bitmap);
+    }
+
+    public  Bitmap getRoundedBitmap(Bitmap mBitmap){
+        Bitmap bgBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
+
+        mCanvas.setBitmap(bgBitmap);
+        Paint mPaint = new Paint();
+        RectF mRectM = new RectF(mContext.getResources().getDimensionPixelSize(R.dimen.left_side_coordinate), mContext.getResources().getDimensionPixelSize(R.dimen.top_side_coordinate), mBitmap.getWidth()-mContext.getResources().getDimensionPixelSize(R.dimen.right_side_coordinate), mBitmap.getHeight()-mContext.getResources().getDimensionPixelSize(R.dimen.bottom_side_coordinate));
+        Rect mRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+
+        float roundPx;
+        roundPx = mContext.getResources().getDimensionPixelSize(R.dimen.icon_round_rect_radius);
+        mPaint.setAntiAlias(true);
+        mPaint.setFilterBitmap(true);
+        mPaint.setDither(true);
+        mCanvas.drawRoundRect(mRectM, roundPx, roundPx, mPaint);
+        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+        mCanvas.drawBitmap(mBitmap, mRect, mRect, mPaint);
+        return bgBitmap;
     }
 
     @Override

添加的folder_shapes_round.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
 Copyright (C) 2019 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.
-->
<shapes xmlns:launcher="http://schemas.android.com/apk/res-auto" >

    <RoundedSquare launcher:folderIconRadius="0.53" />



</shapes>

祝大家玩机愉快!