为 Android 8.0 强制开启全局圆形图标规范

原文地址:https://sspai.com/post/41011

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

为什么还要多此一举?

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

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

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

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

 

MT管理器2.0

相关文章

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

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

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

这里不修改的话cts会提示: 如果您决定使用圆形作为平台遮罩,请确保也要替换 config_useRoundIcon = true。否则,请将此配置值设为 false 或不指定此配置值。

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

可以看到,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

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

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

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

权限设置示意图

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

修改前/修改后

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

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

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>

祝大家玩机愉快!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 8.0 及以上版本,为了增强应用程序的安全性,Android 引入了后台限制,禁止未在前台运行的应用程序启动服务。如果您想在后台启动服务,需要使用 `startForegroundService()` 方法。这个方法会启动一个前台服务,然后你可以在服务启动后在通知栏显示一个通知,以此来告知用户服务正在运行。 以下是一个使用 `startForegroundService()` 的示例代码: ``` if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 创建一个 NotificationChannel NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT); // 向系统注册 NotificationChannel NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } // 创建一个 Intent,启动你的服务 Intent serviceIntent = new Intent(this, YourService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 在 Android 8.0 及以上版本上,需要调用 startForegroundService() 方法启动服务。 startForegroundService(serviceIntent); } else { // 在 Android 8.0 以下版本上,可以直接调用 startService() 方法启动服务。 startService(serviceIntent); } ``` 注意:如果你使用的是 `startForeground()` 方法,会在 Android 8.0 及以上版本上抛出 `IllegalStateException` 异常,因为 Android 8.0 及以上版本禁止在后台启动服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值