| /* | |
| * Copyright (C) 2007 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package com.example.android.home; | |
| import android.app.Activity; | |
| import android.app.ActivityManager; | |
| import android.app.SearchManager; | |
| import android.content.BroadcastReceiver; | |
| import android.content.ComponentName; | |
| import android.content.Context; | |
| import android.content.Intent; | |
| import android.content.IntentFilter; | |
| import android.content.pm.ActivityInfo; | |
| import android.content.pm.PackageManager; | |
| import android.content.pm.ResolveInfo; | |
| import android.graphics.Bitmap; | |
| import android.graphics.Canvas; | |
| import android.graphics.Paint; | |
| import android.graphics.PaintFlagsDrawFilter; | |
| import android.graphics.PixelFormat; | |
| import android.graphics.Rect; | |
| import android.graphics.ColorFilter; | |
| import android.graphics.drawable.BitmapDrawable; | |
| import android.graphics.drawable.Drawable; | |
| import android.graphics.drawable.PaintDrawable; | |
| import android.os.Bundle; | |
| import android.os.Environment; | |
| import android.util.Log; | |
| import android.util.Xml; | |
| import android.view.KeyEvent; | |
| import android.view.LayoutInflater; | |
| import android.view.Menu; | |
| import android.view.MenuItem; | |
| import android.view.View; | |
| import android.view.ViewGroup; | |
| import android.view.animation.Animation; | |
| import android.view.animation.AnimationUtils; | |
| import android.view.animation.LayoutAnimationController; | |
| import android.widget.AdapterView; | |
| import android.widget.ArrayAdapter; | |
| import android.widget.CheckBox; | |
| import android.widget.GridView; | |
| import android.widget.TextView; | |
| import java.io.IOException; | |
| import java.io.FileReader; | |
| import java.io.File; | |
| import java.io.FileNotFoundException; | |
| import java.util.ArrayList; | |
| import java.util.Collections; | |
| import java.util.LinkedList; | |
| import java.util.List; | |
| import org.xmlpull.v1.XmlPullParser; | |
| import org.xmlpull.v1.XmlPullParserException; | |
| public class Home extends Activity { | |
| /** | |
| * Tag used for logging errors. | |
| */ | |
| private static final String LOG_TAG = "Home"; | |
| /** | |
| * Keys during freeze/thaw. | |
| */ | |
| private static final String KEY_SAVE_GRID_OPENED = "grid.opened"; | |
| private static final String DEFAULT_FAVORITES_PATH = "etc/favorites.xml"; | |
| private static final String TAG_FAVORITES = "favorites"; | |
| private static final String TAG_FAVORITE = "favorite"; | |
| private static final String TAG_PACKAGE = "package"; | |
| private static final String TAG_CLASS = "class"; | |
| // Identifiers for option menu items | |
| private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1; | |
| private static final int MENU_SEARCH = MENU_WALLPAPER_SETTINGS + 1; | |
| private static final int MENU_SETTINGS = MENU_SEARCH + 1; | |
| /** | |
| * Maximum number of recent tasks to query. | |
| */ | |
| private static final int MAX_RECENT_TASKS = 20; | |
| private static boolean mWallpaperChecked; | |
| private static ArrayList<ApplicationInfo> mApplications; | |
| private static LinkedList<ApplicationInfo> mFavorites; | |
| private final BroadcastReceiver mWallpaperReceiver = new WallpaperIntentReceiver(); | |
| private final BroadcastReceiver mApplicationsReceiver = new ApplicationsIntentReceiver(); | |
| private GridView mGrid; | |
| private LayoutAnimationController mShowLayoutAnimation; | |
| private LayoutAnimationController mHideLayoutAnimation; | |
| private boolean mBlockAnimation; | |
| private boolean mHomeDown; | |
| private boolean mBackDown; | |
| private View mShowApplications; | |
| private CheckBox mShowApplicationsCheck; | |
| private ApplicationsStackLayout mApplicationsStack; | |
| private Animation mGridEntry; | |
| private Animation mGridExit; | |
| @Override | |
| public void onCreate(Bundle icicle) { | |
| super.onCreate(icicle); | |
| setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); | |
| setContentView(R.layout.home); | |
| registerIntentReceivers(); | |
| setDefaultWallpaper(); | |
| loadApplications(true); | |
| bindApplications(); | |
| bindFavorites(true); | |
| bindRecents(); | |
| bindButtons(); | |
| mGridEntry = AnimationUtils.loadAnimation(this, R.anim.grid_entry); | |
| mGridExit = AnimationUtils.loadAnimation(this, R.anim.grid_exit); | |
| } | |
| @Override | |
| protected void onNewIntent(Intent intent) { | |
| super.onNewIntent(intent); | |
| // Close the menu | |
| if (Intent.ACTION_MAIN.equals(intent.getAction())) { | |
| getWindow().closeAllPanels(); | |
| } | |
| } | |
| @Override | |
| public void onDestroy() { | |
| super.onDestroy(); | |
| // Remove the callback for the cached drawables or we leak | |
| // the previous Home screen on orientation change | |
| final int count = mApplications.size(); | |
| for (int i = 0; i < count; i++) { | |
| mApplications.get(i).icon.setCallback(null); | |
| } | |
| unregisterReceiver(mWallpaperReceiver); | |
| unregisterReceiver(mApplicationsReceiver); | |
| } | |
| @Override | |
| protected void onResume() { | |
| super.onResume(); | |
| bindRecents(); | |
| } | |
| @Override | |
| protected void onRestoreInstanceState(Bundle state) { | |
| super.onRestoreInstanceState(state); | |
| final boolean opened = state.getBoolean(KEY_SAVE_GRID_OPENED, false); | |
| if (opened) { | |
| showApplications(false); | |
| } | |
| } | |
| @Override | |
| protected void onSaveInstanceState(Bundle outState) { | |
| super.onSaveInstanceState(outState); | |
| outState.putBoolean(KEY_SAVE_GRID_OPENED, mGrid.getVisibility() == View.VISIBLE); | |
| } | |
| /** | |
| * Registers various intent receivers. The current implementation registers | |
| * only a wallpaper intent receiver to let other applications change the | |
| * wallpaper. | |
| */ | |
| private void registerIntentReceivers() { | |
| IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); | |
| registerReceiver(mWallpaperReceiver, filter); | |
| filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); | |
| filter.addAction(Intent.ACTION_PACKAGE_REMOVED); | |
| filter.addAction(Intent.ACTION_PACKAGE_CHANGED); | |
| filter.addDataScheme("package"); | |
| registerReceiver(mApplicationsReceiver, filter); | |
| } | |
| /** | |
| * Creates a new appplications adapter for the grid view and registers it. | |
| */ | |
| private void bindApplications() { | |
| if (mGrid == null) { | |
| mGrid = (GridView) findViewById(R.id.all_apps); | |
| } | |
| mGrid.setAdapter(new ApplicationsAdapter(this, mApplications)); | |
| mGrid.setSelection(0); | |
| if (mApplicationsStack == null) { | |
| mApplicationsStack = (ApplicationsStackLayout) findViewById(R.id.faves_and_recents); | |
| } | |
| } | |
| /** | |
| * Binds actions to the various buttons. | |
| */ | |
| private void bindButtons() { | |
| mShowApplications = findViewById(R.id.show_all_apps); | |
| mShowApplications.setOnClickListener(new ShowApplications()); | |
| mShowApplicationsCheck = (CheckBox) findViewById(R.id.show_all_apps_check); | |
| mGrid.setOnItemClickListener(new ApplicationLauncher()); | |
| } | |
| /** | |
| * When no wallpaper was manually set, a default wallpaper is used instead. | |
| */ | |
| private void setDefaultWallpaper() { | |
| if (!mWallpaperChecked) { | |
| Drawable wallpaper = peekWallpaper(); | |
| if (wallpaper == null) { | |
| try { | |
| clearWallpaper(); | |
| } catch (IOException e) { | |
| Log.e(LOG_TAG, "Failed to clear wallpaper " + e); | |
| } | |
| } else { | |
| getWindow().setBackgroundDrawable(new ClippedDrawable(wallpaper)); | |
| } | |
| mWallpaperChecked = true; | |
| } | |
| } | |
| /** | |
| * Refreshes the favorite applications stacked over the all apps button. | |
| * The number of favorites depends on the user. | |
| */ | |
| private void bindFavorites(boolean isLaunching) { | |
| if (!isLaunching || mFavorites == null) { | |
| if (mFavorites == null) { | |
| mFavorites = new LinkedList<ApplicationInfo>(); | |
| } else { | |
| mFavorites.clear(); | |
| } | |
| mApplicationsStack.setFavorites(mFavorites); | |
| FileReader favReader; | |
| // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". | |
| final File favFile = new File(Environment.getRootDirectory(), DEFAULT_FAVORITES_PATH); | |
| try { | |
| favReader = new FileReader(favFile); | |
| } catch (FileNotFoundException e) { | |
| Log.e(LOG_TAG, "Couldn't find or open favorites file " + favFile); | |
| return; | |
| } | |
| final Intent intent = new Intent(Intent.ACTION_MAIN, null); | |
| intent.addCategory(Intent.CATEGORY_LAUNCHER); | |
| final PackageManager packageManager = getPackageManager(); | |
| try { | |
| final XmlPullParser parser = Xml.newPullParser(); | |
| parser.setInput(favReader); | |
| beginDocument(parser, TAG_FAVORITES); | |
| ApplicationInfo info; | |
| while (true) { | |
| nextElement(parser); | |
| String name = parser.getName(); | |
| if (!TAG_FAVORITE.equals(name)) { | |
| break; | |
| } | |
| final String favoritePackage = parser.getAttributeValue(null, TAG_PACKAGE); | |
| final String favoriteClass = parser.getAttributeValue(null, TAG_CLASS); | |
| final ComponentName cn = new ComponentName(favoritePackage, favoriteClass); | |
| intent.setComponent(cn); | |
| intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
| info = getApplicationInfo(packageManager, intent); | |
| if (info != null) { | |
| info.intent = intent; | |
| mFavorites.addFirst(info); | |
| } | |
| } | |
| } catch (XmlPullParserException e) { | |
| Log.w(LOG_TAG, "Got exception parsing favorites.", e); | |
| } catch (IOException e) { | |
| Log.w(LOG_TAG, "Got exception parsing favorites.", e); | |
| } | |
| } | |
| mApplicationsStack.setFavorites(mFavorites); | |
| } | |
| private static void beginDocument(XmlPullParser parser, String firstElementName) | |
| throws XmlPullParserException, IOException { | |
| int type; | |
| while ((type = parser.next()) != XmlPullParser.START_TAG && | |
| type != XmlPullParser.END_DOCUMENT) { | |
| // Empty | |
| } | |
| if (type != XmlPullParser.START_TAG) { | |
| throw new XmlPullParserException("No start tag found"); | |
| } | |
| if (!parser.getName().equals(firstElementName)) { | |
| throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + | |
| ", expected " + firstElementName); | |
| } | |
| } | |
| private static void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException { | |
| int type; | |
| while ((type = parser.next()) != XmlPullParser.START_TAG && | |
| type != XmlPullParser.END_DOCUMENT) { | |
| // Empty | |
| } | |
| } | |
| /** | |
| * Refreshes the recently launched applications stacked over the favorites. The number | |
| * of recents depends on how many favorites are present. | |
| */ | |
| private void bindRecents() { | |
| final PackageManager manager = getPackageManager(); | |
| final ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); | |
| final List<ActivityManager.RecentTaskInfo> recentTasks = tasksManager.getRecentTasks( | |
| MAX_RECENT_TASKS, 0); | |
| final int count = recentTasks.size(); | |
| final ArrayList<ApplicationInfo> recents = new ArrayList<ApplicationInfo>(); | |
| for (int i = count - 1; i >= 0; i--) { | |
| final Intent intent = recentTasks.get(i).baseIntent; | |
| if (Intent.ACTION_MAIN.equals(intent.getAction()) && | |
| !intent.hasCategory(Intent.CATEGORY_HOME)) { | |
| ApplicationInfo info = getApplicationInfo(manager, intent); | |
| if (info != null) { | |
| info.intent = intent; | |
| if (!mFavorites.contains(info)) { | |
| recents.add(info); | |
| } | |
| } | |
| } | |
| } | |
| mApplicationsStack.setRecents(recents); | |
| } | |
| private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) { | |
| final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0); | |
| if (resolveInfo == null) { | |
| return null; | |
| } | |
| final ApplicationInfo info = new ApplicationInfo(); | |
| final ActivityInfo activityInfo = resolveInfo.activityInfo; | |
| info.icon = activityInfo.loadIcon(manager); | |
| if (info.title == null || info.title.length() == 0) { | |
| info.title = activityInfo.loadLabel(manager); | |
| } | |
| if (info.title == null) { | |
| info.title = ""; | |
| } | |
| return info; | |
| } | |
| @Override | |
| public void onWindowFocusChanged(boolean hasFocus) { | |
| super.onWindowFocusChanged(hasFocus); | |
| if (!hasFocus) { | |
| mBackDown = mHomeDown = false; | |
| } | |
| } | |
| @Override | |
| public boolean dispatchKeyEvent(KeyEvent event) { | |
| if (event.getAction() == KeyEvent.ACTION_DOWN) { | |
| switch (event.getKeyCode()) { | |
| case KeyEvent.KEYCODE_BACK: | |
| mBackDown = true; | |
| return true; | |
| case KeyEvent.KEYCODE_HOME: | |
| mHomeDown = true; | |
| return true; | |
| } | |
| } else if (event.getAction() == KeyEvent.ACTION_UP) { | |
| switch (event.getKeyCode()) { | |
| case KeyEvent.KEYCODE_BACK: | |
| if (!event.isCanceled()) { | |
| // Do BACK behavior. | |
| } | |
| mBackDown = true; | |
| return true; | |
| case KeyEvent.KEYCODE_HOME: | |
| if (!event.isCanceled()) { | |
| // Do HOME behavior. | |
| } | |
| mHomeDown = true; | |
| return true; | |
| } | |
| } | |
| return super.dispatchKeyEvent(event); | |
| } | |
| @Override | |
| public boolean onCreateOptionsMenu(Menu menu) { | |
| super.onCreateOptionsMenu(menu); | |
| menu.add(0, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper) | |
| .setIcon(android.R.drawable.ic_menu_gallery) | |
| .setAlphabeticShortcut('W'); | |
| menu.add(0, MENU_SEARCH, 0, R.string.menu_search) | |
| .setIcon(android.R.drawable.ic_search_category_default) | |
| .setAlphabeticShortcut(SearchManager.MENU_KEY); | |
| menu.add(0, MENU_SETTINGS, 0, R.string.menu_settings) | |
| .setIcon(android.R.drawable.ic_menu_preferences) | |
| .setIntent(new Intent(android.provider.Settings.ACTION_SETTINGS)); | |
| return true; | |
| } | |
| @Override | |
| public boolean onOptionsItemSelected(MenuItem item) { | |
| switch (item.getItemId()) { | |
| case MENU_WALLPAPER_SETTINGS: | |
| startWallpaper(); | |
| return true; | |
| case MENU_SEARCH: | |
| onSearchRequested(); | |
| return true; | |
| } | |
| return super.onOptionsItemSelected(item); | |
| } | |
| private void startWallpaper() { | |
| final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER); | |
| startActivity(Intent.createChooser(pickWallpaper, getString(R.string.menu_wallpaper))); | |
| } | |
| /** | |
| * Loads the list of installed applications in mApplications. | |
| */ | |
| private void loadApplications(boolean isLaunching) { | |
| if (isLaunching && mApplications != null) { | |
| return; | |
| } | |
| PackageManager manager = getPackageManager(); | |
| Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); | |
| mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); | |
| final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0); | |
| Collections.sort(apps, new ResolveInfo.DisplayNameComparator(manager)); | |
| if (apps != null) { | |
| final int count = apps.size(); | |
| if (mApplications == null) { | |
| mApplications = new ArrayList<ApplicationInfo>(count); | |
| } | |
| mApplications.clear(); | |
| for (int i = 0; i < count; i++) { | |
| ApplicationInfo application = new ApplicationInfo(); | |
| ResolveInfo info = apps.get(i); | |
| application.title = info.loadLabel(manager); | |
| application.setActivity(new ComponentName( | |
| info.activityInfo.applicationInfo.packageName, | |
| info.activityInfo.name), | |
| Intent.FLAG_ACTIVITY_NEW_TASK | |
| | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); | |
| application.icon = info.activityInfo.loadIcon(manager); | |
| mApplications.add(application); | |
| } | |
| } | |
| } | |
| /** | |
| * Shows all of the applications by playing an animation on the grid. | |
| */ | |
| private void showApplications(boolean animate) { | |
| if (mBlockAnimation) { | |
| return; | |
| } | |
| mBlockAnimation = true; | |
| mShowApplicationsCheck.toggle(); | |
| if (mShowLayoutAnimation == null) { | |
| mShowLayoutAnimation = AnimationUtils.loadLayoutAnimation( | |
| this, R.anim.show_applications); | |
| } | |
| // This enables a layout animation; if you uncomment this code, you need to | |
| // comment the line mGrid.startAnimation() below | |
| // mGrid.setLayoutAnimationListener(new ShowGrid()); | |
| // mGrid.setLayoutAnimation(mShowLayoutAnimation); | |
| // mGrid.startLayoutAnimation(); | |
| if (animate) { | |
| mGridEntry.setAnimationListener(new ShowGrid()); | |
| mGrid.startAnimation(mGridEntry); | |
| } | |
| mGrid.setVisibility(View.VISIBLE); | |
| if (!animate) { | |
| mBlockAnimation = false; | |
| } | |
| // ViewDebug.startHierarchyTracing("Home", mGrid); | |
| } | |
| /** | |
| * Hides all of the applications by playing an animation on the grid. | |
| */ | |
| private void hideApplications() { | |
| if (mBlockAnimation) { | |
| return; | |
| } | |
| mBlockAnimation = true; | |
| mShowApplicationsCheck.toggle(); | |
| if (mHideLayoutAnimation == null) { | |
| mHideLayoutAnimation = AnimationUtils.loadLayoutAnimation( | |
| this, R.anim.hide_applications); | |
| } | |
| mGridExit.setAnimationListener(new HideGrid()); | |
| mGrid.startAnimation(mGridExit); | |
| mGrid.setVisibility(View.INVISIBLE); | |
| mShowApplications.requestFocus(); | |
| // This enables a layout animation; if you uncomment this code, you need to | |
| // comment the line mGrid.startAnimation() above | |
| // mGrid.setLayoutAnimationListener(new HideGrid()); | |
| // mGrid.setLayoutAnimation(mHideLayoutAnimation); | |
| // mGrid.startLayoutAnimation(); | |
| } | |
| /** | |
| * Receives intents from other applications to change the wallpaper. | |
| */ | |
| private class WallpaperIntentReceiver extends BroadcastReceiver { | |
| @Override | |
| public void onReceive(Context context, Intent intent) { | |
| getWindow().setBackgroundDrawable(new ClippedDrawable(getWallpaper())); | |
| } | |
| } | |
| /** | |
| * Receives notifications when applications are added/removed. | |
| */ | |
| private class ApplicationsIntentReceiver extends BroadcastReceiver { | |
| @Override | |
| public void onReceive(Context context, Intent intent) { | |
| loadApplications(false); | |
| bindApplications(); | |
| bindRecents(); | |
| bindFavorites(false); | |
| } | |
| } | |
| /** | |
| * GridView adapter to show the list of all installed applications. | |
| */ | |
| private class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> { | |
| private Rect mOldBounds = new Rect(); | |
| public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps) { | |
| super(context, 0, apps); | |
| } | |
| @Override | |
| public View getView(int position, View convertView, ViewGroup parent) { | |
| final ApplicationInfo info = mApplications.get(position); | |
| if (convertView == null) { | |
| final LayoutInflater inflater = getLayoutInflater(); | |
| convertView = inflater.inflate(R.layout.application, parent, false); | |
| } | |
| Drawable icon = info.icon; | |
| if (!info.filtered) { | |
| //final Resources resources = getContext().getResources(); | |
| int width = 42;//(int) resources.getDimension(android.R.dimen.app_icon_size); | |
| int height = 42;//(int) resources.getDimension(android.R.dimen.app_icon_size); | |
| final int iconWidth = icon.getIntrinsicWidth(); | |
| final int iconHeight = icon.getIntrinsicHeight(); | |
| if (icon instanceof PaintDrawable) { | |
| PaintDrawable painter = (PaintDrawable) icon; | |
| painter.setIntrinsicWidth(width); | |
| painter.setIntrinsicHeight(height); | |
| } | |
| if (width > 0 && height > 0 && (width < iconWidth || height < iconHeight)) { | |
| final float ratio = (float) iconWidth / iconHeight; | |
| if (iconWidth > iconHeight) { | |
| height = (int) (width / ratio); | |
| } else if (iconHeight > iconWidth) { | |
| width = (int) (height * ratio); | |
| } | |
| final Bitmap.Config c = | |
| icon.getOpacity() != PixelFormat.OPAQUE ? | |
| Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; | |
| final Bitmap thumb = Bitmap.createBitmap(width, height, c); | |
| final Canvas canvas = new Canvas(thumb); | |
| canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, 0)); | |
| // Copy the old bounds to restore them later | |
| // If we were to do oldBounds = icon.getBounds(), | |
| // the call to setBounds() that follows would | |
| // change the same instance and we would lose the | |
| // old bounds | |
| mOldBounds.set(icon.getBounds()); | |
| icon.setBounds(0, 0, width, height); | |
| icon.draw(canvas); | |
| icon.setBounds(mOldBounds); | |
| icon = info.icon = new BitmapDrawable(thumb); | |
| info.filtered = true; | |
| } | |
| } | |
| final TextView textView = (TextView) convertView.findViewById(R.id.label); | |
| textView.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null); | |
| textView.setText(info.title); | |
| return convertView; | |
| } | |
| } | |
| /** | |
| * Shows and hides the applications grid view. | |
| */ | |
| private class ShowApplications implements View.OnClickListener { | |
| public void onClick(View v) { | |
| if (mGrid.getVisibility() != View.VISIBLE) { | |
| showApplications(true); | |
| } else { | |
| hideApplications(); | |
| } | |
| } | |
| } | |
| /** | |
| * Hides the applications grid when the layout animation is over. | |
| */ | |
| private class HideGrid implements Animation.AnimationListener { | |
| public void onAnimationStart(Animation animation) { | |
| } | |
| public void onAnimationEnd(Animation animation) { | |
| mBlockAnimation = false; | |
| } | |
| public void onAnimationRepeat(Animation animation) { | |
| } | |
| } | |
| /** | |
| * Shows the applications grid when the layout animation is over. | |
| */ | |
| private class ShowGrid implements Animation.AnimationListener { | |
| public void onAnimationStart(Animation animation) { | |
| } | |
| public void onAnimationEnd(Animation animation) { | |
| mBlockAnimation = false; | |
| // ViewDebug.stopHierarchyTracing(); | |
| } | |
| public void onAnimationRepeat(Animation animation) { | |
| } | |
| } | |
| /** | |
| * Starts the selected activity/application in the grid view. | |
| */ | |
| private class ApplicationLauncher implements AdapterView.OnItemClickListener { | |
| public void onItemClick(AdapterView parent, View v, int position, long id) { | |
| ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position); | |
| startActivity(app.intent); | |
| } | |
| } | |
| /** | |
| * When a drawable is attached to a View, the View gives the Drawable its dimensions | |
| * by calling Drawable.setBounds(). In this application, the View that draws the | |
| * wallpaper has the same size as the screen. However, the wallpaper might be larger | |
| * that the screen which means it will be automatically stretched. Because stretching | |
| * a bitmap while drawing it is very expensive, we use a ClippedDrawable instead. | |
| * This drawable simply draws another wallpaper but makes sure it is not stretched | |
| * by always giving it its intrinsic dimensions. If the wallpaper is larger than the | |
| * screen, it will simply get clipped but it won't impact performance. | |
| */ | |
| private class ClippedDrawable extends Drawable { | |
| private final Drawable mWallpaper; | |
| public ClippedDrawable(Drawable wallpaper) { | |
| mWallpaper = wallpaper; | |
| } | |
| @Override | |
| public void setBounds(int left, int top, int right, int bottom) { | |
| super.setBounds(left, top, right, bottom); | |
| // Ensure the wallpaper is as large as it really is, to avoid stretching it | |
| // at drawing time | |
| mWallpaper.setBounds(left, top, left + mWallpaper.getIntrinsicWidth(), | |
| top + mWallpaper.getIntrinsicHeight()); | |
| } | |
| public void draw(Canvas canvas) { | |
| mWallpaper.draw(canvas); | |
| } | |
| public void setAlpha(int alpha) { | |
| mWallpaper.setAlpha(alpha); | |
| } | |
| public void setColorFilter(ColorFilter cf) { | |
| mWallpaper.setColorFilter(cf); | |
| } | |
| public int getOpacity() { | |
| return mWallpaper.getOpacity(); | |
| } | |
| } | |
| } |