您的位置:首页 > 产品设计 > UI/UE

将原生的Launcher修改成类似MiUI的Launcher

2015-09-23 14:14 615 查看

将原生的Launcher修改成类似MiUi样式的Launcher



上面这个是原生的



上面这个是我们要修改的成果

原生的Launcher已4.2.2版本为base,需要更改一下的几点:

1. Workspace

原生:workspace是存放的App的快捷方式(shortcut)

新生:workspace显示了已经安装的App

2. App的删除方式

原生:在workspace中按住App的快捷方式后,出现Remove的标识,将快捷方式移动到Remove是删除App的快捷方式,并不会卸载此App

新生:在workspace按住App的快捷方式后,出现删除的提示,将App移动到删除提示后,是将此App卸载。

3. 在worksapce中默认是加载的快捷方式,但是原生的App并不一定都是快捷方式,所以需要在Launcher第一次运行的时候,将AllApps加载为Shortcut

那么开始改吧:

1.首先在LauncherModel.java文件中添加一个新类AlreadyInDesktopApps,记录哪些App已经在Desktop上,以及哪个screen已经存在Shortcut

public class AlreadyInDesktopApps {
List<Integer> screenList = null;
List<ShortcutFlag> shortcutFlagList = null;

AlreadyInDesktopApp() {
screenList = new ArrayList<Integer>();
shortcutFlagList = new ArrayList<ShortcutFlag>();
}

public void addScreen(int screen) {
if (!isExistedScreen(screen)) {
screenList.add(screen);
}
}

public List<Integer> getScreens() {
return screenList;
}

public void addShortcutFlag(String packegName, String componentName) {
ShortcutFlag shortcutFlag = new ShortcutFlag(packegName,
componentName);
if (!isExistedShortcutFlag(shortcutFlag)) {
shortcutFlagList.add(shortcutFlag);
}
}

public boolean isExistedScreen(int screen) {
return screenList.contains(screen);
}

public boolean isExistedShortcutFlag(ShortcutFlag shortcutFlag) {
return shortcutFlagList.contains(shortcutFlag);
}

public boolean isExistedShortcutFlag(String packegName,
String componentName) {
ShortcutFlag shortcutFlag = new ShortcutFlag(packegName,
componentName);
return shortcutFlagList.contains(shortcutFlag);
}

private class ShortcutFlag {
String packegName;
String componentName;

public ShortcutFlag(String packegName, String componentName) {
this.packegName = packegName;
this.componentName = componentName;
}

@Override
public boolean equals(Object o) {
if (o instanceof ShortcutFlag) {
ShortcutFlag appFlag = (ShortcutFlag) o;
if (appFlag.packegName.equals(packegName)
&& appFlag.componentName.equals(componentName)) {
return true;
}
}
return false;
}
}
}


在LauncherModel.java中添加函数loadNotInDesktopAllAppsByBatch

private void loadNotInDesktopAllAppsByBatch() {
final Callbacks oldCallbacks = mCallbacks.get();
if (oldCallbacks == null) {
return;
}

final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);

final PackageManager packageManager = mContext.getPackageManager();
List<ResolveInfo> apps = null;

int N = Integer.MAX_VALUE;

int cellCountX = LauncherModel.getCellCountX();
int cellCountY = LauncherModel.getCellCountY();
int maxItemNumOnePage = cellCountX * cellCountY;
int itemTotalNum = 0;
List<Integer> blankScreens = getBlankScreens();

int i = 0;
int batchSize = -1;
while (i < N && !mStopped) {
if (i == 0) {
mBgAllAppsList.clear();
apps = packageManager.queryIntentActivities(mainIntent, 0);
if (apps == null) {
return;
}
N = apps.size();
if (N == 0) {
return;
}
if (mBatchSize == 0) {
batchSize = maxItemNumOnePage;
} else {
batchSize = mBatchSize;
}

Collections.sort(apps,
new LauncherModel.ShortcutNameComparator(
packageManager, mLabelCache));

}
for (int j = 0; i < N && j < batchSi
4000
ze;) {
ApplicationInfo appInfo = new ApplicationInfo(
packageManager, apps.get(i), mIconCache,
mLabelCache);
mBgAllAppsList.add(appInfo);
if (!mAlreadyInDesktopApp.isExistedShortcutFlag(
appInfo.getPackageName(),
appInfo.componentName.getClassName())) {
mBgAllAppsList.added.add(appInfo);
j++;
}
i++;
}

final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
final ArrayList<ApplicationInfo> added = mBgAllAppsList.added;
mBgAllAppsList.added = new ArrayList<ApplicationInfo>();

final ArrayList<ItemInfo> shortcuts = new ArrayList<ItemInfo>();
if (added.size() > 0 && blankScreens.size() > 0) {
for (int n = 0; n < added.size(); n++) {
ShortcutInfo sInfo = new ShortcutInfo(
(ApplicationInfo) added.get(n));
sInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
sInfo.screen = blankScreens.get(itemTotalNum
/ maxItemNumOnePage);
sInfo.cellX = n % cellCountX;
sInfo.cellY = n / cellCountX;
shortcuts.add(sInfo);
addItemToDatabase(mApp.getApplicationContext(), sInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
sInfo.screen, sInfo.cellX, sInfo.cellY, false);
sBgWorkspaceItems.add(sInfo);
sBgItemsIdMap.put(sInfo.id, sInfo);
itemTotalNum++;
}
}

mHandler.post(new Runnable() {
public void run() {
if (callbacks != null && shortcuts.size() > 0) {
callbacks.bindItems(
(ArrayList<ItemInfo>) shortcuts, 0,
shortcuts.size());
} else {
Log.i(TAG, "not binding apps: no Launcher activity");
}
}
});

}
}


在LauncherModel.java中LoaderTask中,添加函数loadAndBindAllNotInDesktopApps,调用上面添加的函数loadNotInDesktopAllAppsByBatch

private void loadAndBindAllNotInDesktopApps() {
if (!mAllAppsLoaded) {
loadNotInDesktopAllAppsByBatch();
synchronized (LoaderTask.this) {
if (mStopped) {
return;
}
mAllAppsLoaded = true;
}
}
}


在LauncherModel.java中的LoaderTask的run中修改

loadAndBindAllNotInDesktopApps();
// second step
//if (loadWorkspaceFirst) {
//    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
//} else {
//    if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
//    loadAndBindWorkspace();
//}
......
loadAndBindAllNotInDesktopApps();
// second step
//if (loadWorkspaceFirst) {
//    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
loadAndBindAllApps();
//} else {
//    if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
//    loadAndBindWorkspace();
//}


在LauncherModel.java的loaderworksapce函数中添加

mAlreadyInDesktopApp = new AlreadyInDesktopApp();//初始化AlreadyInDesktopApp、
......
if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
info = getShortcutInfo(manager, intent, context, c, iconIndex,
titleIndex, mLabelCache);
mAlreadyInDesktopApp   //在从数据库查询Favorites的时候,如果是Shortcut或者是ApplicationInfo则添加到mAlreadyInDesktopApp中,记录哪些App已经被loader到workspace中
.addShortcutFlag(ShortcutInfo
.getPackageName(intent),
info.componentName.getClassName());
} else {


在LauncherModel.java中的PackageUpdatedTask类中修改并添加

if (added != null) {
final ArrayList<ApplicationInfo> addedFinal = added;
processInstallShortcut(mApp.getApplicationContext(), addedFinal);
//mHandler.post(new Runnable() {
//    public void run() {
//        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
//        if (callbacks == cb && cb != null) {
//            callbacks.bindAppsAdded(addedFinal);
//        }
//    }
//});
}

private void processInstallShortcut(Context context,
ArrayList<ApplicationInfo> applicationInfos) {
String spKey = LauncherApplication.getSharedPreferencesKey();
SharedPreferences sp = context.getSharedPreferences(spKey,
Context.MODE_PRIVATE);
LauncherApplication app = (LauncherApplication) context
.getApplicationContext();
final int[] result = { InstallShortcutReceiver.INSTALL_SHORTCUT_SUCCESSFUL };
boolean found = false;
synchronized (app) {
for (int m = 0; m < applicationInfos.size(); m++) {
ApplicationInfo applicationInfo = applicationInfos.get(m);
final ArrayList<ItemInfo> items = LauncherModel
.getItemsInLocalCoordinates(context);
final boolean exists = LauncherModel.shortcutExists(context,
applicationInfo.title.toString(),
applicationInfo.intent);

final int screen = Launcher.DEFAULT_SCREEN;
for (int i = 0; i < (2 * Launcher.SCREEN_COUNT) + 1 && !found; ++i) {
int si = screen + (int) ((i / 2f) + 0.5f)
* ((i % 2 == 1) ? 1 : -1);
if (0 <= si && si < Launcher.SCREEN_COUNT) {

found = installShortcut(context, items,
applicationInfo, si, exists, sp, result);
}
}

if (!found) {
if (result[0] == InstallShortcutReceiver.INSTALL_SHORTCUT_NO_SPACE) {
Toast.makeText(
context,
context.getString(R.string.completely_out_of_space),
Toast.LENGTH_SHORT).show();
} else if (result[0] == InstallShortcutReceiver.INSTALL_SHORTCUT_IS_DUPLICATE) {
Toast.makeText(
context,
context.getString(R.string.shortcut_duplicate,
applicationInfo.title.toString()),
Toast.LENGTH_SHORT).show();
}
}
}
}
}

private boolean installShortcut(Context context, ArrayList<ItemInfo> items,
ApplicationInfo applicationInfo, final int screen,
boolean shortcutExists, final SharedPreferences sharedPrefs,
int[] result) {
int[] tmpCoordinates = new int[2];
if (findEmptyCell(context, items, tmpCoordinates, screen)) {
if (applicationInfo != null) {
if (!shortcutExists) {
int newAppsScreen = sharedPrefs.getInt(
InstallShortcutReceiver.NEW_APPS_PAGE_KEY, screen);
Set<String> newApps = new HashSet<String>();
if (newAppsScreen == screen) {
newApps = sharedPrefs.getStringSet(
InstallShortcutReceiver.NEW_APPS_LIST_KEY,
newApps);
}
synchronized (newApps) {
newApps.add(applicationInfo.intent.toUri(0).toString());
}
final Set<String> savedNewApps = newApps;
new Thread("setNewAppsInstallThread") {
public void run() {
synchronized (savedNewApps) {
sharedPrefs
.edit()
.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY,
screen)
.putStringSet(
InstallShortcutReceiver.NEW_APPS_LIST_KEY,
savedNewApps).commit();
}
}
}.start();
final ArrayList<ItemInfo> shortcuts = new ArrayList<ItemInfo>();
ShortcutInfo sInfo = new ShortcutInfo(applicationInfo);
sInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
sInfo.screen = screen;
sInfo.cellX = tmpCoordinates[0];
sInfo.cellY = tmpCoordinates[1];
shortcuts.add(sInfo);
addItemToDatabase(mApp.getApplicationContext(), sInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
sInfo.screen, sInfo.cellX, sInfo.cellY, false);
sBgWorkspaceItems.add(sInfo);
sBgItemsIdMap.put(sInfo.id, sInfo);
final Callbacks callbacks = mCallbacks.get();
Runnable r = new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks
.get() : null;
if (callbacks == cb && cb != null
&& shortcuts.size() > 0) {
callbacks.bindItemsNotSetLoadOnResume(
(ArrayList<ItemInfo>) shortcuts, 0,
shortcuts.size());
} else {
Log.i(TAG, "not Install apps to desktop");
}
}
};
runOnMainThread(r);
} else {
result[0] = InstallShortcutReceiver.INSTALL_SHORTCUT_IS_DUPLICATE;
}

return true;
}
} else {
result[0] = InstallShortcutReceiver.INSTALL_SHORTCUT_NO_SPACE;
}

return false;
}


在LauncherModel.java中的Callback接口中添加新的接口,用来在新安装了App的时候更新Workspace

public interface Callbacks {
public void bindItemsNotSetLoadOnResume(ArrayList<ItemInfo> shortcuts, int start, int end);
}


在Launcher.java中变更函数startApplicationUninstallActivity,变更后workspace中长按Shortcut后,拖动图标到上方的垃圾桶,卸载App

void startApplicationUninstallActivity(ShortcutInfo shortcut) {
// if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) == 0) {
// System applications cannot be installed. For now, show a toast
// explaining that.
// We may give them the option of disabling apps this way.
// int messageId = R.string.uninstall_system_app_text;
// Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show();
// } else {
// }
mWorkspace.addInScreen(createShortcut(shortcut), shortcut.container,
shortcut.screen, shortcut.cellX, shortcut.cellY, 1, 1, false);
String packageName = shortcut.componentName.getPackageName();
String className = shortcut.componentName.getClassName();
Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts(
"package", packageName, className));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
}


在Launcher.java中实现LauncherModel.java中新定义的Callback接口

public void bindItemsNotSetLoadOnResume(ArrayList<ItemInfo> shortcuts, int start, int end) {
Set<String> newApps = new HashSet<String>();
newApps = mSharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);

Workspace workspace = mWorkspace;
for (int i = start; i < end; i++) {
final ItemInfo item = shortcuts.get(i);

// Short circuit if we are loading dock items for a configuration which has no dock
if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
mHotseat == null) {
continue;
}

switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
ShortcutInfo info = (ShortcutInfo) item;
String uri = info.intent.toUri(0).toString();
View shortcut = createShortcut(info);
workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
item.cellY, 1, 1, false);
break;
}
}
workspace.requestLayout();
}


上面就是比较关键的代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  launcher app