Launcher folder、foldericon

桌面文件夹功能简介
1、界面介绍

长按桌面图标会形成文件夹。
打开的文件夹叫Folder
桌面上和图标一样的文件夹叫FolderIcon

文件夹的主要逻辑代码都在Launcher\src\com\android\launcher3\folder包下面

2、Folder ---- 文件夹打开后的界面

打开后的界面有标题和文件夹列表2部分组成。
2.1、点击图标打开文件夹
之前有介绍过在Launcher\src\com\android\launcher3\touch\ItemClickHandler.java中处理点击事件。

    private static void onClickFolderIcon(View v) {
        Folder folder = ((FolderIcon) v).getFolder();
        if (!folder.isOpen() && !folder.isDestroyed()) {
            // Open the requested folder
            folder.animateOpen();//打开文件夹
            StatsLogManager.newInstance(v.getContext()).logger().withItemInfo(folder.mInfo)
                    .log(LAUNCHER_FOLDER_OPEN);
        }
    }

2.2、文件夹打开动画

private void animateOpen(List<WorkspaceItemInfo> items, int pageNo, boolean skipUserEventLog) {
        Folder openFolder = getOpen(mLauncher);
        if (openFolder != null && openFolder != this) {
            // Close any open folder before opening a folder.
            openFolder.close(true);
        }
        mContent.bindItems(items);//文件夹内图标相关逻辑
        centerAboutIcon();//folder坐标和宽高计算
        mItemsInvalidated = true;
        updateTextViewFocus();

        mIsOpen = true;
        ...
}

2.3、mContent.bindItems
Launcher\src\com\android\launcher3\folder\FolderPagedView.java中
文件夹内图标排列:

//循环列表,判断是否超过当前页面最大值,创建新页面等逻辑
public void arrangeChildren(List<View> list) {
...
setupContentDimensions(itemCount);//根据总数计算行列
mOrganizer.getMaxItemsPerPage()//最大值判断
createAndAddNewPage();//创建新页
...
}
	//创建新页面,也是celllayout
    private CellLayout createAndAddNewPage() {
        DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
        CellLayout page = mViewCache.getView(R.layout.folder_page, getContext(), this);
        page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
        page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
        page.setInvertIfRtl(true);
        page.setGridSize(mGridCountX, mGridCountY);//设置行列号

        addView(page, -1, generateDefaultLayoutParams());
        return page;
    }

Launcher\src\com\android\launcher3\folder\FolderGridOrganizer.java
文件夹网格计算:

//从它的构造方法可以看出,文件夹最大行列数来自于DeviceProfile配置
// Launcher\res\xml\device_profiles_onyx.xml
public FolderGridOrganizer(InvariantDeviceProfile profile) {
        mMaxCountX = profile.numFolderColumns;
        mMaxCountY = profile.numFolderRows;
        mMaxItemsPerPage = mMaxCountX * mMaxCountY;
}
//从注释可以理解一下这个行列数计算的规则。
//1、Y《X
//2、X = 总数的平方根向上取整(比如总数=8,X = 3,Y = 3;总数3,x=2 y=2)
//3、X和Y小于文件夹最大行列数配置
    /**
     * Calculates the grid size such that {@param count} items can fit in the grid.
     * The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
     * maintaining the restrictions of {@link #mMaxCountX} &amp; {@link #mMaxCountY}.
     */
    private void calculateGridSize(int count) {
        boolean done;
        int gridCountX = mCountX;
        int gridCountY = mCountY;

        if (count >= mMaxItemsPerPage) {
            gridCountX = mMaxCountX;
            gridCountY = mMaxCountY;
            done = true;
        } else {
            done = false;
        }

        while (!done) {
            int oldCountX = gridCountX;
            int oldCountY = gridCountY;
            if (gridCountX * gridCountY < count) {
                // Current grid is too small, expand it
                if ((gridCountX <= gridCountY || gridCountY == mMaxCountY)
                        && gridCountX < mMaxCountX) {
                    gridCountX++;
                } else if (gridCountY < mMaxCountY) {
                    gridCountY++;
                }
                if (gridCountY == 0) gridCountY++;
            } else if ((gridCountY - 1) * gridCountX >= count && gridCountY >= gridCountX) {
                gridCountY = Math.max(0, gridCountY - 1);
            } else if ((gridCountX - 1) * gridCountY >= count) {
                gridCountX = Math.max(0, gridCountX - 1);
            }
            done = gridCountX == oldCountX && gridCountY == oldCountY;
        }

        mCountX = gridCountX;
        mCountY = gridCountY;
    }

3、FolderIcon文件夹图标
在桌面上和应用图标一样的文件夹图标,点击即可打开文件夹。
根据行列设计,计算缩放和小图标大小、排列,最终组合成FolderIcon效果。
3.1、文件夹icon坐标计算
Launcher\src\com\android\launcher3\folder\FolderIcon.java
getLocalCenterForIndex方法:

    private float getLocalCenterForIndex(int index, int curNumItems, int[] center) {
        mTmpParams = mPreviewItemManager.computePreviewItemDrawingParams(
                Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index), curNumItems, mTmpParams);

        mTmpParams.transX += mBackground.basePreviewOffsetX;
        mTmpParams.transY += mBackground.basePreviewOffsetY;

        float intrinsicIconSize = mPreviewItemManager.getIntrinsicIconSize();
        float offsetX = mTmpParams.transX + (mTmpParams.scale * intrinsicIconSize) / 2;
        float offsetY = mTmpParams.transY + (mTmpParams.scale * intrinsicIconSize) / 2;

        center[0] = Math.round(offsetX);
        center[1] = Math.round(offsetY);
        return mTmpParams.scale;
    }

Launcher\src\com\android\launcher3\folder\PreviewItemManager.java 预览图管理类
也就是FolderIcon小图标相关的逻辑计算类。
computePreviewItemDrawingParams方法:

    PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
            PreviewItemDrawingParams params) {
        // We use an index of -1 to represent an icon on the workspace for the destroy and
        // create animations
        if (index == -1) {
            return getFinalIconParams(params);
        }
        return mIcon.mPreviewLayoutRule.computePreviewItemDrawingParams(index, curNumItems, params);
    }

Launcher\src\com\android\launcher3\folder\ClippedFolderIconLayoutRule.java

public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
            PreviewItemDrawingParams params) {
	...
	if (index == EXIT_INDEX) {
            // 0 1 * <-- Exit position (row 0, col 2)
            // 2 3
            getGridPosition(0, 2, mTmpPoint);
        } else if (index == ENTER_INDEX) {
            // 0 1
            // 2 3 * <-- Enter position (row 1, col 2)
            getGridPosition(1, 2, mTmpPoint);
        } else if (index >= MAX_NUM_ITEMS_IN_PREVIEW) {
            // Items beyond those displayed in the preview are animated to the center
            mTmpPoint[0] = mTmpPoint[1] = mAvailableSpace / 2 - (mIconSize * totalScale) / 2;
        } else {
            getPosition(index, curNumItems, mTmpPoint);//走这里,根据图标个数和下标计算小图标位置
        }
	...
}

因为FolderIcon场景比较多,初始化、图标拖拽等,所以入口和调用比较多
如果要改原生效果,涉及的点稍微有点多。需要小心仔细修改后充分测试。

尾注

关于文件夹和文件夹icon预览的介绍就到这里。
我是发现有一些bug,导致文件夹打开后图标丢失,跟踪到相关流程。
顺手记录一下~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在 Android 10 中的启动器图标上添加圆角,可以使用以下步骤: 1. 首先,在你的 `drawable` 文件夹中创建一个新的图标资源文件,并命名为 `ic_launcher_round.xml`。 2. 在文件中添加以下代码: ```xml <?xml version="1.0" encoding="utf-8"?> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@color/ic_launcher_background"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/> </adaptive-icon> ``` 这段代码定义了一个自适应图标,并将背景设置为 `ic_launcher_background` 资源文件中的颜色,将前景设置为 `ic_launcher_foreground` 资源文件中的图标。 3. 接下来,在 `values` 文件夹中的 `styles.xml` 文件中添加以下代码: ```xml <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:roundIcon">@drawable/ic_launcher_round</item> </style> ``` 这段代码将你的应用程序主题与新的启动器图标关联起来。 4. 最后,在 `AndroidManifest.xml` 文件中的 `application` 标签中添加以下代码: ```xml <application ... android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round"> ... </application> ``` 这段代码将应用程序的默认图标设置为 `ic_launcher` 资源文件中的图标,并将圆角图标设置为 `ic_launcher_round` 资源文件中的图标。 完成这些步骤后,你的应用程序的启动器图标应该具有圆角效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值