首先要對hotseat等位置有一定的了解砸逊。
首先改橫屏是修改device/qcom/xxx/system.prop文件中的。
persist.panel.orientation=270
逸贾,一開始是persist.panel.orientation=0
。
這個數(shù)值可以通過adb直接修改,重啟后生效津滞。
setprop persist.panel.orientation 270
關(guān)于adb調(diào)屏幕的命令還有
adb shell settings put system show_touches 1
adb shell settings put system pointer_location 1
是打開Show taps和Pointer location([顯示點(diǎn)按操作反饋]和[指針位置])铝侵。
修改點(diǎn)如下。
1.由于是豎屏橫用触徐,所以需要修改hotseat 位置咪鲜,讓其居于底部。修改hotseat_transpose_layout_with_orientation的值撞鹉,由true改成false疟丙。
//packages/apps/Launcher3/res/values/config.xml
<!-- Hotseat -->
- <bool name="hotseat_transpose_layout_with_orientation">true</bool>
+ <bool name="hotseat_transpose_layout_with_orientation">false</bool>
2.需要強(qiáng)制所有app橫屏,在updateRotationUnchecked中增加返回true的部分鸟雏,修改如下享郊。
//frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* UNFREEZE THE SCREEN.
*/
boolean updateRotationUnchecked(boolean forceUpdate) {
+ if (true) {
+ return true;
+ }
+
ScreenRotationAnimation screenRotationAnimation;
if (!forceUpdate) {
if (mDeferredRotationPauseCount > 0) {
3.需調(diào)整navigationbar位置。系統(tǒng)設(shè)置為橫屏顯示后孝鹊,橫屏后 navigationBar默認(rèn)在左邊炊琉。需修改DisplayPolicy中的navigationBarPosition函數(shù),屏蔽判斷部分又活,使其直接返回NAV_BAR_BOTTOM苔咪。
//frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
@NavigationBarPosition
int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
/* if (navigationBarCanMove() && displayWidth > displayHeight) {
if (displayRotation == Surface.ROTATION_270) {
return NAV_BAR_LEFT;
} else if (displayRotation == Surface.ROTATION_90) {
return NAV_BAR_RIGHT;
}
}*/
return NAV_BAR_BOTTOM;
}
4.配置hotseat 位置居于底部后锰悼,allapp界面部分改變了,本身是4x4的布局悼泌,現(xiàn)在圖標(biāo)變小填充并且不再是4x4松捉。需修改availableHeightPx 和availableWidthPx 部分夹界。
//packages/apps/Launcher3/src/com/android/launcher3/DeviceProfile.java
public DeviceProfile(Context context, InvariantDeviceProfile inv,
Point minSize, Point maxSize,
int width, int height, boolean isLandscape, boolean isMultiWindowMode) {
this.inv = inv;
this.isLandscape = isLandscape;
this.isMultiWindowMode = isMultiWindowMode;
// Determine sizes.
widthPx = width;
heightPx = height;
if (isLandscape) {
/* availableWidthPx = maxSize.x;
availableHeightPx = minSize.y;*/
availableWidthPx = minSize.x;
availableHeightPx = maxSize.y;
} else {
availableWidthPx = minSize.x;
availableHeightPx = maxSize.y;
}
5.workspace區(qū)域添加的圖標(biāo)顯示不全馆里。具體修改如下。
//packages/apps/Launcher3/src/com/android/launcher3/CellLayout.java
public class CellLayout extends ViewGroup implements Transposable {
if (mFixedCellWidth < 0 || mFixedCellHeight < 0) {
int cw = DeviceProfile.calculateCellWidth(childWidthSize, mCountX);
- int ch = DeviceProfile.calculateCellHeight(childHeightSize, mCountY);
+ int ch = childHeightSize;//DeviceProfile.calculateCellHeight(childHeightSize, mCountY);
if (cw != mCellWidth || ch != mCellHeight) {
mCellWidth = cw;
mCellHeight = ch;
6.去掉all apps 界面搜索應(yīng)用欄,需修改AllAppsContainerView
和AllAppsTransitionController
可柿。
AllAppsContainerView
中增加mSearchContainer.setVisibility(View.GONE);
AllAppsTransitionController
中注釋掉mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
//packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsContainerView.java
public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
mSearchContainer = findViewById(R.id.search_container_all_apps);
mSearchUiManager = (SearchUiManager) mSearchContainer;
mSearchUiManager.initialize(this);
+
+ mSearchContainer.setVisibility(View.GONE);
+
}
//packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsTransitionController.java
public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
setter.setViewAlpha(mAppsView.getScrollBar(), hasContent ? 1 : 0, allAppsFade);
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasContent, setter,
allAppsFade);
- mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
+ //mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
7.去掉Google 搜索鸠踪。注釋掉bindAndInitFirstWorkspaceScreen
中qsb
部分。
//packages/apps/Launcher3/src/com/android/launcher3/Workspace.java
public void bindAndInitFirstWorkspaceScreen(View qsb) {
if (!FeatureFlags.QSB_ON_FIRST_SCREEN) {
return;
}
// Add the first page
CellLayout firstPage = insertNewWorkspaceScreen(Workspace.FIRST_SCREEN_ID, 0);
// Always add a QSB on the first screen.
/* if (qsb == null) {
// In transposed layout, we add the QSB in the Grid. As workspace does not touch the
// edges, we do not need a full width QSB.
qsb = LayoutInflater.from(getContext())
.inflate(R.layout.search_container_workspace,firstPage, false);
}
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, firstPage.getCountX(), 1);
lp.canReorder = false;
if (!firstPage.addViewToCellLayout(qsb, 0, R.id.search_container_workspace, lp, true)) {
Log.e(TAG, "Failed to add to item at (0, 0) to CellLayout");
}*/
}
8.國內(nèi)基本上都是去掉Android原生的抽屜式的复斥,修改部分基本參考這個营密。太長了就不寫了。
android10.0(Q) Launcher3 去掉抽屜
9.修改hotseat目锭。hotseat一般默認(rèn)是4個评汰,布局為4x1。
現(xiàn)需增加為8個痢虹,布局改成4x2被去。
①首先修改device_profiles.xml,這個文件存在于go\res\xml和res\xml文件夾〗蔽ǎ可以都改一下惨缆,因?yàn)閱为?dú)編譯launcher模塊和全編的話使用的是 不同的device_profiles.xml。
// device_profiles.xml
<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
<grid-option
launcher:name="4_by_4"
launcher:numRows="4"
launcher:numColumns="4"
launcher:numFolderRows="4"
launcher:numFolderColumns="4"
launcher:numHotseatIcons="4"
launcher:defaultLayoutId="@xml/default_workspace_4x4" >
<display-option
launcher:name="Go Device"
launcher:minWidthDps="296"
launcher:minHeightDps="491.33"
launcher:iconImageSize="60"
launcher:iconTextSize="14.0"
launcher:canBeDefault="true" />
</grid-option>
</profiles>
把launcher:numHotseatIcons="4"
改成launcher:numHotseatIcons="8"
丰捷。
②然后修改default_workspace_4x4.xml文件坯墨。增加resolve數(shù)據(jù)。Hotseat的launcher:screen與workspace中不同病往,并不代表屏幕位置捣染,而是代表插入的位置。
修改后如下所示停巷。
<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
<!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
<!-- Dialer, Messaging, Browser, Camera -->
<resolve
launcher:container="-101"
launcher:screen="0"
launcher:x="0"
launcher:y="0" >
<favorite launcher:uri="#Intent;action=android.intent.action.DIAL;end" />
<favorite launcher:uri="tel:123" />
<favorite launcher:uri="#Intent;action=android.intent.action.CALL_BUTTON;end" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="1"
launcher:x="1"
launcher:y="0" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MESSAGING;end" />
<favorite launcher:uri="sms:" />
<favorite launcher:uri="smsto:" />
<favorite launcher:uri="mms:" />
<favorite launcher:uri="mmsto:" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="2"
launcher:x="2"
launcher:y="0" >
<favorite
launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_BROWSER;end" />
<favorite launcher:uri="http://www.example.com/" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="3"
launcher:x="3"
launcher:y="0" >
<favorite launcher:uri="#Intent;action=android.media.action.STILL_IMAGE_CAMERA;end" />
<favorite launcher:uri="#Intent;action=android.intent.action.CAMERA_BUTTON;end" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="0"
launcher:x="0"
launcher:y="1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_CONTACTS;end" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="1"
launcher:x="1"
launcher:y="1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_DeskClock;end" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="2"
launcher:x="2"
launcher:y="1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MUSIC;end" />
</resolve>
<resolve
launcher:container="-101"
launcher:screen="3"
launcher:x="3"
launcher:y="1" >
<favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_CALENDAR;end" />
</resolve>
<!-- Bottom row -->
<!-- <resolve-->
<!-- launcher:screen="0"-->
<!-- launcher:x="0"-->
<!-- launcher:y="-1" >-->
<!-- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_EMAIL;end" />-->
<!-- <favorite launcher:uri="mailto:" />-->
<!-- </resolve>-->
<!-- <resolve-->
<!-- launcher:screen="0"-->
<!-- launcher:x="1"-->
<!-- launcher:y="-1" >-->
<!-- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_GALLERY;end" />-->
<!-- <favorite launcher:uri="#Intent;type=images/*;end" />-->
<!-- </resolve>-->
<!-- <resolve-->
<!-- launcher:screen="0"-->
<!-- launcher:x="3"-->
<!-- launcher:y="-1" >-->
<!-- <favorite launcher:uri="#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MARKET;end" />-->
<!-- <favorite launcher:uri="market://details?id=com.android.launcher" />-->
<!-- </resolve>-->
</favorites>
并且要注意耍攘,缺少category的要在對應(yīng)的apk中添加。例如我的DeskClock叠穆,AndroidManifest.xml缺少
<category android:name="android.intent.category.APP_DeskClock"/>
少漆,要加進(jìn)去。
③屏蔽檢驗(yàn)部分代碼硼被。
LoaderCursor中的checkItemPlacement會判斷hotseat的一行是否填充示损,如果填充了就不能再進(jìn)行填充了。這里會影響數(shù)據(jù)庫的數(shù)據(jù)生成嚷硫,因此要屏蔽部分代碼检访。將hotseatOccupancy內(nèi)的代碼屏蔽始鱼。
//packages/apps/Launcher3/src/com/android/launcher3/model/LoaderCursor.java
/**
* check & update map of what's occupied; used to discard overlapping/invalid items
*/
protected boolean checkItemPlacement(ItemInfo item) {
..........
if (hotseatOccupancy != null) {
/* if (hotseatOccupancy.cells[(int) item.screenId][0]) {
Log.e(TAG, "Error loading shortcut into hotseat " + item
+ " into position (" + item.screenId + ":" + item.cellX + ","
+ item.cellY + ") already occupied");
return false;
} else {
hotseatOccupancy.cells[item.screenId][0] = true;
return true;
}*/
}
..........
}
}
還有就是如果單獨(dú)編譯launcher的情況下,如果修改default_workspace_4x4文件中hotseat的個數(shù)的話脆贵,重新編譯后医清,要刪除設(shè)備上launcher的數(shù)據(jù)庫,否則重新安裝的時候數(shù)據(jù)庫不會更新卖氨。
打開Android studio中的Device File Explorer会烙,找到launcher.db
這個文件。
路徑是/data/user/0/com.android.launcher3/databases/launcher.db
可通過cmd控制臺筒捺,刪除launcher.db柏腻。另外,部分時候也需要查看launcher.db這個數(shù)據(jù)庫系吭∥迳可通過sqlitestudio打開.db文件。
通過查看.db文件肯尺,hotseat數(shù)據(jù)為8個沃缘,接下來的問題就是修改其顯示。
④修改hotseat的高度则吟。
首先要修改GridOccupancy 的行數(shù)槐臀。
將checkItemPlacement中的
final GridOccupancy occupancy = new GridOccupancy(mIDP.numHotseatIcons, 1);
修改為
final GridOccupancy occupancy = new GridOccupancy(mIDP.numHotseatIcons/2, 2);
//packages/apps/Launcher3/src/com/android/launcher3/model/LoaderCursor.java
protected boolean checkItemPlacement(ItemInfo item) {
..........
if (hotseatOccupancy != null) {
/* if (hotseatOccupancy.cells[(int) item.screenId][0]) {
Log.e(TAG, "Error loading shortcut into hotseat " + item
+ " into position (" + item.screenId + ":" + item.cellX + ","
+ item.cellY + ") already occupied");
return false;
} else {
hotseatOccupancy.cells[item.screenId][0] = true;
return true;
}*/
} else {
final GridOccupancy occupancy = new GridOccupancy(mIDP.numHotseatIcons/2, 2);
..........
}
..........
}
將setGridSize(idp.numHotseatIcons, 1);
修改為 setGridSize(idp.numHotseatIcons/2, 2);
修改后如下。
// packages/apps/Launcher3/src/com/android/launcher3/Hotseat.java
public void resetLayout(boolean hasVerticalHotseat) {
removeAllViewsInLayout();
mHasVerticalHotseat = hasVerticalHotseat;
InvariantDeviceProfile idp = mActivity.getDeviceProfile().inv;
if (hasVerticalHotseat) {
setGridSize(1, idp.numHotseatIcons);
} else {
setGridSize(idp.numHotseatIcons/2, 2);
}
}
這樣就占了2層逾滥。
然后修改hotseat高度峰档。
由于是橫條,所以需要將DeviceProfile中的hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()
修改為hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize *2, dm) + (isVerticalBarLayout()
因?yàn)閟etInsets中有一句lp.height = grid.hotseatBarSizePx + insets.bottom;,也就是說Hotseat的height 取決于hotseatBarSizePx 寨昙。
// packages/apps/Launcher3/src/com/android/launcher3/Hotseat.java
@Override
public void setInsets(Rect insets) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
insets = grid.getInsets();
if (grid.isVerticalBarLayout()) {
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
if (grid.isSeascape()) {
lp.gravity = Gravity.LEFT;
lp.width = grid.hotseatBarSizePx + insets.left;
} else {
lp.gravity = Gravity.RIGHT;
lp.width = grid.hotseatBarSizePx + insets.right;
}
} else {
lp.gravity = Gravity.BOTTOM;
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
lp.height = grid.hotseatBarSizePx + insets.bottom;
}
Rect padding = grid.getHotseatLayoutPadding();
setPadding(padding.left, padding.top, padding.right, padding.bottom);
setLayoutParams(lp);
InsettableFrameLayout.dispatchInsets(this, insets);
}
⑤在addInScreen之前屏蔽掉x和y對于hotseat的特殊計(jì)算讥巡,這里計(jì)算會導(dǎo)致hotaset里的圖標(biāo)的y坐標(biāo)永遠(yuǎn)為0,導(dǎo)致只能顯示一行舔哪。
int getCellYFromOrder(int rank) {
return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0;
}
mHasVerticalHotseat是表示hotseat是否為豎條欢顷,由于我這里是橫條所以一直會返回0.從getCellXFromOrder也可以看出hotseat未修改的源碼的x是根據(jù)rank,這里是screenId去賦值的捉蚤。
int getCellXFromOrder(int rank) {
return mHasVerticalHotseat ? 0 : rank;
}
這里要屏蔽掉對x和y的特殊計(jì)算抬驴,讓其根據(jù)default_workspace_4x4.xml中的 launcher:x
和launcher:y
的值去對快捷圖標(biāo)的x和y進(jìn)行賦值,而不是根據(jù)launcher:screen
缆巧。
修改后如下布持。
//packages/apps/Launcher3/src/com/android/launcher3/WorkspaceLayoutManager.java
default void addInScreenFromBind(View child, ItemInfo info) {
int x = info.cellX;
int y = info.cellY;
/*if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
int screenId = info.screenId;
x = getHotseat().getCellXFromOrder(screenId);
y = getHotseat().getCellYFromOrder(screenId);
}*/
addInScreen(child, info.container, info.screenId, x, y, info.spanX, info.spanY);
}
參考鏈接:
Android10.0 MTK 平板橫屏方案修改(強(qiáng)制app橫屏 + 開機(jī)logo/動畫+關(guān)機(jī)充電橫屏 + RecoveryUI 橫屏)