Fixing taskMenu and taskView clicks in fallback activity
> Extracting common methods from Launcher & DragLauncher to base classes > Remoting some dependencies on Launcher and using the base class instead Change-Id: I121cacf8a14190b4703cda60bdeb4f79eee69ded
This commit is contained in:
parent
39b5534b96
commit
0b0847b272
|
@ -15,15 +15,17 @@
|
|||
-->
|
||||
<com.android.quickstep.RecentsRootView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/drag_layer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.android.quickstep.FallbackRecentsView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:theme="@style/HomeScreenElementTheme"
|
||||
android:id="@+id/overview_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false" />
|
||||
android:clipToPadding="false"
|
||||
android:theme="@style/HomeScreenElementTheme" />
|
||||
|
||||
</com.android.quickstep.RecentsRootView>
|
|
@ -36,11 +36,13 @@ public class UiFactory {
|
|||
public static TouchController[] createTouchControllers(Launcher launcher) {
|
||||
if (FeatureFlags.ENABLE_TWO_SWIPE_TARGETS) {
|
||||
return new TouchController[] {
|
||||
launcher.getDragController(),
|
||||
new EdgeSwipeController(launcher),
|
||||
new TwoStepSwipeController(launcher),
|
||||
new OverviewSwipeController(launcher)};
|
||||
} else {
|
||||
return new TouchController[] {
|
||||
launcher.getDragController(),
|
||||
new TwoStepSwipeController(launcher),
|
||||
new OverviewSwipeController(launcher)};
|
||||
}
|
||||
|
|
|
@ -15,17 +15,25 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.badge.BadgeInfo;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
/**
|
||||
* A simple activity to show the recently launched tasks
|
||||
*/
|
||||
public class RecentsActivity extends BaseActivity {
|
||||
public class RecentsActivity extends BaseDraggingActivity {
|
||||
|
||||
private RecentsRootView mRecentsRootView;
|
||||
private FallbackRecentsView mFallbackRecentsView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -39,5 +47,30 @@ public class RecentsActivity extends BaseActivity {
|
|||
: new InvariantDeviceProfile(this).getDeviceProfile(this));
|
||||
|
||||
setContentView(R.layout.fallback_recents_activity);
|
||||
mRecentsRootView = findViewById(R.id.drag_layer);
|
||||
mFallbackRecentsView = findViewById(R.id.overview_panel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseDragLayer getDragLayer() {
|
||||
return mRecentsRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends View> T getOverviewPanel() {
|
||||
return (T) mFallbackRecentsView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateParent(ItemInfo info) { }
|
||||
}
|
||||
|
|
|
@ -21,17 +21,19 @@ import android.graphics.Rect;
|
|||
import android.util.AttributeSet;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
public class RecentsRootView extends InsettableFrameLayout {
|
||||
public class RecentsRootView extends BaseDragLayer<RecentsActivity> {
|
||||
|
||||
private final BaseActivity mActivity;
|
||||
|
||||
public RecentsRootView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mActivity = BaseActivity.fromContext(context);
|
||||
mControllers = new TouchController[0];
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
|
|
|
@ -30,8 +30,8 @@ import android.view.View;
|
|||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutInfo;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
|
@ -70,11 +70,12 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
}
|
||||
|
||||
@Override
|
||||
public View.OnClickListener getOnClickListener(Launcher launcher, ItemInfo itemInfo) {
|
||||
public View.OnClickListener getOnClickListener(
|
||||
BaseDraggingActivity activity, ItemInfo itemInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public View.OnClickListener getOnClickListener(final Launcher launcher, final TaskView view) {
|
||||
public View.OnClickListener getOnClickListener(BaseDraggingActivity activity, TaskView view) {
|
||||
Task task = view.getTask();
|
||||
|
||||
ShortcutInfo dummyInfo = new ShortcutInfo();
|
||||
|
@ -82,14 +83,14 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
ComponentName component = task.getTopComponent();
|
||||
dummyInfo.intent.setComponent(component);
|
||||
dummyInfo.user = UserHandle.of(task.key.userId);
|
||||
dummyInfo.title = TaskUtils.getTitle(launcher, task);
|
||||
dummyInfo.title = TaskUtils.getTitle(activity, task);
|
||||
|
||||
return getOnClickListenerForTask(launcher, task, dummyInfo);
|
||||
return getOnClickListenerForTask(activity, task, dummyInfo);
|
||||
}
|
||||
|
||||
protected View.OnClickListener getOnClickListenerForTask(final Launcher launcher,
|
||||
final Task task, final ItemInfo dummyInfo) {
|
||||
return mSystemShortcut.getOnClickListener(launcher, dummyInfo);
|
||||
protected View.OnClickListener getOnClickListenerForTask(
|
||||
BaseDraggingActivity activity, Task task, ItemInfo dummyInfo) {
|
||||
return mSystemShortcut.getOnClickListener(activity, dummyInfo);
|
||||
}
|
||||
|
||||
public static class AppInfo extends TaskSystemShortcut<SystemShortcut.AppInfo> {
|
||||
|
@ -109,8 +110,9 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
}
|
||||
|
||||
@Override
|
||||
public View.OnClickListener getOnClickListener(Launcher launcher, TaskView taskView) {
|
||||
if (launcher.getDeviceProfile().isMultiWindowMode) {
|
||||
public View.OnClickListener getOnClickListener(
|
||||
BaseDraggingActivity activity, TaskView taskView) {
|
||||
if (activity.getDeviceProfile().isMultiWindowMode) {
|
||||
return null;
|
||||
}
|
||||
final Task task = taskView.getTask();
|
||||
|
@ -119,12 +121,12 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
}
|
||||
mTaskView = taskView;
|
||||
return (v -> {
|
||||
AbstractFloatingView.closeOpenViews(launcher, true,
|
||||
AbstractFloatingView.closeOpenViews(activity, true,
|
||||
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
|
||||
|
||||
if (ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key.id,
|
||||
ActivityOptionsCompat.makeSplitScreenOptions(true))) {
|
||||
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(launcher).getSystemUiProxy();
|
||||
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy();
|
||||
try {
|
||||
sysUiProxy.onSplitScreenInvoked();
|
||||
} catch (RemoteException e) {
|
||||
|
@ -134,7 +136,7 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
|
||||
final Runnable animStartedListener = () -> {
|
||||
mTaskView.getViewTreeObserver().addOnPreDrawListener(SplitScreen.this);
|
||||
launcher.<RecentsView>getOverviewPanel().removeView(taskView);
|
||||
activity.<RecentsView>getOverviewPanel().removeView(taskView);
|
||||
};
|
||||
|
||||
final int[] position = new int[2];
|
||||
|
@ -178,8 +180,9 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
}
|
||||
|
||||
@Override
|
||||
public View.OnClickListener getOnClickListener(Launcher launcher, TaskView taskView) {
|
||||
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(launcher).getSystemUiProxy();
|
||||
public View.OnClickListener getOnClickListener(
|
||||
BaseDraggingActivity activity, TaskView taskView) {
|
||||
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy();
|
||||
if (sysUiProxy == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -211,11 +214,11 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
|||
}
|
||||
|
||||
@Override
|
||||
protected View.OnClickListener getOnClickListenerForTask(Launcher launcher, Task task,
|
||||
ItemInfo itemInfo) {
|
||||
if (InstantAppResolver.newInstance(launcher).isInstantApp(launcher,
|
||||
protected View.OnClickListener getOnClickListenerForTask(
|
||||
BaseDraggingActivity activity, Task task, ItemInfo itemInfo) {
|
||||
if (InstantAppResolver.newInstance(activity).isInstantApp(activity,
|
||||
task.getTopComponent().getPackageName())) {
|
||||
return mSystemShortcut.createOnClickListener(launcher, itemInfo);
|
||||
return mSystemShortcut.createOnClickListener(activity, itemInfo);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
|
@ -34,10 +34,10 @@ public class TaskUtils {
|
|||
|
||||
private static final String TAG = "TaskUtils";
|
||||
|
||||
public static CharSequence getTitle(Launcher launcher, Task task) {
|
||||
LauncherAppsCompat launcherAppsCompat = LauncherAppsCompat.getInstance(launcher);
|
||||
UserManagerCompat userManagerCompat = UserManagerCompat.getInstance(launcher);
|
||||
PackageManager packageManager = launcher.getPackageManager();
|
||||
public static CharSequence getTitle(Context context, Task task) {
|
||||
LauncherAppsCompat launcherAppsCompat = LauncherAppsCompat.getInstance(context);
|
||||
UserManagerCompat userManagerCompat = UserManagerCompat.getInstance(context);
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
UserHandle user = UserHandle.of(task.key.userId);
|
||||
ApplicationInfo applicationInfo = launcherAppsCompat.getApplicationInfo(
|
||||
task.getTopComponent().getPackageName(), 0, user);
|
||||
|
|
|
@ -32,14 +32,14 @@ import android.view.animation.AccelerateDecelerateInterpolator;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.LauncherAnimUtils;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.TaskSystemShortcut;
|
||||
import com.android.quickstep.TaskUtils;
|
||||
|
||||
|
@ -60,7 +60,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
|
||||
private static final long OPEN_CLOSE_DURATION = 220;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private BaseDraggingActivity mActivity;
|
||||
private TextView mTaskIconAndName;
|
||||
private AnimatorSet mOpenCloseAnimator;
|
||||
private TaskView mTaskView;
|
||||
|
@ -72,7 +72,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
public TaskMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mActivity = BaseDraggingActivity.fromContext(context);
|
||||
setClipToOutline(true);
|
||||
setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
|
@ -92,7 +92,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
DragLayer dl = mLauncher.getDragLayer();
|
||||
BaseDragLayer dl = mActivity.getDragLayer();
|
||||
if (!dl.isEventOverView(this, ev)) {
|
||||
// TODO: log this once we have a new container type for it?
|
||||
close(true);
|
||||
|
@ -122,9 +122,9 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
}
|
||||
|
||||
public static boolean showForTask(TaskView taskView) {
|
||||
Launcher launcher = Launcher.getLauncher(taskView.getContext());
|
||||
final TaskMenuView taskMenuView = (TaskMenuView) launcher.getLayoutInflater().inflate(
|
||||
R.layout.task_menu, launcher.getDragLayer(), false);
|
||||
BaseDraggingActivity activity = BaseDraggingActivity.fromContext(taskView.getContext());
|
||||
final TaskMenuView taskMenuView = (TaskMenuView) activity.getLayoutInflater().inflate(
|
||||
R.layout.task_menu, activity.getDragLayer(), false);
|
||||
return taskMenuView.populateAndShowForTask(taskView);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
if (isAttachedToWindow()) {
|
||||
return false;
|
||||
}
|
||||
mLauncher.getDragLayer().addView(this);
|
||||
mActivity.getDragLayer().addView(this);
|
||||
mTaskView = taskView;
|
||||
addMenuOptions(mTaskView);
|
||||
orientAroundTaskView(mTaskView);
|
||||
|
@ -145,11 +145,11 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
int iconSize = getResources().getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
|
||||
icon.setBounds(0, 0, iconSize, iconSize);
|
||||
mTaskIconAndName.setCompoundDrawables(null, icon, null, null);
|
||||
mTaskIconAndName.setText(TaskUtils.getTitle(mLauncher, taskView.getTask()));
|
||||
mTaskIconAndName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
|
||||
mTaskIconAndName.setOnClickListener(v -> close(true));
|
||||
|
||||
for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
|
||||
OnClickListener onClickListener = menuOption.getOnClickListener(mLauncher, taskView);
|
||||
OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, taskView);
|
||||
if (onClickListener != null) {
|
||||
addMenuOption(menuOption, onClickListener);
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
}
|
||||
|
||||
private void addMenuOption(TaskSystemShortcut menuOption, OnClickListener onClickListener) {
|
||||
DeepShortcutView menuOptionView = (DeepShortcutView) mLauncher.getLayoutInflater().inflate(
|
||||
DeepShortcutView menuOptionView = (DeepShortcutView) mActivity.getLayoutInflater().inflate(
|
||||
R.layout.system_shortcut, this, false);
|
||||
menuOptionView.getIconView().setBackgroundResource(menuOption.iconResId);
|
||||
menuOptionView.getBubbleText().setText(menuOption.labelResId);
|
||||
|
@ -167,8 +167,8 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
|
||||
private void orientAroundTaskView(TaskView taskView) {
|
||||
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
|
||||
mLauncher.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
|
||||
Rect insets = mLauncher.getDragLayer().getInsets();
|
||||
mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
|
||||
Rect insets = mActivity.getDragLayer().getInsets();
|
||||
int x = sTempRect.left + (sTempRect.width() - getMeasuredWidth()) / 2 - insets.left;
|
||||
setX(Utilities.isRtl(getResources()) ? -x : x);
|
||||
setY(sTempRect.top - mTaskIconAndName.getPaddingTop() - insets.top);
|
||||
|
@ -211,7 +211,7 @@ public class TaskMenuView extends AbstractFloatingView {
|
|||
|
||||
private void closeComplete() {
|
||||
mIsOpen = false;
|
||||
mLauncher.getDragLayer().removeView(this);
|
||||
mActivity.getDragLayer().removeView(this);
|
||||
}
|
||||
|
||||
private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider() {
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.view.ViewOutlineProvider;
|
|||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.views.RecentsView.PageCallbacks;
|
||||
|
@ -110,7 +111,8 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
|
|||
if (mTask != null) {
|
||||
final ActivityOptions opts;
|
||||
if (animate) {
|
||||
opts = Launcher.getLauncher(getContext()).getActivityLaunchOptions(this, false);
|
||||
opts = BaseDraggingActivity.fromContext(getContext())
|
||||
.getActivityLaunchOptions(this, false);
|
||||
} else {
|
||||
opts = ActivityOptions.makeCustomAnimation(getContext(), 0, 0);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import android.view.MotionEvent;
|
|||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
@ -92,7 +92,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
|||
public final void close(boolean animate) {
|
||||
animate &= !Utilities.isPowerSaverOn(getContext());
|
||||
handleClose(animate);
|
||||
Launcher.getLauncher(getContext()).getUserEventDispatcher()
|
||||
BaseActivity.fromContext(getContext()).getUserEventDispatcher()
|
||||
.resetElapsedContainerMillis("container closed");
|
||||
}
|
||||
|
||||
|
@ -120,8 +120,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
|||
}
|
||||
|
||||
protected static <T extends AbstractFloatingView> T getOpenView(
|
||||
Launcher launcher, @FloatingViewType int type) {
|
||||
DragLayer dragLayer = launcher.getDragLayer();
|
||||
BaseDraggingActivity activity, @FloatingViewType int type) {
|
||||
BaseDragLayer dragLayer = activity.getDragLayer();
|
||||
// Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
|
@ -136,16 +136,17 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
|||
return null;
|
||||
}
|
||||
|
||||
public static void closeOpenContainer(Launcher launcher, @FloatingViewType int type) {
|
||||
AbstractFloatingView view = getOpenView(launcher, type);
|
||||
public static void closeOpenContainer(BaseDraggingActivity activity,
|
||||
@FloatingViewType int type) {
|
||||
AbstractFloatingView view = getOpenView(activity, type);
|
||||
if (view != null) {
|
||||
view.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeOpenViews(Launcher launcher, boolean animate,
|
||||
public static void closeOpenViews(BaseDraggingActivity activity, boolean animate,
|
||||
@FloatingViewType int type) {
|
||||
DragLayer dragLayer = launcher.getDragLayer();
|
||||
BaseDragLayer dragLayer = activity.getDragLayer();
|
||||
// Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
|
@ -159,16 +160,16 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
|||
}
|
||||
}
|
||||
|
||||
public static void closeAllOpenViews(Launcher launcher, boolean animate) {
|
||||
closeOpenViews(launcher, animate, TYPE_ALL);
|
||||
launcher.finishAutoCancelActionMode();
|
||||
public static void closeAllOpenViews(BaseDraggingActivity activity, boolean animate) {
|
||||
closeOpenViews(activity, animate, TYPE_ALL);
|
||||
activity.finishAutoCancelActionMode();
|
||||
}
|
||||
|
||||
public static void closeAllOpenViews(Launcher launcher) {
|
||||
closeAllOpenViews(launcher, true);
|
||||
public static void closeAllOpenViews(BaseDraggingActivity activity) {
|
||||
closeAllOpenViews(activity, true);
|
||||
}
|
||||
|
||||
public static AbstractFloatingView getTopOpenView(Launcher launcher) {
|
||||
return getOpenView(launcher, TYPE_ALL);
|
||||
public static AbstractFloatingView getTopOpenView(BaseDraggingActivity activity) {
|
||||
return getOpenView(activity, TYPE_ALL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.os.StrictMode;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.badge.BadgeInfo;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutManager;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
/**
|
||||
* Extension of BaseActivity allowing support for drag-n-drop
|
||||
*/
|
||||
public abstract class BaseDraggingActivity extends BaseActivity {
|
||||
|
||||
private static final String TAG = "BaseDraggingActivity";
|
||||
|
||||
// The Intent extra that defines whether to ignore the launch animation
|
||||
private static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
|
||||
"com.android.launcher3.intent.extra.shortcut.INGORE_LAUNCH_ANIMATION";
|
||||
|
||||
// When starting an action mode, setting this tag will cause the action mode to be cancelled
|
||||
// automatically when user interacts with the launcher.
|
||||
public static final Object AUTO_CANCEL_ACTION_MODE = new Object();
|
||||
|
||||
private ActionMode mCurrentActionMode;
|
||||
protected boolean mIsSafeModeEnabled;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mIsSafeModeEnabled = getPackageManager().isSafeMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeStarted(ActionMode mode) {
|
||||
super.onActionModeStarted(mode);
|
||||
mCurrentActionMode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeFinished(ActionMode mode) {
|
||||
super.onActionModeFinished(mode);
|
||||
mCurrentActionMode = null;
|
||||
}
|
||||
|
||||
public boolean finishAutoCancelActionMode() {
|
||||
if (mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag()) {
|
||||
mCurrentActionMode.finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract BaseDragLayer getDragLayer();
|
||||
|
||||
public abstract <T extends View> T getOverviewPanel();
|
||||
|
||||
public abstract BadgeInfo getBadgeInfoForItem(ItemInfo info);
|
||||
|
||||
public abstract void invalidateParent(ItemInfo info);
|
||||
|
||||
public static BaseDraggingActivity fromContext(Context context) {
|
||||
if (context instanceof BaseDraggingActivity) {
|
||||
return (BaseDraggingActivity) context;
|
||||
}
|
||||
return ((BaseDraggingActivity) ((ContextWrapper) context).getBaseContext());
|
||||
}
|
||||
|
||||
public Rect getViewBounds(View v) {
|
||||
int[] pos = new int[2];
|
||||
v.getLocationOnScreen(pos);
|
||||
return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
|
||||
}
|
||||
|
||||
public final Bundle getActivityLaunchOptionsAsBundle(View v, boolean useDefaultLaunchOptions) {
|
||||
ActivityOptions activityOptions = getActivityLaunchOptions(v, useDefaultLaunchOptions);
|
||||
return activityOptions == null ? null : activityOptions.toBundle();
|
||||
}
|
||||
|
||||
public abstract ActivityOptions getActivityLaunchOptions(
|
||||
View v, boolean useDefaultLaunchOptions);
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
|
||||
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
|
||||
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only launch using the new animation if the shortcut has not opted out (this is a
|
||||
// private contract between launcher and may be ignored in the future).
|
||||
boolean useLaunchAnimation = (v != null) &&
|
||||
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
|
||||
Bundle optsBundle = useLaunchAnimation
|
||||
? getActivityLaunchOptionsAsBundle(v, isInMultiWindowModeCompat())
|
||||
: null;
|
||||
|
||||
UserHandle user = item == null ? null : item.user;
|
||||
|
||||
// Prepare intent
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (v != null) {
|
||||
intent.setSourceBounds(getViewBounds(v));
|
||||
}
|
||||
try {
|
||||
boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
|
||||
&& (item instanceof ShortcutInfo)
|
||||
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|
||||
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
|
||||
&& !((ShortcutInfo) item).isPromise();
|
||||
if (isShortcut) {
|
||||
// Shortcuts need some special checks due to legacy reasons.
|
||||
startShortcutIntentSafely(intent, optsBundle, item);
|
||||
} else if (user == null || user.equals(Process.myUserHandle())) {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
} else {
|
||||
LauncherAppsCompat.getInstance(this).startActivityForProfile(
|
||||
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
|
||||
}
|
||||
getUserEventDispatcher().logAppLaunch(v, intent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException|SecurityException e) {
|
||||
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
|
||||
try {
|
||||
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
|
||||
try {
|
||||
// Temporarily disable deathPenalty on all default checks. For eg, shortcuts
|
||||
// containing file Uri's would cause a crash as penaltyDeathOnFileUriExposure
|
||||
// is enabled by default on NYC.
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
|
||||
.penaltyLog().build());
|
||||
|
||||
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
String id = ((ShortcutInfo) info).getDeepShortcutId();
|
||||
String packageName = intent.getPackage();
|
||||
DeepShortcutManager.getInstance(this).startShortcut(
|
||||
packageName, id, intent.getSourceBounds(), optsBundle, info.user);
|
||||
} else {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
}
|
||||
} finally {
|
||||
StrictMode.setVmPolicy(oldPolicy);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
if (!onErrorStartingShortcut(intent, info)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -44,7 +44,6 @@ import com.android.launcher3.Launcher.OnResumeCallback;
|
|||
import com.android.launcher3.badge.BadgeInfo;
|
||||
import com.android.launcher3.badge.BadgeRenderer;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.FolderIconPreviewVerifier;
|
||||
import com.android.launcher3.graphics.DrawableFactory;
|
||||
import com.android.launcher3.graphics.IconPalette;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
|
@ -65,7 +64,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
|
||||
private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed};
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final BaseDraggingActivity mActivity;
|
||||
private Drawable mIcon;
|
||||
private final boolean mCenterVertically;
|
||||
|
||||
|
@ -133,8 +132,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
|
||||
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||
mActivity = BaseDraggingActivity.fromContext(context);
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
|
@ -164,7 +163,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
mLongPressHelper = new CheckLongPressHelper(this);
|
||||
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
|
||||
|
||||
setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
|
||||
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
|
||||
|
||||
}
|
||||
|
||||
|
@ -493,10 +492,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
public void applyBadgeState(ItemInfo itemInfo, boolean animate) {
|
||||
if (mIcon instanceof FastBitmapDrawable) {
|
||||
boolean wasBadged = mBadgeInfo != null;
|
||||
mBadgeInfo = mLauncher.getPopupDataProvider().getBadgeInfoForItem(itemInfo);
|
||||
mBadgeInfo = mActivity.getBadgeInfoForItem(itemInfo);
|
||||
boolean isBadged = mBadgeInfo != null;
|
||||
float newBadgeScale = isBadged ? 1f : 0;
|
||||
mBadgeRenderer = mLauncher.getDeviceProfile().mBadgeRenderer;
|
||||
mBadgeRenderer = mActivity.getDeviceProfile().mBadgeRenderer;
|
||||
if (wasBadged || isBadged) {
|
||||
// Animate when a badge is first added or when it is removed.
|
||||
if (animate && (wasBadged ^ isBadged) && isShown()) {
|
||||
|
@ -572,15 +571,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
|||
applyFromApplicationInfo((AppInfo) info);
|
||||
} else if (info instanceof ShortcutInfo) {
|
||||
applyFromShortcutInfo((ShortcutInfo) info);
|
||||
FolderIconPreviewVerifier verifier =
|
||||
new FolderIconPreviewVerifier(mLauncher.getDeviceProfile().inv);
|
||||
if (verifier.isItemInPreview(info.rank) && (info.container >= 0)) {
|
||||
View folderIcon =
|
||||
mLauncher.getWorkspace().getHomescreenIconByItemId(info.container);
|
||||
if (folderIcon != null) {
|
||||
folderIcon.invalidate();
|
||||
}
|
||||
}
|
||||
mActivity.invalidateParent(info);
|
||||
} else if (info instanceof PackageItemInfo) {
|
||||
applyFromPackageItemInfo((PackageItemInfo) info);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import static com.android.launcher3.LauncherState.NORMAL;
|
|||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
|
||||
|
||||
import android.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
|
@ -47,7 +46,6 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Rect;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
@ -60,7 +58,6 @@ import android.text.TextUtils;
|
|||
import android.text.method.TextKeyListener;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ActionMode;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.KeyboardShortcutGroup;
|
||||
import android.view.KeyboardShortcutInfo;
|
||||
|
@ -73,14 +70,13 @@ import android.view.animation.OvershootInterpolator;
|
|||
import android.widget.Toast;
|
||||
|
||||
import com.android.launcher3.DropTarget.DragObject;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.Workspace.ItemOperator;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||
import com.android.launcher3.badge.BadgeInfo;
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.compat.LauncherAppsCompatVO;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
|
@ -88,6 +84,7 @@ import com.android.launcher3.dragndrop.DragLayer;
|
|||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.dynamicui.WallpaperColorInfo;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.FolderIconPreviewVerifier;
|
||||
import com.android.launcher3.keyboard.CustomActionsPopup;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
|
@ -139,7 +136,7 @@ import java.util.Set;
|
|||
/**
|
||||
* Default launcher application.
|
||||
*/
|
||||
public class Launcher extends BaseActivity implements LauncherExterns, LauncherModel.Callbacks,
|
||||
public class Launcher extends BaseDraggingActivity implements LauncherExterns, LauncherModel.Callbacks,
|
||||
LauncherProviderChangeListener, WallpaperColorInfo.OnThemeChangeListener {
|
||||
public static final String TAG = "Launcher";
|
||||
static final boolean LOGD = false;
|
||||
|
@ -166,10 +163,6 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
*/
|
||||
protected static final int REQUEST_LAST = 100;
|
||||
|
||||
// The Intent extra that defines whether to ignore the launch animation
|
||||
static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
|
||||
"com.android.launcher3.intent.extra.shortcut.INGORE_LAUNCH_ANIMATION";
|
||||
|
||||
// Type: int
|
||||
private static final String RUNTIME_STATE_CURRENT_SCREEN = "launcher.current_screen";
|
||||
// Type: int
|
||||
|
@ -181,14 +174,8 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
// Type: SparseArray<Parcelable>
|
||||
private static final String RUNTIME_STATE_WIDGET_PANEL = "launcher.widget_panel";
|
||||
|
||||
// When starting an action mode, setting this tag will cause the action mode to be cancelled
|
||||
// automatically when user interacts with the launcher.
|
||||
public static final Object AUTO_CANCEL_ACTION_MODE = new Object();
|
||||
|
||||
private LauncherStateManager mStateManager;
|
||||
|
||||
private boolean mIsSafeModeEnabled;
|
||||
|
||||
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
|
||||
|
||||
// How long to wait before the new-shortcut animation automatically pans the workspace
|
||||
|
@ -255,7 +242,6 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
private boolean mAppLaunchSuccess;
|
||||
|
||||
private RotationHelper mRotationHelper;
|
||||
private ActionMode mCurrentActionMode;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -288,7 +274,6 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
initDeviceProfile(app.getInvariantDeviceProfile());
|
||||
|
||||
mSharedPrefs = Utilities.getPrefs(this);
|
||||
mIsSafeModeEnabled = getPackageManager().isSafeMode();
|
||||
mIconCache = app.getIconCache();
|
||||
mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);
|
||||
|
||||
|
@ -482,6 +467,22 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
return mPopupDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
|
||||
return mPopupDataProvider.getBadgeInfoForItem(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateParent(ItemInfo info) {
|
||||
FolderIconPreviewVerifier verifier = new FolderIconPreviewVerifier(getDeviceProfile().inv);
|
||||
if (verifier.isItemInPreview(info.rank) && (info.container >= 0)) {
|
||||
View folderIcon = getWorkspace().getHomescreenIconByItemId(info.container);
|
||||
if (folderIcon != null) {
|
||||
folderIcon.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have
|
||||
* a configuration step, this allows the proper animations to run after other transitions.
|
||||
|
@ -941,7 +942,7 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
|
||||
// Setup the drag layer
|
||||
mDragLayer.setup(this, mDragController);
|
||||
mDragLayer.setup(mDragController);
|
||||
|
||||
mWorkspace.setup(mDragController);
|
||||
// Until the workspace is bound, ensure that we keep the wallpaper offset locked to the
|
||||
|
@ -1180,6 +1181,7 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
return (LauncherRootView) mLauncherView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DragLayer getDragLayer() {
|
||||
return mDragLayer;
|
||||
}
|
||||
|
@ -1672,119 +1674,45 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
}
|
||||
}
|
||||
|
||||
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
|
||||
try {
|
||||
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
|
||||
try {
|
||||
// Temporarily disable deathPenalty on all default checks. For eg, shortcuts
|
||||
// containing file Uri's would cause a crash as penaltyDeathOnFileUriExposure
|
||||
// is enabled by default on NYC.
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
|
||||
.penaltyLog().build());
|
||||
|
||||
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
String id = ((ShortcutInfo) info).getDeepShortcutId();
|
||||
String packageName = intent.getPackage();
|
||||
DeepShortcutManager.getInstance(this).startShortcut(
|
||||
packageName, id, intent.getSourceBounds(), optsBundle, info.user);
|
||||
} else {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
}
|
||||
} finally {
|
||||
StrictMode.setVmPolicy(oldPolicy);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// Due to legacy reasons, direct call shortcuts require Launchers to have the
|
||||
// corresponding permission. Show the appropriate permission prompt if that
|
||||
// is the case.
|
||||
if (intent.getComponent() == null
|
||||
&& Intent.ACTION_CALL.equals(intent.getAction())
|
||||
&& checkSelfPermission(Manifest.permission.CALL_PHONE) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
setWaitingForResult(PendingRequestArgs
|
||||
.forIntent(REQUEST_PERMISSION_CALL_PHONE, intent, info));
|
||||
requestPermissions(new String[]{Manifest.permission.CALL_PHONE},
|
||||
REQUEST_PERMISSION_CALL_PHONE);
|
||||
} else {
|
||||
// No idea why this was thrown.
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Bundle getActivityLaunchOptionsAsBundle(View v, boolean useDefaultLaunchOptions) {
|
||||
ActivityOptions activityOptions = getActivityLaunchOptions(v, useDefaultLaunchOptions);
|
||||
return activityOptions == null ? null : activityOptions.toBundle();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public ActivityOptions getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) {
|
||||
return useDefaultLaunchOptions
|
||||
? mAppTransitionManager.getDefaultActivityLaunchOptions(this, v)
|
||||
: mAppTransitionManager.getActivityLaunchOptions(this, v);
|
||||
}
|
||||
|
||||
public Rect getViewBounds(View v) {
|
||||
int[] pos = new int[2];
|
||||
v.getLocationOnScreen(pos);
|
||||
return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
|
||||
// Due to legacy reasons, direct call shortcuts require Launchers to have the
|
||||
// corresponding permission. Show the appropriate permission prompt if that
|
||||
// is the case.
|
||||
if (intent.getComponent() == null
|
||||
&& Intent.ACTION_CALL.equals(intent.getAction())
|
||||
&& checkSelfPermission(android.Manifest.permission.CALL_PHONE) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
setWaitingForResult(PendingRequestArgs
|
||||
.forIntent(REQUEST_PERMISSION_CALL_PHONE, intent, info));
|
||||
requestPermissions(new String[]{android.Manifest.permission.CALL_PHONE},
|
||||
REQUEST_PERMISSION_CALL_PHONE);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
|
||||
mAppLaunchSuccess = false;
|
||||
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
|
||||
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
|
||||
return mAppLaunchSuccess;
|
||||
}
|
||||
|
||||
// Only launch using the new animation if the shortcut has not opted out (this is a
|
||||
// private contract between launcher and may be ignored in the future).
|
||||
boolean useLaunchAnimation = (v != null) &&
|
||||
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
|
||||
Bundle optsBundle = useLaunchAnimation
|
||||
? getActivityLaunchOptionsAsBundle(v, isInMultiWindowModeCompat())
|
||||
: null;
|
||||
|
||||
UserHandle user = item == null ? null : item.user;
|
||||
|
||||
// Prepare intent
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (v != null) {
|
||||
intent.setSourceBounds(getViewBounds(v));
|
||||
}
|
||||
try {
|
||||
boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
|
||||
&& (item instanceof ShortcutInfo)
|
||||
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|
||||
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
|
||||
&& !((ShortcutInfo) item).isPromise();
|
||||
if (isShortcut) {
|
||||
// Shortcuts need some special checks due to legacy reasons.
|
||||
startShortcutIntentSafely(intent, optsBundle, item);
|
||||
} else if (user == null || user.equals(Process.myUserHandle())) {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
} else {
|
||||
LauncherAppsCompat.getInstance(this).startActivityForProfile(
|
||||
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
|
||||
}
|
||||
|
||||
if (v instanceof BubbleTextView) {
|
||||
// This is set to the view that launched the activity that navigated the user away
|
||||
// from launcher. Since there is no callback for when the activity has finished
|
||||
// launching, enable the press state and keep this reference to reset the press
|
||||
// state when we return to launcher.
|
||||
BubbleTextView btv = (BubbleTextView) v;
|
||||
btv.setStayPressed(true);
|
||||
setOnResumeCallback(btv);
|
||||
}
|
||||
mAppLaunchSuccess = true;
|
||||
getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
|
||||
} catch (ActivityNotFoundException|SecurityException e) {
|
||||
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
||||
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
|
||||
mAppLaunchSuccess = super.startActivitySafely(v, intent, item);
|
||||
if (mAppLaunchSuccess && v instanceof BubbleTextView) {
|
||||
// This is set to the view that launched the activity that navigated the user away
|
||||
// from launcher. Since there is no callback for when the activity has finished
|
||||
// launching, enable the press state and keep this reference to reset the press
|
||||
// state when we return to launcher.
|
||||
BubbleTextView btv = (BubbleTextView) v;
|
||||
btv.setStayPressed(true);
|
||||
setOnResumeCallback(btv);
|
||||
}
|
||||
return mAppLaunchSuccess;
|
||||
}
|
||||
|
@ -2515,26 +2443,6 @@ public class Launcher extends BaseActivity implements LauncherExterns, LauncherM
|
|||
return ((Launcher) ((ContextWrapper) context).getBaseContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeStarted(ActionMode mode) {
|
||||
super.onActionModeStarted(mode);
|
||||
mCurrentActionMode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionModeFinished(ActionMode mode) {
|
||||
super.onActionModeFinished(mode);
|
||||
mCurrentActionMode = null;
|
||||
}
|
||||
|
||||
public boolean finishAutoCancelActionMode() {
|
||||
if (mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag()) {
|
||||
mCurrentActionMode.finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for listening for onResume
|
||||
*/
|
||||
|
|
|
@ -3254,8 +3254,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
|||
&& v instanceof FolderIcon) {
|
||||
FolderBadgeInfo folderBadgeInfo = new FolderBadgeInfo();
|
||||
for (ShortcutInfo si : ((FolderInfo) info).contents) {
|
||||
folderBadgeInfo.addBadgeInfo(mLauncher.getPopupDataProvider()
|
||||
.getBadgeInfoForItem(si));
|
||||
folderBadgeInfo.addBadgeInfo(mLauncher.getBadgeInfoForItem(si));
|
||||
}
|
||||
((FolderIcon) v).setBadgeInfo(folderBadgeInfo);
|
||||
}
|
||||
|
|
|
@ -31,21 +31,17 @@ import android.util.AttributeSet;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DropTargetBar;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
|
@ -53,24 +49,20 @@ import com.android.launcher3.graphics.ViewScrim;
|
|||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.uioverrides.UiFactory;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A ViewGroup that coordinates dragging across its descendants
|
||||
*/
|
||||
public class DragLayer extends InsettableFrameLayout {
|
||||
public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
|
||||
public static final int ANIMATION_END_DISAPPEAR = 0;
|
||||
public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
|
||||
|
||||
private final int[] mTmpXY = new int[2];
|
||||
|
||||
@Thunk DragController mDragController;
|
||||
|
||||
private Launcher mLauncher;
|
||||
|
||||
// Variables relating to animation of views after drop
|
||||
private ValueAnimator mDropAnim = null;
|
||||
private final TimeInterpolator mCubicEaseOutInterpolator = Interpolators.DEACCEL_1_5;
|
||||
|
@ -79,9 +71,6 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
@Thunk View mAnchorView = null;
|
||||
|
||||
private boolean mHoverPointClosesFolder = false;
|
||||
private final Rect mHitRect = new Rect();
|
||||
|
||||
private TouchCompleteListener mTouchCompleteListener;
|
||||
|
||||
private int mTopViewIndex;
|
||||
private int mChildCountOnLastUpdate = -1;
|
||||
|
@ -89,8 +78,6 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
// Related to adjacent page hints
|
||||
private final ViewGroupFocusHelper mFocusIndicatorHelper;
|
||||
|
||||
protected TouchController[] mControllers;
|
||||
private TouchController mActiveController;
|
||||
/**
|
||||
* Used to create a new DragLayer from XML.
|
||||
*
|
||||
|
@ -107,10 +94,9 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
|
||||
}
|
||||
|
||||
public void setup(Launcher launcher, DragController dragController) {
|
||||
mLauncher = launcher;
|
||||
public void setup(DragController dragController) {
|
||||
mDragController = dragController;
|
||||
mControllers = UiFactory.createTouchControllers(mLauncher);
|
||||
mControllers = UiFactory.createTouchControllers(mActivity);
|
||||
}
|
||||
|
||||
public ViewGroupFocusHelper getFocusIndicatorHelper() {
|
||||
|
@ -123,7 +109,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
}
|
||||
|
||||
public boolean isEventOverHotseat(MotionEvent ev) {
|
||||
return isEventOverView(mLauncher.getHotseat(), ev);
|
||||
return isEventOverView(mActivity.getHotseat(), ev);
|
||||
}
|
||||
|
||||
private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
|
||||
|
@ -131,12 +117,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
}
|
||||
|
||||
private boolean isEventOverDropTargetBar(MotionEvent ev) {
|
||||
return isEventOverView(mLauncher.getDropTargetBar(), ev);
|
||||
}
|
||||
|
||||
public boolean isEventOverView(View view, MotionEvent ev) {
|
||||
getDescendantRectRelativeToSelf(view, mHitRect);
|
||||
return mHitRect.contains((int) ev.getX(), (int) ev.getY());
|
||||
return isEventOverView(mActivity.getDropTargetBar(), ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,66 +130,33 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
if (mTouchCompleteListener != null) {
|
||||
mTouchCompleteListener.onTouchComplete();
|
||||
}
|
||||
mTouchCompleteListener = null;
|
||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||
mLauncher.finishAutoCancelActionMode();
|
||||
}
|
||||
return findActiveController(ev);
|
||||
}
|
||||
|
||||
private boolean findActiveController(MotionEvent ev) {
|
||||
mActiveController = null;
|
||||
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null && topView.onControllerInterceptTouchEvent(ev)) {
|
||||
mActiveController = topView;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mLauncher.getStateManager().getState().disableInteraction) {
|
||||
protected boolean findActiveController(MotionEvent ev) {
|
||||
if (mActivity.getStateManager().getState().disableInteraction) {
|
||||
// You Shall Not Pass!!!
|
||||
mActiveController = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mDragController.onControllerInterceptTouchEvent(ev)) {
|
||||
mActiveController = mDragController;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (TouchController controller : mControllers) {
|
||||
if (controller.onControllerInterceptTouchEvent(ev)) {
|
||||
mActiveController = controller;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return super.findActiveController(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptHoverEvent(MotionEvent ev) {
|
||||
if (mLauncher == null || mLauncher.getWorkspace() == null) {
|
||||
if (mActivity == null || mActivity.getWorkspace() == null) {
|
||||
return false;
|
||||
}
|
||||
Folder currentFolder = Folder.getOpen(mLauncher);
|
||||
Folder currentFolder = Folder.getOpen(mActivity);
|
||||
if (currentFolder == null) {
|
||||
return false;
|
||||
} else {
|
||||
AccessibilityManager accessibilityManager = (AccessibilityManager)
|
||||
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
AccessibilityManager accessibilityManager = (AccessibilityManager)
|
||||
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
if (accessibilityManager.isTouchExplorationEnabled()) {
|
||||
final int action = ev.getAction();
|
||||
boolean isOverFolderOrSearchBar;
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
|
||||
(isInAccessibleDrag() && isEventOverDropTargetBar(ev));
|
||||
(isInAccessibleDrag() && isEventOverDropTargetBar(ev));
|
||||
if (!isOverFolderOrSearchBar) {
|
||||
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
|
||||
mHoverPointClosesFolder = true;
|
||||
|
@ -218,7 +166,7 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
break;
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
|
||||
(isInAccessibleDrag() && isEventOverDropTargetBar(ev));
|
||||
(isInAccessibleDrag() && isEventOverDropTargetBar(ev));
|
||||
if (!isOverFolderOrSearchBar && !mHoverPointClosesFolder) {
|
||||
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
|
||||
mHoverPointClosesFolder = true;
|
||||
|
@ -239,14 +187,22 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
this, AccessibilityEvent.TYPE_VIEW_FOCUSED, getContext().getString(stringId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHoverEvent(MotionEvent ev) {
|
||||
// If we've received this, we've already done the necessary handling
|
||||
// in onInterceptHoverEvent. Return true to consume the event.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean isInAccessibleDrag() {
|
||||
return mLauncher.getAccessibilityDelegate().isInAccessibleDrag();
|
||||
return mActivity.getAccessibilityDelegate().isInAccessibleDrag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
|
||||
// Shortcuts can appear above folder
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
View topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null) {
|
||||
if (child == topView) {
|
||||
return super.onRequestSendAccessibilityEvent(child, event);
|
||||
|
@ -263,117 +219,23 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
|
||||
@Override
|
||||
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
View topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null) {
|
||||
// Only add the top view as a child for accessibility when it is open
|
||||
childrenForAccessibility.add(topView);
|
||||
|
||||
if (isInAccessibleDrag()) {
|
||||
childrenForAccessibility.add(mLauncher.getDropTargetBar());
|
||||
childrenForAccessibility.add(mActivity.getDropTargetBar());
|
||||
}
|
||||
} else {
|
||||
super.addChildrenForAccessibility(childrenForAccessibility);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHoverEvent(MotionEvent ev) {
|
||||
// If we've received this, we've already done the necessary handling
|
||||
// in onInterceptHoverEvent. Return true to consume the event.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
if (mTouchCompleteListener != null) {
|
||||
mTouchCompleteListener.onTouchComplete();
|
||||
}
|
||||
mTouchCompleteListener = null;
|
||||
}
|
||||
|
||||
if (mActiveController != null) {
|
||||
return mActiveController.onControllerTouchEvent(ev);
|
||||
} else {
|
||||
// In case no child view handled the touch event, we may not get onIntercept anymore
|
||||
return findActiveController(ev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the rect of the descendant in this DragLayer's coordinates
|
||||
*
|
||||
* @param descendant The descendant whose coordinates we want to find.
|
||||
* @param r The rect into which to place the results.
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer.
|
||||
*/
|
||||
public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
|
||||
mTmpXY[0] = 0;
|
||||
mTmpXY[1] = 0;
|
||||
float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
|
||||
|
||||
r.set(mTmpXY[0], mTmpXY[1],
|
||||
(int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
|
||||
(int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
|
||||
return scale;
|
||||
}
|
||||
|
||||
public float getLocationInDragLayer(View child, int[] loc) {
|
||||
loc[0] = 0;
|
||||
loc[1] = 0;
|
||||
return getDescendantCoordRelativeToSelf(child, loc);
|
||||
}
|
||||
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
|
||||
return getDescendantCoordRelativeToSelf(descendant, coord, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
|
||||
* coordinates.
|
||||
*
|
||||
* @param descendant The descendant to which the passed coordinate is relative.
|
||||
* @param coord The coordinate that we want mapped.
|
||||
* @param includeRootScroll Whether or not to account for the scroll of the root descendant:
|
||||
* sometimes this is relevant as in a child's coordinates within the root descendant.
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer. Caution
|
||||
* this scale factor is assumed to be equal in X and Y, and so if at any point this
|
||||
* assumption fails, we will need to return a pair of scale factors.
|
||||
*/
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
|
||||
boolean includeRootScroll) {
|
||||
return Utilities.getDescendantCoordRelativeToAncestor(descendant, this,
|
||||
coord, includeRootScroll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
|
||||
*/
|
||||
public void mapCoordInSelfToDescendant(View descendant, int[] coord) {
|
||||
Utilities.mapCoordInSelfToDescendant(descendant, this, coord);
|
||||
}
|
||||
|
||||
public void getViewRectRelativeToSelf(View v, Rect r) {
|
||||
int[] loc = new int[2];
|
||||
getLocationInWindow(loc);
|
||||
int x = loc[0];
|
||||
int y = loc[1];
|
||||
|
||||
v.getLocationInWindow(loc);
|
||||
int vX = loc[0];
|
||||
int vY = loc[1];
|
||||
|
||||
int left = vX - x;
|
||||
int top = vY - y;
|
||||
r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchUnhandledMove(View focused, int direction) {
|
||||
// Consume the unhandled move if a container is open, to avoid switching pages underneath.
|
||||
boolean isContainerOpen = AbstractFloatingView.getTopOpenView(mLauncher) != null;
|
||||
return isContainerOpen || mDragController.dispatchUnhandledMove(focused, direction);
|
||||
return super.dispatchUnhandledMove(focused, direction)
|
||||
|| mDragController.dispatchUnhandledMove(focused, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -386,91 +248,6 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new LayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateDefaultLayoutParams() {
|
||||
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
// Override to allow type-checking of LayoutParams.
|
||||
@Override
|
||||
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return p instanceof LayoutParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return new LayoutParams(p);
|
||||
}
|
||||
|
||||
public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
|
||||
public int x, y;
|
||||
public boolean customPosition = false;
|
||||
|
||||
public LayoutParams(Context c, AttributeSet attrs) {
|
||||
super(c, attrs);
|
||||
}
|
||||
|
||||
public LayoutParams(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public LayoutParams(ViewGroup.LayoutParams lp) {
|
||||
super(lp);
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
|
||||
if (flp instanceof LayoutParams) {
|
||||
final LayoutParams lp = (LayoutParams) flp;
|
||||
if (lp.customPosition) {
|
||||
child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
|
||||
float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
|
||||
int duration) {
|
||||
|
@ -709,14 +486,14 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
updateChildIndices();
|
||||
UiFactory.onLauncherStateOrFocusChanged(mLauncher);
|
||||
UiFactory.onLauncherStateOrFocusChanged(mActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRemoved(View child) {
|
||||
super.onViewRemoved(child);
|
||||
updateChildIndices();
|
||||
UiFactory.onLauncherStateOrFocusChanged(mLauncher);
|
||||
UiFactory.onLauncherStateOrFocusChanged(mActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -768,32 +545,4 @@ public class DragLayer extends InsettableFrameLayout {
|
|||
mFocusIndicatorHelper.draw(canvas);
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null) {
|
||||
return topView.requestFocus(direction, previouslyFocusedRect);
|
||||
} else {
|
||||
return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
|
||||
View topView = AbstractFloatingView.getTopOpenView(mLauncher);
|
||||
if (topView != null) {
|
||||
topView.addFocusables(views, direction);
|
||||
} else {
|
||||
super.addFocusables(views, direction, focusableMode);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTouchCompleteListener(TouchCompleteListener listener) {
|
||||
mTouchCompleteListener = listener;
|
||||
}
|
||||
|
||||
public interface TouchCompleteListener {
|
||||
void onTouchComplete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -568,7 +568,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
@Override
|
||||
public void onAdd(ShortcutInfo item, int rank) {
|
||||
boolean wasBadged = mBadgeInfo.hasBadge();
|
||||
mBadgeInfo.addBadgeInfo(mLauncher.getPopupDataProvider().getBadgeInfoForItem(item));
|
||||
mBadgeInfo.addBadgeInfo(mLauncher.getBadgeInfoForItem(item));
|
||||
boolean isBadged = mBadgeInfo.hasBadge();
|
||||
updateBadgeScale(wasBadged, isBadged);
|
||||
invalidate();
|
||||
|
@ -578,7 +578,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
|||
@Override
|
||||
public void onRemove(ShortcutInfo item) {
|
||||
boolean wasBadged = mBadgeInfo.hasBadge();
|
||||
mBadgeInfo.subtractBadgeInfo(mLauncher.getPopupDataProvider().getBadgeInfoForItem(item));
|
||||
mBadgeInfo.subtractBadgeInfo(mLauncher.getBadgeInfoForItem(item));
|
||||
boolean isBadged = mBadgeInfo.hasBadge();
|
||||
updateBadgeScale(wasBadged, isBadged);
|
||||
invalidate();
|
||||
|
|
|
@ -745,7 +745,7 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
|
|||
|
||||
private void updateNotificationHeader() {
|
||||
ItemInfoWithIcon itemInfo = (ItemInfoWithIcon) mOriginalIcon.getTag();
|
||||
BadgeInfo badgeInfo = mLauncher.getPopupDataProvider().getBadgeInfoForItem(itemInfo);
|
||||
BadgeInfo badgeInfo = mLauncher.getBadgeInfoForItem(itemInfo);
|
||||
if (mNotificationItemView != null && badgeInfo != null) {
|
||||
mNotificationItemView.updateHeader(
|
||||
badgeInfo.getNotificationCount(), itemInfo.iconColor);
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.os.Bundle;
|
|||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
|
@ -27,7 +28,7 @@ import java.util.List;
|
|||
*
|
||||
* Example system shortcuts, defined as inner classes, include Widgets and AppInfo.
|
||||
*/
|
||||
public abstract class SystemShortcut extends ItemInfo {
|
||||
public abstract class SystemShortcut<T extends BaseDraggingActivity> extends ItemInfo {
|
||||
public final int iconResId;
|
||||
public final int labelResId;
|
||||
|
||||
|
@ -36,10 +37,9 @@ public abstract class SystemShortcut extends ItemInfo {
|
|||
this.labelResId = labelResId;
|
||||
}
|
||||
|
||||
public abstract View.OnClickListener getOnClickListener(final Launcher launcher,
|
||||
final ItemInfo itemInfo);
|
||||
public abstract View.OnClickListener getOnClickListener(T activity, ItemInfo itemInfo);
|
||||
|
||||
public static class Widgets extends SystemShortcut {
|
||||
public static class Widgets extends SystemShortcut<Launcher> {
|
||||
|
||||
public Widgets() {
|
||||
super(R.drawable.ic_widget, R.string.widget_button_text);
|
||||
|
@ -54,17 +54,14 @@ public abstract class SystemShortcut extends ItemInfo {
|
|||
if (widgets == null) {
|
||||
return null;
|
||||
}
|
||||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
AbstractFloatingView.closeAllOpenViews(launcher);
|
||||
WidgetsBottomSheet widgetsBottomSheet =
|
||||
(WidgetsBottomSheet) launcher.getLayoutInflater().inflate(
|
||||
R.layout.widgets_bottom_sheet, launcher.getDragLayer(), false);
|
||||
widgetsBottomSheet.populateAndShow(itemInfo);
|
||||
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
||||
ControlType.WIDGETS_BUTTON, view);
|
||||
}
|
||||
return (view) -> {
|
||||
AbstractFloatingView.closeAllOpenViews(launcher);
|
||||
WidgetsBottomSheet widgetsBottomSheet =
|
||||
(WidgetsBottomSheet) launcher.getLayoutInflater().inflate(
|
||||
R.layout.widgets_bottom_sheet, launcher.getDragLayer(), false);
|
||||
widgetsBottomSheet.populateAndShow(itemInfo);
|
||||
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
||||
ControlType.WIDGETS_BUTTON, view);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -75,18 +72,15 @@ public abstract class SystemShortcut extends ItemInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View.OnClickListener getOnClickListener(final Launcher launcher,
|
||||
final ItemInfo itemInfo) {
|
||||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Rect sourceBounds = launcher.getViewBounds(view);
|
||||
Bundle opts = launcher.getActivityLaunchOptionsAsBundle(view, false);
|
||||
new PackageManagerHelper(launcher).startDetailsActivityForInfo(
|
||||
itemInfo, sourceBounds, opts);
|
||||
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
||||
ControlType.APPINFO_TARGET, view);
|
||||
}
|
||||
public View.OnClickListener getOnClickListener(
|
||||
BaseDraggingActivity activity, ItemInfo itemInfo) {
|
||||
return (view) -> {
|
||||
Rect sourceBounds = activity.getViewBounds(view);
|
||||
Bundle opts = activity.getActivityLaunchOptionsAsBundle(view, false);
|
||||
new PackageManagerHelper(activity).startDetailsActivityForInfo(
|
||||
itemInfo, sourceBounds, opts);
|
||||
activity.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
||||
ControlType.APPINFO_TARGET, view);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -97,28 +91,29 @@ public abstract class SystemShortcut extends ItemInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View.OnClickListener getOnClickListener(final Launcher launcher,
|
||||
final ItemInfo itemInfo) {
|
||||
public View.OnClickListener getOnClickListener(
|
||||
BaseDraggingActivity activity, ItemInfo itemInfo) {
|
||||
boolean supportsWebUI = (itemInfo instanceof ShortcutInfo) &&
|
||||
((ShortcutInfo) itemInfo).hasStatusFlag(ShortcutInfo.FLAG_SUPPORTS_WEB_UI);
|
||||
boolean isInstantApp = false;
|
||||
if (itemInfo instanceof com.android.launcher3.AppInfo) {
|
||||
com.android.launcher3.AppInfo appInfo = (com.android.launcher3.AppInfo) itemInfo;
|
||||
isInstantApp = InstantAppResolver.newInstance(launcher).isInstantApp(appInfo);
|
||||
isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
|
||||
}
|
||||
boolean enabled = supportsWebUI || isInstantApp;
|
||||
if (!enabled) {
|
||||
return null;
|
||||
}
|
||||
return createOnClickListener(launcher, itemInfo);
|
||||
return createOnClickListener(activity, itemInfo);
|
||||
}
|
||||
|
||||
public View.OnClickListener createOnClickListener(Launcher launcher, ItemInfo itemInfo) {
|
||||
public View.OnClickListener createOnClickListener(
|
||||
BaseDraggingActivity activity, ItemInfo itemInfo) {
|
||||
return view -> {
|
||||
Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
|
||||
itemInfo.getTargetComponent().getPackageName());
|
||||
launcher.startActivitySafely(view, intent, itemInfo);
|
||||
AbstractFloatingView.closeAllOpenViews(launcher);
|
||||
activity.startActivitySafely(view, intent, itemInfo);
|
||||
AbstractFloatingView.closeAllOpenViews(activity);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import android.content.pm.PackageManager;
|
|||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
|
@ -47,8 +46,8 @@ public class InstantAppResolver {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isInstantApp(Launcher launcher, String packageName) {
|
||||
PackageManager packageManager = launcher.getPackageManager();
|
||||
public boolean isInstantApp(Context context, String packageName) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
try {
|
||||
return isInstantApp(packageManager.getPackageInfo(packageName, 0).applicationInfo);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* 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.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A viewgroup with utility methods for drag-n-drop and touch interception
|
||||
*/
|
||||
public abstract class BaseDragLayer<T extends BaseDraggingActivity> extends InsettableFrameLayout {
|
||||
|
||||
protected final int[] mTmpXY = new int[2];
|
||||
protected final Rect mHitRect = new Rect();
|
||||
|
||||
protected final T mActivity;
|
||||
|
||||
protected TouchController[] mControllers;
|
||||
protected TouchController mActiveController;
|
||||
private TouchCompleteListener mTouchCompleteListener;
|
||||
|
||||
public BaseDragLayer(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mActivity = (T) BaseActivity.fromContext(context);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEventOverView(View view, MotionEvent ev) {
|
||||
getDescendantRectRelativeToSelf(view, mHitRect);
|
||||
return mHitRect.contains((int) ev.getX(), (int) ev.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
if (mTouchCompleteListener != null) {
|
||||
mTouchCompleteListener.onTouchComplete();
|
||||
}
|
||||
mTouchCompleteListener = null;
|
||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||
mActivity.finishAutoCancelActionMode();
|
||||
}
|
||||
return findActiveController(ev);
|
||||
}
|
||||
|
||||
protected boolean findActiveController(MotionEvent ev) {
|
||||
mActiveController = null;
|
||||
|
||||
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null && topView.onControllerInterceptTouchEvent(ev)) {
|
||||
mActiveController = topView;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (TouchController controller : mControllers) {
|
||||
if (controller.onControllerInterceptTouchEvent(ev)) {
|
||||
mActiveController = controller;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
|
||||
// Shortcuts can appear above folder
|
||||
View topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null) {
|
||||
if (child == topView) {
|
||||
return super.onRequestSendAccessibilityEvent(child, event);
|
||||
}
|
||||
// Skip propagating onRequestSendAccessibilityEvent for all other children
|
||||
// which are not topView
|
||||
return false;
|
||||
}
|
||||
return super.onRequestSendAccessibilityEvent(child, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
|
||||
View topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null) {
|
||||
// Only add the top view as a child for accessibility when it is open
|
||||
childrenForAccessibility.add(topView);
|
||||
} else {
|
||||
super.addChildrenForAccessibility(childrenForAccessibility);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
if (mTouchCompleteListener != null) {
|
||||
mTouchCompleteListener.onTouchComplete();
|
||||
}
|
||||
mTouchCompleteListener = null;
|
||||
}
|
||||
|
||||
if (mActiveController != null) {
|
||||
return mActiveController.onControllerTouchEvent(ev);
|
||||
} else {
|
||||
// In case no child view handled the touch event, we may not get onIntercept anymore
|
||||
return findActiveController(ev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the rect of the descendant in this DragLayer's coordinates
|
||||
*
|
||||
* @param descendant The descendant whose coordinates we want to find.
|
||||
* @param r The rect into which to place the results.
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer.
|
||||
*/
|
||||
public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
|
||||
mTmpXY[0] = 0;
|
||||
mTmpXY[1] = 0;
|
||||
float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
|
||||
|
||||
r.set(mTmpXY[0], mTmpXY[1],
|
||||
(int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
|
||||
(int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
|
||||
return scale;
|
||||
}
|
||||
|
||||
public float getLocationInDragLayer(View child, int[] loc) {
|
||||
loc[0] = 0;
|
||||
loc[1] = 0;
|
||||
return getDescendantCoordRelativeToSelf(child, loc);
|
||||
}
|
||||
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
|
||||
return getDescendantCoordRelativeToSelf(descendant, coord, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
|
||||
* coordinates.
|
||||
*
|
||||
* @param descendant The descendant to which the passed coordinate is relative.
|
||||
* @param coord The coordinate that we want mapped.
|
||||
* @param includeRootScroll Whether or not to account for the scroll of the root descendant:
|
||||
* sometimes this is relevant as in a child's coordinates within the root descendant.
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer. Caution
|
||||
* this scale factor is assumed to be equal in X and Y, and so if at any point this
|
||||
* assumption fails, we will need to return a pair of scale factors.
|
||||
*/
|
||||
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
|
||||
boolean includeRootScroll) {
|
||||
return Utilities.getDescendantCoordRelativeToAncestor(descendant, this,
|
||||
coord, includeRootScroll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
|
||||
*/
|
||||
public void mapCoordInSelfToDescendant(View descendant, int[] coord) {
|
||||
Utilities.mapCoordInSelfToDescendant(descendant, this, coord);
|
||||
}
|
||||
|
||||
public void getViewRectRelativeToSelf(View v, Rect r) {
|
||||
int[] loc = new int[2];
|
||||
getLocationInWindow(loc);
|
||||
int x = loc[0];
|
||||
int y = loc[1];
|
||||
|
||||
v.getLocationInWindow(loc);
|
||||
int vX = loc[0];
|
||||
int vY = loc[1];
|
||||
|
||||
int left = vX - x;
|
||||
int top = vY - y;
|
||||
r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchUnhandledMove(View focused, int direction) {
|
||||
// Consume the unhandled move if a container is open, to avoid switching pages underneath.
|
||||
return AbstractFloatingView.getTopOpenView(mActivity) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
|
||||
View topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null) {
|
||||
return topView.requestFocus(direction, previouslyFocusedRect);
|
||||
} else {
|
||||
return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
|
||||
View topView = AbstractFloatingView.getTopOpenView(mActivity);
|
||||
if (topView != null) {
|
||||
topView.addFocusables(views, direction);
|
||||
} else {
|
||||
super.addFocusables(views, direction, focusableMode);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTouchCompleteListener(TouchCompleteListener listener) {
|
||||
mTouchCompleteListener = listener;
|
||||
}
|
||||
|
||||
public interface TouchCompleteListener {
|
||||
void onTouchComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new LayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateDefaultLayoutParams() {
|
||||
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
// Override to allow type-checking of LayoutParams.
|
||||
@Override
|
||||
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return p instanceof LayoutParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return new LayoutParams(p);
|
||||
}
|
||||
|
||||
public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
|
||||
public int x, y;
|
||||
public boolean customPosition = false;
|
||||
|
||||
public LayoutParams(Context c, AttributeSet attrs) {
|
||||
super(c, attrs);
|
||||
}
|
||||
|
||||
public LayoutParams(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public LayoutParams(ViewGroup.LayoutParams lp) {
|
||||
super(lp);
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
|
||||
if (flp instanceof LayoutParams) {
|
||||
final LayoutParams lp = (LayoutParams) flp;
|
||||
if (lp.customPosition) {
|
||||
child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,7 +47,7 @@ import com.android.launcher3.SimpleOnStylusPressListener;
|
|||
import com.android.launcher3.StylusEventHelper;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.dragndrop.DragLayer.TouchCompleteListener;
|
||||
import com.android.launcher3.views.BaseDragLayer.TouchCompleteListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ import com.android.launcher3.util.TouchController;
|
|||
public class UiFactory {
|
||||
|
||||
public static TouchController[] createTouchControllers(Launcher launcher) {
|
||||
return new TouchController[] {new AllAppsSwipeController(launcher)};
|
||||
return new TouchController[] {
|
||||
launcher.getDragController(), new AllAppsSwipeController(launcher)};
|
||||
}
|
||||
|
||||
public static AccessibilityDelegate newPageIndicatorAccessibilityDelegate() {
|
||||
|
|
Loading…
Reference in New Issue