Launcher3文件夹九宫格显示

本文详细分析了Android Launcher3中文件夹样式的实现原理,重点介绍了如何通过修改源码来改变文件夹的显示风格。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载:http://blog.youkuaiyun.com/zzj000/article/details/53163447(转载只是记录学习,如有侵权请告知)

现在市面上大多数手机的桌面文件夹都是类似iOS那样的风格,将内部包含的app缩略展示在icon图标上;但是Google原生的文件夹风格是圆形背景,app以45度角向外叠起来的。据说Android早期版本也是ios那样的,后来被苹果告侵权才改的。不管怎么说,我个人还是觉得缩略图展示是比较好的,方便查看内部包含的app。正好这段时间比较闲,就来改的玩玩。

以下只是对Launcher3中Folder的源码作了分析,看懂了源码,想要改风格是非常容易的。

Folder的创建起源于Workspace.Java的onDrop回调,每次onDrop都需要判断是否需要创建文件夹。添加文件夹时,首先要将targetCell位置的app从CellLayout中移除,然后再调用Launcher.java的addFolder,将创建好的FolderIcon添加回targetCell这个位置;最后清除放入文件夹的两个app的坐标(因为他们被移出了workspace),并将这两个app添加到FolderIcon中。

boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
            int[] targetCell, float distance, boolean external, DragView dragView,
            Runnable postAnimationRunnable) {
                            …………
            target.removeView(v);

            FolderIcon fi =
                mLauncher.addFolder(target, container, screenId, targetCell[0], targetCell[1]);
            destInfo.cellX = -1;
            destInfo.cellY = -1;
            sourceInfo.cellX = -1;
            sourceInfo.cellY = -1;

            // If the dragView is null, we can't animate
            boolean animate = dragView != null;
            if (animate) {
                fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale,
                        postAnimationRunnable);
            } else {
                fi.addItem(destInfo);
                fi.addItem(sourceInfo);
            }
            return true;
        }
        return false;
    }
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在Launcher.java的addFolder中创建了2个实例,folderInfo和newFolder,并通过Workspace的addInScreen将foler添加到屏幕上。

FolderIcon addFolder(CellLayout layout, long container, final long screenId, int cellX,
            int cellY) {
        final FolderInfo folderInfo = new FolderInfo();
        folderInfo.title = getText(R.string.folder_name);

        // Update the model
        LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screenId,
                cellX, cellY);
        sFolders.put(folderInfo.id, folderInfo);

        // Create the view
        FolderIcon newFolder =
            FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
        mWorkspace.addInScreen(newFolder, container, screenId, cellX, cellY, 1, 1,
                isWorkspaceLocked());
        // Force measure the new folder icon
        CellLayout parent = mWorkspace.getParentCellLayoutForView(newFolder);
        parent.getShortcutsAndWidgets().measureChild(newFolder);
        return newFolder;
    }
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

FolderIcon实际上是一个自定义View,继承自FrameLayout,其核心改写在dispatchDraw。为什么不是onDraw?因为FrameLayout是ViewGroup啊。

@Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

        if (mFolder == null) return;
        if (mFolder.getItemCount() == 0 && !mAnimating) return;

        ArrayList<View> items = mFolder.getItemsInReadingOrder();
        Drawable d;
        TextView v;

        // Update our drawing parameters if necessary
        if (mAnimating) {
            computePreviewDrawingParams(mAnimParams.drawable);
        } else {
            v = (TextView) items.get(0);
            d = getTopDrawable(v);
            computePreviewDrawingParams(d);
        }

        int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW);
        if (!mAnimating) {
            for (int i = nItemsInPreview - 1; i >= 0; i--) {
                v = (TextView) items.get(i);
                if (!mHiddenItems.contains(v.getTag())) {
                    d = getTopDrawable(v);
                    mParams = computePreviewItemDrawingParams(i, mParams);
                    mParams.drawable = d;
                    drawPreviewItem(canvas, mParams);
                }
            }
        } else {
            drawPreviewItem(canvas, mAnimParams);
        }
    }
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

DispatchDraw包含三部分:
computePreviewDrawingParams:计算背景参数
computePreviewItemDrawingParams:计算内部Item参数,主要是计算坐标,缩放尺寸,透明度。
drawPreviewItem:依据参数绘制Icon内的Item。

因此要修改Folder样式,主要就是修改computePreviewItemDrawingParams的逻辑,还是挺简单的。

0
0
 
 
<think>嗯,用户想了解如何自定义或修改Launcher3的图标,特别是在Android系统中。首先,我需要回忆一下Launcher3的结构和相关类。根据提供的引用,有几个核心类被提到,比如BaseIconFactory和FastBitmapDrawable,这些可能涉及到图标的生成和绘制。 用户提到替换第三方应用图标后小不一致的问题,这可能是因为Launcher3在加载图标时自动进行了缩放。所以解决方案可能需要修改这些缩放逻辑。比如在BaseIconFactory.java中,可能有一个方法负责调整图标尺寸,找到并注释掉相关代码,或者调整缩放比例。 另外,引用[5]提到了修改文件夹图标为九宫格,这涉及到FolderIcon类的自定义。可能需要重写绘制方法或替换资源文件。用户可能需要了解如何创建自定义的FolderIcon,并替换默认的图标资源。 用户的需求可能包括调整图标小、替换图标资源、自定义动态图标等。需要分步骤说明,首先找到影响图标处理的核心类,然后修改缩放逻辑或资源引用。同时,要注意不同Android版本的差异,比如引用[3]提到的是Android 13.0,而引用[5]是Android 10.0,可能需要针对不同版本调整代码路径。 可能还需要考虑性能问题,比如关闭自适应缩放后是否会影响其他图标的显示。此外,动态图标的实现可能需要使用自定义的Drawable类,并确保在FastBitmapDrawable中正确处理动画或动态更新。 最后,用户可能需要具体的代码示例,比如如何修改BaseIconFactory中的createIconBitmap方法,或者如何自定义FolderIcon的布局。同时,生成的相关问题可以帮助用户深入了解更多优化和定制方法,比如性能分析、不同图标类型的处理等。</think>### Launcher3图标定制/修改方法分步说明 #### 一、核心实现原理 Launcher3的图标处理主要通过以下模块实现: 1. **图标缩放逻辑**:在$BaseIconFactory$类中实现自适应缩放算法[^3] 2. **图标绘制逻辑**:$FastBitmapDrawable$类控制最终绘制效果[^1] 3. **文件夹图标定义**:$FolderIcon$类实现九宫格布局[^5] #### 二、具体实现步骤 1. **修改图标尺寸(解决缩放问题)**: - 定位$BaseIconFactory.java$的$createIconBitmap$方法 ```java // 原缩放逻辑 float scale = iconScale; if (adaptiveScalingEnabled) { // 关闭此处条件判断 scale *= getAdaptiveScale(bm); } ``` - 修改方案:禁用自适应缩放,直接使用原始尺寸 ```java // 修改后代码 float scale = 1.0f; // 强制设为不缩放 ``` 2. **自定义文件夹图标**: - 在$res/layout/folder_icon.xml$中定义九宫格布局 ```xml <com.android.launcher3.folder.FolderIcon android:layout_width="64dp" // 自定义尺寸 android:layout_height="64dp" android:background="@drawable/custom_folder_bg"/> // 自定义背景 ``` - 重写$FolderIcon.java$的$drawBackground$方法 3. **动态图标支持**: - 继承$FastBitmapDrawable$实现动态绘制 ```java public class AnimatedIcon extends FastBitmapDrawable { @Override public void draw(Canvas canvas) { // 添加动画绘制逻辑 updateAnimationProgress(); // 动态更新状态 super.draw(canvas); } } ``` #### 三、版本适配要点 | Android版本 | 关键文件路径差异 | |------------|------------------| | Android 10 | packages/apps/Launcher3/src/ | | Android 13 | frameworks/libs/systemui/iconloaderlib/[^3] | #### 四、验证方法 1. 使用$adb shell dumpsys activity com.android.launcher3$查看布局参数 2. 通过$getIconSize()$方法验证最终输出尺寸 3. 检查$BaseIconFactory$日志输出: ```logcat IconLoader: Creating bitmap with scale=1.0 // 确认缩放比例 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值