在home节面上,当我们点击中间按键的时候,会跳转到一个下图,
在代码中是如何实现的呢?我们来找一下:
mHandleView = (HandleView) findViewById(R.id.all_apps_button);
mHandleView.setLauncher(this);
mHandleView.setOnClickListener(this);
mHandleView.setOnLongClickListener(this);
再看onclick()方法:在onclick方法中,有一下代码
else if (v == mHandleView) {
if (isAllAppsVisible()) {
closeAllApps(true);
} else {
showAllApps(true);
}
我们再找一下
showAllApps()方法
void showAllApps(boolean animated) {
mAllAppsGrid.zoom(1.0f, animated);
((View) mAllAppsGrid).setFocusable(true);
((View) mAllAppsGrid).requestFocus();
// TODO: fade these two too
mDeleteZone.setVisibility(View.GONE);
mHandleView.setVisibility(View.GONE);
mPreviousView.setVisibility(View.GONE);
mNextView.setVisibility(View.GONE);
hotseatLeft.setVisibility(View.GONE);
hotseatRight.setVisibility(View.GONE);
}
在上面用到了mAllAppsGrid,我们找一下这个控件:
private AllAppsView mAllAppsGrid;
mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
mAllAppsGrid.setLauncher(this);
mAllAppsGrid.setDragController(dragController);
((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.
// Manage focusability manually since this thing is always visible
((View) mAllAppsGrid).setFocusable(false);
上面代码是在Launcher.java中的setupview()方法中定义all_apps_view是在all_app_2d.xml中定义。
你想找到AllApp2D.java中,可以找到mAllAppsGrid使用的方法,如addApps,removeApps,zoom这几个方法:
public void addApps(ArrayList<ApplicationInfo> list) {
// Log.d(TAG, "addApps: " + list.size() + " apps: " + list.toString());
final int N = list.size();
for (int i=0; i<N; i++) {
final ApplicationInfo item = list.get(i);
int index = Collections.binarySearch(mAllAppsList, item,
LauncherModel.APP_NAME_COMPARATOR);
if (index < 0) {
index = -(index+1);
}
mAllAppsList.add(index, item);
}
mAppsAdapter.notifyDataSetChanged();
}
public void removeApps(ArrayList<ApplicationInfo> list) {
final int N = list.size();
for (int i=0; i<N; i++) {
final ApplicationInfo item = list.get(i);
int index = findAppByComponent(mAllAppsList, item);
if (index >= 0) {
mAllAppsList.remove(index);
} else {
Log.w(TAG, "couldn't find a match for item \"" + item + "\"");
// Try to recover. This should keep us from crashing for now.
}
}
mAppsAdapter.notifyDataSetChanged();
}
public void zoom(float zoom, boolean animate) {
// Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed"));
cancelLongPress();
mZoom = zoom;
if (isVisible()) {
getParent().bringChildToFront(this);
setVisibility(View.VISIBLE);
mGrid.setAdapter(mAppsAdapter);
if (animate) {
startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in));
} else {
onAnimationEnd();
}
} else {
if (animate) {
startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out));
} else {
onAnimationEnd();
}
}
}
在zoom()方法里面有mGrid.setAdapter(mAppsAdapter),在构造方法中,给adapter已经赋值。
public AllApps2D(Context context, AttributeSet attrs) {
super(context, attrs);
setVisibility(View.GONE);
setSoundEffectsEnabled(false);
mAppsAdapter = new AppsAdapter(getContext(), mAllAppsList);
mAppsAdapter.setNotifyOnChange(false);
}
那是如何获取应用列表的呢?我们再回到Launcher.java中,在loadHotseats()中:
private void loadHotseats() {
if (mHotseatConfig == null) {
mHotseatConfig = getResources().getStringArray(R.array.hotseats);
if (mHotseatConfig.length > 0) {
mHotseats = new Intent[mHotseatConfig.length];
mHotseatLabels = new CharSequence[mHotseatConfig.length];
mHotseatIcons = new Drawable[mHotseatConfig.length];
} else {
mHotseats = null;
mHotseatIcons = null;
mHotseatLabels = null;
}
TypedArray hotseatIconDrawables = getResources().obtainTypedArray(R.array.hotseat_icons);
for (int i=0; i<mHotseatConfig.length; i++) {
// load icon for this slot; currently unrelated to the actual activity
try {
mHotseatIcons[i] = hotseatIconDrawables.getDrawable(i);
} catch (ArrayIndexOutOfBoundsException ex) {
Log.w(TAG, "Missing hotseat_icons array item #" + i);
mHotseatIcons[i] = null;
}
}
hotseatIconDrawables.recycle();
}
PackageManager pm = getPackageManager();
for (int i=0; i<mHotseatConfig.length; i++) {
Intent intent = null;
if (mHotseatConfig[i].equals("*BROWSER*")) {
// magic value meaning "launch user's default web browser"
// replace it with a generic web request so we can see if there is indeed a default
String defaultUri = getString(R.string.default_browser_url);
intent = new Intent(
Intent.ACTION_VIEW,
((defaultUri != null)
? Uri.parse(defaultUri)
: getDefaultBrowserUri())
).addCategory(Intent.CATEGORY_BROWSABLE);
// note: if the user launches this without a default set, she
// will always be taken to the default URL above; this is
// unavoidable as we must specify a valid URL in order for the
// chooser to appear, and once the user selects something, that
// URL is unavoidably sent to the chosen app.
} else {
try {
intent = Intent.parseUri(mHotseatConfig[i], 0);
} catch (java.net.URISyntaxException ex) {
Log.w(TAG, "Invalid hotseat intent: " + mHotseatConfig[i]);
// bogus; leave intent=null
}
}
if (intent == null) {
mHotseats[i] = null;
mHotseatLabels[i] = getText(R.string.activity_not_found);
continue;
}
if (LOGD) {
Log.d(TAG, "loadHotseats: hotseat " + i
+ " initial intent=["
+ intent.toUri(Intent.URI_INTENT_SCHEME)
+ "]");
}
ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (LOGD) {
Log.d(TAG, "Best match for intent: " + bestMatch);
Log.d(TAG, "All matches: ");
for (ResolveInfo ri : allMatches) {
Log.d(TAG, " --> " + ri);
}
}
// did this resolve to a single app, or the resolver?
if (allMatches.size() == 0 || bestMatch == null) {
// can't find any activity to handle this. let's leave the
// intent as-is and let Launcher show a toast when it fails
// to launch.
mHotseats[i] = intent;
// set accessibility text to "Not installed"
mHotseatLabels[i] = getText(R.string.activity_not_found);
} else {
boolean found = false;
for (ResolveInfo ri : allMatches) {
if (bestMatch.activityInfo.name.equals(ri.activityInfo.name)
&& bestMatch.activityInfo.applicationInfo.packageName
.equals(ri.activityInfo.applicationInfo.packageName)) {
found = true;
break;
}
}
if (!found) {
if (LOGD) Log.d(TAG, "Multiple options, no default yet");
// the bestMatch is probably the ResolveActivity, meaning the
// user has not yet selected a default
// so: we'll keep the original intent for now
mHotseats[i] = intent;
// set the accessibility text to "Select shortcut"
mHotseatLabels[i] = getText(R.string.title_select_shortcut);
} else {
// we have an app!
// now reconstruct the intent to launch it through the front
// door
ComponentName com = new ComponentName(
bestMatch.activityInfo.applicationInfo.packageName,
bestMatch.activityInfo.name);
mHotseats[i] = new Intent(Intent.ACTION_MAIN).setComponent(com);
// load the app label for accessibility
mHotseatLabels[i] = bestMatch.activityInfo.loadLabel(pm);
}
}
if (LOGD) {
Log.d(TAG, "loadHotseats: hotseat " + i
+ " final intent=["
+ ((mHotseats[i] == null)
? "null"
: mHotseats[i].toUri(Intent.URI_INTENT_SCHEME))
+ "] label=[" + mHotseatLabels[i]
+ "]"
);
}
}
}
有点复杂,主要代码其实如下:
PackageManager pm = getPackageManager();
ResolveInfo bestMatch = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
List<ResolveInfo> allMatches = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
这样就获取了。下面以一个简单的例子结束,
获取在sd卡中安装的程序列表:
private void getSdcardApps(){
mSdcardAppsList.clear();
ActivityManager am = (ActivityManager)mLauncher.getSystemService(Activity.ACTIVITY_SERVICE);
PackageManager pm =mLauncher.getPackageManager();
List<android.content.pm.ApplicationInfo> list = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
for (android.content.pm.ApplicationInfo appInfo : list) {
if((appInfo.flags & android.content.pm.ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0){
for (ApplicationInfo applicationInfo : mAllAppsList) {
if(appInfo.packageName.equals(applicationInfo.componentName.getPackageName())){
mSdcardAppsList.add(applicationInfo);
break;
}
}
}
}
mAppsAdapter = new AppsAdapter(getContext(), mSdcardAppsList);
mAppsAdapter.notifyDataSetChanged();
mGrid.setAdapter(mAppsAdapter);
text.setVisibility(View.VISIBLE);
text.setBackgroundResource(R.drawable.tab_mmenu_b3_normal);
}