From ec8345a13fe23db9f481d82bc14ce597c02c4e0f Mon Sep 17 00:00:00 2001 From: Joe Onorato Date: Tue, 26 Oct 2010 19:25:42 -0700 Subject: [PATCH 1/5] When the launcher is paused and we reload stuff in the background, we need to re-re-load it in onResume. Otherwise we can load widgets and other resources from the wrong Configuration. This doesn't completely fix the bug, but it makes it much less likely. We tell the launcher once at the beginning of starting a reload because of SD cards coming back, and once when we bind. Bug: 3126698 Change-Id: I99ee6af38bef91e261832bad4dec978a5d4a8b3d --- src/com/android/launcher2/Launcher.java | 40 ++++++++++++++++++-- src/com/android/launcher2/LauncherModel.java | 15 +++++++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 9626a2ec23..e611303059 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -194,6 +194,7 @@ public final class Launcher extends Activity private boolean mPaused = true; private boolean mRestoring; private boolean mWaitingForResult; + private boolean mOnResumeNeedsLoad; private Bundle mSavedInstanceState; @@ -583,19 +584,19 @@ public final class Launcher extends Activity @Override protected void onResume() { super.onResume(); - mPaused = false; - - if (mRestoring) { + if (mRestoring || mOnResumeNeedsLoad) { mWorkspaceLoading = true; mModel.startLoader(this, true); mRestoring = false; + mOnResumeNeedsLoad = false; } } @Override protected void onPause() { super.onPause(); + mPaused = true; dismissPreview(mPreviousView); dismissPreview(mNextView); mDragController.cancelDrag(); @@ -2124,6 +2125,30 @@ public final class Launcher extends Activity } } + /** + * If the activity is currently paused, signal that we need to re-run the loader + * in onResume. + * + * This needs to be called from incoming places where resources might have been loaded + * while we are paused. That is becaues the Configuration might be wrong + * when we're not running, and if it comes back to what it was when we + * were paused, we are not restarted. + * + * Implementation of the method from LauncherModel.Callbacks. + * + * @return true if we are currently paused. The caller might be able to + * skip some work in that case since we will come back again. + */ + public boolean setLoadOnResume() { + if (mPaused) { + Log.i(TAG, "setLoadOnResume"); + mOnResumeNeedsLoad = true; + return true; + } else { + return false; + } + } + /** * Implementation of the method from LauncherModel.Callbacks. */ @@ -2168,6 +2193,8 @@ public final class Launcher extends Activity */ public void bindItems(ArrayList shortcuts, int start, int end) { + setLoadOnResume(); + final Workspace workspace = mWorkspace; for (int i=start; i folders) { + setLoadOnResume(); sFolders.clear(); sFolders.putAll(folders); } @@ -2215,6 +2243,8 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAppWidget(LauncherAppWidgetInfo item) { + setLoadOnResume(); + final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0; if (DEBUG_WIDGETS) { Log.d(TAG, "bindAppWidget: " + item); @@ -2251,6 +2281,8 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void finishBindingItems() { + setLoadOnResume(); + if (mSavedState != null) { if (!mWorkspace.hasFocus()) { mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus(); @@ -2296,6 +2328,7 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAppsAdded(ArrayList apps) { + setLoadOnResume(); removeDialog(DIALOG_CREATE_SHORTCUT); mAllAppsGrid.addApps(apps); } @@ -2306,6 +2339,7 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAppsUpdated(ArrayList apps) { + setLoadOnResume(); removeDialog(DIALOG_CREATE_SHORTCUT); mWorkspace.updateShortcuts(apps); mAllAppsGrid.updateApps(apps); diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java index cb19fe37f9..b819510afe 100644 --- a/src/com/android/launcher2/LauncherModel.java +++ b/src/com/android/launcher2/LauncherModel.java @@ -96,6 +96,7 @@ public class LauncherModel extends BroadcastReceiver { private Bitmap mDefaultIcon; public interface Callbacks { + public boolean setLoadOnResume(); public int getCurrentWorkspaceScreen(); public void startBinding(); public void bindItems(ArrayList shortcuts, int start, int end); @@ -349,7 +350,19 @@ public class LauncherModel extends BroadcastReceiver { String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages)); // Then, rebind everything. - startLoader(mApp, false); + boolean runLoader = true; + if (mCallbacks != null) { + Callbacks callbacks = mCallbacks.get(); + if (callbacks != null) { + // If they're paused, we can skip loading, because they'll do it again anyway + if (callbacks.setLoadOnResume()) { + runLoader = false; + } + } + } + if (runLoader) { + startLoader(mApp, false); + } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); From ef2efcff5e70e5900f4f10f9e46c3fa17c03b0ec Mon Sep 17 00:00:00 2001 From: Joe Onorato Date: Wed, 27 Oct 2010 13:21:00 -0700 Subject: [PATCH 2/5] When the launcher is paused and we reload stuff in the background, we need to re-re-load it in onResume. Otherwise we can load widgets and other resources from the wrong Configuration. This doesn't completely fix the bug, but it makes it much less likely. We tell the launcher once at the beginning of starting a reload because of SD cards coming back, and once when we bind. cherry pick of I99ee6af38bef91e261832bad4dec978a5d4a8b3d Bug: 3126698 Change-Id: I917bdb3982e3eea4924c6e9a8f3c037fd493f415 --- src/com/android/launcher2/Launcher.java | 40 ++++++++++++++++++-- src/com/android/launcher2/LauncherModel.java | 15 +++++++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 5d45d27146..444357ebc9 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -217,6 +217,7 @@ public final class Launcher extends Activity private boolean mPaused = true; private boolean mRestoring; private boolean mWaitingForResult; + private boolean mOnResumeNeedsLoad; private Bundle mSavedInstanceState; @@ -680,13 +681,12 @@ public final class Launcher extends Activity @Override protected void onResume() { super.onResume(); - mPaused = false; - - if (mRestoring) { + if (mRestoring || mOnResumeNeedsLoad) { mWorkspaceLoading = true; mModel.startLoader(this, true); mRestoring = false; + mOnResumeNeedsLoad = false; } // When we resume Launcher, a different Activity might be responsible for the app // market intent, so refresh the icon @@ -703,6 +703,7 @@ public final class Launcher extends Activity if (mNextView != null) { dismissPreview(mNextView); } + mPaused = true; mDragController.cancelDrag(); } @@ -2869,6 +2870,30 @@ public final class Launcher extends Activity } } + /** + * If the activity is currently paused, signal that we need to re-run the loader + * in onResume. + * + * This needs to be called from incoming places where resources might have been loaded + * while we are paused. That is becaues the Configuration might be wrong + * when we're not running, and if it comes back to what it was when we + * were paused, we are not restarted. + * + * Implementation of the method from LauncherModel.Callbacks. + * + * @return true if we are currently paused. The caller might be able to + * skip some work in that case since we will come back again. + */ + public boolean setLoadOnResume() { + if (mPaused) { + Log.i(TAG, "setLoadOnResume"); + mOnResumeNeedsLoad = true; + return true; + } else { + return false; + } + } + /** * Implementation of the method from LauncherModel.Callbacks. */ @@ -2917,6 +2942,8 @@ public final class Launcher extends Activity */ public void bindItems(ArrayList shortcuts, int start, int end) { + setLoadOnResume(); + final Workspace workspace = mWorkspace; for (int i=start; i folders) { + setLoadOnResume(); sFolders.clear(); sFolders.putAll(folders); } @@ -2964,6 +2992,8 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAppWidget(LauncherAppWidgetInfo item) { + setLoadOnResume(); + final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0; if (DEBUG_WIDGETS) { Log.d(TAG, "bindAppWidget: " + item); @@ -3000,6 +3030,8 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void finishBindingItems() { + setLoadOnResume(); + if (mSavedState != null) { if (!mWorkspace.hasFocus()) { mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus(); @@ -3050,6 +3082,7 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAppsAdded(ArrayList apps) { + setLoadOnResume(); removeDialog(DIALOG_CREATE_SHORTCUT); mAllAppsGrid.addApps(apps); if (mCustomizePagedView != null) { @@ -3065,6 +3098,7 @@ public final class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAppsUpdated(ArrayList apps) { + setLoadOnResume(); removeDialog(DIALOG_CREATE_SHORTCUT); mWorkspace.updateShortcuts(apps); mAllAppsGrid.updateApps(apps); diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java index eff5ed63b8..1e58ca0e42 100644 --- a/src/com/android/launcher2/LauncherModel.java +++ b/src/com/android/launcher2/LauncherModel.java @@ -108,6 +108,7 @@ public class LauncherModel extends BroadcastReceiver { private static int mCellCountY; public interface Callbacks { + public boolean setLoadOnResume(); public int getCurrentWorkspaceScreen(); public void startBinding(); public void bindItems(ArrayList shortcuts, int start, int end); @@ -433,7 +434,19 @@ public class LauncherModel extends BroadcastReceiver { String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages)); // Then, rebind everything. - startLoader(mApp, false); + boolean runLoader = true; + if (mCallbacks != null) { + Callbacks callbacks = mCallbacks.get(); + if (callbacks != null) { + // If they're paused, we can skip loading, because they'll do it again anyway + if (callbacks.setLoadOnResume()) { + runLoader = false; + } + } + } + if (runLoader) { + startLoader(mApp, false); + } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); From 0620bec8406c0f247a1f8d16c9963d08addbb9a2 Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Mon, 25 Oct 2010 17:50:09 -0700 Subject: [PATCH 3/5] Generating holographic outlines in helper thread Change-Id: Ie6fb0827b0c746d512c5baba44bf16de54e309bc --- src/com/android/launcher2/PagedViewIcon.java | 165 ++++++++++--------- 1 file changed, 88 insertions(+), 77 deletions(-) diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java index 010c573f1b..be4999d584 100644 --- a/src/com/android/launcher2/PagedViewIcon.java +++ b/src/com/android/launcher2/PagedViewIcon.java @@ -16,6 +16,9 @@ package com.android.launcher2; +import com.android.launcher.R; +import com.android.launcher2.PagedView.PagedViewIconCache; + import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -23,17 +26,14 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.PointF; import android.graphics.Rect; -import android.graphics.Region.Op; -import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; import android.util.AttributeSet; import android.widget.Checkable; import android.widget.TextView; -import com.android.launcher.R; -import com.android.launcher2.PagedView.PagedViewIconCache; - /** @@ -49,8 +49,8 @@ public class PagedViewIcon extends TextView implements Checkable { private Bitmap mCheckedOutline; private Bitmap mHolographicOutline; private Canvas mHolographicOutlineCanvas; - private boolean mIsHolographicUpdatePass; private Rect mDrawableClipRect; + private Bitmap mIcon; private Object mIconCacheKey; private PagedViewIconCache mIconCache; @@ -67,6 +67,36 @@ public class PagedViewIcon extends TextView implements Checkable { private int mCheckedBlurColor; private int mCheckedOutlineColor; + private static final HandlerThread sWorkerThread = new HandlerThread("pagedviewicon-helper"); + static { + sWorkerThread.start(); + } + + private static final int MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE = 1; + + private static final Handler sWorker = new Handler(sWorkerThread.getLooper()) { + private DeferredHandler mHandler = new DeferredHandler(); + private Paint mPaint = new Paint(); + public void handleMessage(Message msg) { + final PagedViewIcon icon = (PagedViewIcon) msg.obj; + + final Bitmap holographicOutline = Bitmap.createBitmap( + icon.mIcon.getWidth(), icon.mIcon.getHeight(), Bitmap.Config.ARGB_8888); + Canvas holographicOutlineCanvas = new Canvas(holographicOutline); + holographicOutlineCanvas.drawBitmap(icon.mIcon, 0, 0, mPaint); + + sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(holographicOutline, + holographicOutlineCanvas, icon.mHoloBlurColor, icon.mHoloOutlineColor); + + mHandler.post(new Runnable() { + public void run() { + icon.mHolographicOutline = holographicOutline; + icon.mIconCache.addOutline(icon.mIconCacheKey, holographicOutline); + icon.invalidate(); + } + }); + } + }; public PagedViewIcon(Context context) { this(context, null); @@ -95,23 +125,32 @@ public class PagedViewIcon extends TextView implements Checkable { setBackgroundDrawable(null); } + private void queueHolographicOutlineCreation() { + // Generate the outline in the background + if (mHolographicOutline == null) { + Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE); + m.obj = this; + sWorker.sendMessage(m); + } + } + public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache, boolean scaleUp) { mIconCache = cache; mIconCacheKey = info; mHolographicOutline = mIconCache.getOutline(mIconCacheKey); - Bitmap icon; if (scaleUp) { - icon = Bitmap.createScaledBitmap(info.iconBitmap, mScaledIconSize, + mIcon = Bitmap.createScaledBitmap(info.iconBitmap, mScaledIconSize, mScaledIconSize, true); } else { - icon = info.iconBitmap; + mIcon = info.iconBitmap; } - setCompoundDrawablesWithIntrinsicBounds(null, - new FastBitmapDrawable(icon), null, null); + setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null); setText(info.title); setTag(info); + + queueHolographicOutlineCreation(); } public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager, @@ -120,11 +159,12 @@ public class PagedViewIcon extends TextView implements Checkable { mIconCacheKey = info; mHolographicOutline = mIconCache.getOutline(mIconCacheKey); - Bitmap image = Utilities.createIconBitmap(info.loadIcon(packageManager), mContext); - setCompoundDrawablesWithIntrinsicBounds(null, - new FastBitmapDrawable(image), null, null); + mIcon = Utilities.createIconBitmap(info.loadIcon(packageManager), mContext); + setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null); setText(info.loadLabel(packageManager)); setTag(info); + + queueHolographicOutlineCreation(); } @Override @@ -144,60 +184,39 @@ public class PagedViewIcon extends TextView implements Checkable { } @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); + protected void onDraw(Canvas canvas) { + if (mAlpha > 0) { + super.onDraw(canvas); + } - if (mIconCache != null && mHolographicOutline == null) { - // update the clipping rect to be used in the holographic pass below - getDrawingRect(mDrawableClipRect); - mDrawableClipRect.bottom = getPaddingTop() + getCompoundPaddingTop(); + Bitmap overlay = null; - // set a flag to indicate that we are going to draw the view at full alpha with the text - // clipped for the generation of the holographic icon - mIsHolographicUpdatePass = true; - mHolographicOutline = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), - Bitmap.Config.ARGB_8888); - mHolographicOutlineCanvas = new Canvas(mHolographicOutline); - mHolographicOutlineCanvas.concat(getMatrix()); - draw(mHolographicOutlineCanvas); - sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(mHolographicOutline, - mHolographicOutlineCanvas, mHoloBlurColor, mHoloOutlineColor); - mIsHolographicUpdatePass = false; - mIconCache.addOutline(mIconCacheKey, mHolographicOutline); - mHolographicOutlineCanvas = null; + // draw any blended overlays + if (mCheckedOutline == null) { + if (mHolographicOutline != null && mHolographicAlpha > 0) { + mPaint.setAlpha(mHolographicAlpha); + overlay = mHolographicOutline; + } + } else { + mPaint.setAlpha(255); + overlay = mCheckedOutline; + } + + if (overlay != null) { + final int compoundPaddingLeft = getCompoundPaddingLeft(); + final int compoundPaddingRight = getCompoundPaddingRight(); + int hspace = getWidth() - compoundPaddingRight - compoundPaddingLeft; + canvas.drawBitmap(overlay, + compoundPaddingLeft + (hspace - overlay.getWidth()) / 2, + mPaddingTop, + mPaint); } } @Override - protected void onDraw(Canvas canvas) { - // draw the view itself - if (mIsHolographicUpdatePass) { - // only clip to the text view (restore its alpha so that we get a proper outline) - canvas.save(); - canvas.clipRect(mDrawableClipRect, Op.REPLACE); - final float alpha = getAlpha(); - super.setAlpha(1.0f); - super.onDraw(canvas); - super.setAlpha(alpha); - canvas.restore(); - } else { - if (mAlpha > 0) { - super.onDraw(canvas); - } - } - - // draw any blended overlays - if (!mIsHolographicUpdatePass) { - if (mCheckedOutline == null) { - if (mHolographicOutline != null && mHolographicAlpha > 0) { - mPaint.setAlpha(mHolographicAlpha); - canvas.drawBitmap(mHolographicOutline, 0, 0, mPaint); - } - } else { - mPaint.setAlpha(255); - canvas.drawBitmap(mCheckedOutline, 0, 0, mPaint); - } - } + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this); } @Override @@ -211,22 +230,14 @@ public class PagedViewIcon extends TextView implements Checkable { mIsChecked = checked; if (mIsChecked) { - // update the clipping rect to be used in the holographic pass below - getDrawingRect(mDrawableClipRect); - mDrawableClipRect.bottom = getPaddingTop() + getCompoundPaddingTop(); - - // set a flag to indicate that we are going to draw the view at full alpha with the text - // clipped for the generation of the holographic icon - mIsHolographicUpdatePass = true; - mCheckedOutline = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), + mCheckedOutline = Bitmap.createBitmap(mIcon.getWidth(), mIcon.getHeight(), Bitmap.Config.ARGB_8888); - mHolographicOutlineCanvas = new Canvas(mCheckedOutline); - mHolographicOutlineCanvas.concat(getMatrix()); - draw(mHolographicOutlineCanvas); + Canvas checkedOutlineCanvas = new Canvas(mCheckedOutline); + mPaint.setAlpha(255); + checkedOutlineCanvas.drawBitmap(mIcon, 0, 0, mPaint); + sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(mCheckedOutline, - mHolographicOutlineCanvas, mCheckedBlurColor, mCheckedOutlineColor); - mIsHolographicUpdatePass = false; - mHolographicOutlineCanvas = null; + checkedOutlineCanvas, mCheckedBlurColor, mCheckedOutlineColor); } else { invalidateCheckedImage(); } From 0f640fce05df448604c0d6bed3eb0e756e4b1b43 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Wed, 27 Oct 2010 14:33:07 -0700 Subject: [PATCH 4/5] Import revised translations. Change-Id: Idf7ef6a9edc4c63d38640fe1542d6e280cca2140 --- res/values-cs/strings.xml | 26 ++++++++++++++------------ res/values-da/strings.xml | 26 ++++++++++++++------------ res/values-de/strings.xml | 28 +++++++++++++++------------- res/values-el/strings.xml | 26 ++++++++++++++------------ res/values-es-rUS/strings.xml | 26 +++++++++++++------------- res/values-es/strings.xml | 26 ++++++++++++++------------ res/values-fr/strings.xml | 26 ++++++++++++++------------ res/values-it/strings.xml | 26 ++++++++++++++------------ res/values-ja/strings.xml | 26 ++++++++++++++------------ res/values-ko/strings.xml | 26 ++++++++++++++------------ res/values-nb/strings.xml | 26 ++++++++++++++------------ res/values-nl/strings.xml | 26 ++++++++++++++------------ res/values-pl/strings.xml | 26 ++++++++++++++------------ res/values-pt-rPT/strings.xml | 26 ++++++++++++++------------ res/values-pt/strings.xml | 26 ++++++++++++++------------ res/values-rm/strings.xml | 18 +++++++++++++++--- res/values-ru/strings.xml | 26 ++++++++++++++------------ res/values-sv/strings.xml | 26 ++++++++++++++------------ res/values-tr/strings.xml | 26 ++++++++++++++------------ res/values-zh-rCN/strings.xml | 26 ++++++++++++++------------ res/values-zh-rTW/strings.xml | 28 +++++++++++++++------------- 21 files changed, 296 insertions(+), 246 deletions(-) diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index b127e1ea72..e938b73d90 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -29,17 +29,17 @@ "Konfigurace..." "Widgety" "Složky" - - + "Další" "Tapety" - - + "Zástupci aplikací" "Toto bude karta Tapety" "Vše" "Aplikace" "Hry" "Stažené" - + + + "Název složky" "Přejmenovat složku" @@ -60,21 +60,23 @@ "Zástupce %s byl odebrán." "Zástupce %s již existuje." "Vyberte zástupce" + "Výběr aplikace" "Vybrat složku" - "Všechny aplikace" + "Aplikace" "Plocha" "Přidat" + "Spravovat aplikace" "Tapeta" "Hledat" "Oznámení" "Gesta" "Nastavení" - - - - - - + "Odinstalovat aplikaci" + "Podrobnosti o aplikaci" + "Vybrána 1 aplikace" + "Vybrán 1 widget" + "Vybrána 1 složka" + "Vybrán 1 zástupce" "instalovat zástupce" "Povoluje aplikaci přidat zástupce bez zásahu uživatele." "odinstalovat zástupce" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index c3b069ef07..576abce027 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -29,17 +29,17 @@ "Konfigurer ..." "Widgets" "Mapper" - - + "Flere" "Tapeter" - - + "Programgenvej" "Dette er fanen for tapeter" "Alle" "Programmer" "Spil" "Downloadet" - + + + "Mappenavn" "Omdøb mappe" @@ -60,21 +60,23 @@ "Genvejen \"%s\" blev fjernet." "Genvejen \"%s\" findes allerede." "Vælg genvej" + "Vælg program" "Vælg mappe" - "Alle programmer" + "Programmer" "Start" "Tilføj" + "Administrer programmer" "Tapet" "Søg" "Meddelelser" "Gestus" "Indstillinger" - - - - - - + "Afinstaller program" + "Programoplysninger" + "1 program er valgt" + "1 widget er valgt" + "1 mappe er valgt" + "1 genvej er valgt" "installer genveje" "Tillader, at et program tilføjer genveje uden brugerindgriben." "afinstaller genveje" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 6b5401f0b4..575db07149 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -29,17 +29,17 @@ "Konfigurieren..." "Widgets" "Ordner" - - + "Mehr" "Hintergründe" - - + "App-Verknüpfungen" "Dies ist der Tab \"Hintergründe\"" "Alle" - "Anwendungen" + "Apps" "Spiele" "Heruntergeladen" - + + + "Ordnername" "Ordner umbenennen" @@ -60,21 +60,23 @@ "\"%s\"-Verknüpfung wurde entfernt." "\"%s\"-Verknüpfung ist bereits vorhanden." "Tastenkürzel auswählen" + "Anwendung auswählen" "Ordner auswählen" - "Alle Anwendungen" + "Anwendungen" "Startseite" "Hinzufügen" + "Apps verwalten" "Hintergrund" "Suchen" "Benachrichtigungen" "Bewegungen" "Einstellungen" - - - - - - + "Anwendung deinstallieren" + "Anwendungsdetails" + "1 Anwendung ausgewählt" + "1 Widget ausgewählt" + "1 Ordner ausgewählt" + "1 Verknüpfung ausgewählt" "Verknüpfungen installieren" "Ermöglicht einer Anwendung das Hinzufügen von Verknüpfungen ohne Eingriff des Nutzers." "Verknüpfungen deinstallieren" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 9326a932c8..0937c5b587 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -29,17 +29,17 @@ "Διαμόρφωση..." "Γραφικά στοιχεία" "Φάκελοι" - - + "Περισσότερα" "Ταπετσαρίες" - - + "Συντομεύσεις Εφαρμογών" "Αυτή θα είναι η καρτέλα ταπετσαριών" "Κάθε ηλικία" "Εφαρμογές" "Παιχνίδια" "Η λήψη ολοκληρώθηκε" - + + + "Όνομα φακέλου" "Μετονομασία φακέλου" @@ -60,21 +60,23 @@ "Η συντόμευση \"%s\" καταργήθηκε." "Η συντόμευση \"%s\" υπάρχει ήδη." "Επιλογή συντόμευσης" + "Επιλέξτε εφαρμογή" "Επιλογή φακέλου" - "Όλες οι εφαρμογές" + "Εφαρμογές" "Αρχική σελίδα" "Προσθήκη" + "Διαχείριση εφαρμογών" "Ταπετσαρία" "Αναζήτηση" "Ειδοποιήσεις" "Χειρονομίες" "Ρυθμίσεις" - - - - - - + "Κατάργηση εγκατάστασης εφαρμογής" + "Λεπτομέρειες εφαρμογής" + "Επιλέχθηκε 1 εφαρμογή" + "Επιλέχθηκε 1 γραφικό στοιχείο" + "Επιλέχθηκε 1 φάκελος" + "Επιλέχθηκε 1 συντόμευση" "εγκατάσταση συντομεύσεων" "Επιτρέπει σε μια εφαρμογή την προσθήκη συντομεύσεων χωρίς την παρέμβαση του χρήστη." "κατάργηση εγκατάστασης συντομεύσεων" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index b4e65d0f65..d718936230 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -29,18 +29,16 @@ "Configurar..." "Widgets" "Carpetas" - - + "Más" "Papeles tapiz" - - + "Accesos directos a aplicaciones" "Ésta será la pestaña para los papeles tapiz" "Todos" "Google Apps" "Juegos" "Descargado" - - + "No" + "No Google Apps" "Nombre de carpeta" "Cambiar nombre de carpeta" "Aceptar" @@ -60,21 +58,23 @@ "El acceso directo \"%s\" ha sido eliminado." "El acceso directo \"%s\" ya existe." "Seleccionar acceso directo" + "Seleccionar aplicación" "Seleccionar carpeta" - "Todas las aplicaciones" + "Google Apps" "Página principal" "Agregar" + "Administrar aplicaciones" "Papel tapiz" "Buscar" "Notificaciones" "Gestos" "Configuración" - - - - - - + "Desinstalar la aplicación" + "Detalles de la aplicación" + "Se seleccionó 1 aplicación" + "Se seleccionó 1 widget" + "Se seleccionó 1 carpeta" + "Se seleccionó 1 acceso directo" "instalar accesos directos" "Permite a una aplicación agregar accesos directos sin intervención del usuario." "desinstalar papel tapiz" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index ecbe8afe40..ab0485a090 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -29,17 +29,17 @@ "Configurar..." "Widgets" "Carpetas" - - + "Más" "Fondos de pantalla" - - + "Accesos directos de aplicaciones" "Será la carpeta de fondos de pantalla." "Todas las aplicaciones" "Aplicaciones" "Juegos" "Descargadas" - + + + "Nombre de carpeta" "Cambiar nombre de carpeta" @@ -60,21 +60,23 @@ "Se ha eliminado el acceso directo \"%s\"." "El acceso directo \"%s\" ya existe." "Seleccionar acceso directo" + "Seleccionar aplicación" "Seleccionar carpeta" - "Todas las aplicaciones" + "Aplicaciones" "Inicio" "Añadir" + "Administrar aplicaciones" "Fondo de pantalla" "Buscar con Google" "Notificaciones" "Gestos" "Ajustes" - - - - - - + "Desinstalar aplicación" + "Información de la aplicación" + "Se ha seleccionado una aplicación." + "Se ha seleccionado un widget." + "Se ha seleccionado una carpeta." + "Se ha seleccionado un acceso directo." "instalar accesos directos" "Permite que una aplicación añada accesos directos sin intervención del usuario." "desinstalar accesos directos" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index c6d530dd6b..35ee775bec 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -29,17 +29,17 @@ "Configurer..." "Widgets" "Dossiers" - - + "Plus" "Fonds d\'écran" - - + "Raccourcis des applications" "Onglet des fonds d\'écran" "Toutes" "Applications" "Jeux" "Téléchargées" - + + + "Nom du dossier" "Renommer le dossier" @@ -60,21 +60,23 @@ "Le raccourci \"%s\" a été supprimé." "Le raccourci \"%s\" existe déjà." "Sélectionner un raccourci" + "Sélection d\'une application" "Sélectionner le dossier" - "Toutes les applications" + "Applications" "Page d\'accueil" "Ajouter" + "Gérer les applications" "Fond d\'écran" "Rechercher" "Notifications" "Gestes" "Paramètres" - - - - - - + "Désinstaller l\'application" + "Infos sur l\'application" + "1 application sélectionnée" + "1 widget sélectionné" + "1 dossier sélectionné" + "1 raccourci sélectionné" "installer des raccourcis" "Permet à une application d\'ajouter des raccourcis sans l\'intervention de l\'utilisateur." "désinstaller les raccourcis" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index f25156a3d5..7705763ce0 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -29,17 +29,17 @@ "Configura..." "Widget" "Cartelle" - - + "Altro" "Sfondi" - - + "Scorciatoie applicazioni" "Questa sarà la scheda degli sfondi" "Tutte" "Applicazioni" "Giochi" "Scaricate" - + + + "Nome cartella" "Rinomina cartella" @@ -60,21 +60,23 @@ "La scorciatoia \"%s\" è stata rimossa." "Scorciatoia \"%s\" già presente." "Seleziona scorciatoia" + "Seleziona applicazione" "Seleziona cartella" - "Tutte le applicazioni" + "Applicazioni" "Home" "Aggiungi" + "Gestisci applicazioni" "Sfondo" "Cerca" "Notifiche" "Gesti" "Impostazioni" - - - - - - + "Disinstalla applicazione" + "Dettagli applicazione" + "1 applicazione selezionata" + "1 widget selezionato" + "1 cartella selezionata" + "1 scorciatoia selezionata" "aggiungere scorciatoie" "Consente a un\'applicazione di aggiungere scorciatoie automaticamente." "eliminare scorciatoie" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 98f042bec0..2a7a218c46 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -29,17 +29,17 @@ "設定..." "ウィジェット" "フォルダ" - - + "その他" "壁紙" - - + "アプリのショートカット" "ここが壁紙タブになります" "すべて" "アプリ" "ゲーム" "ダウンロード済み" - + + + "フォルダ名" "フォルダ名を変更" @@ -60,21 +60,23 @@ "ショートカット「%s」を削除しました。" "ショートカット「%s」は既に存在します。" "ショートカットを選択" + "アプリを選択" "フォルダの選択" - "すべてのアプリケーション" + "アプリ" "ホーム" "追加" + "アプリの管理" "壁紙" "検索" "通知" "ジェスチャー" "設定" - - - - - - + "アプリケーションのアンインストール" + "アプリケーションの詳細" + "1つのアプリケーションが選択されています" + "1つのウィジェットが選択されています" + "1つのフォルダが選択されています" + "1つのショートカットが選択されています" "ショートカットのインストール" "ユーザー操作なしでショートカットの追加をアプリケーションに許可します。" "ショートカットのアンインストール" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 521332611b..b23450d434 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -29,17 +29,17 @@ "구성..." "위젯" "폴더" - - + "더보기" "배경화면" - - + "앱 바로가기" "배경화면 탭이 됩니다." "모두" "애플리케이션" "게임" "다운로드앱" - + + + "폴더 이름" "폴더 이름 바꾸기" @@ -60,21 +60,23 @@ "바로가기(\'%s\')가 삭제되었습니다." "바로가기(\'%s\')가 이미 있습니다." "바로가기 선택" + "애플리케이션 선택" "폴더 선택" - "모든 애플리케이션" + "애플리케이션" "홈" "추가" + "애플리케이션 관리" "배경화면" "검색" "알림" "동작" "설정" - - - - - - + "애플리케이션 제거" + "애플리케이션 세부정보" + "1개 애플리케이션 선택" + "1개 위젯 선택" + "1개 폴더 선택" + "1개 바로가기 선택" "바로가기 설치" "애플리케이션이 사용자의 작업 없이 바로가기를 추가할 수 있도록 합니다." "바로가기 제거" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 0d24eb9546..5026744f97 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -29,17 +29,17 @@ "Konfigurer" "Moduler" "Mapper" - - + "Mer" "Bakgrunner" - - + "Programsnarveier" "Dette er nå bakgrunnsfanen" "Alle" "Programmer" "Spill" "Nedlastet" - + + + "Mappenavn" "Gi nytt navn til mappe" @@ -60,21 +60,23 @@ "Fjernet snarveien «%s»." "Snarveien «%s» fins allerede." "Velg snarvei" + "Velg program" "Velg mappe" - "Alle programmer" + "Programmer" "Startsiden" "Legg til" + "Administrer programmer" "Bakgrunnsbilde" "Søk" "Varslinger" "Bevegelser" "Innstillinger" - - - - - - + "Avinstaller program" + "Søknadsopplysninger" + "1 program valgt" + "1 modul valgt" + "1 mappe valgt" + "1 snarvei valgt" "installere snarveier" "Lar applikasjonen legge til snarveier uten å involvere brukeren." "avinstallere snarveier" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 5a2a269a83..65625294bb 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -29,17 +29,17 @@ "Configureren..." "Widgets" "Mappen" - - + "Meer" "Achtergronden" - - + "Toepassingssnelkoppelingen" "Dit wordt het tabblad \'Achtergronden\'" "Alle" "Toepassingen" "Games" "Gedownload" - + + + "Mapnaam" "Naam van map wijzigen" @@ -60,21 +60,23 @@ "Snelkoppeling \'%s\' is verwijderd." "Snelkoppeling \'%s\' bestaat al." "Snelkoppeling selecteren" + "Toepassing selecteren" "Map selecteren" - "Alle toepassingen" + "Toepassingen" "Startpagina" "Toevoegen" + "Toepassingen beheren" "Achtergrond" "Zoeken" "Meldingen" "Gebaren" "Instellingen" - - - - - - + "Toepassing verwijderen" + "Toepassingsdetails" + "1 toepassing geselecteerd" + "1 widget geselecteerd" + "1 map geselecteerd" + "1 snelkoppeling geselecteerd" "snelkoppelingen installeren" "Een toepassing toestaan om snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker." "snelkoppelingen verwijderen" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 0c8e91be4b..f2ac81daaf 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -29,17 +29,17 @@ "Konfiguruj..." "Widżety" "Foldery" - - + "Więcej" "Tapety" - - + "Skróty do aplikacji" "To będzie karta tapet" "Wszystkie" "Aplikacje" "Gry" "Pobrane" - + + + "Nazwa folderu" "Zmień nazwę folderu" @@ -60,21 +60,23 @@ "Skrót „%s” został usunięty." "Skrót „%s” już istnieje." "Wybierz skrót" + "Wybierz aplikację" "Wybierz folder" - "Wszystkie aplikacje" + "Aplikacje" "Ekran główny" "Dodaj" + "Zarządzaj aplikacjami" "Tapeta" "Szukaj" "Powiadomienia" "Gesty" "Ustawienia" - - - - - - + "Odinstaluj aplikację" + "Szczegóły aplikacji" + "Zaznaczono 1 aplikację" + "Zaznaczono 1 widżet" + "Zaznaczono 1 folder" + "Zaznaczono 1 skrót" "zainstaluj skróty" "Umożliwia aplikacji dodawanie skrótów bez interwencji użytkownika." "odinstaluj skróty" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index cdff3bfd02..a3c432d6b9 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -29,17 +29,17 @@ "Configurar..." "Widgets" "Pastas" - - + "Mais" "Imagens de fundo" - - + "Atalhos de aplicações" "Isto será o separador de imagens de fundo" "Todas" "Aplicações" "Jogos" "Transferidas" - + + + "Nome da pasta" "Mudar o nome da pasta" @@ -60,21 +60,23 @@ "O atalho \"%s\" foi removido." "O atalho \"%s\" já existe." "Seleccione o atalho" + "Seleccionar aplicação" "Seleccione a pasta" - "Todas as aplicações" + "Aplicações" "Página inicial" "Adicionar" + "Gerir aplicações" "Imagem de fundo" "Pesquisar" "Notificações" "Gestos" "Definições" - - - - - - + "Desinstalar aplicação" + "Detalhes da aplicação" + "1 aplicação seleccionada" + "1 widget seleccionado" + "1 pasta seleccionada" + "1 atalho seleccionado" "instalar atalhos" "Permite que uma aplicação adicione atalhos sem a intervenção do utilizador." "desinstalar atalhos" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index bdebb87c58..3941c4f606 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -29,17 +29,17 @@ "Configurar..." "Widgets" "Pastas" - - + "Mais" "Papéis de parede" - - + "Atalhos de aplicativo" "Esta será a guia de papéis de parede" "Todos" "Aplicativos" "Jogos" "Download concluído" - + + + "Nome da pasta" "Renomear pasta" @@ -60,21 +60,23 @@ "O atalho \"%s\" foi removido." "O atalho \"%s\" já existe." "Selecionar atalho" + "Selecionar aplicativo" "Selecionar pasta" - "Todos os aplicativos" + "Aplicativos" "Página inicial" "Adicionar" + "Gerenciar aplicativos" "Plano de fundo" "Pesquisa" "Notificações" "Gestos" "Configurações" - - - - - - + "Desinstalar aplicativo" + "Detalhes do aplicativo" + "Um aplicativo selecionado" + "Um widget selecionado" + "Uma pasta selecionada" + "Um atalho selecionado" "instalar atalhos" "Permite que um aplicativo adicione os atalhos sem a intervenção do usuário." "desinstalar atalhos" diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml index 0e4e4da7ca..10cbc4ae6c 100644 --- a/res/values-rm/strings.xml +++ b/res/values-rm/strings.xml @@ -47,7 +47,9 @@ - + + + "Num da l\'ordinatur" "Renumnar l\'ordinatur" @@ -68,10 +70,14 @@ "\"La scursanida \"\"%s\"\" è vegnida stizzada.\"" "\"La scursanida \"\"%s\"\" exista gia.\"" "Tscherner ina cumbinaziun da tastas" + + "Tscherner l\'ordinatur" - "Tut las applicaziuns" + "Tut las applicaziuns" "Pagina da partenza" "Agiuntar" + + "Fund davos" "Tschertgar" "Avis" @@ -81,7 +87,13 @@ - + + + + + + + "Installar scursanidas" "Pussibilitescha ch\'ina applicaziun agiunta scursanidas senza l\'intervenziun da l\'utilisader." diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index bb874451d7..fd5b35dcd6 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -29,17 +29,17 @@ "Настроить..." "Виджеты" "Папки" - - + "Еще" "Обои" - - + "Ярлыки приложений" "Это будет вкладка обоев" "Все" "Приложения" "Игры" "Загруженные" - + + + "Название папки" "Переименовать папку" @@ -60,21 +60,23 @@ "Ярлык \"%s\" удален." "Ярлык \"%s\" уже существует." "Выберите ярлык" + "Выбор приложения" "Выбор папки" - "Все приложения" + "Приложения" "Главная" "Добавить" + "Управление приложениями" "Обои" "Поиск" "Уведомления" "Жесты" "Настройки" - - - - - - + "Удалить приложение" + "Сведения о приложении" + "Выбрано 1 приложение" + "Выбран 1 виджет" + "Выбрана 1 папка" + "Выбран 1 ярлык" "устанавливать ярлыки" "Позволяет приложению добавлять ярлыки без вмешательства пользователя" "удалять ярлыки" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index be6ee7fdd0..17a6cdce02 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -29,17 +29,17 @@ "Konfigurera..." "Widgetar" "Mappar" - - + "Mer" "Bakgrundsbilder" - - + "Genvägar för appar" "Det här kommer att vara fliken för bakgrundsbilder" "Alla" "Program" "Spel" "Hämtade" - + + + "Mappnamn" "Byt namn på mapp" @@ -60,21 +60,23 @@ "Genvägen \"%s\" har tagits bort." "Genvägen \"%s\" finns redan." "Välj genväg" + "Välj program" "Välj mapp" - "Alla program" + "Program" "Startsida" "Lägg till" + "Hantera appar" "Bakgrund" "Sök" "Aviseringar" "Gester" "Inställningar" - - - - - - + "Avinstallera program" + "Programinformation" + "1 program har valts" + "1 widget vald" + "1 mapp vald" + "1 genväg har valts" "installera genvägar" "Tillåter att ett program lägger till genvägar utan åtgärd från användaren." "avinstallera genvägar" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 59c816d61c..19417f0fd6 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -29,17 +29,17 @@ "Yapılandır..." "Widget\'lar" "Klasörler" - - + "Diğer" "Duvar Kağıtları" - - + "Uygulama Kısayolları" "Bu duvar kağıdı sekmesi olacaktır" "Tümü" "Uygulamalar" "Oyunlar" "İndirilenler" - + + + "Klasör adı" "Klasörü yeniden adlandır" @@ -60,21 +60,23 @@ "\"%s\" kısayolu kaldırıldı." "\"%s\" kısayolu zaten var." "Kısayolu seçin" + "Uygulama seç" "Klasörü seçin" - "Tüm uygulamalar" + "Uygulamalar" "Ana Sayfa" "Ekle" + "Uyglm yönet" "Duvar Kağıdı" "Ara" "Bildirimler" "Hareketler" "Ayarlar" - - - - - - + "Uygulamanın yüklemesini kaldır" + "Uygulama ayrıntıları" + "1 uygulama seçildi" + "1 widget seçildi" + "1 klasör seçildi" + "1 kısayol seçildi" "kısayolları yükle" "Bir uygulamaya, kısayolları kullanıcı müdahale etmeden ekleme izni verir." "kısayolları kaldır" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 58f61787bf..751474b193 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -29,17 +29,17 @@ "配置..." "窗口小部件" "文件夹" - - + "更多" "壁纸" - - + "应用程序快捷方式" "这将会成为壁纸标签" "全部" "应用程序" "游戏" "已下载" - + + + "文件夹名称" "重命名文件夹" @@ -60,21 +60,23 @@ "已删除“%s”快捷方式。" "“%s”快捷方式已存在。" "选择快捷方式" + "选择应用程序" "选择文件夹" - "所有应用程序" + "应用程序" "主屏幕" "添加" + "管理应用程序" "壁纸" "搜索" "通知" "手势" "设置" - - - - - - + "卸载应用程序" + "应用程序详细信息" + "已选中 1 个应用程序" + "已选中 1 个窗口小部件" + "已选中 1 个文件夹" + "已选中 1 个快捷方式" "安装快捷方式" "允许应用程序在没有用户介入的情况下添加快捷方式。" "卸载快捷方式" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index a7cd0988be..824ec64a25 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -29,23 +29,23 @@ "設定..." "小工具" "資料夾" - - + "更多選項" "桌布" - - + "應用程式捷徑" "桌布標籤保留位" "全部" "應用程式" "遊戲" "下載內容" - + + + "資料夾名稱" "重新命名資料夾" "確定" "取消" - "新增至首頁畫面" + "新增至主畫面" "應用程式" "捷徑" "新資料夾" @@ -60,21 +60,23 @@ "已移除「%s」捷徑。" "「%s」捷徑已經存在。" "選取捷徑" + "選取應用程式" "選取資料夾" - "所有應用程式" + "應用程式" "主螢幕" "新增" + "管理應用程式" "桌布" "搜尋" "通知" "觸控動作" "設定" - - - - - - + "解除安裝應用程式" + "應用程式詳細資料" + "已選取 1 個應用程式" + "已選取 1 個小工具" + "已選取 1 個資料夾" + "已選取 1 個捷徑" "安裝捷徑" "允許應用程式自動新增快速鍵。" "解除安裝捷徑" From a9abd0e0bdedb5cbbd12b84cb83037a735e79a20 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 27 Oct 2010 17:18:37 -0700 Subject: [PATCH 5/5] Initial changes to allow dragging external shortcuts to launcher using the same InstallShortcut intent. Change-Id: I21b57115429ed37d604084ae01308d1d3f33ee7e --- res/values-xlarge/dimens.xml | 3 + src/com/android/launcher2/CellLayout.java | 32 +++-- .../launcher2/InstallShortcutReceiver.java | 2 +- src/com/android/launcher2/Launcher.java | 4 + src/com/android/launcher2/LauncherModel.java | 23 +++- src/com/android/launcher2/Workspace.java | 126 +++++++++++++++++- 6 files changed, 168 insertions(+), 22 deletions(-) diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml index a84926d07c..a834a2e48f 100644 --- a/res/values-xlarge/dimens.xml +++ b/res/values-xlarge/dimens.xml @@ -22,6 +22,9 @@ 0dp 0dp + + 10dp + 0dip diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 63da108d06..3c82290f82 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -16,7 +16,7 @@ package com.android.launcher2; -import com.android.launcher.R; +import java.util.Arrays; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -26,6 +26,7 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.WallpaperManager; +import android.content.ClipDescription; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -41,6 +42,7 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.ContextMenu; +import android.view.DragEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; @@ -49,7 +51,7 @@ import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.LayoutAnimationController; -import java.util.Arrays; +import com.android.launcher.R; public class CellLayout extends ViewGroup implements Dimmable { static final String TAG = "CellLayout"; @@ -972,7 +974,11 @@ public class CellLayout extends ViewGroup implements Dimmable { final int oldDragCellX = mDragCell[0]; final int oldDragCellY = mDragCell[1]; final int[] nearest = findNearestVacantArea(originX, originY, spanX, spanY, v, mDragCell); - mDragCenter.set(originX + (v.getWidth() / 2), originY + (v.getHeight() / 2)); + if (v != null) { + mDragCenter.set(originX + (v.getWidth() / 2), originY + (v.getHeight() / 2)); + } else { + mDragCenter.set(originX, originY); + } if (nearest != null && (nearest[0] != oldDragCellX || nearest[1] != oldDragCellY)) { // Find the top left corner of the rect the object will occupy @@ -982,15 +988,17 @@ public class CellLayout extends ViewGroup implements Dimmable { int left = topLeft[0]; int top = topLeft[1]; - if (v.getParent() instanceof CellLayout) { - LayoutParams lp = (LayoutParams) v.getLayoutParams(); - left += lp.leftMargin; - top += lp.topMargin; - } + if (v != null) { + if (v.getParent() instanceof CellLayout) { + LayoutParams lp = (LayoutParams) v.getLayoutParams(); + left += lp.leftMargin; + top += lp.topMargin; + } - // Offsets due to the size difference between the View and the dragOutline - left += (v.getWidth() - dragOutline.getWidth()) / 2; - top += (v.getHeight() - dragOutline.getHeight()) / 2; + // Offsets due to the size difference between the View and the dragOutline + left += (v.getWidth() - dragOutline.getWidth()) / 2; + top += (v.getHeight() - dragOutline.getHeight()) / 2; + } final int oldIndex = mDragOutlineCurrent; mDragOutlineAnims[oldIndex].animateOut(); @@ -1271,7 +1279,7 @@ public class CellLayout extends ViewGroup implements Dimmable { * It may have begun over this layout (in which case onDragChild is called first), * or it may have begun on another layout. */ - void onDragEnter(View dragView) { + void onDragEnter() { if (!mDragging) { // Fade in the drag indicators if (mCrosshairsAnimator != null) { diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java index caeb12b4a5..8d72531d50 100644 --- a/src/com/android/launcher2/InstallShortcutReceiver.java +++ b/src/com/android/launcher2/InstallShortcutReceiver.java @@ -26,7 +26,7 @@ import android.widget.Toast; import com.android.launcher.R; public class InstallShortcutReceiver extends BroadcastReceiver { - private static final String ACTION_INSTALL_SHORTCUT = + public static final String ACTION_INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT"; private final int[] mCoordinates = new int[2]; diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 444357ebc9..346e472c52 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -1144,6 +1144,10 @@ public final class Launcher extends Activity return mAppWidgetHost; } + public LauncherModel getModel() { + return mModel; + } + void closeSystemDialogs() { getWindow().closeAllPanels(); diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java index 1e58ca0e42..179a5d5c0c 100644 --- a/src/com/android/launcher2/LauncherModel.java +++ b/src/com/android/launcher2/LauncherModel.java @@ -1513,14 +1513,25 @@ public class LauncherModel extends BroadcastReceiver { ShortcutInfo addShortcut(Context context, Intent data, int screen, int cellX, int cellY, boolean notify) { - final ShortcutInfo info = infoFromShortcutIntent(context, data); + final ShortcutInfo info = infoFromShortcutIntent(context, data, null); addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, cellX, cellY, notify); return info; } - private ShortcutInfo infoFromShortcutIntent(Context context, Intent data) { + /** + * Ensures that a given shortcut intent actually has all the fields that we need to create a + * proper ShortcutInfo. + */ + boolean validateShortcutIntent(Intent data) { + // We don't require Intent.EXTRA_SHORTCUT_ICON, since we can pull a default fallback icon + return InstallShortcutReceiver.ACTION_INSTALL_SHORTCUT.equals(data.getAction()) && + (data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT) != null) && + (data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME) != null); + } + + ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) { Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON); @@ -1553,8 +1564,12 @@ public class LauncherModel extends BroadcastReceiver { final ShortcutInfo info = new ShortcutInfo(); if (icon == null) { - icon = getFallbackIcon(); - info.usingFallbackIcon = true; + if (fallbackIcon != null) { + icon = fallbackIcon; + } else { + icon = getFallbackIcon(); + info.usingFallbackIcon = true; + } } info.setIcon(icon); diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index ce613f1353..07faed101a 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -16,7 +16,8 @@ package com.android.launcher2; -import com.android.launcher.R; +import java.util.ArrayList; +import java.util.HashSet; import android.animation.Animator; import android.animation.Animator.AnimatorListener; @@ -27,6 +28,8 @@ import android.animation.PropertyValuesHolder; import android.app.WallpaperManager; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; +import android.content.ClipData; +import android.content.ClipDescription; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -36,8 +39,11 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Matrix; +import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -45,12 +51,13 @@ import android.os.IBinder; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; +import android.view.DragEvent; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; +import android.widget.Toast; -import java.util.ArrayList; -import java.util.HashSet; +import com.android.launcher.R; /** * The workspace is a wide area with a wallpaper and a finite number of pages. @@ -144,6 +151,9 @@ public class Workspace extends SmoothPagedView private final Rect mTempRect = new Rect(); private final int[] mTempXY = new int[2]; + // Paint used to draw external drop outline + private final Paint mExternalDragOutlinePaint = new Paint(); + /** * Used to inflate the Workspace from XML. * @@ -193,6 +203,7 @@ public class Workspace extends SmoothPagedView Launcher.setScreen(mCurrentPage); LauncherApplication app = (LauncherApplication)context.getApplicationContext(); mIconCache = app.getIconCache(); + mExternalDragOutlinePaint.setAntiAlias(true); mUnshrinkAnimationListener = new AnimatorListenerAdapter() { public void onAnimationStart(Animator animation) { @@ -983,6 +994,29 @@ public class Workspace extends SmoothPagedView return b; } + /** + * Creates a drag outline to represent a drop (that we don't have the actual information for + * yet). May be changed in the future to alter the drop outline slightly depending on the + * clip description mime data. + */ + private Bitmap createExternalDragOutline(Canvas canvas, int padding) { + Resources r = getResources(); + final int outlineColor = r.getColor(R.color.drag_outline_color); + final int iconWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width); + final int iconHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height); + final int rectRadius = r.getDimensionPixelSize(R.dimen.external_drop_icon_rect_radius); + final int inset = (int) (Math.min(iconWidth, iconHeight) * 0.2f); + final Bitmap b = Bitmap.createBitmap( + iconWidth + padding, iconHeight + padding, Bitmap.Config.ARGB_8888); + + canvas.setBitmap(b); + canvas.drawRoundRect(new RectF(inset, inset, iconWidth - inset, iconHeight - inset), + rectRadius, rectRadius, mExternalDragOutlinePaint); + mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true); + + return b; + } + /** * Returns a new bitmap to show when the given View is being dragged around. * Responsibility for the bitmap is transferred to the caller. @@ -1136,7 +1170,7 @@ public class Workspace extends SmoothPagedView if (!mIsSmall) { mDragTargetLayout = getCurrentDropLayout(); - mDragTargetLayout.onDragEnter(dragView); + mDragTargetLayout.onDragEnter(); showOutlines(); } } @@ -1182,6 +1216,88 @@ public class Workspace extends SmoothPagedView return null; } + /** + * Global drag and drop handler + */ + @Override + public boolean onDragEvent(DragEvent event) { + final CellLayout layout = (CellLayout) getChildAt(mCurrentPage); + final int[] pos = new int[2]; + layout.getLocationOnScreen(pos); + // We need to offset the drag coordinates to layout coordinate space + final int x = (int) event.getX() - pos[0]; + final int y = (int) event.getY() - pos[1]; + + switch (event.getAction()) { + case DragEvent.ACTION_DRAG_STARTED: + // Check if we have enough space on this screen to add a new shortcut + if (!layout.findCellForSpan(pos, 1, 1)) { + Toast.makeText(mContext, mContext.getString(R.string.out_of_space), + Toast.LENGTH_SHORT).show(); + return false; + } + + ClipDescription desc = event.getClipDescription(); + if (desc.filterMimeTypes(ClipDescription.MIMETYPE_TEXT_INTENT) != null) { + // Create the drag outline + // We need to add extra padding to the bitmap to make room for the glow effect + final Canvas canvas = new Canvas(); + final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS; + mDragOutline = createExternalDragOutline(canvas, bitmapPadding); + + // Show the current page outlines to indicate that we can accept this drop + showOutlines(); + layout.setHover(true); + layout.onDragEnter(); + layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1); + + return true; + } + break; + case DragEvent.ACTION_DRAG_LOCATION: + // Visualize the drop location + layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1); + return true; + case DragEvent.ACTION_DROP: + // Check if we have enough space on this screen to add a new shortcut + if (!layout.findCellForSpan(pos, 1, 1)) { + Toast.makeText(mContext, mContext.getString(R.string.out_of_space), + Toast.LENGTH_SHORT).show(); + return false; + } + + // Try and add any shortcuts + int newDropCount = 0; + final LauncherModel model = mLauncher.getModel(); + final ClipData data = event.getClipData(); + final int itemCount = data.getItemCount(); + for (int i = 0; i < itemCount; ++i) { + final Intent intent = data.getItem(i).getIntent(); + if (intent != null && model.validateShortcutIntent(intent)) { + ShortcutInfo info = model.infoFromShortcutIntent(mContext, intent, data. + getIcon()); + onDropExternal(x, y, info, layout); + newDropCount++; + } + } + + // Show error message if we couldn't accept any of the items + if (newDropCount <= 0) { + Toast.makeText(mContext, "Only Shortcut Intents accepted.", + Toast.LENGTH_SHORT).show(); + } + + return true; + case DragEvent.ACTION_DRAG_ENDED: + // Hide the page outlines after the drop + layout.setHover(false); + layout.onDragExit(); + hideOutlines(); + return true; + } + return super.onDragEvent(event); + } + /* * * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's @@ -1382,7 +1498,7 @@ public class Workspace extends SmoothPagedView if (mDragTargetLayout != null) { mDragTargetLayout.onDragExit(); } - layout.onDragEnter(dragView); + layout.onDragEnter(); mDragTargetLayout = layout; }