android 6.0 Launcher3 去掉抽屉式,显示所有 app
效果图
修改思路
1、去除 allAppsButton,调整 HotSeat 布局,禁止增删,禁止生成 Folder
2、将 AllAppsContainerView 中的图标加载到 Workspace
3、去除 Workspace 图标长按删除选项
上代码
1、增加全局控制开关,方便客户选择是否需要去掉抽屉界面。
Launcher3\src\com\android\launcher3\LauncherAppState.java
//cczheng add check is need allappbutton
public static boolean isDisableAllApps() {
if (sContext != null) {
return Settings.System.getInt(sContext.getContentResolver(), "sys.launcher3.is_full_app", 1) == 1;
}
return true;
}
在 LauncherAppState 中添加获取变量的值,对应的值修改可以在 Setting 中通过增加 SwitchPreference 开关或者在 workSpace 长按显示的 view 中增加。
2、取消占位,去除 allAppsButton 按钮
packages\apps\Launcher3\src\com\android\launcher3\Hotseat.java
取消占位
public boolean isAllAppsButtonRank(int rank) {
//cczheng add cancel allAppsButton location
log("isAllAppsButtonRank=="+rank + " mAllAppsButtonRank="+mAllAppsButtonRank);
if (LauncherAppState.isDisableAllApps()) {
return false;
}
return rank == mAllAppsButtonRank;
}
去除 allAppsButton 按钮
void resetLayout() {
mContent.removeAllViewsInLayout();
// cczheng add juge is need add allAppsButton S
if (!LauncherAppState.isDisableAllApps()) {
Context context = getContext();
LayoutInflater inflater = LayoutInflater.from(context);
TextView allAppsButton = (TextView)
inflater.inflate(R.layout.all_apps_button, mContent, false);
Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
mLauncher.resizeIconDrawable(d);
allAppsButton.setCompoundDrawables(null, d, null, null);
allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
if (mLauncher != null) {
mLauncher.setAllAppsButton(allAppsButton);
allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
allAppsButton.setOnClickListener(mLauncher);
allAppsButton.setOnLongClickListener(mLauncher);
allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
}
// Note: We do this to ensure that the hotseat is always laid out in the orientation of
// the hotseat in order regardless of which orientation they were added
int x = getCellXFromOrder(mAllAppsButtonRank);
int y = getCellYFromOrder(mAllAppsButtonRank);
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
lp.canReorder = false;
mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
}//E
}
HotSeat 增加背景
@Override
protected void onFinishInflate() {
super.onFinishInflate();
DeviceProfile grid = mLauncher.getDeviceProfile();
mAllAppsButtonRank = grid.inv.hotseatAllAppsRank;
mContent = (CellLayout) findViewById(R.id.layout);
if (grid.isLandscape && !grid.isLargeTablet) {
mContent.setGridSize(1, (int) grid.inv.numHotseatIcons);
} else {
mContent.setGridSize((int) grid.inv.numHotseatIcons, 1);
}
mContent.setIsHotseat(true);
Log.i(TAG, "onFinishInflate,(int) grid.numHotseatIcons: ");
//cczheng add hotseat bg [s]
if (LauncherAppState.isDisableAllApps()) {
setBackgroundResource(R.drawable.hotseat_bg);
}//E
resetLayout();
}
hotseat_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke
android:width="0.1dp"
android:color="#ffffffff" />
<solid android:color="#50000000" />
<corners android:radius="10dp" />
</shape>
3、HotSeat 区域图标大小调整
Launcher3\src\com\android\launcher3\DeviceProfile.java
区域大小调整
public void layout(Launcher launcher) {
FrameLayout.LayoutParams lp;
boolean hasVerticalBarLayout = isVerticalBarLayout();
final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
....
else {
// For phones, layout the hotseat without any bottom margin
// to ensure that we have space for the folders
/*lp.gravity = Gravity.BOTTOM;
lp.width = LayoutParams.MATCH_PARENT;
lp.height = hotseatBarHeightPx;
hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
2 * edgeMarginPx, 0);*/
//cczheng add if change hotseat default size S
if (LauncherAppState.isDisableAllApps()) {
lp.gravity = Gravity.BOTTOM | Gravity.CENTER;
lp.width = 600;
lp.height = 120;
}else{//E
lp.gravity = Gravity.BOTTOM;
lp.width = LayoutParams.MATCH_PARENT;
lp.height = hotseatBarHeightPx;
hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
2 * edgeMarginPx, 0);
}
}
hotseat.setLayoutParams(lp);
...
}
图标大小调整
Launcher3\src\com\android\launcher3\CellLayout.java
public float getChildrenScale() {
//cczheng add don't sclae large hotseat
return mIsHotseat ? (LauncherAppState.isDisableAllApps() ? 0.75f : mHotseatScale) : 1.0f;
}
4、HotSeat 禁止增删,禁止生成 Folder
禁用长按事件
Launcher3\src\com\android\launcher3\Launcher.java
public boolean onLongClick(View v) {
....
CellLayout.CellInfo longClickCellInfo = null;
View itemUnderLongClick = null;
if (v.getTag() instanceof ItemInfo) {
ItemInfo info = (ItemInfo) v.getTag();
longClickCellInfo = new CellLayout.CellInfo(v, info);
itemUnderLongClick = longClickCellInfo.cell;
resetAddInfo();
}
//cczheng add , hotseat can't be moved and deleted [S]
if (LauncherAppState.isDisableAllApps()) {
if(longClickCellInfo != null && longClickCellInfo.container==-101){
return false;
}
}//E
...
}
禁止生成 Folder
Launcher3\src\com\android\launcher3\Workspace.java
boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
int[] targetCell, float distance, boolean external, DragView dragView,
Runnable postAnimationRunnable) {
....
if (v == null || hasntMoved || !mCreateUserFolderOnDrop) {
if (LauncherLog.DEBUG) {
LauncherLog.d(TAG, "Do not create user folder: hasntMoved = " + hasntMoved
+ ", mCreateUserFolderOnDrop = " + mCreateUserFolderOnDrop + ", v = " + v);
}
return false;
}
//cczheng add don't creat folder in hotseat area [S]
if (LauncherAppState.isDisableAllApps() && mLauncher.isHotseatLayout(target)) {
Log.e("Launcher3", "isHotseatLayout return false");
return false;
}
//[E]
mCreateUserFolderOnDrop = false;
final long screenId = (targetCell == null) ? mDragInfo.screenId : getIdForScreen(target);
....
}
屏蔽圆形浮窗文件夹背景
Launcher3\src\com\android\launcher3\Workspace.java
public void onDragOver(DragObject d) {
if (LauncherLog.DEBUG_DRAG) {
LauncherLog.d(TAG, "onDragOver: d = " + d + ", dragInfo = " + d.dragInfo
+ ", mInScrollArea = " + mInScrollArea + ", mIsSwitchingState = "
+ mIsSwitchingState);
}
// Skip drag over events while we are dragging over side pages
if (mInScrollArea || !transitionStateShouldAllowDrop()) return;
.....
// Handle the drag over
if (mDragTargetLayout != null) {
// We want the point to be mapped to the dragTarget.
if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
//cczheng don't show folder cicle when dragtarget in hotseat are
if (LauncherAppState.isDisableAllApps()) {
Log.d("Launcher3", "don't show folder cicle when dragtarget in hotseat are");
return;
}else{//E
mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
}
} else {
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
}
....
5、将 AllAppsContainerView 中的图标加载到 Workspace
Launcher3\src\com\android\launcher3\LauncherModel.java
内部类 LoaderTask 中, run 方法
private class LoaderTask implements Runnable {
private Context mContext;
@Thunk boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
@Thunk boolean mLoadAndBindStepFinished;
private int mFlags;
LoaderTask(Context context, int flags) {
mContext = context;
mFlags = flags;
}
....
public void run() {
....
// Optimize for end-user experience: if the Launcher is up and // running with the
// All Apps interface in the foreground, load All Apps first. Otherwise, load the
// workspace first (default).
keep_running: {
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
loadAndBindWorkspace();
if (mStopped) {
LauncherLog.i(TAG, "LoadTask break in the middle, this = " + this);
break keep_running;
}
waitForIdle();
// second step
if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
//cczheng add for load all app shortcut on workspace
if (LauncherAppState.isDisableAllApps()) {
verifyApplications();
}//E
}
....
}
...
在 loadAndBindAllApps() 附近增加 verifyApplications()
//cczheng add for load all app shortcut on workspace
private void verifyApplications() {
Log.e("Launcher3", "verifyApplications()");
final Context context = mApp.getContext();
// Cross reference all the applications in our apps list with items in the workspace
ArrayList<ItemInfo> tmpInfos;
ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();
Log.i("Launcher3", "mBgAllAppsList.data size=="+mBgAllAppsList.data.size());
synchronized (sBgLock) {
for (AppInfo app : mBgAllAppsList.data) {
tmpInfos = getItemInfoForComponentName(app.componentName, app.user, app.title.toString());
if (tmpInfos.isEmpty()) {
// We are missing an application icon, so add this to the workspace
added.add(app);
// This is a rare event, so lets log it
Log.e("Launcher3", "Missing Application on load: " + app);
}else{
Log.i("Launcher3", "app.componentName: " + app.componentName);
}
}
}
Log.e("Launcher3", "added.isEmpty()="+added.isEmpty());
if (!added.isEmpty()) {
addAndBindAddedWorkspaceItems(context, added);
}
}
//E
private void loadAndBindAllApps() {
....
}
内部类 PackageUpdatedTask 中,run 方法
Launcher3\src\com\android\launcher3\LauncherModel.java
private class PackageUpdatedTask implements Runnable {
int mOp;
String[] mPackages;
UserHandleCompat mUser;
public static final int OP_NONE = 0;
public static final int OP_ADD = 1;
public static final int OP_UPDATE = 2;
public static final int OP_REMOVE = 3; // uninstlled
public static final int OP_UNAVAILABLE = 4; // external media unmounted
public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {
mOp = op;
mPackages = packages;
mUser = user;
}
public void run() {
....
if (LauncherLog.DEBUG) {
LauncherLog.d(TAG, "PackageUpdatedTask: added = " + added + ",modified = "
+ modified + ",removedApps = " + removedApps);
}
final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
new HashMap<ComponentName, AppInfo>();
if (added != null) {
//cczheng add for load all app shortcut on workspace
if (LauncherAppState.isDisableAllApps()) {
final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
addAndBindAddedWorkspaceItems(context, addedInfos);
}else{//E
addAppsToAllApps(context, added);
}
for (AppInfo ai : added) {
addedOrUpdatedApps.put(ai.componentName, ai);
}
}
....
}
6、去除 Workspace 图标长按删除选项
ButtonDropTarget 的三个实现类,onDragStart() 中 通过 supportsDrop() 控制 ViewGroup 是否显示,那么我只需让 DeleteDropTarget 中 supportsDrop() 为 false
DeleteDropTarget
InfoDropTarget
UninstallDropTarget
public static boolean supportsDrop(Object info) {
//cczheng add for don't show delete icon for shortcut [S]
android.util.Log.e("ccz","dele drop ");
if (LauncherAppState.isDisableAllApps()) {
if (info instanceof ShortcutInfo) {
ShortcutInfo item = (ShortcutInfo) info;
return item.itemType != LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
}
return info instanceof LauncherAppWidgetInfo;
}
//cczheng add for don't show delete icon for shortcut [E]
return (info instanceof ShortcutInfo)
|| (info instanceof LauncherAppWidgetInfo)
|| (info instanceof FolderInfo);
}
7、根据全局控制开关,加载不同的布局
Launcher3\src\com\android\launcher3\InvariantDeviceProfile.java
public class InvariantDeviceProfile {
....
DeviceProfile landscapeProfile;
DeviceProfile portraitProfile;
//cczheng add
boolean isDisableAllApps = LauncherAppState.isDisableAllApps();
InvariantDeviceProfile() {
}
...
ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles() {
ArrayList<InvariantDeviceProfile> predefinedDeviceProfiles = new ArrayList<>();
....
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus S",
296, 491.33f, 4, 4, 4, 4, 4, 48, 13, 5, 48, R.xml.default_workspace_4x4));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 4",
335, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Nexus 5",
359, 567, 4, 4, 4, 4, 4, DEFAULT_ICON_SIZE_DP, 13, 5, 56, R.xml.default_workspace_4x4));
//cczheng add,4x5 xml,5 rows,4 columns [S]
predefinedDeviceProfiles.add(new InvariantDeviceProfile("MTK",
375, 567, 5, 4, 5, 4, 4, 56, 10, isDisableAllApps ? 3 : 5,
56,
isDisableAllApps ? R.xml.default_workspace_4x5_no_all_apps : R.xml.default_workspace_4x5));
//cczheng add,4x5 xml,5 rows,4 columns [E]
predefinedDeviceProfiles.add(new InvariantDeviceProfile("Large Phone",
406, 694, 5, 5, 4, 4, 4, 64, 14.4f, 5, 56, R.xml.default_workspace_5x5));
....
return predefinedDeviceProfiles;
}
....
}
上一篇: 简单明了--5G技术的五大技术支持
下一篇: 永磁同步电机(PMSM)参数辨识(一)