首先要对hotseat等位置有一定的了解。
https://blog.csdn.net/baidu_41672657/article/details/83383137
首先改横屏是修改device/qcom/xxx/system.prop文件中的。
persist.panel.orientation=270
,一开始是persist.panel.orientation=0
。
这个数值可以通过adb直接修改,重启后生效。
setprop persist.panel.orientation 270
关于adb调屏幕的命令还有
adb shell settings put system show_touches 1
adb shell settings put system pointer_location 1
是打开Show taps和Pointer location([显示点按操作反馈]和[指针位置])。
修改点如下。
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.需要强制所有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.需调整navigationbar位置。系统设置为横屏显示后,横屏后 navigationBar默认在左边。需修改DisplayPolicy中的navigationBarPosition函数,屏蔽判断部分,使其直接返回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的布局,现在图标变小填充并且不再是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区域添加的图标显示不全。具体修改如下。
//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 界面搜索应用栏,需修改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.国内基本上都是去掉Android原生的抽屉式的,修改部分基本参考这个。太长了就不写了。
android10.0(Q) Launcher3 去掉抽屉
9.修改hotseat。hotseat一般默认是4个,布局为4x1。
现需增加为8个,布局改成4x2。
①首先修改device_profiles.xml,这个文件存在于go\res\xml和res\xml文件夹。可以都改一下,因为单独编译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数据。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的要在对应的apk中添加。例如我的DeskClock,AndroidManifest.xml缺少
<category android:name="android.intent.category.APP_DeskClock"/>
,要加进去。
③屏蔽检验部分代码。
LoaderCursor中的checkItemPlacement会判断hotseat的一行是否填充,如果填充了就不能再进行填充了。这里会影响数据库的数据生成,因此要屏蔽部分代码。将hotseatOccupancy内的代码屏蔽。
//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;
}*/
}
..........
}
}
还有就是如果单独编译launcher的情况下,如果修改default_workspace_4x4文件中hotseat的个数的话,重新编译后,要删除设备上launcher的数据库,否则重新安装的时候数据库不会更新。
打开Android studio中的Device File Explorer,找到launcher.db
这个文件。
路径是/data/user/0/com.android.launcher3/databases/launcher.db
可通过cmd控制台,删除launcher.db。另外,部分时候也需要查看launcher.db这个数据库。可通过sqlitestudio打开.db文件。
通过查看.db文件,hotseat数据为8个,接下来的问题就是修改其显示。
④修改hotseat的高度。
首先要修改GridOccupancy 的行数。
将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()
因为setInsets中有一句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的特殊计算,这里计算会导致hotaset里的图标的y坐标永远为0,导致只能显示一行。
int getCellYFromOrder(int rank) {
return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0;
}
mHasVerticalHotseat是表示hotseat是否为竖条,由于我这里是横条所以一直会返回0.从getCellXFromOrder也可以看出hotseat未修改的源码的x是根据rank,这里是screenId去赋值的。
int getCellXFromOrder(int rank) {
return mHasVerticalHotseat ? 0 : rank;
}
这里要屏蔽掉对x和y的特殊计算,让其根据default_workspace_4x4.xml中的 launcher:x
和launcher:y
的值去对快捷图标的x和y进行赋值,而不是根据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 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)
网友评论