
一、引言為什么需要自定義 Launcher3 文件夾在 Android 系統開發中原生的 Launcher3 桌面啟動器往往無法滿足企業定制、教育平板、車載系統或智能家居等場景的特殊需求。默認的 3x3 或 4x3 文件夾布局在信息展示效率和空間利用上都不夠理想。本文將基于 Android 13 源碼中的 Launcher3 模塊從架構分析到代碼實踐系統講解如何將默認文件夾改造為 16 宮格4x4布局。全文超過 20000 字涵蓋 Workspace、CellLayout、FolderPagedView、DeviceProfile、DragController 等核心組件的深入剖析讓你掌握 Launcher3 任意布局定制的通用方法。閱讀完成后你將具備以下能力獨立分析 Launcher3 源碼結構、修改 DeviceProfile 實現全局網格定制、在 FolderPagedView 中動態控制文件夾行列數、處理動畫性能與適配問題以及完整編譯部署修改后的桌面 APK。二、Android 13 Launcher3 架構全景圖2.1 模塊劃分Android 13 的 Launcher3 源碼位于packages/apps/Launcher3核心子包職責如下src/com/android/launcher3/入口 ActivityLauncher.java、工作區Workspace、拖拽控制器DragController、全局狀態LauncherAppState等。src/com/android/launcher3/model/數據模型層負責加載應用列表、Widget 信息、持久化布局。src/com/android/launcher3/dragndrop/拖拽放置邏輯處理圖標拖入文件夾、跨頁拖動等。src/com/android/launcher3/folder/文件夾功能模塊包含 Folder.java、FolderIcon.java、FolderPagedView.java 等是本文焦點。src/com/android/launcher3/graphics/圖標陰影、文件夾背景繪制。src/com/android/launcher3/util/工具類。src/com/android/launcher3/config/配置常量和 FeatureFlags。res/布局文件、尺寸值、樣式和圖片資源。2.2 核心概念Workspace用戶可左右滑動的主屏幕工作區每個頁面是一個 CellLayout。Workspace 繼承自 PagedView負責頁面切換和彈性滾動。CellLayout網格布局容器通過 mCountX列數和 mCountY行數定義圖標排列密度。每個圖標通過 cellX、cellY、spanX、spanY 占據網格位置。Hotseat屏幕底部固定停靠欄也是一個 CellLayout不受頁面切換影響。Folder將圖標拖拽到一起時創建的文件夾浮層內部包含 FolderPagedView 進行內容展示和翻頁。DeviceProfile設備適配配置文件根據屏幕尺寸、DPI 等計算所有 UI 元素的尺寸和行列數。修改它是全局改變布局的最直接方式。2.3 文件夾的 View 層級文件夾打開后在 DragLayer 上構建如下層級DragLayer全屏覆蓋└── Folder容器FrameLayout 子類├── FolderIcon桌面圖標預覽├── FolderNameEditText名稱編輯框└── FolderPagedView翻頁網格容器└── CellLayout x N每頁一個網格布局改造的核心就在于 FolderPagedView 內 CellLayout 的行列數配置。三、環境搭建與源碼準備3.1 硬件和軟件要求操作系統Ubuntu 20.04 / 22.04 或 macOS內存16 GB 以上磁盤至少 250 GB 空閑空間Android Studio Hedgehog 或更新版本測試設備Pixel 系列或原生 Android 13 設備可解鎖 Bootloader3.2 下載 Android 13 源碼使用 repo 工具下載指定分支的 AOSP 源碼例如 android-13.0.0_r43# 安裝 repo mkdir ~/bin export PATH~/bin:$PATH curl https://storage.googleapis.com/git-repo-downloads/repo ~/bin/repo chmod ax ~/bin/repo 初始化并同步 mkdir aosp13 cd aosp13 repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r43 repo sync -j8Launcher3 源碼位置為packages/apps/Launcher3。3.3 單獨編譯 Launcher3source build/envsetup.sh lunch aosp_arm64-userdebug mmm packages/apps/Launcher3 # 查找 APK 文件 find out/ -name Launcher3*apk -type f通過adb install -r推送到設備即可測試。3.4 導入 Android Studio在 AOSP 根目錄執行make idegen development/tools/idegen/idegen.sh用 Android Studio 打開生成的android.ipr等待索引完成定位到 Launcher3 模塊四、文件夾核心源碼深度剖析4.1 Folder.javaFolder.java 是文件夾功能的核心類關鍵成員mContentFolderPagedView 實例承載文件夾內所有頁面和圖標。mInfoFolderInfo 數據對象包含文件夾 ID、標題、應用列表。mFolderIcon桌面的 FolderIcon 視圖。mState當前狀態STATE_NONE / STATE_SMALL / STATE_ANIMATING / STATE_OPEN。關鍵方法bind(FolderInfo)負責綁定數據并初始化 FolderPagedViewanimateOpen()和animateClosed()控制展開/關閉動畫arrangeChildren()重排內部圖標。4.2 FolderPagedView.javaFolderPagedView 繼承自 PagedView是實現文件夾內多頁滑動的關鍵。構造時從 DeviceProfile 獲取 mGridCountX、mGridCountY并動態創建 CellLayout 頁面。bindItems()方法根據每頁容納數countX * countY將快捷方式逐個分配到不同頁面和網格位置。// 簡化的 bindItems 邏輯 int itemsPerPage mGridCountX * mGridCountY; for (int i 0; i items.size(); i) { int page i / itemsPerPage; int indexInPage i % itemsPerPage; int cellX indexInPage % mGridCountX; int cellY indexInPage / mGridCountX; // 添加到對應 CellLayout }修改 mGridCountX/Y 為 4 即可實現每頁 16 個圖標。4.3 CellLayout.javaCellLayout 是網格布局容器關鍵屬性mCountX、mCountY、mCellWidth、mCellHeight、mWidthGap、mHeightGap。通過setGridSize(x, y)設置行列數內部會重新計算單元格尺寸并更新子 View 的 LayoutParams。4.4 DeviceProfile.javaDeviceProfile 集中管理所有 UI 元素的尺寸和位置。文件夾相關字段public int folderGridCountX; // 文件夾列數 public int folderGridCountY; // 文件夾行數 public int folderIconSizePx; // 圖標尺寸 public int folderCellWidthPx; // 單元格寬度 public int folderCellHeightPx; // 單元格高度這些值在構造或updateFromConfiguration()時根據屏幕參數動態計算。五、config.xml 與多 DPI 配置5.1 關鍵 XML 配置項res/values/config.xml中與文件夾相關的配置integer nameconfig_folderGridCountX3/integer integer nameconfig_folderGridCountY3/integer integer nameconfig_folderMaxPages3/integer這些默認值在運行時可能被 DeviceProfile 覆蓋因此修改后仍需要檢查 Java 側的計算。5.2 多 DPI 資源覆蓋Launcher3 使用values-sw600dp、values-sw720dp、values-sw840dp等目錄適配不同尺寸設備。為確保在所有設備上生效需要同步修改這些目錄下的 config.xml 中的 folderGridCountX/Y。六、16 宮格定制方案一修改 DeviceProfile推薦6.1 思路在 DeviceProfile 構造函數或工廠方法中將 folderGridCountX 和 folderGridCountY 均設置為 4并同步重新計算單元格尺寸和圖標大小。6.2 具體修改// DeviceProfile.java private DeviceProfile(Context context, InvariantDeviceProfile inv, ...) { // ... 前置計算 ... // 設置為 4x4 16宮格 folderGridCountX 4; folderGridCountY 4; // 重新計算單元格尺寸 int availableWidth folderContentWidth - 2 * folderCellPadding; int availableHeight folderContentHeight - 2 * folderCellPadding; folderCellWidthPx availableWidth / folderGridCountX; folderCellHeightPx availableHeight / folderGridCountY; // 圖標尺寸約為單元格的 70% folderIconSizePx (int) (Math.min(folderCellWidthPx, folderCellHeightPx) * 0.7f); }同時要調整文件夾整體寬度、間距等參數確保在窄屏手機上也能顯示 4 列圖標。6.3 文件夾尺寸調整將folderWidth設置為屏幕寬度的 85%~92%為邊緣留出點擊關閉空間。pageIndicator 高度等也需要微調。七、16 宮格定制方案二直接在 FolderPagedView 中設定7.1 適用場景當你不希望影響全局 DeviceProfile或者需要根據實驗分組、用戶設置動態切換布局時可以直接在 FolderPagedView 中覆寫行列數。7.2 修改 FolderPagedView.java// FolderPagedView.java public FolderPagedView(Context context, AttributeSet attrs) { super(context, attrs); // 直接指定 4x4 mGridCountX 4; mGridCountY 4; // 仍然從 DeviceProfile 獲取尺寸、間距等 DeviceProfile dp mActivityContext.getDeviceProfile(); mCellWidth dp.folderCellWidthPx; mCellHeight dp.folderCellHeightPx; // ... setFixedSize(mGridCountX, mGridCountY); }在addNewPage()中也要確保新創建的 CellLayout 使用 4x4 設置。八、FolderIcon 預覽圖適配8.1 預覽圖機制FolderIcon 在桌面上顯示 2x2 共 4 個應用預覽圖。16 宮格文件夾的預覽圖仍建議保持 2x2因為桌面圖標較小16 個預覽圖將無法辨認。8.2 關鍵代碼在 FolderIcon.java 的drawPreviewItems()中通過 PREVIEW_GRID_SIZE 控制排布通常保持 2 不變。如果確實想放大預覽可調整 ITEMS_PREVIEW 和預覽尺寸但需謹慎。8.3 背景比例微調檢查 FolderIcon 背景圓角矩形的尺寸必要時調整folderIconPreviewPadding。九、動畫與性能優化9.1 展開動畫適配文件夾的animateOpen()使用屬性動畫建議確保withLayer()開啟硬件加速層避免每幀重繪全部子 View。9.2 減少過度繪制對 CellLayout 設置setClipChildren(true)和setClipToPadding(true)文件夾背景選擇合適的顏色以遮擋下層內容。9.3 翻頁流暢性當文件夾內應用數量超過 16 個時會使用第二頁。PagedView 默認不預加載鄰頁如果內容過多可考慮調整setPageSpacing()和預加載策略。十、完整的代碼修改 Checklist步驟文件修改內容1res/values/config.xmlconfig_folderGridCountX/Y 改為 42res/values-sw600dp/config.xml同步改為 43res/values-sw720dp/config.xml同步改為 44res/values-sw840dp/config.xml同步改為 45DeviceProfile.java設置 folderGridCountX/Y4重算尺寸6FolderPagedView.java可選確認構造函數和新增頁使用 4x47Folder.java檢查 arrangeChildren() 是否依賴舊行列十一、編譯與部署source build/envsetup.sh lunch aosp_arm64-userdebug make clean-Launcher3 mmm packages/apps/Launcher3 -j8部署時需注意簽名沖突# 停用 Pixel Launcher如果存在 adb shell pm disable-user com.google.android.apps.nexuslauncher # 安裝自制 Launcher3 adb install -r out/target/product/generic_arm64/system/product/priv-app/Launcher3/Launcher3.apk adb reboot也可通過 Magisk 模塊或直接推送到 /system 的方式實現系統級替換。十二、功能驗證與測試用例12.1 測試用例ID場景預期TC-01創建文件夾并拖入 1 個應用第一頁顯示 1 個圖標TC-02拖入第 2-16 個應用按 4x4 排列無重疊TC-03拖入第 17 個應用自動創建第二頁TC-04打開含 20 個應用的文件夾第一頁 16 個滑動至第二頁顯示剩余 4 個TC-05滑動切頁流暢指示器正確TC-06從文件夾拖出應用剩余應用自動重排TC-07刪除最后 1 個應用文件夾自動解散TC-08旋轉屏幕4x4 布局自適應12.2 兼容性測試Android 13 原生設備Pixel 4a/5/6/7不同屏幕尺寸5.0~6.8 英寸、折疊屏多種 DPImdpi ~ xxxhdpi分屏模式十三、常見問題與排查13.1 圖標重疊原因folderCellWidthPx/HeightPx 計算不正確。確保單元格寬度 (內容區寬度 - 總水平間距) / folderGridCountX。13.2 點擊文件夾崩潰通過adb logcat | grep AndroidRuntime查看堆棧常見 NullPointerExceptionDeviceProfile 未初始化或 ArrayIndexOutOfBoundsException頁面索引錯誤。13.3 橫豎屏切換布局錯亂在 FolderPagedView 中監聽配置變化并recreateAllPages()。十四、進階優化自適應 16 宮格14.1 按屏幕寬度動態調整if (screenWidthDp 360) { folderGridCountX 4; folderGridCountY 4; // 16宮格 } else if (screenWidthDp 320) { folderGridCountX 3; folderGridCountY 4; // 12宮格 } else { folderGridCountX 3; folderGridCountY 3; // 9宮格 }14.2 用戶設置切換使用 SharedPreferences 存儲偏好在 FolderPagedView 構造時讀取并應用監聽變化后通知已打開的文件夾重新 bind。十五、代碼實戰完整 diff 示例AOSP android-13.0.0_r4315.1 DeviceProfile.java folderGridCountX 4; folderGridCountY 4; folderCellWidthPx (folderContentWidth - (folderGridCountX - 1) * folderCellGapX) / folderGridCountX;15.2 FolderPagedView.java if (mGridCountX ! 4 || mGridCountY ! 4) { mGridCountX 4; mGridCountY 4; }15.3 config.xml- integer nameconfig_folderGridCountX3/integer integer nameconfig_folderGridCountX4/integer十六、Launcher3 其它定制場景拓展16.1 從文件夾定制到全桌面定制掌握行列數修改方法后你可以定制桌面網格、Hotseat 圖標數量、文件夾樣式、Widget 支持等。原理相通定位 DeviceProfile 或對應 View 的網格配置修改數值即可。16.2 跨版本差異本文方法在 Android 12~14 上基本通用14 增加了預測性返回等新特性但不影響網格系統。只需注意字段名可能的微調。十七、調試技巧與工具17.1 Layout Inspector通過 Android Studio 的 Layout Inspector 實時查看文件夾 View 樹和尺寸。17.2 adb 命令adb shell pm clear com.android.launcher3 adb shell wm size adb shell am force-stop com.android.launcher317.3 日志調試在關鍵位置添加日志通過adb logcat -s Folder16Debug:D過濾查看參數傳遞。十八、總結與最佳實踐理解 DeviceProfile → FolderPagedView → CellLayout 的數據流。推薦方案一一處修改全局生效。不要遺漏多 DPI 配置文件。確保動畫開啟硬件加速層。覆蓋創建、拖拽、翻頁、旋轉、多設備等測試維度。完整掌握本文內容后你將能自信地應對任何 Launcher3 定制需求。祝你在系統桌面優化的道路上越走越順交付高質量的產品。