Adding support for hiding widgets from the widget tray and reconfiguring widgets
> Removing AppInfo target > Switching between uninstall and setup based on the drag view Bug: 63931362 Change-Id: Iccd6f965fa3d61992244a365efc242122292c0ca
This commit is contained in:
parent
f454ded32c
commit
b29a5fa55c
|
@ -15,5 +15,5 @@
|
|||
-->
|
||||
<com.android.launcher3.graphics.ShadowDrawable
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/ic_info_no_shadow"
|
||||
android:src="@drawable/ic_setting"
|
||||
android:elevation="@dimen/drop_target_shadow_elevation" />
|
|
@ -17,9 +17,10 @@ Copyright (C) 2016 The Android Open Source Project
|
|||
android:width="@dimen/options_menu_icon_size"
|
||||
android:height="@dimen/options_menu_icon_size"
|
||||
android:viewportWidth="48.0"
|
||||
android:viewportHeight="48.0">
|
||||
android:viewportHeight="48.0"
|
||||
android:tint="?android:attr/textColorPrimary" >
|
||||
<path
|
||||
android:fillColor="?android:attr/textColorPrimary"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M42.8,28.4l-3.88-2.9c0.06-0.5,0.08-1,0.08-1.52s-0.02-1.02-0.08-1.52l3.88-2.86c0.84-0.62,1.04-1.88,
|
||||
0.48-2.82l-3.2-5.52c-0.56-0.96-1.76-1.4-2.72-1l-4.28,1.82c-0.96-0.74-2.02-1.36-3.14-1.84l-0.54-4.4C29.28,4.8,28.28,4,
|
||||
27.18,4h-6.36c-1.1,0-2.1,0.8-2.22,1.84l-0.52,4.38c-1.14,0.48-2.2,1.1-3.16,1.84l-4.28-1.82c-0.96-0.4-2.16,0.04-2.72,
|
||||
|
|
|
@ -32,18 +32,8 @@
|
|||
android:gravity="center"
|
||||
android:text="@string/remove_drop_target_label" />
|
||||
|
||||
<!-- App Info -->
|
||||
<com.android.launcher3.InfoDropTarget
|
||||
android:id="@+id/info_target_text"
|
||||
style="@style/DropTargetButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_info_drop_target_label" />
|
||||
|
||||
<!-- Uninstall target -->
|
||||
<com.android.launcher3.UninstallDropTarget
|
||||
<com.android.launcher3.SecondaryDropTarget
|
||||
android:id="@+id/uninstall_target_text"
|
||||
style="@style/DropTargetButton"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
<!-- Accessibility actions -->
|
||||
<item type="id" name="action_remove" />
|
||||
<item type="id" name="action_uninstall" />
|
||||
<item type="id" name="action_info" />
|
||||
<item type="id" name="action_reconfigure" />
|
||||
<item type="id" name="action_add_to_workspace" />
|
||||
<item type="id" name="action_move" />
|
||||
<item type="id" name="action_move_to_workspace" />
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<drawable name="ic_info_shadow">@drawable/ic_info_no_shadow</drawable>
|
||||
<drawable name="ic_setup_shadow">@drawable/ic_setting</drawable>
|
||||
<drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
|
||||
<drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
|
||||
</resources>
|
|
@ -108,6 +108,12 @@ public abstract class ButtonDropTarget extends TextView
|
|||
setContentDescription(mText);
|
||||
}
|
||||
|
||||
protected void updateText(int resId) {
|
||||
setText(resId);
|
||||
mText = getText();
|
||||
setContentDescription(mText);
|
||||
}
|
||||
|
||||
protected void setDrawable(int resId) {
|
||||
// We do not set the drawable in the xml as that inflates two drawables corresponding to
|
||||
// drawableLeft and drawableStart.
|
||||
|
@ -236,9 +242,7 @@ public abstract class ButtonDropTarget extends TextView
|
|||
|
||||
protected abstract boolean supportsDrop(ItemInfo info);
|
||||
|
||||
public boolean supportsAccessibilityDrop(ItemInfo info) {
|
||||
return supportsDrop(info);
|
||||
}
|
||||
public abstract boolean supportsAccessibilityDrop(ItemInfo info, View view);
|
||||
|
||||
@Override
|
||||
public boolean isDropEnabled() {
|
||||
|
@ -368,4 +372,6 @@ public abstract class ButtonDropTarget extends TextView
|
|||
TextUtils.TruncateAt.END);
|
||||
return !mText.equals(displayedText);
|
||||
}
|
||||
|
||||
public abstract int getControlTypeForLogging();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.view.View;
|
|||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
|
||||
|
||||
public class DeleteDropTarget extends ButtonDropTarget {
|
||||
|
||||
|
@ -54,7 +55,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
* @return true for items that should have a "Remove" action in accessibility.
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsAccessibilityDrop(ItemInfo info) {
|
||||
public boolean supportsAccessibilityDrop(ItemInfo info, View view) {
|
||||
return (info instanceof ShortcutInfo)
|
||||
|| (info instanceof LauncherAppWidgetInfo)
|
||||
|| (info instanceof FolderInfo);
|
||||
|
@ -103,4 +104,9 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
|||
mLauncher.getDragLayer()
|
||||
.announceForAccessibility(getContext().getString(R.string.item_removed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlTypeForLogging() {
|
||||
return ControlType.REMOVE_TARGET;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.android.launcher3;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
public class InfoDropTarget extends UninstallDropTarget {
|
||||
|
||||
private static final String TAG = "InfoDropTarget";
|
||||
|
||||
public InfoDropTarget(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public InfoDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupUi() {
|
||||
// Get the hover color
|
||||
mHoverColor = Themes.getColorAccent(getContext());
|
||||
setDrawable(R.drawable.ic_info_shadow);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ComponentName performDropAction(ItemInfo item) {
|
||||
return performDropAction(mLauncher, item, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the activity was started.
|
||||
*/
|
||||
public static boolean startDetailsActivityForInfo(
|
||||
ItemInfo info, Launcher launcher, Rect sourceBounds, Bundle opts) {
|
||||
return performDropAction(launcher, info, sourceBounds, opts) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the drop action and returns the target component for the dragObject or null if
|
||||
* the action was not performed.
|
||||
*/
|
||||
private static ComponentName performDropAction(Context context, ItemInfo info,
|
||||
Rect sourceBounds, Bundle opts) {
|
||||
if (info instanceof PromiseAppInfo) {
|
||||
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
|
||||
context.startActivity(promiseAppInfo.getMarketIntent(context));
|
||||
return null;
|
||||
}
|
||||
ComponentName componentName = null;
|
||||
if (info instanceof AppInfo) {
|
||||
componentName = ((AppInfo) info).componentName;
|
||||
} else if (info instanceof ShortcutInfo) {
|
||||
componentName = info.getTargetComponent();
|
||||
} else if (info instanceof PendingAddItemInfo) {
|
||||
componentName = ((PendingAddItemInfo) info).componentName;
|
||||
} else if (info instanceof LauncherAppWidgetInfo) {
|
||||
componentName = ((LauncherAppWidgetInfo) info).providerName;
|
||||
}
|
||||
if (componentName != null) {
|
||||
try {
|
||||
LauncherAppsCompat.getInstance(context)
|
||||
.showAppDetailsForProfile(componentName, info.user, sourceBounds, opts);
|
||||
return componentName;
|
||||
} catch (SecurityException | ActivityNotFoundException e) {
|
||||
Toast.makeText(context, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
Log.e(TAG, "Unable to launch settings", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAccessibilityAction() {
|
||||
return LauncherAccessibilityDelegate.INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsDrop(ItemInfo info) {
|
||||
// Only show the App Info drop target if developer settings are enabled.
|
||||
boolean developmentSettingsEnabled = Settings.Global.getInt(
|
||||
getContext().getContentResolver(),
|
||||
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1;
|
||||
if (!developmentSettingsEnabled) {
|
||||
return false;
|
||||
}
|
||||
return info.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT &&
|
||||
(info instanceof AppInfo ||
|
||||
(info instanceof ShortcutInfo && !((ShortcutInfo) info).isPromise()) ||
|
||||
(info instanceof LauncherAppWidgetInfo &&
|
||||
((LauncherAppWidgetInfo) info).restoreStatus == 0) ||
|
||||
info instanceof PendingAddItemInfo);
|
||||
}
|
||||
}
|
|
@ -94,4 +94,12 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
|
|||
public boolean isCustomWidget() {
|
||||
return provider.getClassName().startsWith(CLS_CUSTOM_WIDGET_PREFIX);
|
||||
}
|
||||
|
||||
public int getWidgetFeatures() {
|
||||
if (Utilities.ATLEAST_P) {
|
||||
return widgetFeatures;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
package com.android.launcher3;
|
||||
|
||||
import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||
import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_RECONFIGURABLE;
|
||||
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_SYSTEM_MASK;
|
||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_SYSTEM_NO;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
|
||||
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE;
|
||||
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.SETTINGS_BUTTON;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.UNINSTALL_TARGET;
|
||||
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -20,27 +31,33 @@ import android.view.View;
|
|||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.Launcher.OnResumeCallback;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmListener {
|
||||
/**
|
||||
* Drop target which provides a secondary option for an item.
|
||||
* For app targets: shows as uninstall
|
||||
* For configurable widgets: shows as setup
|
||||
*/
|
||||
public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmListener {
|
||||
|
||||
private static final String TAG = "UninstallDropTarget";
|
||||
private static final String TAG = "SecondaryDropTarget";
|
||||
|
||||
private static final long CACHE_EXPIRE_TIMEOUT = 5000;
|
||||
private final ArrayMap<UserHandle, Boolean> mUninstallDisabledCache = new ArrayMap<>(1);
|
||||
|
||||
private final Alarm mCacheExpireAlarm;
|
||||
|
||||
public UninstallDropTarget(Context context, AttributeSet attrs) {
|
||||
private int mCurrentAccessibilityAction = -1;
|
||||
public SecondaryDropTarget(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public UninstallDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
||||
public SecondaryDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mCacheExpireAlarm = new Alarm();
|
||||
|
@ -50,13 +67,24 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
setupUi();
|
||||
setupUi(UNINSTALL);
|
||||
}
|
||||
|
||||
protected void setupUi() {
|
||||
// Get the hover color
|
||||
mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint);
|
||||
setDrawable(R.drawable.ic_uninstall_shadow);
|
||||
private void setupUi(int action) {
|
||||
if (action == mCurrentAccessibilityAction) {
|
||||
return;
|
||||
}
|
||||
mCurrentAccessibilityAction = action;
|
||||
|
||||
if (action == UNINSTALL) {
|
||||
mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint);
|
||||
setDrawable(R.drawable.ic_uninstall_shadow);
|
||||
updateText(R.string.uninstall_drop_target_label);
|
||||
} else {
|
||||
mHoverColor = Themes.getColorAccent(getContext());
|
||||
setDrawable(R.drawable.ic_setup_shadow);
|
||||
updateText(R.string.gadget_setup_text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,11 +94,30 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
|
||||
@Override
|
||||
public int getAccessibilityAction() {
|
||||
return LauncherAccessibilityDelegate.UNINSTALL;
|
||||
return mCurrentAccessibilityAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlTypeForLogging() {
|
||||
return mCurrentAccessibilityAction == UNINSTALL ? UNINSTALL_TARGET : SETTINGS_BUTTON;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsDrop(ItemInfo info) {
|
||||
return supportsAccessibilityDrop(info, getViewUnderDrag(info));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAccessibilityDrop(ItemInfo info, View view) {
|
||||
if (view instanceof AppWidgetHostView) {
|
||||
if (getReconfigurableWidgetId(view) != INVALID_APPWIDGET_ID) {
|
||||
setupUi(RECONFIGURE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setupUi(UNINSTALL);
|
||||
Boolean uninstallDisabled = mUninstallDisabledCache.get(info.user);
|
||||
if (uninstallDisabled == null) {
|
||||
UserManager userManager =
|
||||
|
@ -126,7 +173,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
|
||||
@Override
|
||||
public void completeDrop(final DragObject d) {
|
||||
ComponentName target = performDropAction(d.dragInfo);
|
||||
ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo);
|
||||
if (d.dragSource instanceof DeferredOnComplete) {
|
||||
DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
|
||||
if (target != null) {
|
||||
|
@ -138,11 +185,48 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
}
|
||||
}
|
||||
|
||||
private View getViewUnderDrag(ItemInfo info) {
|
||||
if (info instanceof LauncherAppWidgetInfo && info.container == CONTAINER_DESKTOP &&
|
||||
mLauncher.getWorkspace().getDragInfo() != null) {
|
||||
return mLauncher.getWorkspace().getDragInfo().cell;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the view is an reconfigurable widget and returns the corresponding widget Id,
|
||||
* otherwise return {@code INVALID_APPWIDGET_ID}
|
||||
*/
|
||||
private int getReconfigurableWidgetId(View view) {
|
||||
if (!(view instanceof AppWidgetHostView)) {
|
||||
return INVALID_APPWIDGET_ID;
|
||||
}
|
||||
AppWidgetHostView hostView = (AppWidgetHostView) view;
|
||||
AppWidgetProviderInfo widgetInfo = hostView.getAppWidgetInfo();
|
||||
if (widgetInfo == null || widgetInfo.configure == null) {
|
||||
return INVALID_APPWIDGET_ID;
|
||||
}
|
||||
if ( (LauncherAppWidgetProviderInfo.fromProviderInfo(getContext(), widgetInfo)
|
||||
.getWidgetFeatures() & WIDGET_FEATURE_RECONFIGURABLE) == 0) {
|
||||
return INVALID_APPWIDGET_ID;
|
||||
}
|
||||
return hostView.getAppWidgetId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the drop action and returns the target component for the dragObject or null if
|
||||
* the action was not performed.
|
||||
*/
|
||||
protected ComponentName performDropAction(ItemInfo info) {
|
||||
protected ComponentName performDropAction(View view, ItemInfo info) {
|
||||
if (mCurrentAccessibilityAction == RECONFIGURE) {
|
||||
int widgetId = getReconfigurableWidgetId(view);
|
||||
if (widgetId != INVALID_APPWIDGET_ID) {
|
||||
mLauncher.getAppWidgetHost().startConfigActivity(mLauncher, widgetId, -1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// else: mCurrentAccessibilityAction == UNINSTALL
|
||||
|
||||
ComponentName cn = getUninstallTarget(info);
|
||||
if (cn == null) {
|
||||
// System applications cannot be installed. For now, show a toast explaining that.
|
||||
|
@ -164,7 +248,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
|
||||
@Override
|
||||
public void onAccessibilityDrop(View view, ItemInfo item) {
|
||||
performDropAction(item);
|
||||
performDropAction(view, item);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,7 +287,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
.getApplicationInfo(mPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
|
||||
mDragObject.dragInfo.user) == null) {
|
||||
mDragObject.dragSource = mOriginal;
|
||||
mOriginal.onDropCompleted(UninstallDropTarget.this, mDragObject, true);
|
||||
mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, true);
|
||||
} else {
|
||||
sendFailure();
|
||||
}
|
||||
|
@ -212,7 +296,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
|||
public void sendFailure() {
|
||||
mDragObject.dragSource = mOriginal;
|
||||
mDragObject.cancelled = true;
|
||||
mOriginal.onDropCompleted(UninstallDropTarget.this, mDragObject, false);
|
||||
mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,8 +47,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
private static final String TAG = "LauncherAccessibilityDelegate";
|
||||
|
||||
public static final int REMOVE = R.id.action_remove;
|
||||
public static final int INFO = R.id.action_info;
|
||||
public static final int UNINSTALL = R.id.action_uninstall;
|
||||
public static final int RECONFIGURE = R.id.action_reconfigure;
|
||||
protected static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
|
||||
protected static final int MOVE = R.id.action_move;
|
||||
protected static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace;
|
||||
|
@ -77,10 +77,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
|
||||
mActions.put(REMOVE, new AccessibilityAction(REMOVE,
|
||||
launcher.getText(R.string.remove_drop_target_label)));
|
||||
mActions.put(INFO, new AccessibilityAction(INFO,
|
||||
launcher.getText(R.string.app_info_drop_target_label)));
|
||||
mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
|
||||
launcher.getText(R.string.uninstall_drop_target_label)));
|
||||
mActions.put(RECONFIGURE, new AccessibilityAction(RECONFIGURE,
|
||||
launcher.getText(R.string.gadget_setup_text)));
|
||||
mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
|
||||
launcher.getText(R.string.action_add_to_workspace)));
|
||||
mActions.put(MOVE, new AccessibilityAction(MOVE,
|
||||
|
@ -110,7 +110,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
}
|
||||
|
||||
for (ButtonDropTarget target : mLauncher.getDropTargetBar().getDropTargets()) {
|
||||
if (target.supportsAccessibilityDrop(item)) {
|
||||
if (target.supportsAccessibilityDrop(item, host)) {
|
||||
info.addAction(mActions.get(target.getAccessibilityAction()));
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +222,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
|||
return PopupContainerWithArrow.showForIcon((BubbleTextView) host) != null;
|
||||
} else {
|
||||
for (ButtonDropTarget dropTarget : mLauncher.getDropTargetBar().getDropTargets()) {
|
||||
if (action == dropTarget.getAccessibilityAction()) {
|
||||
if (dropTarget.supportsAccessibilityDrop(item, host) &&
|
||||
action == dropTarget.getAccessibilityAction()) {
|
||||
dropTarget.onAccessibilityDrop(host, item);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,8 @@ import android.util.SparseArray;
|
|||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.ButtonDropTarget;
|
||||
import com.android.launcher3.DeleteDropTarget;
|
||||
import com.android.launcher3.InfoDropTarget;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.UninstallDropTarget;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
|
@ -165,12 +162,8 @@ public class LoggerUtils {
|
|||
return newTarget(Target.Type.CONTAINER);
|
||||
}
|
||||
Target t = newTarget(Target.Type.CONTROL);
|
||||
if (v instanceof InfoDropTarget) {
|
||||
t.controlType = ControlType.APPINFO_TARGET;
|
||||
} else if (v instanceof UninstallDropTarget) {
|
||||
t.controlType = ControlType.UNINSTALL_TARGET;
|
||||
} else if (v instanceof DeleteDropTarget) {
|
||||
t.controlType = ControlType.REMOVE_TARGET;
|
||||
if (v instanceof ButtonDropTarget) {
|
||||
t.controlType = ((ButtonDropTarget) v).getControlTypeForLogging();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;
|
||||
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
@ -153,6 +155,11 @@ public class WidgetsModel {
|
|||
// add and update.
|
||||
for (WidgetItem item : rawWidgetsShortcuts) {
|
||||
if (item.widgetInfo != null) {
|
||||
if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) {
|
||||
// Widget is hidden from picker
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure that all widgets we show can be added on a workspace of this size
|
||||
int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX);
|
||||
int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY);
|
||||
|
|
|
@ -9,7 +9,6 @@ import android.os.Bundle;
|
|||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.InfoDropTarget;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
|
@ -83,7 +82,8 @@ public abstract class SystemShortcut extends ItemInfo {
|
|||
public void onClick(View view) {
|
||||
Rect sourceBounds = launcher.getViewBounds(view);
|
||||
Bundle opts = launcher.getActivityLaunchOptionsAsBundle(view, false);
|
||||
InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, sourceBounds, opts);
|
||||
new PackageManagerHelper(launcher).startDetailsActivityForInfo(
|
||||
itemInfo, sourceBounds, opts);
|
||||
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
||||
ControlType.APPINFO_TARGET, view);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package com.android.launcher3.util;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
|
@ -24,13 +26,23 @@ import android.content.pm.LauncherActivityInfo;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.PendingAddItemInfo;
|
||||
import com.android.launcher3.PromiseAppInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutInfo;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
|
||||
|
@ -42,6 +54,8 @@ import java.util.List;
|
|||
*/
|
||||
public class PackageManagerHelper {
|
||||
|
||||
private static final String TAG = "PackageManagerHelper";
|
||||
|
||||
private final Context mContext;
|
||||
private final PackageManager mPm;
|
||||
private final LauncherAppsCompat mLauncherApps;
|
||||
|
@ -169,4 +183,35 @@ public class PackageManagerHelper {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts the details activity for {@code info}
|
||||
*/
|
||||
public void startDetailsActivityForInfo(ItemInfo info, Rect sourceBounds, Bundle opts) {
|
||||
if (info instanceof PromiseAppInfo) {
|
||||
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
|
||||
mContext.startActivity(promiseAppInfo.getMarketIntent(mContext));
|
||||
return;
|
||||
}
|
||||
ComponentName componentName = null;
|
||||
if (info instanceof AppInfo) {
|
||||
componentName = ((AppInfo) info).componentName;
|
||||
} else if (info instanceof ShortcutInfo) {
|
||||
componentName = info.getTargetComponent();
|
||||
} else if (info instanceof PendingAddItemInfo) {
|
||||
componentName = ((PendingAddItemInfo) info).componentName;
|
||||
} else if (info instanceof LauncherAppWidgetInfo) {
|
||||
componentName = ((LauncherAppWidgetInfo) info).providerName;
|
||||
}
|
||||
if (componentName != null) {
|
||||
try {
|
||||
mLauncherApps.showAppDetailsForProfile(
|
||||
componentName, info.user, sourceBounds, opts);
|
||||
} catch (SecurityException | ActivityNotFoundException e) {
|
||||
Toast.makeText(mContext, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
Log.e(TAG, "Unable to launch settings", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,17 @@
|
|||
android:resource="@xml/appwidget_no_config" />
|
||||
</receiver>
|
||||
|
||||
|
||||
<receiver
|
||||
android:name="com.android.launcher3.testcomponent.AppWdigetHidden"
|
||||
android:label="Hidden widget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.appwidget.provider"
|
||||
android:resource="@xml/appwidget_hidden" />
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig"
|
||||
android:label="With Config">
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="110dp"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:initialLayout="@layout/test_layout_appwidget_blue"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:widgetFeatures="hide_from_picker"
|
||||
android:widgetCategory="home_screen">
|
||||
</appwidget-provider>
|
|
@ -7,5 +7,6 @@
|
|||
android:initialLayout="@layout/test_layout_appwidget_blue"
|
||||
android:configure="com.android.launcher3.testcomponent.WidgetConfigActivity"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:widgetFeatures="reconfigurable"
|
||||
android:widgetCategory="home_screen">
|
||||
</appwidget-provider>
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.android.launcher3.testcomponent;
|
||||
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
|
||||
/**
|
||||
* A simple app widget without any configuration screen and is hidden in picker.
|
||||
*/
|
||||
public class AppWidgetHidden extends AppWidgetProvider { }
|
Loading…
Reference in New Issue