Snap for 4690345 from 96992e9e05 to qt-release
Change-Id: Ia05cc073421d590b48a55860f89eb492ec0597bc
@@ -39,7 +39,7 @@
|
||||
public int getY();
|
||||
}
|
||||
|
||||
-keep class com.android.launcher3.dragndrop.DragLayer$LayoutParams {
|
||||
-keep class com.android.launcher3.views.BaseDragLayer$LayoutParams {
|
||||
public void setWidth(int);
|
||||
public int getWidth();
|
||||
public void setHeight(int);
|
||||
|
||||
@@ -47,7 +47,21 @@
|
||||
<!-- STOPSHIP: Change exported to false once all the integration is complete.
|
||||
It is set to true so that the activity can be started from command line -->
|
||||
<activity android:name="com.android.quickstep.RecentsActivity"
|
||||
android:exported="true" />
|
||||
android:exported="true"
|
||||
android:excludeFromRecents="true" />
|
||||
|
||||
<!-- Content provider to settings search -->
|
||||
<provider
|
||||
android:name="com.android.quickstep.LauncherSearchIndexablesProvider"
|
||||
android:authorities="com.android.launcher3"
|
||||
android:grantUriPermissions="true"
|
||||
android:multiprocess="true"
|
||||
android:permission="android.permission.READ_SEARCH_INDEXABLES"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
|
||||
</intent-filter>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
|
Before Width: | Height: | Size: 563 B |
|
Before Width: | Height: | Size: 527 B |
|
Before Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 433 B |
|
Before Width: | Height: | Size: 648 B |
|
Before Width: | Height: | Size: 631 B |
|
Before Width: | Height: | Size: 798 B |
|
Before Width: | Height: | Size: 787 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 576 B |
@@ -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>
|
||||
@@ -21,7 +21,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:alpha="0.0"
|
||||
android:visibility="invisible" >
|
||||
android:visibility="invisible"
|
||||
android:focusableInTouchMode="true" >
|
||||
|
||||
</com.android.quickstep.views.LauncherRecentsView>
|
||||
@@ -22,7 +22,6 @@
|
||||
<dimen name="task_corner_radius">2dp</dimen>
|
||||
<dimen name="task_fade_length">20dp</dimen>
|
||||
<dimen name="recents_page_spacing">10dp</dimen>
|
||||
<dimen name="recents_page_fade_length">100dp</dimen>
|
||||
|
||||
<!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
|
||||
loading full resolution screenshots. -->
|
||||
@@ -34,7 +33,7 @@
|
||||
<!-- Launcher app transition -->
|
||||
<dimen name="content_trans_y">25dp</dimen>
|
||||
<dimen name="workspace_trans_y">80dp</dimen>
|
||||
<dimen name="recents_adjacent_trans_x">120dp</dimen>
|
||||
<dimen name="recents_adjacent_trans_x">140dp</dimen>
|
||||
<dimen name="recents_adjacent_trans_y">80dp</dimen>
|
||||
<fraction name="recents_adjacent_scale">150%</fraction>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 Google Inc.
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SwitchPreference
|
||||
android:key="pref_add_icon_to_home"
|
||||
android:title="@string/auto_add_shortcuts_label"
|
||||
android:summary="@string/auto_add_shortcuts_description"
|
||||
android:defaultValue="true"
|
||||
/>
|
||||
|
||||
<ListPreference
|
||||
android:key="pref_override_icon_shape"
|
||||
android:title="@string/icon_shape_override_label"
|
||||
android:summary="@string/icon_shape_override_label_location"
|
||||
android:entries="@array/icon_shape_override_paths_names"
|
||||
android:entryValues="@array/icon_shape_override_paths_values"
|
||||
android:defaultValue=""
|
||||
android:persistent="false" />
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -15,27 +15,92 @@
|
||||
*/
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities
|
||||
.postAtFrontOfQueueAsynchronously;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.BinderThread;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public abstract class LauncherAnimationRunner extends AnimatorListenerAdapter
|
||||
implements RemoteAnimationRunnerCompat {
|
||||
|
||||
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
|
||||
private static final int REFRESH_RATE_MS = 16;
|
||||
|
||||
AnimatorSet mAnimator;
|
||||
private Launcher mLauncher;
|
||||
private final Handler mHandler;
|
||||
|
||||
LauncherAnimationRunner(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
private Runnable mSysFinishRunnable;
|
||||
|
||||
private AnimatorSet mAnimator;
|
||||
|
||||
public LauncherAnimationRunner(Handler handler) {
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats, Runnable runnable) {
|
||||
postAtFrontOfQueueAsynchronously(mHandler, () -> {
|
||||
// Finish any previous animation
|
||||
finishSystemAnimation();
|
||||
|
||||
mSysFinishRunnable = runnable;
|
||||
mAnimator = getAnimator(targetCompats);
|
||||
if (mAnimator == null) {
|
||||
finishSystemAnimation();
|
||||
return;
|
||||
}
|
||||
mAnimator.addListener(this);
|
||||
mAnimator.start();
|
||||
// Because t=0 has the app icon in its original spot, we can skip the
|
||||
// first frame and have the same movement one frame earlier.
|
||||
mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@UiThread
|
||||
public abstract AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats);
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (animation == mAnimator) {
|
||||
mAnimator = null;
|
||||
finishSystemAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system
|
||||
*/
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
postAtFrontOfQueueAsynchronously(mLauncher.getWindow().getDecorView().getHandler(), () -> {
|
||||
postAtFrontOfQueueAsynchronously(mHandler, () -> {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
mAnimator.removeListener(this);
|
||||
mAnimator.end();
|
||||
mAnimator = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void finishSystemAnimation() {
|
||||
if (mSysFinishRunnable != null) {
|
||||
mSysFinishRunnable.run();
|
||||
mSysFinishRunnable = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
|
||||
|
||||
@@ -41,6 +40,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
@@ -80,7 +80,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
implements OnDeviceProfileChangeListener {
|
||||
|
||||
private static final String TAG = "LauncherTransition";
|
||||
private static final int REFRESH_RATE_MS = 16;
|
||||
private static final int STATUS_BAR_TRANSITION_DURATION = 120;
|
||||
|
||||
private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION =
|
||||
@@ -99,7 +98,9 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
|
||||
private final DragLayer mDragLayer;
|
||||
private final Launcher mLauncher;
|
||||
private DeviceProfile mDeviceProfile;
|
||||
|
||||
private final Handler mHandler;
|
||||
private final boolean mIsRtl;
|
||||
|
||||
private final float mContentTransY;
|
||||
private final float mWorkspaceTransY;
|
||||
@@ -107,17 +108,23 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
private final float mRecentsTransY;
|
||||
private final float mRecentsScale;
|
||||
|
||||
private DeviceProfile mDeviceProfile;
|
||||
private View mFloatingView;
|
||||
private boolean mIsRtl;
|
||||
|
||||
private LauncherTransitionAnimator mCurrentAnimator;
|
||||
private final AnimatorListenerAdapter mReapplyStateListener = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mLauncher.getStateManager().reapplyState();
|
||||
}
|
||||
};
|
||||
|
||||
public LauncherAppTransitionManagerImpl(Context context) {
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mDragLayer = mLauncher.getDragLayer();
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mIsRtl = Utilities.isRtl(mLauncher.getResources());
|
||||
mDeviceProfile = mLauncher.getDeviceProfile();
|
||||
|
||||
mIsRtl = Utilities.isRtl(mLauncher.getResources());
|
||||
|
||||
Resources res = mLauncher.getResources();
|
||||
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
|
||||
@@ -135,26 +142,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
mDeviceProfile = dp;
|
||||
}
|
||||
|
||||
private void setCurrentAnimator(LauncherTransitionAnimator animator) {
|
||||
if (isAnimating()) {
|
||||
mCurrentAnimator.cancel();
|
||||
}
|
||||
mCurrentAnimator = animator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishLauncherAnimation() {
|
||||
if (isAnimating()) {
|
||||
mCurrentAnimator.finishLauncherAnimation();
|
||||
}
|
||||
mCurrentAnimator = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimating() {
|
||||
return mCurrentAnimator != null && mCurrentAnimator.isRunning();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ActivityOptions with remote animations that controls how the window of the opening
|
||||
* targets are displayed.
|
||||
@@ -162,58 +149,26 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
@Override
|
||||
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
|
||||
if (hasControlRemoteAppTransitionPermission()) {
|
||||
TaskView taskView = findTaskViewToLaunch(launcher, v);
|
||||
try {
|
||||
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mLauncher) {
|
||||
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler) {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
|
||||
Runnable finishedCallback) {
|
||||
// Post at front of queue ignoring sync barriers to make sure it gets
|
||||
// processed before the next frame.
|
||||
postAtFrontOfQueueAsynchronously(v.getHandler(), () -> {
|
||||
final boolean removeTrackingView;
|
||||
LauncherTransitionAnimator animator = composeRecentsLaunchAnimator(
|
||||
taskView == null ? v : taskView, targets);
|
||||
if (animator != null) {
|
||||
// We are animating the task view directly, do not remove it after
|
||||
removeTrackingView = false;
|
||||
} else {
|
||||
animator = composeAppLaunchAnimator(v, targets);
|
||||
// A new floating view is created for the animation, remove it after
|
||||
removeTrackingView = true;
|
||||
}
|
||||
|
||||
setCurrentAnimator(animator);
|
||||
mAnimator = animator.getAnimatorSet();
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Reset launcher to normal state
|
||||
v.setVisibility(View.VISIBLE);
|
||||
if (removeTrackingView) {
|
||||
((ViewGroup) mDragLayer.getParent()).removeView(
|
||||
mFloatingView);
|
||||
}
|
||||
|
||||
mDragLayer.setAlpha(1f);
|
||||
mDragLayer.setTranslationY(0f);
|
||||
|
||||
View appsView = mLauncher.getAppsView();
|
||||
appsView.setAlpha(1f);
|
||||
appsView.setTranslationY(0f);
|
||||
|
||||
finishedCallback.run();
|
||||
}
|
||||
});
|
||||
mAnimator.start();
|
||||
// Because t=0 has the app icon in its original spot, we can skip the
|
||||
// first frame and have the same movement one frame earlier.
|
||||
mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
|
||||
});
|
||||
public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
|
||||
Animator[] anims = composeRecentsLaunchAnimator(v, targetCompats);
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
if (anims != null) {
|
||||
anim.playTogether(anims);
|
||||
} else {
|
||||
anim.play(getLauncherAnimators(v, targetCompats));
|
||||
anim.play(getWindowAnimators(v, targetCompats));
|
||||
}
|
||||
mLauncher.getStateManager().setCurrentAnimation(anim);
|
||||
return anim;
|
||||
}
|
||||
};
|
||||
|
||||
int duration = taskView != null ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION;
|
||||
int duration = findTaskViewToLaunch(launcher, v, null) != null
|
||||
? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION;
|
||||
int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION;
|
||||
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
|
||||
runner, duration, statusBarTransitionDelay));
|
||||
@@ -232,18 +187,19 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
* Otherwise, we will assume we are using a normal app transition, but it's possible that the
|
||||
* opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView.
|
||||
*/
|
||||
private TaskView findTaskViewToLaunch(Launcher launcher, View v) {
|
||||
private TaskView findTaskViewToLaunch(
|
||||
BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) {
|
||||
if (v instanceof TaskView) {
|
||||
return (TaskView) v;
|
||||
}
|
||||
if (!launcher.isInState(LauncherState.OVERVIEW)) {
|
||||
return null;
|
||||
}
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
|
||||
// It's possible that the launched view can still be resolved to a visible task view, check
|
||||
// the task id of the opening task and see if we can find a match.
|
||||
if (v.getTag() instanceof ItemInfo) {
|
||||
ItemInfo itemInfo = (ItemInfo) v.getTag();
|
||||
ComponentName componentName = itemInfo.getTargetComponent();
|
||||
if (componentName != null) {
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
for (int i = 0; i < recentsView.getChildCount(); i++) {
|
||||
TaskView taskView = (TaskView) recentsView.getPageAt(i);
|
||||
if (recentsView.isTaskViewVisible(taskView)) {
|
||||
@@ -255,32 +211,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes the animations for a launch from the recents list if possible.
|
||||
*/
|
||||
private LauncherTransitionAnimator composeRecentsLaunchAnimator(View v,
|
||||
RemoteAnimationTargetCompat[] targets) {
|
||||
RecentsView recentsView = mLauncher.getOverviewPanel();
|
||||
boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING);
|
||||
MutableBoolean skipLauncherChanges = new MutableBoolean(!launcherClosing);
|
||||
if (v instanceof TaskView) {
|
||||
// We already found a task view to launch, so use that for the animation.
|
||||
TaskView taskView = (TaskView) v;
|
||||
return new LauncherTransitionAnimator(getRecentsLauncherAnimator(recentsView, taskView),
|
||||
getRecentsWindowAnimator(taskView, skipLauncherChanges, targets));
|
||||
}
|
||||
|
||||
// It's possible that the launched view can still be resolved to a visible task view, check
|
||||
// the task id of the opening task and see if we can find a match.
|
||||
|
||||
// Ensure recents is actually visible
|
||||
if (!mLauncher.getStateManager().getState().overviewUi) {
|
||||
if (targets == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Resolve the opening task id
|
||||
int openingTaskId = -1;
|
||||
for (RemoteAnimationTargetCompat target : targets) {
|
||||
@@ -301,19 +235,35 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
if (taskView == null || !recentsView.isTaskViewVisible(taskView)) {
|
||||
return null;
|
||||
}
|
||||
return taskView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes the animations for a launch from the recents list if possible.
|
||||
*/
|
||||
private Animator[] composeRecentsLaunchAnimator(View v,
|
||||
RemoteAnimationTargetCompat[] targets) {
|
||||
// Ensure recents is actually visible
|
||||
if (!mLauncher.getStateManager().getState().overviewUi) {
|
||||
return null;
|
||||
}
|
||||
|
||||
RecentsView recentsView = mLauncher.getOverviewPanel();
|
||||
boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING);
|
||||
boolean skipLauncherChanges = !launcherClosing;
|
||||
|
||||
TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
|
||||
if (taskView == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Found a visible recents task that matches the opening app, lets launch the app from there
|
||||
Animator launcherAnim;
|
||||
AnimatorListenerAdapter windowAnimEndListener;
|
||||
final AnimatorListenerAdapter windowAnimEndListener;
|
||||
if (launcherClosing) {
|
||||
launcherAnim = getRecentsLauncherAnimator(recentsView, taskView);
|
||||
windowAnimEndListener = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Make sure recents gets fixed up by resetting task alphas and scales, etc.
|
||||
mLauncher.getStateManager().reapplyState();
|
||||
}
|
||||
};
|
||||
// Make sure recents gets fixed up by resetting task alphas and scales, etc.
|
||||
windowAnimEndListener = mReapplyStateListener;
|
||||
} else {
|
||||
AnimatorPlaybackController controller =
|
||||
mLauncher.getStateManager()
|
||||
@@ -330,7 +280,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
|
||||
Animator windowAnim = getRecentsWindowAnimator(taskView, skipLauncherChanges, targets);
|
||||
windowAnim.addListener(windowAnimEndListener);
|
||||
return new LauncherTransitionAnimator(launcherAnim, windowAnim, skipLauncherChanges);
|
||||
return new Animator[] {launcherAnim, windowAnim};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,26 +322,24 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
} else {
|
||||
// We are launching an adjacent task, so parallax the center and other adjacent task.
|
||||
TaskView centerTask = (TaskView) recentsView.getPageAt(centerTaskIndex);
|
||||
float translationX = Math.abs(v.getTranslationX());
|
||||
ObjectAnimator centerTaskParallaxToRight =
|
||||
float translationX = mRecentsTransX / 2;
|
||||
ObjectAnimator centerTaskParallaxOffscreen =
|
||||
LauncherAnimUtils.ofPropertyValuesHolder(centerTask,
|
||||
new PropertyListBuilder()
|
||||
.scale(v.getScaleX())
|
||||
.translationX(isRtl ? -translationX : translationX)
|
||||
.build());
|
||||
launcherAnimator.play(centerTaskParallaxToRight);
|
||||
launcherAnimator.play(centerTaskParallaxOffscreen);
|
||||
int otherAdjacentTaskIndex = centerTaskIndex + (centerTaskIndex - launchedTaskIndex);
|
||||
if (otherAdjacentTaskIndex >= 0
|
||||
&& otherAdjacentTaskIndex < recentsView.getPageCount()) {
|
||||
TaskView otherAdjacentTask = (TaskView) recentsView.getPageAt(
|
||||
otherAdjacentTaskIndex);
|
||||
ObjectAnimator otherAdjacentTaskParallaxToRight =
|
||||
ObjectAnimator otherAdjacentTaskParallaxOffscreen =
|
||||
LauncherAnimUtils.ofPropertyValuesHolder(otherAdjacentTask,
|
||||
new PropertyListBuilder()
|
||||
.translationX(otherAdjacentTask.getTranslationX()
|
||||
+ (isRtl ? -translationX : translationX))
|
||||
.translationX(isRtl ? -translationX : translationX)
|
||||
.build());
|
||||
launcherAnimator.play(otherAdjacentTaskParallaxToRight);
|
||||
launcherAnimator.play(otherAdjacentTaskParallaxOffscreen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +368,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
* @return Animator that controls the window of the opening targets for the recents launch
|
||||
* animation.
|
||||
*/
|
||||
private ValueAnimator getRecentsWindowAnimator(TaskView v, MutableBoolean skipLauncherChanges,
|
||||
private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges,
|
||||
RemoteAnimationTargetCompat[] targets) {
|
||||
Rect taskViewBounds = new Rect();
|
||||
mDragLayer.getDescendantRectRelativeToSelf(v, taskViewBounds);
|
||||
@@ -456,7 +404,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
final float percent = animation.getAnimatedFraction();
|
||||
TaskWindowBounds tw = recentsInterpolator.interpolate(percent);
|
||||
|
||||
if (!skipLauncherChanges.value) {
|
||||
if (!skipLauncherChanges) {
|
||||
v.setScaleX(tw.taskScale);
|
||||
v.setScaleY(tw.taskScale);
|
||||
v.setTranslationX(tw.taskX);
|
||||
@@ -471,9 +419,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
crop.set(tw.winCrop);
|
||||
|
||||
// Fade in the app window.
|
||||
float alphaDelay = 0;
|
||||
float alphaDuration = 75;
|
||||
float alpha = getValue(0f, 1f, alphaDelay, alphaDuration,
|
||||
float alpha = getValue(0f, 1f, 0, alphaDuration,
|
||||
appAnimator.getDuration() * percent, Interpolators.LINEAR);
|
||||
|
||||
TransactionCompat t = new TransactionCompat();
|
||||
@@ -487,7 +434,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
t.setMatrix(target.leash, matrix);
|
||||
t.setWindowCrop(target.leash, crop);
|
||||
|
||||
if (!skipLauncherChanges.value) {
|
||||
if (!skipLauncherChanges) {
|
||||
t.deferTransactionUntil(target.leash, surface, frameNumber);
|
||||
}
|
||||
}
|
||||
@@ -504,15 +451,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
return appAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes the animations for a launch from an app icon.
|
||||
*/
|
||||
private LauncherTransitionAnimator composeAppLaunchAnimator(View v,
|
||||
RemoteAnimationTargetCompat[] targets) {
|
||||
return new LauncherTransitionAnimator(getLauncherAnimators(v, targets),
|
||||
getWindowAnimators(v, targets));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Animators that control the movements of the Launcher and icon of the opening target.
|
||||
*/
|
||||
@@ -543,7 +481,9 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
|
||||
if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) {
|
||||
// All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
|
||||
View appsView = mLauncher.getAppsView();
|
||||
final View appsView = mLauncher.getAppsView();
|
||||
final float startAlpha = appsView.getAlpha();
|
||||
final float startY = appsView.getTranslationY();
|
||||
appsView.setAlpha(alphas[0]);
|
||||
appsView.setTranslationY(trans[0]);
|
||||
|
||||
@@ -556,6 +496,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
|
||||
launcherAnimator.play(alpha);
|
||||
launcherAnimator.play(transY);
|
||||
|
||||
launcherAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
appsView.setAlpha(startAlpha);
|
||||
appsView.setTranslationY(startY);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mDragLayer.setAlpha(alphas[0]);
|
||||
mDragLayer.setTranslationY(trans[0]);
|
||||
@@ -570,6 +518,13 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
|
||||
launcherAnimator.play(dragLayerAlpha);
|
||||
launcherAnimator.play(dragLayerTransY);
|
||||
launcherAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mDragLayer.setAlpha(1);
|
||||
mDragLayer.setTranslationY(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
return launcherAnimator;
|
||||
}
|
||||
@@ -588,22 +543,19 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
|
||||
// Position the floating view exactly on top of the original
|
||||
Rect rect = new Rect();
|
||||
final boolean isDeepShortcutTextView = v instanceof DeepShortcutTextView
|
||||
&& v.getParent() != null && v.getParent() instanceof DeepShortcutView;
|
||||
if (isDeepShortcutTextView) {
|
||||
// Deep shortcut views have their icon drawn in a sibling view.
|
||||
final boolean fromDeepShortcutView = v.getParent() instanceof DeepShortcutView;
|
||||
if (fromDeepShortcutView) {
|
||||
// Deep shortcut views have their icon drawn in a separate view.
|
||||
DeepShortcutView view = (DeepShortcutView) v.getParent();
|
||||
mDragLayer.getDescendantRectRelativeToSelf(view.getIconView(), rect);
|
||||
} else {
|
||||
mDragLayer.getDescendantRectRelativeToSelf(v, rect);
|
||||
}
|
||||
final int viewLocationStart = mIsRtl
|
||||
? mDeviceProfile.widthPx - rect.right
|
||||
: rect.left;
|
||||
final int viewLocationTop = rect.top;
|
||||
int viewLocationLeft = rect.left;
|
||||
int viewLocationTop = rect.top;
|
||||
|
||||
float startScale = 1f;
|
||||
if (isBubbleTextView && !isDeepShortcutTextView) {
|
||||
if (isBubbleTextView && !fromDeepShortcutView) {
|
||||
BubbleTextView btv = (BubbleTextView) v;
|
||||
btv.getIconBounds(rect);
|
||||
Drawable dr = btv.getIcon();
|
||||
@@ -613,12 +565,24 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
} else {
|
||||
rect.set(0, 0, rect.width(), rect.height());
|
||||
}
|
||||
viewLocationLeft += rect.left;
|
||||
viewLocationTop += rect.top;
|
||||
int viewLocationStart = mIsRtl
|
||||
? mDeviceProfile.widthPx - rect.right
|
||||
: viewLocationLeft;
|
||||
LayoutParams lp = new LayoutParams(rect.width(), rect.height());
|
||||
lp.ignoreInsets = true;
|
||||
lp.setMarginStart(viewLocationStart + rect.left);
|
||||
lp.topMargin = viewLocationTop + rect.top;
|
||||
lp.setMarginStart(viewLocationStart);
|
||||
lp.topMargin = viewLocationTop;
|
||||
mFloatingView.setLayoutParams(lp);
|
||||
|
||||
// Set the properties here already to make sure they'are available when running the first
|
||||
// animation frame.
|
||||
mFloatingView.setLeft(viewLocationLeft);
|
||||
mFloatingView.setTop(viewLocationTop);
|
||||
mFloatingView.setRight(viewLocationLeft + rect.width());
|
||||
mFloatingView.setBottom(viewLocationTop + rect.height());
|
||||
|
||||
// Swap the two views in place.
|
||||
((ViewGroup) mDragLayer.getParent()).addView(mFloatingView);
|
||||
v.setVisibility(View.INVISIBLE);
|
||||
@@ -663,6 +627,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
alpha.setInterpolator(Interpolators.LINEAR);
|
||||
appIconAnimatorSet.play(alpha);
|
||||
|
||||
appIconAnimatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Reset launcher to normal state
|
||||
v.setVisibility(View.VISIBLE);
|
||||
((ViewGroup) mDragLayer.getParent()).removeView(mFloatingView);
|
||||
}
|
||||
});
|
||||
return appIconAnimatorSet;
|
||||
}
|
||||
|
||||
@@ -671,10 +643,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
*/
|
||||
private ValueAnimator getWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
|
||||
Rect bounds = new Rect();
|
||||
boolean isDeepShortcutTextView = v instanceof DeepShortcutTextView
|
||||
&& v.getParent() != null && v.getParent() instanceof DeepShortcutView;
|
||||
if (isDeepShortcutTextView) {
|
||||
// Deep shortcut views have their icon drawn in a sibling view.
|
||||
if (v.getParent() instanceof DeepShortcutView) {
|
||||
// Deep shortcut views have their icon drawn in a separate view.
|
||||
DeepShortcutView view = (DeepShortcutView) v.getParent();
|
||||
mDragLayer.getDescendantRectRelativeToSelf(view.getIconView(), bounds);
|
||||
} else if (v instanceof BubbleTextView) {
|
||||
@@ -728,9 +698,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
matrix.postTranslate(transX0, transY0);
|
||||
|
||||
// Fade in the app window.
|
||||
float alphaDelay = 0;
|
||||
float alphaDuration = 60;
|
||||
float alpha = getValue(0f, 1f, alphaDelay, alphaDuration,
|
||||
float alpha = getValue(0f, 1f, 0, alphaDuration,
|
||||
appAnimator.getDuration() * percent, Interpolators.LINEAR);
|
||||
|
||||
// Animate the window crop so that it starts off as a square, and then reveals
|
||||
@@ -775,6 +744,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
try {
|
||||
RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
|
||||
definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
|
||||
WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
|
||||
new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(),
|
||||
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
|
||||
|
||||
@@ -802,40 +772,25 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
* ie. pressing home, swiping up from nav bar.
|
||||
*/
|
||||
private RemoteAnimationRunnerCompat getWallpaperOpenRunner() {
|
||||
return new LauncherAnimationRunner(mLauncher) {
|
||||
return new LauncherAnimationRunner(mHandler) {
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
|
||||
Runnable finishedCallback) {
|
||||
Handler handler = mLauncher.getWindow().getDecorView().getHandler();
|
||||
postAtFrontOfQueueAsynchronously(handler, () -> {
|
||||
if ((Utilities.getPrefs(mLauncher)
|
||||
.getBoolean("pref_use_screenshot_for_swipe_up", false)
|
||||
&& mLauncher.getStateManager().getState().overviewUi)
|
||||
|| !launcherIsATargetWithMode(targets, MODE_OPENING)) {
|
||||
// We use a separate transition for Overview mode. And we can skip the
|
||||
// animation in cases where Launcher is not in the set of opening targets.
|
||||
// This can happen when Launcher is already visible. ie. Closing a dialog.
|
||||
setCurrentAnimator(null);
|
||||
finishedCallback.run();
|
||||
return;
|
||||
}
|
||||
public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
|
||||
if (mLauncher.getStateManager().getState().overviewUi) {
|
||||
// We use a separate transition for Overview mode.
|
||||
return null;
|
||||
}
|
||||
|
||||
LauncherTransitionAnimator animator = new LauncherTransitionAnimator(
|
||||
getLauncherResumeAnimation(), getClosingWindowAnimators(targets));
|
||||
setCurrentAnimator(animator);
|
||||
mAnimator = animator.getAnimatorSet();
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
finishedCallback.run();
|
||||
}
|
||||
});
|
||||
mAnimator.start();
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(getClosingWindowAnimators(targetCompats));
|
||||
|
||||
// Because t=0 has the app icon in its original spot, we can skip the
|
||||
// first frame and have the same movement one frame earlier.
|
||||
mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
|
||||
});
|
||||
if (launcherIsATargetWithMode(targetCompats, MODE_OPENING)) {
|
||||
AnimatorSet contentAnimation = getLauncherResumeAnimation();
|
||||
anim.play(contentAnimation);
|
||||
|
||||
// Only register the content animation for cancellation when state changes
|
||||
mLauncher.getStateManager().setCurrentAnimation(contentAnimation);
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -906,12 +861,17 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
return contentAnimator;
|
||||
} else {
|
||||
AnimatorSet workspaceAnimator = new AnimatorSet();
|
||||
|
||||
mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY);
|
||||
mLauncher.getWorkspace().setAlpha(0f);
|
||||
workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(),
|
||||
View.TRANSLATION_Y, mWorkspaceTransY, 0));
|
||||
workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(), View.ALPHA,
|
||||
0, 1f));
|
||||
|
||||
View currentPage = ((CellLayout) mLauncher.getWorkspace()
|
||||
.getChildAt(mLauncher.getWorkspace().getCurrentPage()))
|
||||
.getShortcutsAndWidgets();
|
||||
currentPage.setAlpha(0f);
|
||||
workspaceAnimator.play(ObjectAnimator.ofFloat(currentPage, View.ALPHA, 0, 1f));
|
||||
|
||||
workspaceAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
|
||||
workspaceAnimator.setDuration(333);
|
||||
workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
@@ -939,6 +899,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
|
||||
AnimatorSet resumeLauncherAnimation = new AnimatorSet();
|
||||
resumeLauncherAnimation.play(workspaceAnimator);
|
||||
resumeLauncherAnimation.playSequentially(allAppsSlideIn, allAppsOvershoot);
|
||||
|
||||
resumeLauncherAnimation.addListener(mReapplyStateListener);
|
||||
return resumeLauncherAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
|
||||
import com.android.launcher3.states.InternalStateHandler;
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class LauncherInitListener extends InternalStateHandler implements ActivityInitListener {
|
||||
|
||||
private final BiPredicate<Launcher, Boolean> mOnInitListener;
|
||||
|
||||
public LauncherInitListener(BiPredicate<Launcher, Boolean> onInitListener) {
|
||||
mOnInitListener = onInitListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean init(Launcher launcher, boolean alreadyOnHome) {
|
||||
// For the duration of the gesture, lock the screen orientation to ensure that we do not
|
||||
// rotate mid-quickscrub
|
||||
launcher.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK);
|
||||
return mOnInitListener.test(launcher, alreadyOnHome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
initWhenReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
clearReference();
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
|
||||
/**
|
||||
* Creates an AnimatorSet consisting on one Animator for Launcher transition, and one Animator for
|
||||
* the Window transitions.
|
||||
*
|
||||
* Allows for ending the Launcher animator without ending the Window animator.
|
||||
*/
|
||||
public class LauncherTransitionAnimator {
|
||||
|
||||
private final MutableBoolean mLauncherAnimCancelState;
|
||||
|
||||
private AnimatorSet mAnimatorSet;
|
||||
private Animator mLauncherAnimator;
|
||||
private Animator mWindowAnimator;
|
||||
|
||||
LauncherTransitionAnimator(Animator launcherAnimator, Animator windowAnimator) {
|
||||
this(launcherAnimator, windowAnimator, new MutableBoolean(false));
|
||||
}
|
||||
|
||||
|
||||
LauncherTransitionAnimator(Animator launcherAnimator, Animator windowAnimator,
|
||||
MutableBoolean launcherAnimCancelState) {
|
||||
mLauncherAnimCancelState = launcherAnimCancelState;
|
||||
if (launcherAnimator != null) {
|
||||
mLauncherAnimator = launcherAnimator;
|
||||
}
|
||||
mWindowAnimator = windowAnimator;
|
||||
|
||||
mAnimatorSet = new AnimatorSet();
|
||||
if (launcherAnimator != null) {
|
||||
mAnimatorSet.play(launcherAnimator);
|
||||
}
|
||||
mAnimatorSet.play(windowAnimator);
|
||||
}
|
||||
|
||||
public AnimatorSet getAnimatorSet() {
|
||||
return mAnimatorSet;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
mAnimatorSet.cancel();
|
||||
mLauncherAnimCancelState.value = true;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return mAnimatorSet.isRunning();
|
||||
}
|
||||
|
||||
public void finishLauncherAnimation() {
|
||||
if (mLauncherAnimator != null) {
|
||||
mLauncherAnimCancelState.value = true;
|
||||
mLauncherAnimator.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class MutableBoolean {
|
||||
public boolean value;
|
||||
|
||||
public MutableBoolean(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import android.view.View;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
|
||||
@@ -33,8 +32,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
*/
|
||||
public class AllAppsState extends LauncherState {
|
||||
|
||||
private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY
|
||||
| FLAG_SHOW_SCRIM | FLAG_ALL_APPS_SCRIM;
|
||||
private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY | FLAG_ALL_APPS_SCRIM;
|
||||
|
||||
private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
|
||||
@Override
|
||||
@@ -85,8 +83,15 @@ public class AllAppsState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getHoseatAlpha(Launcher launcher) {
|
||||
return 0;
|
||||
public int getVisibleElements(Launcher launcher) {
|
||||
return ALL_APPS_HEADER | ALL_APPS_HEADER_EXTRA | ALL_APPS_CONTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getOverviewTranslationFactor(Launcher launcher) {
|
||||
// Keep the same translation as in overview, so that we don't slide around when
|
||||
// transitioning to All Apps.
|
||||
return LauncherState.OVERVIEW.getOverviewTranslationFactor(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.uioverrides;
|
||||
|
||||
import com.android.launcher3.Alarm;
|
||||
import com.android.launcher3.OnAlarmListener;
|
||||
|
||||
/**
|
||||
* Utility class to detect a pause during a drag.
|
||||
*/
|
||||
public class DragPauseDetector implements OnAlarmListener {
|
||||
|
||||
private static final float MAX_VELOCITY_TO_PAUSE = 0.2f;
|
||||
private static final long PAUSE_DURATION = 100;
|
||||
|
||||
private final Alarm mAlarm;
|
||||
private final Runnable mOnPauseCallback;
|
||||
|
||||
private boolean mTriggered = false;
|
||||
private int mDisabledFlags = 0;
|
||||
|
||||
public DragPauseDetector(Runnable onPauseCallback) {
|
||||
mOnPauseCallback = onPauseCallback;
|
||||
|
||||
mAlarm = new Alarm();
|
||||
mAlarm.setOnAlarmListener(this);
|
||||
mAlarm.setAlarm(PAUSE_DURATION);
|
||||
}
|
||||
|
||||
public void onDrag(float velocity) {
|
||||
if (mTriggered || !isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.abs(velocity) > MAX_VELOCITY_TO_PAUSE) {
|
||||
// Cancel any previous alarm and set a new alarm
|
||||
mAlarm.setAlarm(PAUSE_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAlarm(Alarm alarm) {
|
||||
if (!mTriggered && isEnabled()) {
|
||||
mTriggered = true;
|
||||
mOnPauseCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTriggered () {
|
||||
return mTriggered;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mDisabledFlags == 0;
|
||||
}
|
||||
|
||||
public void addDisabledFlags(int flags) {
|
||||
boolean wasEnabled = isEnabled();
|
||||
mDisabledFlags |= flags;
|
||||
resetAlarm(wasEnabled);
|
||||
}
|
||||
|
||||
public void clearDisabledFlags(int flags) {
|
||||
boolean wasEnabled = isEnabled();
|
||||
mDisabledFlags &= ~flags;
|
||||
resetAlarm(wasEnabled);
|
||||
}
|
||||
|
||||
private void resetAlarm(boolean wasEnabled) {
|
||||
boolean isEnabled = isEnabled();
|
||||
if (wasEnabled == isEnabled) {
|
||||
// Nothing has changed
|
||||
} if (isEnabled && !mTriggered) {
|
||||
mAlarm.setAlarm(PAUSE_DURATION);
|
||||
} else if (!isEnabled) {
|
||||
mAlarm.cancelAlarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* 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.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.touch.SwipeDetector.DIRECTION_NEGATIVE;
|
||||
import static com.android.launcher3.touch.SwipeDetector.DIRECTION_POSITIVE;
|
||||
import static com.android.launcher3.touch.SwipeDetector.HORIZONTAL;
|
||||
import static com.android.launcher3.touch.SwipeDetector.VERTICAL;
|
||||
import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.metrics.LogMaker;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.VerticalSwipeController;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
class EventLogTags {
|
||||
private EventLogTags() {
|
||||
} // don't instantiate
|
||||
|
||||
/** 524292 sysui_multi_action (content|4) */
|
||||
public static final int SYSUI_MULTI_ACTION = 524292;
|
||||
|
||||
public static void writeSysuiMultiAction(Object[] content) {
|
||||
android.util.EventLog.writeEvent(SYSUI_MULTI_ACTION, content);
|
||||
}
|
||||
}
|
||||
|
||||
class MetricsLogger {
|
||||
private static MetricsLogger sMetricsLogger;
|
||||
|
||||
private static MetricsLogger getLogger() {
|
||||
if (sMetricsLogger == null) {
|
||||
sMetricsLogger = new MetricsLogger();
|
||||
}
|
||||
return sMetricsLogger;
|
||||
}
|
||||
|
||||
protected void saveLog(Object[] rep) {
|
||||
EventLogTags.writeSysuiMultiAction(rep);
|
||||
}
|
||||
|
||||
public void write(LogMaker content) {
|
||||
if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) {
|
||||
content.setType(4/*MetricsEvent.TYPE_ACTION*/);
|
||||
}
|
||||
saveLog(content.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of {@link VerticalSwipeController} to go from NORMAL to OVERVIEW.
|
||||
*/
|
||||
public class EdgeSwipeController extends VerticalSwipeController implements
|
||||
OnDeviceProfileChangeListener {
|
||||
|
||||
private static final Rect sTempRect = new Rect();
|
||||
|
||||
private final MetricsLogger mMetricsLogger = new MetricsLogger();
|
||||
|
||||
public EdgeSwipeController(Launcher l) {
|
||||
super(l, NORMAL, OVERVIEW, l.getDeviceProfile().isVerticalBarLayout()
|
||||
? HORIZONTAL : VERTICAL);
|
||||
l.addOnDeviceProfileChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceProfileChanged(DeviceProfile dp) {
|
||||
mDetector.updateDirection(dp.isVerticalBarLayout() ? HORIZONTAL : VERTICAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldInterceptTouch(MotionEvent ev) {
|
||||
return mLauncher.isInState(NORMAL) && (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSwipeDirection(MotionEvent ev) {
|
||||
return isTransitionFlipped() ? DIRECTION_NEGATIVE : DIRECTION_POSITIVE;
|
||||
}
|
||||
|
||||
public EdgeSwipeController(Launcher l, LauncherState baseState) {
|
||||
super(l, baseState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isTransitionFlipped() {
|
||||
return mLauncher.getDeviceProfile().isSeascape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionComplete(boolean wasFling, boolean stateChanged) {
|
||||
if (stateChanged && mToState instanceof OverviewState) {
|
||||
// Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for
|
||||
// "Recents" activity for app transition tests.
|
||||
final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/);
|
||||
builder.setPackageName("com.android.systemui");
|
||||
builder.addTaggedData(871/*FIELD_CLASS_NAME*/,
|
||||
"com.android.systemui.recents.RecentsActivity");
|
||||
builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/,
|
||||
0/* zero time */);
|
||||
mMetricsLogger.write(builder);
|
||||
|
||||
// Add user event logging for launcher pipeline
|
||||
int direction = Direction.UP;
|
||||
if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
direction = Direction.LEFT;
|
||||
if (mLauncher.getDeviceProfile().isSeascape()) {
|
||||
direction = Direction.RIGHT;
|
||||
}
|
||||
}
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(
|
||||
wasFling ? Touch.FLING : Touch.SWIPE, direction,
|
||||
ContainerType.NAVBAR, ContainerType.WORKSPACE, // src target
|
||||
ContainerType.TASKSWITCHER, // dst target
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getShiftRange() {
|
||||
return getShiftRange(mLauncher);
|
||||
}
|
||||
|
||||
public static float getShiftRange(Launcher launcher) {
|
||||
RecentsView.getPageRect(launcher.getDeviceProfile(), launcher, sTempRect);
|
||||
DragLayer dl = launcher.getDragLayer();
|
||||
Rect insets = dl.getInsets();
|
||||
DeviceProfile dp = launcher.getDeviceProfile();
|
||||
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
if (dp.isSeascape()) {
|
||||
return insets.left + sTempRect.left;
|
||||
} else {
|
||||
return dl.getWidth() - sTempRect.right + insets.right;
|
||||
}
|
||||
} else {
|
||||
return dl.getHeight() - sTempRect.bottom + insets.bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.quickstep.QuickScrubController;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
@@ -25,12 +26,10 @@ import com.android.quickstep.views.RecentsView;
|
||||
public class FastOverviewState extends OverviewState {
|
||||
|
||||
private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_DISABLE_RESTORE
|
||||
| FLAG_DISABLE_INTERACTION | FLAG_OVERVIEW_UI;
|
||||
|
||||
private static final boolean DEBUG_DIFFERENT_UI = false;
|
||||
| FLAG_DISABLE_INTERACTION | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON;
|
||||
|
||||
public FastOverviewState(int id) {
|
||||
super(id, QuickScrubController.QUICK_SWITCH_START_DURATION, STATE_FLAGS);
|
||||
super(id, QuickScrubController.QUICK_SCRUB_START_DURATION, STATE_FLAGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,11 +39,18 @@ public class FastOverviewState extends OverviewState {
|
||||
recentsView.getQuickScrubController().onFinishedTransitionToQuickScrub();
|
||||
}
|
||||
|
||||
public void onStateEnabled(Launcher launcher) {
|
||||
super.onStateEnabled(launcher);
|
||||
AbstractFloatingView.closeAllOpenViews(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getHoseatAlpha(Launcher launcher) {
|
||||
if (DEBUG_DIFFERENT_UI) {
|
||||
return 0;
|
||||
}
|
||||
return super.getHoseatAlpha(launcher);
|
||||
public int getVisibleElements(Launcher launcher) {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getOverviewTranslationFactor(Launcher launcher) {
|
||||
return new float[] {0f, 0.5f};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.quickstep.util.SysuiEventLogger;
|
||||
|
||||
/**
|
||||
* Touch controller for handling edge swipes in landscape/seascape UI
|
||||
*/
|
||||
public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchController {
|
||||
|
||||
public LandscapeEdgeSwipeController(Launcher l) {
|
||||
super(l, SwipeDetector.HORIZONTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (mCurrentAnimation != null) {
|
||||
// If we are already animating from a previous state, we can intercept.
|
||||
return true;
|
||||
}
|
||||
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
|
||||
return false;
|
||||
}
|
||||
return mLauncher.isInState(NORMAL) && (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSwipeDirection(MotionEvent ev) {
|
||||
mFromState = NORMAL;
|
||||
mToState = OVERVIEW;
|
||||
return SwipeDetector.DIRECTION_BOTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getShiftRange() {
|
||||
return mLauncher.getDragLayer().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float initCurrentAnimation() {
|
||||
float range = getShiftRange();
|
||||
long maxAccuracy = (long) (2 * range);
|
||||
mCurrentAnimation = mLauncher.getStateManager()
|
||||
.createAnimationToNewWorkspace(mToState, maxAccuracy);
|
||||
return (mLauncher.getDeviceProfile().isSeascape() ? 2 : -2) / range;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDirectionForLog() {
|
||||
return mLauncher.getDeviceProfile().isSeascape() ? Direction.RIGHT : Direction.LEFT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
|
||||
super.onSwipeInteractionCompleted(targetState, logAction);
|
||||
if (mFromState == NORMAL && targetState == OVERVIEW) {
|
||||
SysuiEventLogger.writeDummyRecentsTransition(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
* Touch controller from going from OVERVIEW to ALL_APPS
|
||||
*/
|
||||
public class LandscapeStatesTouchController extends PortraitStatesTouchController {
|
||||
|
||||
public LandscapeStatesTouchController(Launcher l) {
|
||||
super(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (mCurrentAnimation != null) {
|
||||
// If we are already animating from a previous state, we can intercept.
|
||||
return true;
|
||||
}
|
||||
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
|
||||
return false;
|
||||
}
|
||||
if (mLauncher.isInState(ALL_APPS)) {
|
||||
// In all-apps only listen if the container cannot scroll itself
|
||||
return mLauncher.getAppsView().shouldContainerScroll(ev);
|
||||
} else if (mLauncher.isInState(NORMAL)) {
|
||||
return true;
|
||||
} else if (mLauncher.isInState(OVERVIEW)) {
|
||||
RecentsView rv = mLauncher.getOverviewPanel();
|
||||
return ev.getY() > (rv.getBottom() - rv.getPaddingBottom());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected LauncherState getTargetState() {
|
||||
if (mLauncher.isInState(ALL_APPS)) {
|
||||
// Should swipe down go to OVERVIEW instead?
|
||||
return TouchInteractionService.isConnected() ?
|
||||
mLauncher.getStateManager().getLastState() : NORMAL;
|
||||
} else {
|
||||
return ALL_APPS;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.Workspace;
|
||||
@@ -56,6 +57,11 @@ public class OverviewState extends LauncherState {
|
||||
return getScaleAndTranslationForPageRect(launcher, pageRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getOverviewTranslationFactor(Launcher launcher) {
|
||||
return new float[] {0f, 0f};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateEnabled(Launcher launcher) {
|
||||
RecentsView rv = launcher.getOverviewPanel();
|
||||
@@ -100,4 +106,29 @@ public class OverviewState extends LauncherState {
|
||||
|
||||
return new float[] {scale, 0, translationY};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVisibleElements(Launcher launcher) {
|
||||
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
return NONE;
|
||||
} else {
|
||||
return launcher.getAppsView().getFloatingHeaderView().hasVisibleContent()
|
||||
? HOTSEAT_EXTRA | ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS | HOTSEAT_EXTRA;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVerticalProgress(Launcher launcher) {
|
||||
if ((getVisibleElements(launcher) & ALL_APPS_HEADER_EXTRA) == 0) {
|
||||
// We have no all apps content, so we're still at the fully down progress.
|
||||
return super.getVerticalProgress(launcher);
|
||||
}
|
||||
return 1 - (getDefaultSwipeHeight(launcher)
|
||||
/ launcher.getAllAppsController().getShiftRange());
|
||||
}
|
||||
|
||||
public static float getDefaultSwipeHeight(Launcher launcher) {
|
||||
DeviceProfile dp = launcher.getDeviceProfile();
|
||||
return dp.allAppsCellHeightPx - dp.allAppsIconTextSizePx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.VerticalSwipeController;
|
||||
|
||||
/**
|
||||
* Extension of {@link VerticalSwipeController} which allows swipe up from OVERVIEW to ALL_APPS
|
||||
* Note that the swipe down is handled by {@link TwoStepSwipeController}.
|
||||
*/
|
||||
public class OverviewSwipeUpController extends VerticalSwipeController {
|
||||
|
||||
public OverviewSwipeUpController(Launcher l) {
|
||||
super(l, OVERVIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldInterceptTouch(MotionEvent ev) {
|
||||
if (!mLauncher.isInState(OVERVIEW)) {
|
||||
return false;
|
||||
}
|
||||
if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
return ev.getY() >
|
||||
mLauncher.getDragLayer().getHeight() * OVERVIEW.getVerticalProgress(mLauncher);
|
||||
} else {
|
||||
return mLauncher.getDragLayer().isEventOverHotseat(ev);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSwipeDirection(MotionEvent ev) {
|
||||
return SwipeDetector.DIRECTION_POSITIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTransitionComplete(boolean wasFling, boolean stateChanged) {
|
||||
if (stateChanged) {
|
||||
// Transition complete. log the action
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(
|
||||
wasFling ? Touch.FLING : Touch.SWIPE,
|
||||
Direction.UP,
|
||||
ContainerType.HOTSEAT,
|
||||
ContainerType.TASKSWITCHER,
|
||||
ContainerType.ALLAPPS,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* 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.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.touch.AbstractStateChangeTouchController;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
import com.android.quickstep.util.SysuiEventLogger;
|
||||
|
||||
/**
|
||||
* Touch controller for handling various state transitions in portrait UI.
|
||||
*/
|
||||
public class PortraitStatesTouchController extends AbstractStateChangeTouchController {
|
||||
|
||||
private static final float TOTAL_DISTANCE_MULTIPLIER = 2f;
|
||||
private static final float LINEAR_SCALE_LIMIT = 1 / TOTAL_DISTANCE_MULTIPLIER;
|
||||
|
||||
// Much be greater than LINEAR_SCALE_LIMIT;
|
||||
private static final float MAXIMUM_DISTANCE_FACTOR = 0.9f;
|
||||
|
||||
// Maximum amount to overshoot.
|
||||
private static final float MAX_OVERSHOOT = 0.3f;
|
||||
|
||||
private static final double PI_BY_2 = Math.PI / 2;
|
||||
|
||||
private InterpolatorWrapper mAllAppsInterpolatorWrapper = new InterpolatorWrapper();
|
||||
|
||||
// If > 0, the animation progress is clamped at that value as long as user is dragging.
|
||||
private float mClampProgressUpdate = -1;
|
||||
|
||||
// If true, we will finish the current animation instantly on second touch.
|
||||
private boolean mFinishFastOnSecondTouch;
|
||||
|
||||
private final Interpolator mAllAppsDampedInterpolator = new Interpolator() {
|
||||
|
||||
private final double mAngleMultiplier = Math.PI /
|
||||
(2 * (MAXIMUM_DISTANCE_FACTOR - LINEAR_SCALE_LIMIT));
|
||||
|
||||
@Override
|
||||
public float getInterpolation(float v) {
|
||||
if (v <= LINEAR_SCALE_LIMIT) {
|
||||
return v * TOTAL_DISTANCE_MULTIPLIER;
|
||||
}
|
||||
float overshoot = (v - LINEAR_SCALE_LIMIT);
|
||||
return (float) (1 + MAX_OVERSHOOT * Math.sin(overshoot * mAngleMultiplier));
|
||||
}
|
||||
};
|
||||
|
||||
private final Interpolator mOverviewBoundInterpolator = (v) -> {
|
||||
if (v >= MAXIMUM_DISTANCE_FACTOR) {
|
||||
return 1;
|
||||
}
|
||||
return FAST_OUT_SLOW_IN.getInterpolation(v / MAXIMUM_DISTANCE_FACTOR);
|
||||
};
|
||||
|
||||
public PortraitStatesTouchController(Launcher l) {
|
||||
super(l, SwipeDetector.VERTICAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (mCurrentAnimation != null) {
|
||||
if (mFinishFastOnSecondTouch) {
|
||||
// TODO: Animate to finish instead.
|
||||
mCurrentAnimation.getAnimationPlayer().end();
|
||||
}
|
||||
|
||||
// If we are already animating from a previous state, we can intercept.
|
||||
return true;
|
||||
}
|
||||
if (mLauncher.isInState(ALL_APPS)) {
|
||||
// In all-apps only listen if the container cannot scroll itself
|
||||
if (!mLauncher.getAppsView().shouldContainerScroll(ev)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// For all other states, only listen if the event originated below the hotseat height
|
||||
DeviceProfile dp = mLauncher.getDeviceProfile();
|
||||
int hotseatHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
|
||||
if (ev.getY() < (mLauncher.getDragLayer().getHeight() - hotseatHeight)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSwipeDirection(MotionEvent ev) {
|
||||
final int directionsToDetectScroll;
|
||||
if (mLauncher.isInState(ALL_APPS)) {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE;
|
||||
mStartContainerType = ContainerType.ALLAPPS;
|
||||
} else if (mLauncher.isInState(NORMAL)) {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
|
||||
mStartContainerType = ContainerType.HOTSEAT;
|
||||
} else if (mLauncher.isInState(OVERVIEW)) {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
|
||||
mStartContainerType = ContainerType.TASKSWITCHER;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
mFromState = mLauncher.getStateManager().getState();
|
||||
mToState = getTargetState();
|
||||
if (mFromState == mToState) {
|
||||
return 0;
|
||||
}
|
||||
return directionsToDetectScroll;
|
||||
}
|
||||
|
||||
protected LauncherState getTargetState() {
|
||||
if (mLauncher.isInState(ALL_APPS)) {
|
||||
// Should swipe down go to OVERVIEW instead?
|
||||
return TouchInteractionService.isConnected() ?
|
||||
mLauncher.getStateManager().getLastState() : NORMAL;
|
||||
} else if (mLauncher.isInState(OVERVIEW)) {
|
||||
return ALL_APPS;
|
||||
} else {
|
||||
return TouchInteractionService.isConnected() ? OVERVIEW : ALL_APPS;
|
||||
}
|
||||
}
|
||||
|
||||
private AnimatorSetBuilder getNormalToOverviewAnimation() {
|
||||
mAllAppsInterpolatorWrapper.baseInterpolator = mAllAppsDampedInterpolator;
|
||||
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper);
|
||||
|
||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATION, mOverviewBoundInterpolator);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateProgress(float fraction) {
|
||||
if (mClampProgressUpdate > 0) {
|
||||
mCurrentAnimation.setPlayFraction(Math.min(fraction, mClampProgressUpdate));
|
||||
} else {
|
||||
super.updateProgress(fraction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float initCurrentAnimation() {
|
||||
float range = getShiftRange();
|
||||
long maxAccuracy = (long) (2 * range);
|
||||
|
||||
float startVerticalShift = mFromState.getVerticalProgress(mLauncher) * range;
|
||||
float endVerticalShift = mToState.getVerticalProgress(mLauncher) * range;
|
||||
|
||||
float totalShift = endVerticalShift - startVerticalShift;
|
||||
|
||||
final AnimatorSetBuilder builder;
|
||||
|
||||
if (mFromState == NORMAL && mToState == OVERVIEW && totalShift != 0) {
|
||||
builder = getNormalToOverviewAnimation();
|
||||
totalShift = totalShift * TOTAL_DISTANCE_MULTIPLIER;
|
||||
mClampProgressUpdate = MAXIMUM_DISTANCE_FACTOR;
|
||||
} else {
|
||||
builder = new AnimatorSetBuilder();
|
||||
mClampProgressUpdate = -1;
|
||||
}
|
||||
|
||||
mCurrentAnimation = mLauncher.getStateManager()
|
||||
.createAnimationToNewWorkspace(mToState, builder, maxAccuracy);
|
||||
|
||||
if (totalShift == 0) {
|
||||
totalShift = Math.signum(mFromState.ordinal - mToState.ordinal)
|
||||
* OverviewState.getDefaultSwipeHeight(mLauncher);
|
||||
}
|
||||
return 1 / totalShift;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
|
||||
LauncherState targetState, float velocity, boolean isFling) {
|
||||
if (mFromState == NORMAL && mToState == OVERVIEW && targetState == OVERVIEW) {
|
||||
mFinishFastOnSecondTouch = true;
|
||||
|
||||
// Update all apps interpolator
|
||||
float currentFraction = mCurrentAnimation.getProgressFraction();
|
||||
float absVelocity = Math.abs(velocity);
|
||||
float currentValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction);
|
||||
|
||||
if (isFling && absVelocity > 1 && currentFraction < LINEAR_SCALE_LIMIT) {
|
||||
|
||||
// TODO: Clean up these magic calculations
|
||||
// Linearly interpolate the max value based on the velocity.
|
||||
float maxValue = Math.max(absVelocity > 4 ? 1 + MAX_OVERSHOOT :
|
||||
1 + (absVelocity - 1) * MAX_OVERSHOOT / 3,
|
||||
currentValue);
|
||||
double angleToPeak = PI_BY_2 - Math.asin(currentValue / maxValue);
|
||||
|
||||
if (expectedDuration != 0 && angleToPeak != 0) {
|
||||
|
||||
float distanceLeft = 1 - currentFraction;
|
||||
mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> {
|
||||
float scaledF = (f - currentFraction) / distanceLeft;
|
||||
|
||||
if (scaledF < 0.5f) {
|
||||
double angle = PI_BY_2 - angleToPeak + scaledF * angleToPeak / 0.5f;
|
||||
return (float) (maxValue * Math.sin(angle));
|
||||
}
|
||||
|
||||
scaledF = ((scaledF - .5f) / .5f);
|
||||
double angle = PI_BY_2 + 3 * scaledF * PI_BY_2;
|
||||
float amplitude = (1 - scaledF) * (1 - scaledF) * (maxValue - 1);
|
||||
return 1 + (float) (amplitude * Math.sin(angle));
|
||||
};
|
||||
|
||||
animator.setDuration(expectedDuration).setInterpolator(LINEAR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFraction < LINEAR_SCALE_LIMIT) {
|
||||
mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
|
||||
super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState,
|
||||
velocity, isFling);
|
||||
return;
|
||||
}
|
||||
float extraValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction) - 1;
|
||||
float distanceLeft = 1 - currentFraction;
|
||||
|
||||
animator.setFloatValues(currentFraction, 1);
|
||||
mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> {
|
||||
float scaledF = (f - currentFraction) / distanceLeft;
|
||||
|
||||
double angle = scaledF * 1.5 * Math.PI;
|
||||
float amplitude = (1 - scaledF) * (1 - scaledF) * extraValue;
|
||||
return 1 + (float) (amplitude * Math.sin(angle));
|
||||
};
|
||||
animator.setDuration(200).setInterpolator(LINEAR);
|
||||
return;
|
||||
}
|
||||
mFinishFastOnSecondTouch = false;
|
||||
super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState,
|
||||
velocity, isFling);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
|
||||
super.onSwipeInteractionCompleted(targetState, logAction);
|
||||
if (mFromState == NORMAL && targetState == OVERVIEW) {
|
||||
SysuiEventLogger.writeDummyRecentsTransition(0);
|
||||
}
|
||||
}
|
||||
|
||||
private static class InterpolatorWrapper implements Interpolator {
|
||||
|
||||
public TimeInterpolator baseInterpolator = LINEAR;
|
||||
|
||||
@Override
|
||||
public float getInterpolation(float v) {
|
||||
return baseInterpolator.getInterpolation(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,36 +16,32 @@
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.AlphaUpdateListener.updateVisibility;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
|
||||
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_X_FACTOR;
|
||||
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.view.View;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.quickstep.views.LauncherRecentsView;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class RecentsViewStateController implements StateHandler {
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final RecentsView mRecentsView;
|
||||
|
||||
private final AnimatedFloat mTransitionProgress = new AnimatedFloat(this::onTransitionProgress);
|
||||
// The fraction representing the visibility of the RecentsView. This allows delaying the
|
||||
// overall transition while the RecentsView is being shown or hidden.
|
||||
private final AnimatedFloat mVisibilityMultiplier = new AnimatedFloat(this::onVisibilityProgress);
|
||||
|
||||
private boolean mIsRecentsSlidingInOrOut;
|
||||
private final LauncherRecentsView mRecentsView;
|
||||
|
||||
public RecentsViewStateController(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
@@ -54,8 +50,11 @@ public class RecentsViewStateController implements StateHandler {
|
||||
|
||||
@Override
|
||||
public void setState(LauncherState state) {
|
||||
setVisibility(state.overviewUi);
|
||||
setTransitionProgress(state.overviewUi ? 1 : 0);
|
||||
mRecentsView.setContentAlpha(state.overviewUi ? 1 : 0);
|
||||
updateVisibility(mRecentsView, isAccessibilityEnabled(mLauncher));
|
||||
float[] translationFactor = state.getOverviewTranslationFactor(mLauncher);
|
||||
mRecentsView.setTranslationXFactor(translationFactor[0]);
|
||||
mRecentsView.setTranslationYFactor(translationFactor[1]);
|
||||
if (state.overviewUi) {
|
||||
mRecentsView.resetTaskVisuals();
|
||||
}
|
||||
@@ -64,11 +63,9 @@ public class RecentsViewStateController implements StateHandler {
|
||||
@Override
|
||||
public void setStateWithAnimation(final LauncherState toState,
|
||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
||||
LauncherState fromState = mLauncher.getStateManager().getState();
|
||||
mIsRecentsSlidingInOrOut = fromState == NORMAL && toState.overviewUi
|
||||
|| fromState.overviewUi && toState == NORMAL;
|
||||
|
||||
// Scroll to the workspace card before changing to the NORMAL state.
|
||||
LauncherState fromState = mLauncher.getStateManager().getState();
|
||||
int currPage = mRecentsView.getCurrentPage();
|
||||
if (fromState.overviewUi && toState == NORMAL && currPage != 0 && !config.userControlled) {
|
||||
int maxSnapDuration = PagedView.SLOW_PAGE_SNAP_ANIMATION_DURATION;
|
||||
@@ -79,78 +76,24 @@ public class RecentsViewStateController implements StateHandler {
|
||||
builder.setStartDelay(snapDuration / 4);
|
||||
}
|
||||
|
||||
ObjectAnimator progressAnim =
|
||||
mTransitionProgress.animateToValue(toState.overviewUi ? 1 : 0);
|
||||
progressAnim.setDuration(config.duration);
|
||||
progressAnim.setInterpolator(Interpolators.LINEAR);
|
||||
progressAnim.addListener(new AnimationSuccessListener() {
|
||||
PropertySetter setter = config.getProperSetter(builder);
|
||||
float[] translationFactor = toState.getOverviewTranslationFactor(mLauncher);
|
||||
setter.setFloat(mRecentsView, TRANSLATION_X_FACTOR,
|
||||
translationFactor[0],
|
||||
builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
|
||||
setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR,
|
||||
translationFactor[1],
|
||||
builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR));
|
||||
setter.setFloat(mRecentsView, CONTENT_ALPHA, toState.overviewUi ? 1 : 0, LINEAR);
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mRecentsView.setCurrentPage(mRecentsView.getPageNearestToCenterOfScreen());
|
||||
}
|
||||
});
|
||||
builder.play(progressAnim);
|
||||
|
||||
ObjectAnimator visibilityAnim = animateVisibility(toState.overviewUi);
|
||||
visibilityAnim.setDuration(config.duration);
|
||||
visibilityAnim.setInterpolator(Interpolators.LINEAR);
|
||||
builder.play(visibilityAnim);
|
||||
}
|
||||
|
||||
public void setVisibility(boolean isVisible) {
|
||||
mVisibilityMultiplier.cancelAnimation();
|
||||
mRecentsView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
|
||||
mVisibilityMultiplier.updateValue(isVisible ? 1 : 0);
|
||||
}
|
||||
|
||||
public ObjectAnimator animateVisibility(boolean isVisible) {
|
||||
ObjectAnimator anim = mVisibilityMultiplier.animateToValue(isVisible ? 1 : 0);
|
||||
if (isVisible) {
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mRecentsView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (toState.overviewUi) {
|
||||
ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1);
|
||||
updateAnim.addUpdateListener(valueAnimator -> {
|
||||
// While animating into recents, update the visible task data as needed
|
||||
mRecentsView.loadVisibleTaskData();
|
||||
});
|
||||
} else {
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mRecentsView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
public void setTransitionProgress(float progress) {
|
||||
mTransitionProgress.cancelAnimation();
|
||||
mTransitionProgress.updateValue(progress);
|
||||
}
|
||||
|
||||
private void onTransitionProgress() {
|
||||
applyProgress();
|
||||
if (mIsRecentsSlidingInOrOut) {
|
||||
float interpolatedProgress = ACCEL.getInterpolation(mTransitionProgress.value);
|
||||
// Slide in from the side as we swipe.
|
||||
int translation = mRecentsView.getWidth();
|
||||
if (mRecentsView.isRtl()) {
|
||||
translation = -translation;
|
||||
}
|
||||
mRecentsView.setTranslationX(translation * (1 - interpolatedProgress));
|
||||
}
|
||||
}
|
||||
|
||||
private void onVisibilityProgress() {
|
||||
applyProgress();
|
||||
}
|
||||
|
||||
private void applyProgress() {
|
||||
mRecentsView.setAlpha(mTransitionProgress.value * mVisibilityMultiplier.value);
|
||||
if (mIsRecentsSlidingInOrOut) {
|
||||
// While animating into recents, update the visible task data as needed
|
||||
mRecentsView.loadVisibleTaskData();
|
||||
updateAnim.setDuration(config.duration);
|
||||
builder.play(updateAnim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.uioverrides;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TaggedAnimatorSetBuilder extends AnimatorSetBuilder {
|
||||
|
||||
/**
|
||||
* Map of the index in {@link #mAnims} to tag. All the animations in {@link #mAnims} starting
|
||||
* from this index correspond to the tag (until a new tag is specified for an index)
|
||||
*/
|
||||
private final SparseArray<Object> mTags = new SparseArray<>();
|
||||
|
||||
@Override
|
||||
public void startTag(Object obj) {
|
||||
mTags.put(mAnims.size(), obj);
|
||||
}
|
||||
|
||||
public List<Animator> getAnimationsForTag(Object tag) {
|
||||
int startIndex = mTags.indexOfValue(tag);
|
||||
if (startIndex < 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
int startPos = mTags.keyAt(startIndex);
|
||||
|
||||
int endIndex = startIndex + 1;
|
||||
int endPos = endIndex >= mTags.size() ? mAnims.size() : mTags.keyAt(endIndex);
|
||||
|
||||
return mAnims.subList(startPos, endPos);
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||
|
||||
@@ -30,24 +28,21 @@ import android.view.View;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.PendingAnimation;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
||||
/**
|
||||
* Touch controller for swipe interaction in Overview state
|
||||
* Touch controller for handling task view card swipes
|
||||
*/
|
||||
public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
public class TaskViewTouchController extends AnimatorListenerAdapter
|
||||
implements TouchController, SwipeDetector.Listener {
|
||||
|
||||
private static final String TAG = "OverviewSwipeController";
|
||||
@@ -68,16 +63,14 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
private boolean mCurrentAnimationIsGoingUp;
|
||||
|
||||
private boolean mNoIntercept;
|
||||
private boolean mSwipeDownEnabled;
|
||||
|
||||
private float mDisplacementShift;
|
||||
private float mProgressMultiplier;
|
||||
private float mEndDisplacement;
|
||||
private int mStartingTarget;
|
||||
|
||||
private TaskView mTaskBeingDragged;
|
||||
|
||||
public OverviewSwipeController(Launcher launcher) {
|
||||
public TaskViewTouchController(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
mRecentsView = launcher.getOverviewPanel();
|
||||
mDetector = new SwipeDetector(launcher, this, SwipeDetector.VERTICAL);
|
||||
@@ -94,15 +87,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
return mLauncher.isInState(OVERVIEW);
|
||||
}
|
||||
|
||||
private boolean isEventOverHotseat(MotionEvent ev) {
|
||||
if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
return ev.getY() >
|
||||
mLauncher.getDragLayer().getHeight() * OVERVIEW.getVerticalProgress(mLauncher);
|
||||
} else {
|
||||
return mLauncher.getDragLayer().isEventOverHotseat(ev);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) {
|
||||
@@ -129,22 +113,14 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
ignoreSlopWhenSettling = true;
|
||||
} else {
|
||||
mTaskBeingDragged = null;
|
||||
mSwipeDownEnabled = true;
|
||||
|
||||
View view = mRecentsView.getChildAt(mRecentsView.getCurrentPage());
|
||||
if (view instanceof TaskView && mLauncher.getDragLayer().isEventOverView(view, ev)) {
|
||||
// The tile can be dragged down to open the task.
|
||||
mTaskBeingDragged = (TaskView) view;
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
|
||||
mStartingTarget = LauncherLogProto.ItemType.TASK;
|
||||
} else if (isEventOverHotseat(ev)) {
|
||||
// The hotseat is being dragged
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
|
||||
mSwipeDownEnabled = false;
|
||||
mStartingTarget = ContainerType.HOTSEAT;
|
||||
} else {
|
||||
mNoIntercept = true;
|
||||
mStartingTarget = ContainerType.WORKSPACE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -167,9 +143,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
}
|
||||
|
||||
private void reInitAnimationController(boolean goingUp) {
|
||||
if (!goingUp && !mSwipeDownEnabled) {
|
||||
goingUp = true;
|
||||
}
|
||||
if (mCurrentAnimation != null && mCurrentAnimationIsGoingUp == goingUp) {
|
||||
// No need to init
|
||||
return;
|
||||
@@ -187,31 +160,20 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
long maxDuration = (long) (2 * range);
|
||||
DragLayer dl = mLauncher.getDragLayer();
|
||||
|
||||
if (mTaskBeingDragged == null) {
|
||||
// User is either going to all apps or home
|
||||
mCurrentAnimation = mLauncher.getStateManager()
|
||||
.createAnimationToNewWorkspace(goingUp ? ALL_APPS : NORMAL, maxDuration);
|
||||
if (goingUp) {
|
||||
mEndDisplacement = -range;
|
||||
} else {
|
||||
mEndDisplacement = EdgeSwipeController.getShiftRange(mLauncher);
|
||||
}
|
||||
if (goingUp) {
|
||||
mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
|
||||
true /* animateTaskView */, true /* removeTask */, maxDuration);
|
||||
mCurrentAnimation = AnimatorPlaybackController
|
||||
.wrap(mPendingAnimation.anim, maxDuration);
|
||||
mEndDisplacement = -mTaskBeingDragged.getHeight();
|
||||
} else {
|
||||
if (goingUp) {
|
||||
mPendingAnimation = mRecentsView
|
||||
.createTaskDismissAnimation(mTaskBeingDragged, maxDuration);
|
||||
mCurrentAnimation = AnimatorPlaybackController
|
||||
.wrap(mPendingAnimation.anim, maxDuration);
|
||||
mEndDisplacement = -mTaskBeingDragged.getHeight();
|
||||
} else {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
// TODO: Setup a zoom animation
|
||||
mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration);
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
// TODO: Setup a zoom animation
|
||||
mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration);
|
||||
|
||||
mTempCords[1] = mTaskBeingDragged.getHeight();
|
||||
dl.getDescendantCoordRelativeToSelf(mTaskBeingDragged, mTempCords);
|
||||
mEndDisplacement = dl.getHeight() - mTempCords[1];
|
||||
}
|
||||
mTempCords[1] = mTaskBeingDragged.getHeight();
|
||||
dl.getDescendantCoordRelativeToSelf(mTaskBeingDragged, mTempCords);
|
||||
mEndDisplacement = dl.getHeight() - mTempCords[1];
|
||||
}
|
||||
|
||||
mCurrentAnimation.getTarget().addListener(this);
|
||||
@@ -249,9 +211,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
if (fling) {
|
||||
logAction = Touch.FLING;
|
||||
boolean goingUp = velocity < 0;
|
||||
if (!goingUp && !mSwipeDownEnabled) {
|
||||
goingToEnd = false;
|
||||
} else if (goingUp != mCurrentAnimationIsGoingUp) {
|
||||
if (goingUp != mCurrentAnimationIsGoingUp) {
|
||||
// In case the fling is in opposite direction, make sure if is close enough
|
||||
// from the start position
|
||||
if (mCurrentAnimation.getProgressFraction()
|
||||
@@ -277,7 +237,6 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
float nextFrameProgress = Utilities.boundToRange(
|
||||
progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f);
|
||||
|
||||
|
||||
mCurrentAnimation.setEndAction(() -> onCurrentAnimationEnd(goingToEnd, logAction));
|
||||
|
||||
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
|
||||
@@ -292,25 +251,13 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
||||
mPendingAnimation.finish(wasSuccess);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
if (mTaskBeingDragged == null) {
|
||||
LauncherState state = wasSuccess ?
|
||||
(mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW;
|
||||
mLauncher.getStateManager().goToState(state, false);
|
||||
|
||||
} else if (wasSuccess) {
|
||||
if (wasSuccess) {
|
||||
if (!mCurrentAnimationIsGoingUp) {
|
||||
mTaskBeingDragged.launchTask(false);
|
||||
mLauncher.getUserEventDispatcher().logTaskLaunch(logAction,
|
||||
Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent());
|
||||
}
|
||||
}
|
||||
if (mTaskBeingDragged == null || (wasSuccess && mCurrentAnimationIsGoingUp)) {
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
|
||||
mCurrentAnimationIsGoingUp ? Direction.UP : Direction.DOWN,
|
||||
mStartingTarget, ContainerType.TASKSWITCHER,
|
||||
mLauncher.getStateManager().getState().containerType,
|
||||
mRecentsView.getCurrentPage());
|
||||
}
|
||||
mDetector.finishedScrolling();
|
||||
mTaskBeingDragged = null;
|
||||
mCurrentAnimation = null;
|
||||
@@ -1,447 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||
import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.FloatRange;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
|
||||
/**
|
||||
* Handles vertical touch gesture on the DragLayer
|
||||
*/
|
||||
public class TwoStepSwipeController extends AnimatorListenerAdapter
|
||||
implements TouchController, SwipeDetector.Listener {
|
||||
|
||||
private static final String TAG = "TwoStepSwipeController";
|
||||
|
||||
private static final float RECATCH_REJECTION_FRACTION = .0875f;
|
||||
private static final int SINGLE_FRAME_MS = 16;
|
||||
private static final long QUICK_SNAP_TO_OVERVIEW_DURATION = 250;
|
||||
|
||||
// Progress after which the transition is assumed to be a success in case user does not fling
|
||||
private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
|
||||
|
||||
/**
|
||||
* Index of the vertical swipe handles in {@link LauncherStateManager#getStateHandlers()}.
|
||||
*/
|
||||
private static final int SWIPE_HANDLER_INDEX = 0;
|
||||
|
||||
/**
|
||||
* Index of various UI handlers in {@link LauncherStateManager#getStateHandlers()} not related
|
||||
* to vertical swipe.
|
||||
*/
|
||||
private static final int OTHER_HANDLERS_START_INDEX = SWIPE_HANDLER_INDEX + 1;
|
||||
|
||||
// Swipe progress range (when starting from NORMAL state) where OVERVIEW state is allowed
|
||||
private static final float MIN_PROGRESS_TO_OVERVIEW = 0.1f;
|
||||
private static final float MAX_PROGRESS_TO_OVERVIEW = 0.4f;
|
||||
|
||||
private static final int FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE = 1 << 0;
|
||||
private static final int FLAG_OVERVIEW_DISABLED_FLING = 1 << 1;
|
||||
private static final int FLAG_OVERVIEW_DISABLED_CANCEL_STATE = 1 << 2;
|
||||
private static final int FLAG_OVERVIEW_DISABLED = 1 << 4;
|
||||
private static final int FLAG_DISABLED_TWO_TARGETS = 1 << 5;
|
||||
private static final int FLAG_DISABLED_BACK_TARGET = 1 << 6;
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final SwipeDetector mDetector;
|
||||
|
||||
private boolean mNoIntercept;
|
||||
private int mStartContainerType;
|
||||
|
||||
private DragPauseDetector mDragPauseDetector;
|
||||
private FloatRange mOverviewProgressRange;
|
||||
private TaggedAnimatorSetBuilder mTaggedAnimatorSetBuilder;
|
||||
private AnimatorSet mQuickOverviewAnimation;
|
||||
private boolean mAnimatingToOverview;
|
||||
private CroppedAnimationController mCroppedAnimationController;
|
||||
|
||||
private AnimatorPlaybackController mCurrentAnimation;
|
||||
private LauncherState mFromState;
|
||||
private LauncherState mToState;
|
||||
|
||||
private float mStartProgress;
|
||||
// Ratio of transition process [0, 1] to drag displacement (px)
|
||||
private float mProgressMultiplier;
|
||||
|
||||
public TwoStepSwipeController(Launcher l) {
|
||||
mLauncher = l;
|
||||
mDetector = new SwipeDetector(l, this, SwipeDetector.VERTICAL);
|
||||
}
|
||||
|
||||
private boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (mCurrentAnimation != null) {
|
||||
// If we are already animating from a previous state, we can intercept.
|
||||
return true;
|
||||
}
|
||||
if (mLauncher.isInState(NORMAL)) {
|
||||
if ((ev.getEdgeFlags() & EDGE_NAV_BAR) != 0 &&
|
||||
!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
// On normal swipes ignore edge swipes
|
||||
return false;
|
||||
}
|
||||
} else if (mLauncher.isInState(ALL_APPS)) {
|
||||
if (!mLauncher.getAppsView().shouldContainerScroll(ev)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Don't listen for the swipe gesture if we are already in some other state.
|
||||
return false;
|
||||
}
|
||||
if (mAnimatingToOverview) {
|
||||
return false;
|
||||
}
|
||||
if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
if (mCurrentAnimation != null && animation == mCurrentAnimation.getOriginalTarget()) {
|
||||
Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception());
|
||||
clearState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
mNoIntercept = !canInterceptTouch(ev);
|
||||
if (mNoIntercept) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now figure out which direction scroll events the controller will start
|
||||
// calling the callbacks.
|
||||
final int directionsToDetectScroll;
|
||||
boolean ignoreSlopWhenSettling = false;
|
||||
|
||||
if (mCurrentAnimation != null) {
|
||||
if (mCurrentAnimation.getProgressFraction() > 1 - RECATCH_REJECTION_FRACTION) {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
|
||||
} else if (mCurrentAnimation.getProgressFraction() < RECATCH_REJECTION_FRACTION ) {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE;
|
||||
} else {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
|
||||
ignoreSlopWhenSettling = true;
|
||||
}
|
||||
} else {
|
||||
if (mLauncher.isInState(ALL_APPS)) {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE;
|
||||
mStartContainerType = ContainerType.ALLAPPS;
|
||||
} else {
|
||||
directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE;
|
||||
mStartContainerType = mLauncher.getDragLayer().isEventOverHotseat(ev) ?
|
||||
ContainerType.HOTSEAT : ContainerType.WORKSPACE;
|
||||
}
|
||||
}
|
||||
|
||||
mDetector.setDetectableScrollConditions(
|
||||
directionsToDetectScroll, ignoreSlopWhenSettling);
|
||||
}
|
||||
|
||||
if (mNoIntercept) {
|
||||
return false;
|
||||
}
|
||||
|
||||
onControllerTouchEvent(ev);
|
||||
return mDetector.isDraggingOrSettling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerTouchEvent(MotionEvent ev) {
|
||||
return mDetector.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragStart(boolean start) {
|
||||
if (mCurrentAnimation == null) {
|
||||
float range = getShiftRange();
|
||||
long maxAccuracy = (long) (2 * range);
|
||||
|
||||
mDragPauseDetector = new DragPauseDetector(this::onDragPauseDetected);
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE);
|
||||
if (FeatureFlags.ENABLE_TWO_SWIPE_TARGETS) {
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_DISABLED_TWO_TARGETS);
|
||||
}
|
||||
|
||||
mOverviewProgressRange = new FloatRange();
|
||||
mOverviewProgressRange.start = mLauncher.isInState(NORMAL)
|
||||
? MIN_PROGRESS_TO_OVERVIEW
|
||||
: 1 - MAX_PROGRESS_TO_OVERVIEW;
|
||||
mOverviewProgressRange.end = mOverviewProgressRange.start
|
||||
+ MAX_PROGRESS_TO_OVERVIEW - MIN_PROGRESS_TO_OVERVIEW;
|
||||
|
||||
// Build current animation
|
||||
mFromState = mLauncher.getStateManager().getState();
|
||||
mToState = mLauncher.isInState(ALL_APPS) ? NORMAL : ALL_APPS;
|
||||
|
||||
if (mToState == NORMAL && mLauncher.getStateManager().getLastState() == OVERVIEW) {
|
||||
mToState = OVERVIEW;
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_DISABLED_BACK_TARGET);
|
||||
}
|
||||
|
||||
mTaggedAnimatorSetBuilder = new TaggedAnimatorSetBuilder();
|
||||
mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(
|
||||
mToState, mTaggedAnimatorSetBuilder, maxAccuracy);
|
||||
|
||||
if (!TouchInteractionService.isConnected()) {
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED);
|
||||
}
|
||||
|
||||
mCurrentAnimation.getTarget().addListener(this);
|
||||
mStartProgress = 0;
|
||||
mProgressMultiplier = (mLauncher.isInState(ALL_APPS) ? 1 : -1) / range;
|
||||
mCurrentAnimation.dispatchOnStart();
|
||||
} else {
|
||||
mCurrentAnimation.pause();
|
||||
mStartProgress = mCurrentAnimation.getProgressFraction();
|
||||
|
||||
mDragPauseDetector.clearDisabledFlags(FLAG_OVERVIEW_DISABLED_FLING);
|
||||
updatePauseDetectorRangeFlag();
|
||||
}
|
||||
}
|
||||
|
||||
private float getShiftRange() {
|
||||
return mLauncher.getAllAppsController().getShiftRange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(float displacement, float velocity) {
|
||||
float deltaProgress = mProgressMultiplier * displacement;
|
||||
mCurrentAnimation.setPlayFraction(deltaProgress + mStartProgress);
|
||||
|
||||
updatePauseDetectorRangeFlag();
|
||||
mDragPauseDetector.onDrag(velocity);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updatePauseDetectorRangeFlag() {
|
||||
if (mOverviewProgressRange.contains(mCurrentAnimation.getProgressFraction())) {
|
||||
mDragPauseDetector.clearDisabledFlags(FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE);
|
||||
} else {
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_OUT_OF_RANGE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragEnd(float velocity, boolean fling) {
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_FLING);
|
||||
|
||||
final int logAction;
|
||||
LauncherState targetState;
|
||||
final float progress = mCurrentAnimation.getProgressFraction();
|
||||
|
||||
if (fling) {
|
||||
logAction = Touch.FLING;
|
||||
targetState = velocity < 0 ? ALL_APPS : mLauncher.getStateManager().getLastState();
|
||||
// snap to top or bottom using the release velocity
|
||||
} else {
|
||||
logAction = Touch.SWIPE;
|
||||
targetState = (progress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
|
||||
}
|
||||
|
||||
float endProgress;
|
||||
|
||||
if (mDragPauseDetector.isTriggered() && targetState == NORMAL) {
|
||||
targetState = OVERVIEW;
|
||||
endProgress = OVERVIEW.getVerticalProgress(mLauncher);
|
||||
if (mFromState == NORMAL) {
|
||||
endProgress = 1 - endProgress;
|
||||
}
|
||||
} else if (targetState == mToState) {
|
||||
endProgress = 1;
|
||||
} else {
|
||||
endProgress = 0;
|
||||
}
|
||||
|
||||
LauncherState targetStateFinal = targetState;
|
||||
mCurrentAnimation.setEndAction(() ->
|
||||
onSwipeInteractionCompleted(targetStateFinal, logAction));
|
||||
|
||||
float nextFrameProgress = Utilities.boundToRange(
|
||||
progress + velocity * SINGLE_FRAME_MS / getShiftRange(), 0f, 1f);
|
||||
|
||||
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
|
||||
anim.setFloatValues(nextFrameProgress, endProgress);
|
||||
anim.setDuration(
|
||||
SwipeDetector.calculateDuration(velocity, Math.abs(endProgress - progress)));
|
||||
anim.setInterpolator(scrollInterpolatorForVelocity(velocity));
|
||||
anim.start();
|
||||
}
|
||||
|
||||
private void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
|
||||
if (targetState != mFromState) {
|
||||
// Transition complete. log the action
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
|
||||
mToState == ALL_APPS ? Direction.UP : Direction.DOWN,
|
||||
mStartContainerType,
|
||||
mFromState.containerType,
|
||||
mToState.containerType,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
}
|
||||
clearState();
|
||||
|
||||
// TODO: mQuickOverviewAnimation might still be running in which changing a state instantly
|
||||
// may cause a jump. Animate the state change with a short duration in this case?
|
||||
mLauncher.getStateManager().goToState(targetState, false /* animated */);
|
||||
}
|
||||
|
||||
private void onDragPauseDetected() {
|
||||
final ValueAnimator twoStepAnimator = ValueAnimator.ofFloat(0, 1);
|
||||
twoStepAnimator.setDuration(mCurrentAnimation.getDuration());
|
||||
StateHandler[] handlers = mLauncher.getStateManager().getStateHandlers();
|
||||
|
||||
// Change the current animation to only play the vertical handle
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.playTogether(mTaggedAnimatorSetBuilder.getAnimationsForTag(
|
||||
handlers[SWIPE_HANDLER_INDEX]));
|
||||
anim.play(twoStepAnimator);
|
||||
mCurrentAnimation = mCurrentAnimation.cloneFor(anim);
|
||||
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
AnimationConfig config = new AnimationConfig();
|
||||
config.duration = QUICK_SNAP_TO_OVERVIEW_DURATION;
|
||||
for (int i = OTHER_HANDLERS_START_INDEX; i < handlers.length; i++) {
|
||||
handlers[i].setStateWithAnimation(OVERVIEW, builder, config);
|
||||
}
|
||||
mQuickOverviewAnimation = builder.build();
|
||||
mQuickOverviewAnimation.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
onQuickOverviewAnimationComplete(twoStepAnimator);
|
||||
}
|
||||
});
|
||||
mQuickOverviewAnimation.start();
|
||||
}
|
||||
|
||||
private void onQuickOverviewAnimationComplete(ValueAnimator animator) {
|
||||
if (mAnimatingToOverview) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For the remainder to the interaction, the user can either go to the ALL_APPS state or
|
||||
// the OVERVIEW state.
|
||||
// The remaining state handlers are on the OVERVIEW state. Create one animation towards the
|
||||
// ALL_APPS state and only call it when the user moved above the current range.
|
||||
AnimationConfig config = new AnimationConfig();
|
||||
config.duration = (long) (2 * getShiftRange());
|
||||
config.userControlled = true;
|
||||
|
||||
AnimatorSetBuilder builderToAllAppsState = new AnimatorSetBuilder();
|
||||
StateHandler[] handlers = mLauncher.getStateManager().getStateHandlers();
|
||||
for (int i = OTHER_HANDLERS_START_INDEX; i < handlers.length; i++) {
|
||||
handlers[i].setStateWithAnimation(ALL_APPS, builderToAllAppsState, config);
|
||||
}
|
||||
|
||||
mCroppedAnimationController = new CroppedAnimationController(
|
||||
AnimatorPlaybackController.wrap(builderToAllAppsState.build(), config.duration),
|
||||
new FloatRange(animator.getAnimatedFraction(), mToState == ALL_APPS ? 1 : 0));
|
||||
animator.addUpdateListener(mCroppedAnimationController);
|
||||
}
|
||||
|
||||
private void clearState() {
|
||||
mCurrentAnimation = null;
|
||||
mTaggedAnimatorSetBuilder = null;
|
||||
if (mDragPauseDetector != null) {
|
||||
mDragPauseDetector.addDisabledFlags(FLAG_OVERVIEW_DISABLED_CANCEL_STATE);
|
||||
}
|
||||
mDragPauseDetector = null;
|
||||
|
||||
if (mQuickOverviewAnimation != null) {
|
||||
mQuickOverviewAnimation.cancel();
|
||||
mQuickOverviewAnimation = null;
|
||||
}
|
||||
mCroppedAnimationController = null;
|
||||
mAnimatingToOverview = false;
|
||||
|
||||
mDetector.finishedScrolling();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link AnimatorUpdateListener} which controls another animation for a fraction of range
|
||||
*/
|
||||
private static class CroppedAnimationController implements AnimatorUpdateListener {
|
||||
|
||||
private final AnimatorPlaybackController mTarget;
|
||||
private final FloatRange mRange;
|
||||
|
||||
CroppedAnimationController(AnimatorPlaybackController target, FloatRange range) {
|
||||
mTarget = target;
|
||||
mRange = range;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
float fraction = valueAnimator.getAnimatedFraction();
|
||||
|
||||
if (mRange.start < mRange.end) {
|
||||
if (fraction <= mRange.start) {
|
||||
mTarget.setPlayFraction(0);
|
||||
} else if (fraction >= mRange.end) {
|
||||
mTarget.setPlayFraction(1);
|
||||
} else {
|
||||
mTarget.setPlayFraction((fraction - mRange.start) / (mRange.end - mRange.start));
|
||||
}
|
||||
} else if (mRange.start > mRange.end) {
|
||||
if (fraction >= mRange.start) {
|
||||
mTarget.setPlayFraction(0);
|
||||
} else if (fraction <= mRange.end) {
|
||||
mTarget.setPlayFraction(1);
|
||||
} else {
|
||||
mTarget.setPlayFraction((fraction - mRange.start) / (mRange.end - mRange.start));
|
||||
}
|
||||
} else {
|
||||
// mRange.start == mRange.end
|
||||
mTarget.setPlayFraction(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,19 @@
|
||||
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.Utilities.getPrefs;
|
||||
import static com.android.quickstep.OverviewInteractionState.KEY_SWIPE_UP_ENABLED;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.view.View;
|
||||
import android.view.View.AccessibilityDelegate;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.OverviewInteractionState;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
@@ -34,15 +37,25 @@ import com.android.quickstep.views.RecentsView;
|
||||
public class UiFactory {
|
||||
|
||||
public static TouchController[] createTouchControllers(Launcher launcher) {
|
||||
if (FeatureFlags.ENABLE_TWO_SWIPE_TARGETS) {
|
||||
SharedPreferences prefs = getPrefs(launcher);
|
||||
boolean swipeUpEnabled = prefs.getBoolean(KEY_SWIPE_UP_ENABLED, true);
|
||||
if (!swipeUpEnabled) {
|
||||
return new TouchController[] {
|
||||
new EdgeSwipeController(launcher),
|
||||
new TwoStepSwipeController(launcher),
|
||||
new OverviewSwipeController(launcher)};
|
||||
launcher.getDragController(),
|
||||
new LandscapeStatesTouchController(launcher),
|
||||
new TaskViewTouchController(launcher)};
|
||||
}
|
||||
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
return new TouchController[] {
|
||||
launcher.getDragController(),
|
||||
new LandscapeStatesTouchController(launcher),
|
||||
new LandscapeEdgeSwipeController(launcher),
|
||||
new TaskViewTouchController(launcher)};
|
||||
} else {
|
||||
return new TouchController[] {
|
||||
new TwoStepSwipeController(launcher),
|
||||
new OverviewSwipeController(launcher)};
|
||||
launcher.getDragController(),
|
||||
new PortraitStatesTouchController(launcher),
|
||||
new TaskViewTouchController(launcher)};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,21 +70,15 @@ public class UiFactory {
|
||||
}
|
||||
|
||||
public static void onLauncherStateOrFocusChanged(Launcher launcher) {
|
||||
boolean shouldBackButtonBeVisible = launcher == null
|
||||
|| !launcher.isInState(NORMAL)
|
||||
|| !launcher.hasWindowFocus();
|
||||
if (!shouldBackButtonBeVisible) {
|
||||
boolean shouldBackButtonBeHidden = launcher != null
|
||||
&& launcher.getStateManager().getState().hideBackButton
|
||||
&& launcher.hasWindowFocus();
|
||||
if (shouldBackButtonBeHidden) {
|
||||
// Show the back button if there is a floating view visible.
|
||||
DragLayer dragLayer = launcher.getDragLayer();
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = dragLayer.getChildAt(i);
|
||||
if (child instanceof AbstractFloatingView) {
|
||||
shouldBackButtonBeVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenView(launcher) == null;
|
||||
}
|
||||
OverviewInteractionState.setBackButtonVisible(launcher, shouldBackButtonBeVisible);
|
||||
OverviewInteractionState.getInstance(launcher)
|
||||
.setBackButtonVisible(!shouldBackButtonBeHidden);
|
||||
}
|
||||
|
||||
public static void resetOverview(Launcher launcher) {
|
||||
@@ -79,17 +86,24 @@ public class UiFactory {
|
||||
recents.reset();
|
||||
}
|
||||
|
||||
public static void onStart(Launcher launcher) {
|
||||
RecentsModel model = RecentsModel.getInstance(launcher);
|
||||
public static void onStart(Context context) {
|
||||
RecentsModel model = RecentsModel.getInstance(context);
|
||||
if (model != null) {
|
||||
model.onStart();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onTrimMemory(Launcher launcher, int level) {
|
||||
RecentsModel model = RecentsModel.getInstance(launcher);
|
||||
public static void onTrimMemory(Context context, int level) {
|
||||
RecentsModel model = RecentsModel.getInstance(context);
|
||||
if (model != null) {
|
||||
model.onTrimMemory(level);
|
||||
}
|
||||
}
|
||||
|
||||
public static View[] getHotseatExtraContent(Hotseat hotseat) {
|
||||
return new View[] {
|
||||
hotseat.findViewById(R.id.drag_indicator),
|
||||
hotseat.findViewById(R.id.search_container_hotseat),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* 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.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherInitListener;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.util.ViewOnDrawExecutor;
|
||||
import com.android.quickstep.views.LauncherLayoutListener;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.AssistDataReceiver;
|
||||
import com.android.systemui.shared.system.RecentsAnimationListener;
|
||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
|
||||
*/
|
||||
public interface ActivityControlHelper<T extends BaseDraggingActivity> {
|
||||
|
||||
LayoutListener createLayoutListener(T activity);
|
||||
|
||||
void onQuickstepGestureStarted(T activity, boolean activityVisible);
|
||||
|
||||
void onQuickInteractionStart(T activity, boolean activityVisible);
|
||||
|
||||
void executeOnNextDraw(T activity, TaskView targetView, Runnable action);
|
||||
|
||||
void onTransitionCancelled(T activity, boolean activityVisible);
|
||||
|
||||
int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);
|
||||
|
||||
void onSwipeUpComplete(T activity);
|
||||
|
||||
void prepareRecentsUI(T activity, boolean activityVisible);
|
||||
|
||||
AnimatorPlaybackController createControllerForVisibleActivity(T activity);
|
||||
|
||||
AnimatorPlaybackController createControllerForHiddenActivity(T activity, int transitionLength);
|
||||
|
||||
ActivityInitListener createActivityInitListener(BiPredicate<T, Boolean> onInitListener);
|
||||
|
||||
void startRecents(Context context, Intent intent, AssistDataReceiver assistDataReceiver,
|
||||
RecentsAnimationListener remoteAnimationListener);
|
||||
|
||||
@UiThread
|
||||
@Nullable
|
||||
RecentsView getVisibleRecentsView();
|
||||
|
||||
@UiThread
|
||||
boolean switchToRecentsIfVisible();
|
||||
|
||||
class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
|
||||
|
||||
@Override
|
||||
public LayoutListener createLayoutListener(Launcher activity) {
|
||||
return new LauncherLayoutListener(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickstepGestureStarted(Launcher activity, boolean activityVisible) {
|
||||
activity.onQuickstepGestureStarted(activityVisible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickInteractionStart(Launcher activity, boolean activityVisible) {
|
||||
activity.getStateManager().goToState(FAST_OVERVIEW, activityVisible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeOnNextDraw(Launcher activity, TaskView targetView, Runnable action) {
|
||||
ViewOnDrawExecutor executor = new ViewOnDrawExecutor() {
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
if (!isCompleted()) {
|
||||
runAllTasks();
|
||||
}
|
||||
}
|
||||
};
|
||||
executor.attachTo(activity, targetView, false /* waitForLoadAnimation */);
|
||||
executor.execute(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
|
||||
RecentsView.getPageRect(dp, context, outRect);
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
Rect targetInsets = dp.getInsets();
|
||||
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
|
||||
return dp.hotseatBarSizePx + dp.hotseatBarSidePaddingPx + hotseatInset;
|
||||
} else {
|
||||
return dp.heightPx - outRect.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionCancelled(Launcher activity, boolean activityVisible) {
|
||||
LauncherState startState = activity.getStateManager().getRestState();
|
||||
activity.getStateManager().goToState(startState, activityVisible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeUpComplete(Launcher activity) {
|
||||
// Re apply state in case we did something funky during the transition.
|
||||
activity.getStateManager().reapplyState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareRecentsUI(Launcher activity, boolean activityVisible) {
|
||||
LauncherState startState = activity.getStateManager().getState();
|
||||
if (startState.disableRestore) {
|
||||
startState = activity.getStateManager().getRestState();
|
||||
}
|
||||
activity.getStateManager().setRestState(startState);
|
||||
|
||||
if (!activityVisible) {
|
||||
// Since the launcher is not visible, we can safely reset the scroll position.
|
||||
// This ensures then the next swipe up to all-apps starts from scroll 0.
|
||||
activity.getAppsView().reset(false /* animate */);
|
||||
activity.getStateManager().goToState(OVERVIEW, false);
|
||||
|
||||
// Optimization, hide the all apps view to prevent layout while initializing
|
||||
activity.getAppsView().getContentView().setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatorPlaybackController createControllerForVisibleActivity(Launcher activity) {
|
||||
DeviceProfile dp = activity.getDeviceProfile();
|
||||
long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
|
||||
return activity.getStateManager().createAnimationToNewWorkspace(OVERVIEW, accuracy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatorPlaybackController createControllerForHiddenActivity(
|
||||
Launcher activity, int transitionLength) {
|
||||
AllAppsTransitionController controller = activity.getAllAppsController();
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
if (activity.getDeviceProfile().isVerticalBarLayout()) {
|
||||
// TODO:
|
||||
} else {
|
||||
float scrollRange = Math.max(controller.getShiftRange(), 1);
|
||||
float progressDelta = (transitionLength / scrollRange);
|
||||
|
||||
float endProgress = OVERVIEW.getVerticalProgress(activity);
|
||||
float startProgress = endProgress + progressDelta;
|
||||
ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(
|
||||
controller, ALL_APPS_PROGRESS, startProgress, endProgress);
|
||||
shiftAnim.setInterpolator(LINEAR);
|
||||
anim.play(shiftAnim);
|
||||
}
|
||||
|
||||
// TODO: Link this animation to state animation, so that it is cancelled
|
||||
// automatically on state change
|
||||
anim.setDuration(transitionLength * 2);
|
||||
return AnimatorPlaybackController.wrap(anim, transitionLength * 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityInitListener createActivityInitListener(
|
||||
BiPredicate<Launcher, Boolean> onInitListener) {
|
||||
return new LauncherInitListener(onInitListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecents(Context context, Intent intent,
|
||||
AssistDataReceiver assistDataReceiver,
|
||||
RecentsAnimationListener remoteAnimationListener) {
|
||||
ActivityManagerWrapper.getInstance().startRecentsActivity(
|
||||
intent, assistDataReceiver, remoteAnimationListener, null, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@UiThread
|
||||
private Launcher getVisibleLaucher() {
|
||||
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
|
||||
if (app == null) {
|
||||
return null;
|
||||
}
|
||||
Launcher launcher = (Launcher) app.getModel().getCallback();
|
||||
return (launcher != null) && launcher.isStarted() && launcher.hasWindowFocus() ?
|
||||
launcher : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RecentsView getVisibleRecentsView() {
|
||||
Launcher launcher = getVisibleLaucher();
|
||||
return launcher != null && launcher.isInState(OVERVIEW)
|
||||
? launcher.getOverviewPanel() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean switchToRecentsIfVisible() {
|
||||
Launcher launcher = getVisibleLaucher();
|
||||
if (launcher != null) {
|
||||
launcher.getStateManager().goToState(OVERVIEW);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
|
||||
|
||||
@Override
|
||||
public void onQuickstepGestureStarted(RecentsActivity activity, boolean activityVisible) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickInteractionStart(RecentsActivity activity, boolean activityVisible) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeOnNextDraw(RecentsActivity activity, TaskView targetView,
|
||||
Runnable action) {
|
||||
// TODO:
|
||||
new Handler(Looper.getMainLooper()).post(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionCancelled(RecentsActivity activity, boolean activityVisible) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
|
||||
FallbackRecentsView.getCenterPageRect(dp, context, outRect);
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
Rect targetInsets = dp.getInsets();
|
||||
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
|
||||
return dp.hotseatBarSizePx + dp.hotseatBarSidePaddingPx + hotseatInset;
|
||||
} else {
|
||||
return dp.heightPx - outRect.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeUpComplete(RecentsActivity activity) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareRecentsUI(RecentsActivity activity, boolean activityVisible) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatorPlaybackController createControllerForVisibleActivity(
|
||||
RecentsActivity activity) {
|
||||
DeviceProfile dp = activity.getDeviceProfile();
|
||||
return createControllerForHiddenActivity(activity, Math.max(dp.widthPx, dp.heightPx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatorPlaybackController createControllerForHiddenActivity(
|
||||
RecentsActivity activity, int transitionLength) {
|
||||
// We do not animate anything. Create a empty controller
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
return AnimatorPlaybackController.wrap(anim, transitionLength * 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutListener createLayoutListener(RecentsActivity activity) {
|
||||
// We do not change anything as part of layout changes in fallback activity. Return a
|
||||
// default layout listener.
|
||||
return new LayoutListener() {
|
||||
@Override
|
||||
public void open() { }
|
||||
|
||||
@Override
|
||||
public void setHandler(WindowTransformSwipeHandler handler) { }
|
||||
|
||||
@Override
|
||||
public void finish() { }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityInitListener createActivityInitListener(
|
||||
BiPredicate<RecentsActivity, Boolean> onInitListener) {
|
||||
return new RecentsActivityTracker(onInitListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecents(Context context, Intent intent,
|
||||
AssistDataReceiver assistDataReceiver,
|
||||
final RecentsAnimationListener remoteAnimationListener) {
|
||||
ActivityOptions options =
|
||||
ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
|
||||
new FallbackActivityOptions(remoteAnimationListener), 10000, 10000));
|
||||
context.startActivity(intent, options.toBundle());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RecentsView getVisibleRecentsView() {
|
||||
RecentsActivity activity = RecentsActivityTracker.getCurrentActivity();
|
||||
if (activity != null && activity.hasWindowFocus()) {
|
||||
return activity.getOverviewPanel();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean switchToRecentsIfVisible() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
interface LayoutListener {
|
||||
|
||||
void open();
|
||||
|
||||
void setHandler(WindowTransformSwipeHandler handler);
|
||||
|
||||
void finish();
|
||||
}
|
||||
|
||||
interface ActivityInitListener {
|
||||
|
||||
void register();
|
||||
|
||||
void unregister();
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.quickstep;
|
||||
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.states.InternalStateHandler;
|
||||
import com.android.quickstep.TouchConsumer.InteractionType;
|
||||
|
||||
public abstract class BaseSwipeInteractionHandler extends InternalStateHandler {
|
||||
|
||||
protected Runnable mGestureEndCallback;
|
||||
protected boolean mIsGoingToHome;
|
||||
|
||||
public void setGestureEndCallback(Runnable gestureEndCallback) {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
|
||||
public void reset() {}
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onGestureStarted();
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onGestureEnded(float endVelocity);
|
||||
|
||||
public abstract void updateInteractionType(@InteractionType int interactionType);
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onQuickScrubEnd();
|
||||
|
||||
@WorkerThread
|
||||
public abstract void onQuickScrubProgress(float progress);
|
||||
|
||||
@WorkerThread
|
||||
public abstract void updateDisplacement(float displacement);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.quickstep;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
|
||||
import com.android.systemui.shared.system.RecentsAnimationListener;
|
||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
/**
|
||||
* Temporary class to create activity options to emulate recents transition for fallback activtiy.
|
||||
*/
|
||||
public class FallbackActivityOptions implements RemoteAnimationRunnerCompat {
|
||||
|
||||
private final RecentsAnimationListener mListener;
|
||||
|
||||
public FallbackActivityOptions(RecentsAnimationListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats,
|
||||
Runnable runnable) {
|
||||
DummyRecentsAnimationControllerCompat dummyRecentsAnim =
|
||||
new DummyRecentsAnimationControllerCompat(runnable);
|
||||
|
||||
Rect insets = new Rect();
|
||||
WindowManagerWrapper.getInstance().getStableInsets(insets);
|
||||
mListener.onAnimationStart(dummyRecentsAnim, targetCompats, insets, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
mListener.onAnimationCanceled();
|
||||
}
|
||||
|
||||
private static class DummyRecentsAnimationControllerCompat
|
||||
extends RecentsAnimationControllerCompat {
|
||||
|
||||
final Runnable mFinishCallback;
|
||||
|
||||
public DummyRecentsAnimationControllerCompat(Runnable finishCallback) {
|
||||
mFinishCallback = finishCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThumbnailData screenshotTask(int taskId) {
|
||||
return new ThumbnailData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputConsumerEnabled(boolean enabled) { }
|
||||
|
||||
@Override
|
||||
public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) { }
|
||||
|
||||
@Override
|
||||
public void finish(boolean toHome) {
|
||||
if (toHome) {
|
||||
mFinishCallback.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,10 +48,21 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> implements
|
||||
setPadding(padding.left, padding.top, padding.right, padding.bottom);
|
||||
}
|
||||
|
||||
public static void verticalCenter(Rect padding, DeviceProfile dp) {
|
||||
private static void verticalCenter(Rect padding, DeviceProfile dp) {
|
||||
Rect insets = dp.getInsets();
|
||||
int totalSpace = (padding.top + padding.bottom - insets.top - insets.bottom) / 2;
|
||||
padding.top = insets.top + totalSpace;
|
||||
padding.bottom = insets.bottom + totalSpace;
|
||||
}
|
||||
|
||||
public static void getCenterPageRect(DeviceProfile grid, Context context, Rect outRect) {
|
||||
Rect targetPadding = getPadding(grid, context);
|
||||
verticalCenter(targetPadding, grid);
|
||||
Rect insets = grid.getInsets();
|
||||
outRect.set(
|
||||
targetPadding.left + insets.left,
|
||||
targetPadding.top + insets.top,
|
||||
grid.widthPx - targetPadding.right - insets.right,
|
||||
grid.heightPx - targetPadding.bottom - insets.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.quickstep;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.os.Build;
|
||||
import android.provider.SearchIndexablesContract.XmlResource;
|
||||
import android.provider.SearchIndexablesProvider;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.IconShapeOverride;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
|
||||
import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
|
||||
import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class LauncherSearchIndexablesProvider extends SearchIndexablesProvider {
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryXmlResources(String[] strings) {
|
||||
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
|
||||
ResolveInfo settingsActivity = getContext().getPackageManager().resolveActivity(
|
||||
new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
|
||||
.setPackage(getContext().getPackageName()), 0);
|
||||
cursor.newRow()
|
||||
.add(XmlResource.COLUMN_XML_RESID, R.xml.indexable_launcher_prefs)
|
||||
.add(XmlResource.COLUMN_INTENT_ACTION, Intent.ACTION_APPLICATION_PREFERENCES)
|
||||
.add(XmlResource.COLUMN_INTENT_TARGET_PACKAGE, getContext().getPackageName())
|
||||
.add(XmlResource.COLUMN_INTENT_TARGET_CLASS, settingsActivity.activityInfo.name);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryRawData(String[] projection) {
|
||||
return new MatrixCursor(INDEXABLES_RAW_COLUMNS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryNonIndexableKeys(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
|
||||
if (!getContext().getSystemService(LauncherApps.class).hasShortcutHostPermission()) {
|
||||
// We are not the current launcher. Hide all preferences
|
||||
try (XmlResourceParser parser = getContext().getResources()
|
||||
.getXml(R.xml.indexable_launcher_prefs)) {
|
||||
final int depth = parser.getDepth();
|
||||
final int[] attrs = new int[] { android.R.attr.key };
|
||||
int type;
|
||||
while (((type = parser.next()) != XmlPullParser.END_TAG ||
|
||||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
TypedArray a = getContext().obtainStyledAttributes(
|
||||
Xml.asAttributeSet(parser), attrs);
|
||||
cursor.addRow(new String[] {a.getString(0)});
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
} catch (IOException |XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (!IconShapeOverride.isSupported(getContext())) {
|
||||
cursor.addRow(new String[] {IconShapeOverride.KEY_PREFERENCE});
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,7 @@ import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
import static android.view.MotionEvent.ACTION_MASK;
|
||||
import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
@@ -43,17 +41,17 @@ public class MotionEventQueue {
|
||||
|
||||
private static final int ACTION_VIRTUAL = ACTION_MASK - 1;
|
||||
|
||||
private static final int ACTION_QUICK_SWITCH =
|
||||
ACTION_VIRTUAL | (1 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_QUICK_SCRUB_START =
|
||||
ACTION_VIRTUAL | (2 << ACTION_POINTER_INDEX_SHIFT);
|
||||
ACTION_VIRTUAL | (1 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_QUICK_SCRUB_PROGRESS =
|
||||
ACTION_VIRTUAL | (3 << ACTION_POINTER_INDEX_SHIFT);
|
||||
ACTION_VIRTUAL | (2 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_QUICK_SCRUB_END =
|
||||
ACTION_VIRTUAL | (4 << ACTION_POINTER_INDEX_SHIFT);
|
||||
ACTION_VIRTUAL | (3 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_RESET =
|
||||
ACTION_VIRTUAL | (5 << ACTION_POINTER_INDEX_SHIFT);
|
||||
ACTION_VIRTUAL | (4 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_DEFER_INIT =
|
||||
ACTION_VIRTUAL | (5 << ACTION_POINTER_INDEX_SHIFT);
|
||||
private static final int ACTION_SHOW_OVERVIEW_FROM_ALT_TAB =
|
||||
ACTION_VIRTUAL | (6 << ACTION_POINTER_INDEX_SHIFT);
|
||||
|
||||
private final EventArray mEmptyArray = new EventArray();
|
||||
@@ -143,9 +141,6 @@ public class MotionEventQueue {
|
||||
MotionEvent event = array.get(i);
|
||||
if (event.getActionMasked() == ACTION_VIRTUAL) {
|
||||
switch (event.getAction()) {
|
||||
case ACTION_QUICK_SWITCH:
|
||||
mConsumer.updateTouchTracking(INTERACTION_QUICK_SWITCH);
|
||||
break;
|
||||
case ACTION_QUICK_SCRUB_START:
|
||||
mConsumer.updateTouchTracking(INTERACTION_QUICK_SCRUB);
|
||||
break;
|
||||
@@ -161,6 +156,10 @@ public class MotionEventQueue {
|
||||
case ACTION_DEFER_INIT:
|
||||
mConsumer.deferInit();
|
||||
break;
|
||||
case ACTION_SHOW_OVERVIEW_FROM_ALT_TAB:
|
||||
mConsumer.onShowOverviewFromAltTab();
|
||||
mConsumer.updateTouchTracking(INTERACTION_QUICK_SCRUB);
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Invalid virtual event: " + event.getAction());
|
||||
}
|
||||
@@ -189,14 +188,14 @@ public class MotionEventQueue {
|
||||
queueNoPreProcess(MotionEvent.obtain(0, 0, action, progress, 0, 0));
|
||||
}
|
||||
|
||||
public void onQuickSwitch() {
|
||||
queueVirtualAction(ACTION_QUICK_SWITCH, 0);
|
||||
}
|
||||
|
||||
public void onQuickScrubStart() {
|
||||
queueVirtualAction(ACTION_QUICK_SCRUB_START, 0);
|
||||
}
|
||||
|
||||
public void onOverviewShownFromAltTab() {
|
||||
queueVirtualAction(ACTION_SHOW_OVERVIEW_FROM_ALT_TAB, 0);
|
||||
}
|
||||
|
||||
public void onQuickScrubProgress(float progress) {
|
||||
queueVirtualAction(ACTION_QUICK_SCRUB_PROGRESS, progress);
|
||||
}
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.quickstep;
|
||||
|
||||
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH;
|
||||
import static com.android.quickstep.TouchConsumer.isInteractionQuick;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.RectEvaluator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Launcher.OnResumeCallback;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.TouchConsumer.InteractionType;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class NavBarSwipeInteractionHandler extends BaseSwipeInteractionHandler implements
|
||||
OnResumeCallback {
|
||||
|
||||
private static final int STATE_LAUNCHER_READY = 1 << 0;
|
||||
private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 4;
|
||||
private static final int STATE_SCALED_SNAPSHOT_RECENTS = 1 << 5;
|
||||
private static final int STATE_SCALED_SNAPSHOT_APP = 1 << 6;
|
||||
|
||||
private static final long MAX_SWIPE_DURATION = 200;
|
||||
private static final long MIN_SWIPE_DURATION = 80;
|
||||
|
||||
// Ideal velocity for a smooth transition
|
||||
private static final float PIXEL_PER_MS = 2f;
|
||||
|
||||
private static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f;
|
||||
|
||||
private final Rect mStableInsets = new Rect();
|
||||
private final Rect mSourceRect = new Rect();
|
||||
private final Rect mTargetRect = new Rect();
|
||||
private final Rect mCurrentRect = new Rect();
|
||||
private final RectEvaluator mRectEvaluator = new RectEvaluator(mCurrentRect);
|
||||
|
||||
// Shift in the range of [0, 1].
|
||||
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
|
||||
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
|
||||
// visible.
|
||||
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
|
||||
|
||||
// Activity multiplier in the range of [0, 1]. When the activity becomes visible, this is
|
||||
// animated to 1, so allow for a smooth transition.
|
||||
private final AnimatedFloat mActivityMultiplier = new AnimatedFloat(this::updateFinalShift);
|
||||
|
||||
private final int mRunningTaskId;
|
||||
private final Context mContext;
|
||||
|
||||
private final MultiStateCallback mStateCallback;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private SnapshotDragView mDragView;
|
||||
private RecentsView mRecentsView;
|
||||
private QuickScrubController mQuickScrubController;
|
||||
private Hotseat mHotseat;
|
||||
|
||||
private boolean mWasLauncherAlreadyVisible;
|
||||
|
||||
private boolean mLauncherReady;
|
||||
private boolean mTouchEndHandled;
|
||||
private float mCurrentDisplacement;
|
||||
|
||||
private @InteractionType int mInteractionType;
|
||||
private boolean mStartedQuickScrubFromHome;
|
||||
|
||||
private Bitmap mTaskSnapshot;
|
||||
|
||||
NavBarSwipeInteractionHandler(RunningTaskInfo runningTaskInfo, Context context,
|
||||
@InteractionType int interactionType) {
|
||||
mContext = context;
|
||||
mInteractionType = interactionType;
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
|
||||
|
||||
DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
|
||||
// TODO: If in multi window mode, dp = dp.getMultiWindowProfile()
|
||||
dp = dp.copy(mContext);
|
||||
// TODO: Use different insets for multi-window mode
|
||||
dp.updateInsets(mStableInsets);
|
||||
RecentsView.getPageRect(dp, mContext, mTargetRect);
|
||||
mSourceRect.set(0, 0, dp.widthPx - mStableInsets.left - mStableInsets.right,
|
||||
dp.heightPx - mStableInsets.top - mStableInsets.bottom);
|
||||
|
||||
// Build the state callback
|
||||
mStateCallback = new MultiStateCallback();
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_READY, this::onLauncherReady);
|
||||
mStateCallback.addCallback(STATE_SCALED_SNAPSHOT_APP, this::resumeLastTask);
|
||||
mStateCallback.addCallback(
|
||||
STATE_SCALED_SNAPSHOT_RECENTS | STATE_ACTIVITY_MULTIPLIER_COMPLETE,
|
||||
this::onAnimationToLauncherComplete);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_SCALED_SNAPSHOT_APP,
|
||||
this::cleanupLauncher);
|
||||
}
|
||||
|
||||
private void onLauncherReady() {
|
||||
mLauncherReady = true;
|
||||
executeFrameUpdate();
|
||||
|
||||
long duration = Math.min(MAX_SWIPE_DURATION,
|
||||
Math.max((long) (-mCurrentDisplacement / PIXEL_PER_MS), MIN_SWIPE_DURATION));
|
||||
if (mCurrentShift.getCurrentAnimation() != null) {
|
||||
ObjectAnimator anim = mCurrentShift.getCurrentAnimation();
|
||||
long theirDuration = anim.getDuration() - anim.getCurrentPlayTime();
|
||||
|
||||
// TODO: Find a better heuristic
|
||||
duration = (duration + theirDuration) / 2;
|
||||
}
|
||||
ObjectAnimator anim = mActivityMultiplier.animateToValue(1)
|
||||
.setDuration(duration);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
public void setTaskSnapshot(Bitmap taskSnapshot) {
|
||||
mTaskSnapshot = taskSnapshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLauncherResume() {
|
||||
TraceHelper.partitionSection("TouchInt", "Launcher On resume");
|
||||
mDragView.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
mDragView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
mStateCallback.setState(STATE_LAUNCHER_READY);
|
||||
TraceHelper.partitionSection("TouchInt", "Launcher drawn");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean init(Launcher launcher, boolean alreadyOnHome) {
|
||||
launcher.setOnResumeCallback(this);
|
||||
mLauncher = launcher;
|
||||
mRecentsView = launcher.getOverviewPanel();
|
||||
mRecentsView.showTask(mRunningTaskId);
|
||||
mHotseat = mLauncher.getHotseat();
|
||||
mWasLauncherAlreadyVisible = alreadyOnHome;
|
||||
|
||||
AbstractFloatingView.closeAllOpenViews(mLauncher, alreadyOnHome);
|
||||
mLauncher.getStateManager().goToState(LauncherState.OVERVIEW, alreadyOnHome);
|
||||
|
||||
mDragView = new SnapshotDragView(mLauncher, mTaskSnapshot);
|
||||
mLauncher.getDragLayer().addView(mDragView);
|
||||
mDragView.setPivotX(0);
|
||||
mDragView.setPivotY(0);
|
||||
|
||||
if (isInteractionQuick(mInteractionType)) {
|
||||
updateUiForQuickScrub();
|
||||
}
|
||||
|
||||
// Optimization
|
||||
if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
// All-apps search box is visible in vertical bar layout.
|
||||
mLauncher.getAppsView().setVisibility(View.GONE);
|
||||
}
|
||||
TraceHelper.partitionSection("TouchInt", "Launcher on new intent");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateInteractionType(@InteractionType int interactionType) {
|
||||
Preconditions.assertUIThread();
|
||||
if (mInteractionType != INTERACTION_NORMAL) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change interaction type from " + mInteractionType);
|
||||
}
|
||||
if (!isInteractionQuick(interactionType)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change interaction type to " + interactionType);
|
||||
}
|
||||
mInteractionType = interactionType;
|
||||
|
||||
if (mLauncher != null) {
|
||||
updateUiForQuickScrub();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUiForQuickScrub() {
|
||||
mStartedQuickScrubFromHome = mWasLauncherAlreadyVisible;
|
||||
mQuickScrubController = mRecentsView.getQuickScrubController();
|
||||
mQuickScrubController.onQuickScrubStart(mStartedQuickScrubFromHome);
|
||||
animateToProgress(1f, MAX_SWIPE_DURATION);
|
||||
if (mStartedQuickScrubFromHome) {
|
||||
mDragView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void updateDisplacement(float displacement) {
|
||||
mCurrentDisplacement = displacement;
|
||||
executeFrameUpdate();
|
||||
}
|
||||
|
||||
private void executeFrameUpdate() {
|
||||
if (mLauncherReady) {
|
||||
final float displacement = -mCurrentDisplacement;
|
||||
int hotseatSize = getHotseatSize();
|
||||
float translation = Utilities.boundToRange(displacement, 0, hotseatSize);
|
||||
float shift = hotseatSize == 0 ? 0 : translation / hotseatSize;
|
||||
mCurrentShift.updateValue(shift);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void updateFinalShift() {
|
||||
if (!mLauncherReady || mStartedQuickScrubFromHome) {
|
||||
return;
|
||||
}
|
||||
|
||||
float shift = mCurrentShift.value * mActivityMultiplier.value;
|
||||
|
||||
AllAppsTransitionController controller = mLauncher.getAllAppsController();
|
||||
float range = getHotseatSize() / controller.getShiftRange();
|
||||
controller.setProgress(1 + (1 - shift) * range);
|
||||
|
||||
mRectEvaluator.evaluate(shift, mSourceRect, mTargetRect);
|
||||
|
||||
float scale = (float) mCurrentRect.width() / mSourceRect.width();
|
||||
mDragView.setTranslationX(mCurrentRect.left - mStableInsets.left * scale * shift);
|
||||
mDragView.setTranslationY(mCurrentRect.top - mStableInsets.top * scale * shift);
|
||||
mDragView.setScaleX(scale);
|
||||
mDragView.setScaleY(scale);
|
||||
// TODO: mDragView.getViewBounds().setClipLeft((int) (mStableInsets.left * shift));
|
||||
mDragView.getViewBounds().setClipTop((int) (mStableInsets.top * shift));
|
||||
// TODO: mDragView.getViewBounds().setClipRight((int) (mStableInsets.right * shift));
|
||||
mDragView.getViewBounds().setClipBottom((int) (mStableInsets.bottom * shift));
|
||||
}
|
||||
|
||||
private int getHotseatSize() {
|
||||
return mLauncher.getDeviceProfile().isVerticalBarLayout()
|
||||
? mHotseat.getWidth() : mHotseat.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureStarted() { }
|
||||
|
||||
@UiThread
|
||||
public void onGestureEnded(float endVelocity) {
|
||||
if (mTouchEndHandled) {
|
||||
return;
|
||||
}
|
||||
mTouchEndHandled = true;
|
||||
|
||||
Resources res = mContext.getResources();
|
||||
float flingThreshold = res.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||
|
||||
long duration = MAX_SWIPE_DURATION;
|
||||
final float endShift;
|
||||
if (!isFling) {
|
||||
endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? 1 : 0;
|
||||
} else {
|
||||
endShift = endVelocity < 0 ? 1 : 0;
|
||||
float minFlingVelocity = res.getDimension(R.dimen.quickstep_fling_min_velocity);
|
||||
if (Math.abs(endVelocity) > minFlingVelocity && mLauncherReady) {
|
||||
float distanceToTravel = (endShift - mCurrentShift.value) * getHotseatSize();
|
||||
|
||||
// we want the page's snap velocity to approximately match the velocity at
|
||||
// which the user flings, so we scale the duration by a value near to the
|
||||
// derivative of the scroll interpolator at zero, ie. 5.
|
||||
duration = 5 * Math.round(1000 * Math.abs(distanceToTravel / endVelocity));
|
||||
}
|
||||
}
|
||||
|
||||
animateToProgress(endShift, duration);
|
||||
}
|
||||
|
||||
/** Animates to the given progress, where 0 is the current app and 1 is overview. */
|
||||
private void animateToProgress(float progress, long duration) {
|
||||
mIsGoingToHome = Float.compare(progress, 1) == 0;
|
||||
ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration);
|
||||
anim.setInterpolator(Interpolators.SCROLL);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mStateCallback.setState(mIsGoingToHome
|
||||
? STATE_SCALED_SNAPSHOT_RECENTS : STATE_SCALED_SNAPSHOT_APP);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void resumeLastTask() {
|
||||
RecentsTaskLoadPlan loadPlan = RecentsModel.getInstance(mContext).getLastLoadPlan();
|
||||
if (loadPlan != null) {
|
||||
Task task = loadPlan.getTaskStack().findTaskWithId(mRunningTaskId);
|
||||
if (task != null) {
|
||||
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
|
||||
null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupLauncher() {
|
||||
reset();
|
||||
|
||||
// TODO: These should be done as part of ActivityOptions#OnAnimationStarted
|
||||
mLauncher.getStateManager().reapplyState();
|
||||
mLauncher.setOnResumeCallback(() -> mDragView.close(false));
|
||||
}
|
||||
|
||||
private void onAnimationToLauncherComplete() {
|
||||
reset();
|
||||
|
||||
mDragView.close(false);
|
||||
View currentRecentsPage = mRecentsView.getPageAt(mRecentsView.getCurrentPage());
|
||||
if (currentRecentsPage instanceof TaskView) {
|
||||
((TaskView) currentRecentsPage).animateIconToScale(1f);
|
||||
}
|
||||
if (mInteractionType == INTERACTION_QUICK_SWITCH) {
|
||||
if (mQuickScrubController != null) {
|
||||
mQuickScrubController.onQuickSwitch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onQuickScrubEnd() {
|
||||
if (mQuickScrubController != null) {
|
||||
mQuickScrubController.onQuickScrubEnd();
|
||||
} else {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
public void onQuickScrubProgress(float progress) {
|
||||
if (mQuickScrubController != null) {
|
||||
mQuickScrubController.onQuickScrubProgress(progress);
|
||||
} else {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,28 +21,20 @@ import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.MotionEvent.INVALID_POINTER_ID;
|
||||
|
||||
import static com.android.quickstep.RemoteRunnable.executeSafely;
|
||||
import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.os.SystemClock;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.MotionEvent;
|
||||
@@ -52,9 +44,7 @@ import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.AssistDataReceiver;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
@@ -73,16 +63,15 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer {
|
||||
private static final String TAG = "ActivityTouchConsumer";
|
||||
|
||||
private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150;
|
||||
private static final int[] DEFERRED_HIT_TARGETS = DEBUG_SHOW_OVERVIEW_BUTTON
|
||||
private static final int[] DEFERRED_HIT_TARGETS = false
|
||||
? new int[] {HIT_TARGET_BACK, HIT_TARGET_OVERVIEW} : new int[] {HIT_TARGET_BACK};
|
||||
|
||||
private final RunningTaskInfo mRunningTask;
|
||||
private final RecentsModel mRecentsModel;
|
||||
private final Intent mHomeIntent;
|
||||
private final ISystemUiProxy mISystemUiProxy;
|
||||
private final ActivityControlHelper mActivityControlHelper;
|
||||
private final MainThreadExecutor mMainThreadExecutor;
|
||||
private final Choreographer mBackgroundThreadChoreographer;
|
||||
|
||||
@@ -93,7 +82,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
private boolean mTouchThresholdCrossed;
|
||||
private int mTouchSlop;
|
||||
private float mStartDisplacement;
|
||||
private BaseSwipeInteractionHandler mInteractionHandler;
|
||||
private WindowTransformSwipeHandler mInteractionHandler;
|
||||
private int mDisplayRotation;
|
||||
private Rect mStableInsets = new Rect();
|
||||
|
||||
@@ -102,7 +91,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
private boolean mIsGoingToHome;
|
||||
|
||||
public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo,
|
||||
RecentsModel recentsModel, Intent homeIntent, ISystemUiProxy systemUiProxy,
|
||||
RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
|
||||
MainThreadExecutor mainThreadExecutor, Choreographer backgroundThreadChoreographer,
|
||||
@HitTarget int downHitTarget, VelocityTracker velocityTracker) {
|
||||
super(base);
|
||||
@@ -110,12 +99,17 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
mRecentsModel = recentsModel;
|
||||
mHomeIntent = homeIntent;
|
||||
mVelocityTracker = velocityTracker;
|
||||
mISystemUiProxy = systemUiProxy;
|
||||
mActivityControlHelper = activityControl;
|
||||
mMainThreadExecutor = mainThreadExecutor;
|
||||
mBackgroundThreadChoreographer = backgroundThreadChoreographer;
|
||||
mIsDeferredDownTarget = Arrays.binarySearch(DEFERRED_HIT_TARGETS, downHitTarget) >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowOverviewFromAltTab() {
|
||||
startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MotionEvent ev) {
|
||||
if (mVelocityTracker == null) {
|
||||
@@ -132,7 +126,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
|
||||
// Start the window animation on down to give more time for launcher to draw if the
|
||||
// user didn't start the gesture over the back button
|
||||
if (!isUsingScreenShot() && !mIsDeferredDownTarget) {
|
||||
if (!mIsDeferredDownTarget) {
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
}
|
||||
|
||||
@@ -172,14 +166,11 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
if (mTouchThresholdCrossed) {
|
||||
mStartDisplacement = Math.signum(displacement) * mTouchSlop;
|
||||
|
||||
if (isUsingScreenShot()) {
|
||||
startTouchTrackingForScreenshotAnimation();
|
||||
} else if (mIsDeferredDownTarget) {
|
||||
if (mIsDeferredDownTarget) {
|
||||
// If we deferred starting the window animation on touch down, then
|
||||
// start tracking now
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
}
|
||||
|
||||
notifyGestureStarted();
|
||||
}
|
||||
} else if (mInteractionHandler != null) {
|
||||
@@ -205,11 +196,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
}
|
||||
// Notify the handler that the gesture has actually started
|
||||
mInteractionHandler.onGestureStarted();
|
||||
|
||||
// Notify the system that we have started tracking the event
|
||||
if (mISystemUiProxy != null) {
|
||||
executeSafely(mISystemUiProxy::onRecentsAnimationStarted);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNavBarOnRight() {
|
||||
@@ -220,69 +206,10 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
return mDisplayRotation == Surface.ROTATION_270 && mStableInsets.left > 0;
|
||||
}
|
||||
|
||||
private boolean isUsingScreenShot() {
|
||||
return Utilities.getPrefs(this).getBoolean("pref_use_screenshot_for_swipe_up", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the gesture has started.
|
||||
*/
|
||||
private void startTouchTrackingForScreenshotAnimation() {
|
||||
// Create the shared handler
|
||||
final NavBarSwipeInteractionHandler handler =
|
||||
new NavBarSwipeInteractionHandler(mRunningTask, this, INTERACTION_NORMAL);
|
||||
|
||||
TraceHelper.partitionSection("TouchInt", "Thershold crossed ");
|
||||
|
||||
// Start the recents activity on a background thread
|
||||
BackgroundExecutor.get().submit(() -> {
|
||||
// Get the snap shot before
|
||||
handler.setTaskSnapshot(getCurrentTaskSnapshot());
|
||||
|
||||
// Start the launcher activity with our custom handler
|
||||
Intent homeIntent = handler.addToIntent(new Intent(mHomeIntent));
|
||||
startActivity(homeIntent, ActivityOptions.makeCustomAnimation(this, 0, 0).toBundle());
|
||||
TraceHelper.partitionSection("TouchInt", "Home started");
|
||||
});
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.loadTasks(mRunningTask.id, null);
|
||||
mInteractionHandler = handler;
|
||||
mInteractionHandler.setGestureEndCallback(mEventQueue::reset);
|
||||
}
|
||||
|
||||
private Bitmap getCurrentTaskSnapshot() {
|
||||
TraceHelper.beginSection("TaskSnapshot");
|
||||
// TODO: We are using some hardcoded layers for now, to best approximate the activity layers
|
||||
Point displaySize = new Point();
|
||||
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
|
||||
display.getRealSize(displaySize);
|
||||
int rotation = display.getRotation();
|
||||
// The rotation is backwards in landscape, so flip it.
|
||||
if (rotation == Surface.ROTATION_270) {
|
||||
rotation = Surface.ROTATION_90;
|
||||
} else if (rotation == Surface.ROTATION_90) {
|
||||
rotation = Surface.ROTATION_270;
|
||||
}
|
||||
try {
|
||||
return mISystemUiProxy.screenshot(new Rect(), displaySize.x, displaySize.y, 0, 100000,
|
||||
false, rotation).toBitmap();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error capturing snapshot", e);
|
||||
|
||||
// Return a dummy bitmap
|
||||
Bitmap bitmap = Bitmap.createBitmap(displaySize.x, displaySize.y, Config.RGB_565);
|
||||
bitmap.eraseColor(Color.WHITE);
|
||||
return bitmap;
|
||||
} finally {
|
||||
TraceHelper.endSection("TaskSnapshot");
|
||||
}
|
||||
}
|
||||
|
||||
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
|
||||
// Create the shared handler
|
||||
final WindowTransformSwipeHandler handler =
|
||||
new WindowTransformSwipeHandler(mRunningTask, this, touchTimeMs);
|
||||
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
|
||||
mRunningTask, this, touchTimeMs, mActivityControlHelper);
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.loadTasks(mRunningTask.id, null);
|
||||
@@ -299,8 +226,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
handler.initWhenReady();
|
||||
|
||||
TraceHelper.beginSection("RecentsController");
|
||||
Runnable startActivity = () -> ActivityManagerWrapper.getInstance()
|
||||
.startRecentsActivity(mHomeIntent,
|
||||
Runnable startActivity = () -> mActivityControlHelper.startRecents(this, mHomeIntent,
|
||||
new AssistDataReceiver() {
|
||||
@Override
|
||||
public void onHandleAssistData(Bundle bundle) {
|
||||
@@ -329,7 +255,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
handler.onRecentsAnimationCanceled();
|
||||
}
|
||||
}
|
||||
}, null, null);
|
||||
});
|
||||
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
startActivity.run();
|
||||
@@ -358,7 +284,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
: isNavBarOnLeft() ? -mVelocityTracker.getXVelocity(mActivePointerId)
|
||||
: mVelocityTracker.getYVelocity(mActivePointerId);
|
||||
mInteractionHandler.onGestureEnded(velocity);
|
||||
} else if (!isUsingScreenShot()) {
|
||||
} else {
|
||||
// Since we start touch tracking on DOWN, we may reach this state without actually
|
||||
// starting the gesture. In that case, just cleanup immediately.
|
||||
reset();
|
||||
@@ -375,7 +301,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
public void reset() {
|
||||
// Clean up the old interaction handler
|
||||
if (mInteractionHandler != null) {
|
||||
final BaseSwipeInteractionHandler handler = mInteractionHandler;
|
||||
final WindowTransformSwipeHandler handler = mInteractionHandler;
|
||||
mInteractionHandler = null;
|
||||
mIsGoingToHome = handler.mIsGoingToHome;
|
||||
mMainThreadExecutor.execute(handler::reset);
|
||||
@@ -385,24 +311,15 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
|
||||
@Override
|
||||
public void updateTouchTracking(int interactionType) {
|
||||
notifyGestureStarted();
|
||||
|
||||
if (isUsingScreenShot()) {
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
if (mInteractionHandler != null) {
|
||||
mInteractionHandler.updateInteractionType(interactionType);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (mInteractionHandler != null) {
|
||||
mInteractionHandler.updateInteractionType(interactionType);
|
||||
}
|
||||
if (mInteractionHandler != null) {
|
||||
mInteractionHandler.updateInteractionType(interactionType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Choreographer getIntrimChoreographer(MotionEventQueue queue) {
|
||||
mEventQueue = queue;
|
||||
return isUsingScreenShot() ? null : mBackgroundThreadChoreographer;
|
||||
return mBackgroundThreadChoreographer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,24 +16,55 @@
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RecentTaskInfo;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.states.InternalStateHandler;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper;
|
||||
import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
|
||||
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
|
||||
import com.android.systemui.shared.recents.view.RecentsTransition;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.AssistDataReceiver;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
|
||||
import com.android.systemui.shared.system.RecentsAnimationListener;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Helper class to handle various atomic commands for switching between Overview.
|
||||
@@ -41,56 +72,263 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class OverviewCommandHelper extends InternalStateHandler {
|
||||
|
||||
private static final boolean DEBUG_START_FALLBACK_ACTIVITY = DEBUG_SHOW_OVERVIEW_BUTTON;
|
||||
private static final int RID_RESET_SWIPE_HANDLER = 0;
|
||||
private static final int RID_CANCEL_CONTROLLER = 1;
|
||||
private static final int RID_CANCEL_ZOOM_OUT_ANIMATION = 2;
|
||||
|
||||
private static final long RECENTS_LAUNCH_DURATION = 150;
|
||||
|
||||
private static final String TAG = "OverviewCommandHelper";
|
||||
private static final boolean DEBUG_START_FALLBACK_ACTIVITY = false;
|
||||
|
||||
private final Context mContext;
|
||||
private final ActivityManagerWrapper mAM;
|
||||
private final RecentsModel mRecentsModel;
|
||||
private final MainThreadExecutor mMainThreadExecutor;
|
||||
|
||||
public final Intent homeIntent;
|
||||
public final ComponentName launcher;
|
||||
|
||||
private final SparseArray<Runnable> mCurrentCommandFinishRunnables = new SparseArray<>();
|
||||
// Monotonically increasing command ids.
|
||||
private int mCurrentCommandId = 0;
|
||||
|
||||
private long mLastToggleTime;
|
||||
private WindowTransformSwipeHandler mWindowTransformSwipeHandler;
|
||||
|
||||
private final Point mWindowSize = new Point();
|
||||
private final Rect mTaskTargetRect = new Rect();
|
||||
private final RectF mTempTaskTargetRect = new RectF();
|
||||
|
||||
public OverviewCommandHelper(Context context) {
|
||||
mContext = context;
|
||||
mAM = ActivityManagerWrapper.getInstance();
|
||||
mMainThreadExecutor = new MainThreadExecutor();
|
||||
mRecentsModel = RecentsModel.getInstance(mContext);
|
||||
|
||||
homeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setPackage(context.getPackageName())
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
ResolveInfo info = context.getPackageManager().resolveActivity(homeIntent, 0);
|
||||
launcher = new ComponentName(context.getPackageName(), info.activityInfo.name);
|
||||
|
||||
if (DEBUG_START_FALLBACK_ACTIVITY) {
|
||||
launcher = new ComponentName(context, RecentsActivity.class);
|
||||
homeIntent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
.removeCategory(Intent.CATEGORY_HOME);
|
||||
} else {
|
||||
launcher = new ComponentName(context.getPackageName(), info.activityInfo.name);
|
||||
}
|
||||
|
||||
// Clear the packageName as system can fail to dedupe it b/64108432
|
||||
homeIntent.setComponent(launcher).setPackage(null);
|
||||
}
|
||||
|
||||
public void onOverviewToggle() {
|
||||
if (DEBUG_START_FALLBACK_ACTIVITY) {
|
||||
mContext.startActivity(new Intent(mContext, RecentsActivity.class)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
|
||||
return;
|
||||
}
|
||||
private void openRecents() {
|
||||
Intent intent = addToIntent(new Intent(homeIntent));
|
||||
mContext.startActivity(intent);
|
||||
initWhenReady();
|
||||
}
|
||||
|
||||
long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
|
||||
mLastToggleTime = SystemClock.elapsedRealtime();
|
||||
|
||||
if (isOverviewAlmostVisible()) {
|
||||
boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
|
||||
startNonLauncherTask(isQuickTap ? 2 : 1);
|
||||
@UiThread
|
||||
private void addFinishCommand(int requestId, int id, Runnable action) {
|
||||
if (requestId < mCurrentCommandId) {
|
||||
action.run();
|
||||
} else {
|
||||
Intent intent = addToIntent(new Intent(homeIntent));
|
||||
mContext.startActivity(intent);
|
||||
initWhenReady();
|
||||
mCurrentCommandFinishRunnables.put(id, action);
|
||||
}
|
||||
}
|
||||
|
||||
private void startNonLauncherTask(int backStackCount) {
|
||||
for (RecentTaskInfo rti : mAM.getRecentTasks(backStackCount, UserHandle.myUserId())) {
|
||||
backStackCount--;
|
||||
if (backStackCount == 0) {
|
||||
mAM.startActivityFromRecents(rti.id, null);
|
||||
@UiThread
|
||||
private void clearFinishCommand(int requestId, int id) {
|
||||
if (requestId == mCurrentCommandId) {
|
||||
mCurrentCommandFinishRunnables.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void initSwipeHandler(ActivityControlHelper helper, long time,
|
||||
Consumer<WindowTransformSwipeHandler> onAnimationInitCallback) {
|
||||
final int commandId = mCurrentCommandId;
|
||||
RunningTaskInfo taskInfo = ActivityManagerWrapper.getInstance().getRunningTask();
|
||||
final WindowTransformSwipeHandler handler =
|
||||
new WindowTransformSwipeHandler(taskInfo, mContext, time, helper);
|
||||
|
||||
// Preload the plan
|
||||
mRecentsModel.loadTasks(taskInfo.id, null);
|
||||
mWindowTransformSwipeHandler = handler;
|
||||
|
||||
mTempTaskTargetRect.setEmpty();
|
||||
handler.setGestureEndCallback(() -> {
|
||||
if (mWindowTransformSwipeHandler == handler) {
|
||||
mWindowTransformSwipeHandler = null;
|
||||
mTempTaskTargetRect.setEmpty();
|
||||
}
|
||||
clearFinishCommand(commandId, RID_RESET_SWIPE_HANDLER);
|
||||
clearFinishCommand(commandId, RID_CANCEL_CONTROLLER);
|
||||
});
|
||||
handler.initWhenReady();
|
||||
addFinishCommand(commandId, RID_RESET_SWIPE_HANDLER, handler::reset);
|
||||
|
||||
TraceHelper.beginSection(TAG);
|
||||
Runnable startActivity = () -> helper.startRecents(mContext, homeIntent,
|
||||
new AssistDataReceiver() {
|
||||
@Override
|
||||
public void onHandleAssistData(Bundle bundle) {
|
||||
mRecentsModel.preloadAssistData(taskInfo.id, bundle);
|
||||
}
|
||||
},
|
||||
new RecentsAnimationListener() {
|
||||
public void onAnimationStart(
|
||||
RecentsAnimationControllerCompat controller,
|
||||
RemoteAnimationTargetCompat[] apps, Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
if (mWindowTransformSwipeHandler == handler) {
|
||||
TraceHelper.partitionSection(TAG, "Received");
|
||||
handler.onRecentsAnimationStart(controller, apps, homeContentInsets,
|
||||
minimizedHomeBounds);
|
||||
mTempTaskTargetRect.set(handler.getTargetRect(mWindowSize));
|
||||
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
addFinishCommand(commandId,
|
||||
RID_CANCEL_CONTROLLER, () -> controller.finish(true));
|
||||
if (commandId == mCurrentCommandId) {
|
||||
onAnimationInitCallback.accept(handler);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
TraceHelper.endSection(TAG, "Finishing no handler");
|
||||
controller.finish(false /* toHome */);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAnimationCanceled() {
|
||||
TraceHelper.endSection(TAG, "Cancelled: " + handler);
|
||||
if (mWindowTransformSwipeHandler == handler) {
|
||||
handler.onRecentsAnimationCanceled();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// We should almost always get touch-town on background thread. This is an edge case
|
||||
// when the background Choreographer has not yet initialized.
|
||||
BackgroundExecutor.get().submit(startActivity);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void startZoomOutAnim(final WindowTransformSwipeHandler handler) {
|
||||
final int commandId = mCurrentCommandId;
|
||||
ValueAnimator anim = ValueAnimator.ofInt(0, -handler.getTransitionLength());
|
||||
anim.addUpdateListener((a) -> handler.updateDisplacement((Integer) a.getAnimatedValue()));
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
handler.onGestureEnded(0);
|
||||
clearFinishCommand(commandId, RID_CANCEL_ZOOM_OUT_ANIMATION);
|
||||
}
|
||||
});
|
||||
handler.onGestureStarted();
|
||||
anim.setDuration(RECENTS_LAUNCH_DURATION);
|
||||
anim.setInterpolator(Interpolators.AGGRESSIVE_EASE);
|
||||
anim.start();
|
||||
addFinishCommand(commandId, RID_CANCEL_ZOOM_OUT_ANIMATION, anim::cancel);
|
||||
}
|
||||
|
||||
public void onOverviewToggle() {
|
||||
long time = SystemClock.elapsedRealtime();
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
long elapsedTime = time - mLastToggleTime;
|
||||
mLastToggleTime = time;
|
||||
|
||||
mCurrentCommandId++;
|
||||
mTempTaskTargetRect.round(mTaskTargetRect);
|
||||
boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
|
||||
int runnableCount = mCurrentCommandFinishRunnables.size();
|
||||
if (runnableCount > 0) {
|
||||
for (int i = 0; i < runnableCount; i++) {
|
||||
mCurrentCommandFinishRunnables.valueAt(i).run();
|
||||
}
|
||||
mCurrentCommandFinishRunnables.clear();
|
||||
isQuickTap = true;
|
||||
}
|
||||
|
||||
ActivityControlHelper helper = getActivityControlHelper();
|
||||
RecentsView recents = helper.getVisibleRecentsView();
|
||||
if (recents != null) {
|
||||
int childCount = recents.getChildCount();
|
||||
if (childCount != 0) {
|
||||
((TaskView) recents.getChildAt(childCount >= 2 ? 1 : 0)).launchTask(true);
|
||||
}
|
||||
|
||||
// There are not enough tasks. Skip
|
||||
return;
|
||||
}
|
||||
|
||||
if (isQuickTap) {
|
||||
// Focus last task. Start is on background thread so that all ActivityManager calls
|
||||
// are serialized
|
||||
BackgroundExecutor.get().submit(this::startLastTask);
|
||||
return;
|
||||
}
|
||||
if (helper.switchToRecentsIfVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
initSwipeHandler(helper, time, this::startZoomOutAnim);
|
||||
});
|
||||
}
|
||||
|
||||
public void onOverviewShown() {
|
||||
getLauncher().runOnUiThread(() -> {
|
||||
if (isOverviewAlmostVisible()) {
|
||||
final RecentsView rv = getLauncher().getOverviewPanel();
|
||||
rv.snapToTaskAfterNext();
|
||||
} else {
|
||||
openRecents();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void onOverviewHidden() {
|
||||
getLauncher().runOnUiThread(() -> {
|
||||
if (isOverviewAlmostVisible()) {
|
||||
final RecentsView rv = getLauncher().getOverviewPanel();
|
||||
rv.launchNextTask();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void startLastTask() {
|
||||
// TODO: This should go through recents model.
|
||||
List<RecentTaskInfo> tasks = mAM.getRecentTasks(2, UserHandle.myUserId());
|
||||
if (tasks.size() > 1) {
|
||||
RecentTaskInfo rti = tasks.get(1);
|
||||
|
||||
final ActivityOptions options;
|
||||
if (!mTaskTargetRect.isEmpty()) {
|
||||
final Rect targetRect = new Rect(mTaskTargetRect);
|
||||
targetRect.offset(Utilities.isRtl(mContext.getResources())
|
||||
? - mTaskTargetRect.width() : mTaskTargetRect.width(), 0);
|
||||
final AppTransitionAnimationSpecCompat specCompat =
|
||||
new AppTransitionAnimationSpecCompat(rti.id, null, targetRect);
|
||||
AppTransitionAnimationSpecsFuture specFuture =
|
||||
new AppTransitionAnimationSpecsFuture(mMainThreadExecutor.getHandler()) {
|
||||
|
||||
@Override
|
||||
public List<AppTransitionAnimationSpecCompat> composeSpecs() {
|
||||
return Collections.singletonList(specCompat);
|
||||
}
|
||||
};
|
||||
options = RecentsTransition.createAspectScaleAnimation(mContext,
|
||||
mMainThreadExecutor.getHandler(), true /* scaleUp */,
|
||||
specFuture, () -> {});
|
||||
} else {
|
||||
options = ActivityOptions.makeBasic();
|
||||
}
|
||||
mAM.startActivityFromRecents(rti.id, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,4 +355,15 @@ public class OverviewCommandHelper extends InternalStateHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUsingFallbackActivity() {
|
||||
return DEBUG_START_FALLBACK_ACTIVITY;
|
||||
}
|
||||
|
||||
public ActivityControlHelper getActivityControlHelper() {
|
||||
if (DEBUG_START_FALLBACK_ACTIVITY) {
|
||||
return new FallbackActivityControllerHelper();
|
||||
} else {
|
||||
return new LauncherActivityControllerHelper();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,20 +15,28 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON;
|
||||
import static com.android.launcher3.Utilities.getPrefs;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* Sets overview interaction flags, such as:
|
||||
*
|
||||
@@ -39,55 +47,109 @@ import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
*
|
||||
* @see com.android.systemui.shared.system.NavigationBarCompat.InteractionType and associated flags.
|
||||
*/
|
||||
public class OverviewInteractionState {
|
||||
public class OverviewInteractionState implements OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = "OverviewFlags";
|
||||
private static final Handler sUiHandler = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
updateOverviewInteractionFlag((Context) msg.obj, msg.what, msg.arg1 == 1);
|
||||
}
|
||||
};
|
||||
private static final Handler sBackgroundHandler = new Handler(
|
||||
UiThreadHelper.getBackgroundLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
ISystemUiProxy systemUiProxy = (ISystemUiProxy) msg.obj;
|
||||
int flags = msg.what;
|
||||
try {
|
||||
systemUiProxy.setInteractionState(flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Unable to update overview interaction flags", e);
|
||||
|
||||
// We do not need any synchronization for this variable as its only written on UI thread.
|
||||
private static OverviewInteractionState INSTANCE;
|
||||
|
||||
public static OverviewInteractionState getInstance(final Context context) {
|
||||
if (INSTANCE == null) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
INSTANCE = new OverviewInteractionState(context.getApplicationContext());
|
||||
} else {
|
||||
try {
|
||||
return new MainThreadExecutor().submit(
|
||||
() -> OverviewInteractionState.getInstance(context)).get();
|
||||
} catch (InterruptedException|ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static int sFlags = DEBUG_SHOW_OVERVIEW_BUTTON ? FLAG_SHOW_OVERVIEW_BUTTON : 0;
|
||||
|
||||
public static void setBackButtonVisible(Context context, boolean visible) {
|
||||
updateFlagOnUi(context, FLAG_HIDE_BACK_BUTTON, !visible);
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static void updateFlagOnUi(Context context, int flag, boolean enabled) {
|
||||
sUiHandler.removeMessages(flag);
|
||||
sUiHandler.sendMessage(sUiHandler.obtainMessage(flag, enabled ? 1 : 0, 0, context));
|
||||
public static final String KEY_SWIPE_UP_ENABLED = "pref_enable_quickstep";
|
||||
|
||||
private static final int MSG_SET_PROXY = 200;
|
||||
private static final int MSG_SET_BACK_BUTTON_VISIBLE = 201;
|
||||
private static final int MSG_SET_SWIPE_UP_ENABLED = 202;
|
||||
|
||||
private final Handler mUiHandler;
|
||||
private final Handler mBgHandler;
|
||||
|
||||
// These are updated on the background thread
|
||||
private ISystemUiProxy mISystemUiProxy;
|
||||
private boolean mBackButtonVisible = true;
|
||||
private boolean mSwipeUpEnabled = true;
|
||||
|
||||
private OverviewInteractionState(Context context) {
|
||||
mUiHandler = new Handler(this::handleUiMessage);
|
||||
mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
|
||||
|
||||
SharedPreferences prefs = getPrefs(context);
|
||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||
onSharedPreferenceChanged(prefs, KEY_SWIPE_UP_ENABLED);
|
||||
}
|
||||
|
||||
private static void updateOverviewInteractionFlag(Context context, int flag, boolean enabled) {
|
||||
if (enabled) {
|
||||
sFlags |= flag;
|
||||
} else {
|
||||
sFlags &= ~flag;
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String s) {
|
||||
if (KEY_SWIPE_UP_ENABLED.equals(s)) {
|
||||
mUiHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED);
|
||||
boolean swipeUpEnabled = prefs.getBoolean(s, true);
|
||||
mUiHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED,
|
||||
swipeUpEnabled ? 1 : 0, 0).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
ISystemUiProxy systemUiProxy = RecentsModel.getInstance(context).getSystemUiProxy();
|
||||
if (systemUiProxy == null) {
|
||||
Log.w(TAG, "Unable to update overview interaction flags; not bound to service");
|
||||
public void setBackButtonVisible(boolean visible) {
|
||||
mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_VISIBLE);
|
||||
mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_VISIBLE, visible ? 1 : 0, 0)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
public void setSystemUiProxy(ISystemUiProxy proxy) {
|
||||
mBgHandler.obtainMessage(MSG_SET_PROXY, proxy).sendToTarget();
|
||||
}
|
||||
|
||||
private boolean handleUiMessage(Message msg) {
|
||||
mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2).sendToTarget();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleBgMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_SET_PROXY:
|
||||
mISystemUiProxy = (ISystemUiProxy) msg.obj;
|
||||
break;
|
||||
case MSG_SET_BACK_BUTTON_VISIBLE:
|
||||
mBackButtonVisible = msg.arg1 != 0;
|
||||
break;
|
||||
case MSG_SET_SWIPE_UP_ENABLED:
|
||||
mSwipeUpEnabled = msg.arg1 != 0;
|
||||
break;
|
||||
}
|
||||
applyFlags();
|
||||
return true;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void applyFlags() {
|
||||
if (mISystemUiProxy == null) {
|
||||
return;
|
||||
}
|
||||
// If we aren't already setting these flags, do so now on the background thread.
|
||||
if (!sBackgroundHandler.hasMessages(sFlags)) {
|
||||
sBackgroundHandler.sendMessage(sBackgroundHandler.obtainMessage(sFlags, systemUiProxy));
|
||||
|
||||
int flags;
|
||||
if (mSwipeUpEnabled) {
|
||||
flags = mBackButtonVisible ? 0 : FLAG_HIDE_BACK_BUTTON;
|
||||
} else {
|
||||
flags = FLAG_DISABLE_SWIPE_UP | FLAG_DISABLE_QUICK_SCRUB | FLAG_SHOW_OVERVIEW_BUTTON;
|
||||
}
|
||||
try {
|
||||
mISystemUiProxy.setInteractionState(flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Unable to update overview interaction flags", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.android.quickstep.views.TaskView;
|
||||
*/
|
||||
public class QuickScrubController implements OnAlarmListener {
|
||||
|
||||
public static final int QUICK_SWITCH_START_DURATION = 210;
|
||||
public static final int QUICK_SCRUB_START_DURATION = 210;
|
||||
|
||||
private static final boolean ENABLE_AUTO_ADVANCE = true;
|
||||
private static final int NUM_QUICK_SCRUB_SECTIONS = 3;
|
||||
@@ -53,7 +53,6 @@ public class QuickScrubController implements OnAlarmListener {
|
||||
private int mQuickScrubSection;
|
||||
private boolean mStartedFromHome;
|
||||
private boolean mHasAlarmRun;
|
||||
private boolean mQuickSwitched;
|
||||
private boolean mFinishedTransitionToQuickScrub;
|
||||
|
||||
public QuickScrubController(BaseActivity activity, RecentsView recentsView) {
|
||||
@@ -70,7 +69,6 @@ public class QuickScrubController implements OnAlarmListener {
|
||||
mStartedFromHome = startingFromHome;
|
||||
mQuickScrubSection = 0;
|
||||
mHasAlarmRun = false;
|
||||
mQuickSwitched = false;
|
||||
mFinishedTransitionToQuickScrub = false;
|
||||
|
||||
snapToNextTaskIfAvailable();
|
||||
@@ -84,7 +82,13 @@ public class QuickScrubController implements OnAlarmListener {
|
||||
}
|
||||
int page = mRecentsView.getNextPage();
|
||||
Runnable launchTaskRunnable = () -> {
|
||||
((TaskView) mRecentsView.getPageAt(page)).launchTask(true);
|
||||
TaskView taskView = ((TaskView) mRecentsView.getPageAt(page));
|
||||
if (taskView != null) {
|
||||
taskView.launchTask(true);
|
||||
} else {
|
||||
// Break out of quick scrub so user can interact with launcher.
|
||||
mActivity.onBackPressed();
|
||||
}
|
||||
};
|
||||
int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen())
|
||||
* QUICKSCRUB_END_SNAP_DURATION_PER_PAGE;
|
||||
@@ -119,48 +123,24 @@ public class QuickScrubController implements OnAlarmListener {
|
||||
}
|
||||
}
|
||||
|
||||
public void onQuickSwitch() {
|
||||
mQuickSwitched = true;
|
||||
quickSwitchIfReady();
|
||||
}
|
||||
|
||||
public void onFinishedTransitionToQuickScrub() {
|
||||
mFinishedTransitionToQuickScrub = true;
|
||||
quickSwitchIfReady();
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately launches the current task (which we snapped to in onQuickScrubStart) if we've
|
||||
* gotten the onQuickSwitch callback and the transition to quick scrub has completed.
|
||||
*/
|
||||
private void quickSwitchIfReady() {
|
||||
if (mQuickSwitched && mFinishedTransitionToQuickScrub) {
|
||||
onQuickScrubEnd();
|
||||
mActivity.getUserEventDispatcher().logActionOnControl(Touch.FLING,
|
||||
ControlType.QUICK_SCRUB_BUTTON, null, mStartedFromHome ?
|
||||
ContainerType.WORKSPACE : ContainerType.APP);
|
||||
}
|
||||
}
|
||||
|
||||
public void snapToNextTaskIfAvailable() {
|
||||
if (mInQuickScrub && mRecentsView.getChildCount() > 0) {
|
||||
int toPage = mStartedFromHome ? 0 : mRecentsView.getNextPage() + 1;
|
||||
goToPageWithHaptic(toPage, QUICK_SWITCH_START_DURATION);
|
||||
mRecentsView.snapToPage(toPage, QUICK_SCRUB_START_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
private void goToPageWithHaptic(int pageToGoTo) {
|
||||
goToPageWithHaptic(pageToGoTo, -1);
|
||||
}
|
||||
|
||||
private void goToPageWithHaptic(int pageToGoTo, int overrideDuration) {
|
||||
pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getPageCount() - 1);
|
||||
if (pageToGoTo != mRecentsView.getNextPage()) {
|
||||
int duration = overrideDuration > -1 ? overrideDuration
|
||||
: Math.abs(pageToGoTo - mRecentsView.getNextPage())
|
||||
int duration = Math.abs(pageToGoTo - mRecentsView.getNextPage())
|
||||
* QUICKSCRUB_SNAP_DURATION_PER_PAGE;
|
||||
mRecentsView.snapToPage(pageToGoTo, duration);
|
||||
mRecentsView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP,
|
||||
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
|
||||
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,26 @@
|
||||
*/
|
||||
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.uioverrides.UiFactory;
|
||||
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 +48,55 @@ 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);
|
||||
|
||||
RecentsActivityTracker.onRecentsActivityCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseDragLayer getDragLayer() {
|
||||
return mRecentsRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getRootView() {
|
||||
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) { }
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
UiFactory.onStart(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
UiFactory.onTrimMemory(this, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
RecentsActivityTracker.onRecentsActivityDestroy(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.quickstep;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* Utility class to track create/destroy for RecentsActivity
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class RecentsActivityTracker implements ActivityInitListener {
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static WeakReference<RecentsActivityTracker> sTracker = new WeakReference<>(null);
|
||||
private static WeakReference<RecentsActivity> sCurrentActivity = new WeakReference<>(null);
|
||||
|
||||
private final BiPredicate<RecentsActivity, Boolean> mOnInitListener;
|
||||
|
||||
public RecentsActivityTracker(BiPredicate<RecentsActivity, Boolean> onInitListener) {
|
||||
mOnInitListener = onInitListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
synchronized (LOCK) {
|
||||
sTracker = new WeakReference<>(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
synchronized (LOCK) {
|
||||
if (sTracker.get() == this) {
|
||||
sTracker.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void onRecentsActivityCreate(RecentsActivity activity) {
|
||||
synchronized (LOCK) {
|
||||
RecentsActivityTracker tracker = sTracker.get();
|
||||
if (tracker != null && tracker.mOnInitListener.test(activity, false)) {
|
||||
sTracker.clear();
|
||||
}
|
||||
sCurrentActivity = new WeakReference<>(activity);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onRecentsActivityDestroy(RecentsActivity activity) {
|
||||
synchronized (LOCK) {
|
||||
if (sCurrentActivity.get() == activity) {
|
||||
sCurrentActivity.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static RecentsActivity getCurrentActivity() {
|
||||
synchronized (LOCK) {
|
||||
return sCurrentActivity.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import android.os.UserHandle;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.LruCache;
|
||||
import android.util.SparseArray;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.R;
|
||||
@@ -85,6 +86,7 @@ public class RecentsModel extends TaskStackChangeListener {
|
||||
private ISystemUiProxy mSystemUiProxy;
|
||||
private boolean mClearAssistCacheOnStackChange = true;
|
||||
private final boolean mPreloadTasksInBackground;
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
|
||||
private RecentsModel(Context context) {
|
||||
mContext = context;
|
||||
@@ -111,6 +113,7 @@ public class RecentsModel extends TaskStackChangeListener {
|
||||
|
||||
mTaskChangeId = 1;
|
||||
loadTasks(-1, null);
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
}
|
||||
|
||||
public RecentsTaskLoader getRecentsTaskLoader() {
|
||||
@@ -140,7 +143,7 @@ public class RecentsModel extends TaskStackChangeListener {
|
||||
// Preload the plan
|
||||
RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(mContext);
|
||||
PreloadOptions opts = new PreloadOptions();
|
||||
opts.loadTitles = false;
|
||||
opts.loadTitles = mAccessibilityManager.isEnabled();
|
||||
loadPlan.preloadPlan(opts, mRecentsTaskLoader, taskId, UserHandle.myUserId());
|
||||
// Set the load plan on UI thread
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
@@ -187,7 +190,7 @@ public class RecentsModel extends TaskStackChangeListener {
|
||||
launchOpts.onlyLoadPausedActivities = true;
|
||||
launchOpts.loadThumbnails = true;
|
||||
PreloadOptions preloadOpts = new PreloadOptions();
|
||||
preloadOpts.loadTitles = false;
|
||||
preloadOpts.loadTitles = mAccessibilityManager.isEnabled();
|
||||
plan.preloadPlan(preloadOpts, mRecentsTaskLoader, -1, userId);
|
||||
mRecentsTaskLoader.loadTasks(plan, launchOpts);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.quickstep;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.systemui.shared.recents.view.AnimateableViewBounds;
|
||||
|
||||
/**
|
||||
* Floating view which shows the task snapshot allowing it to be dragged and placed.
|
||||
*/
|
||||
public class SnapshotDragView extends AbstractFloatingView implements Insettable {
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final Bitmap mSnapshot;
|
||||
private final AnimateableViewBounds mViewBounds;
|
||||
|
||||
public SnapshotDragView(Launcher launcher, Bitmap snapshot) {
|
||||
super(launcher, null);
|
||||
mLauncher = launcher;
|
||||
mSnapshot = snapshot;
|
||||
mViewBounds = new AnimateableViewBounds(this, 0);
|
||||
setWillNotDraw(false);
|
||||
setClipToOutline(true);
|
||||
setOutlineProvider(mViewBounds);
|
||||
}
|
||||
|
||||
AnimateableViewBounds getViewBounds() {
|
||||
return mViewBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mSnapshot != null) {
|
||||
setMeasuredDimension(mSnapshot.getWidth(), mSnapshot.getHeight());
|
||||
} else {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mSnapshot != null) {
|
||||
canvas.drawBitmap(mSnapshot, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleClose(boolean animate) {
|
||||
// We dont suupport animate.
|
||||
mLauncher.getDragLayer().removeView(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logActionCommand(int command) {
|
||||
// We should probably log the weather
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOfType(int type) {
|
||||
return (type & TYPE_QUICKSTEP_PREVIEW) != 0;
|
||||
}
|
||||
}
|
||||
@@ -30,13 +30,15 @@ import android.view.View;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
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;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskThumbnailView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
@@ -70,11 +72,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 +85,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> {
|
||||
@@ -98,10 +101,13 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
||||
}
|
||||
}
|
||||
|
||||
public static class SplitScreen extends TaskSystemShortcut implements OnPreDrawListener {
|
||||
public static class SplitScreen extends TaskSystemShortcut implements OnPreDrawListener,
|
||||
DeviceProfile.OnDeviceProfileChangeListener, View.OnLayoutChangeListener {
|
||||
|
||||
private Handler mHandler;
|
||||
private RecentsView mRecentsView;
|
||||
private TaskView mTaskView;
|
||||
private BaseDraggingActivity mActivity;
|
||||
|
||||
public SplitScreen() {
|
||||
super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen);
|
||||
@@ -109,22 +115,27 @@ 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();
|
||||
final int taskId = task.key.id;
|
||||
if (!task.isDockable) {
|
||||
return null;
|
||||
}
|
||||
mActivity = activity;
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
mTaskView = taskView;
|
||||
final TaskThumbnailView thumbnailView = taskView.getThumbnail();
|
||||
return (v -> {
|
||||
AbstractFloatingView.closeOpenViews(launcher, true,
|
||||
AbstractFloatingView.closeOpenViews(activity, true,
|
||||
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
|
||||
|
||||
if (ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key.id,
|
||||
if (ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
|
||||
ActivityOptionsCompat.makeSplitScreenOptions(true))) {
|
||||
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(launcher).getSystemUiProxy();
|
||||
ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy();
|
||||
try {
|
||||
sysUiProxy.onSplitScreenInvoked();
|
||||
} catch (RemoteException e) {
|
||||
@@ -132,26 +143,35 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a device profile change listener to kick off animating the side tasks
|
||||
// once we enter multiwindow mode and relayout
|
||||
activity.addOnDeviceProfileChangeListener(this);
|
||||
|
||||
final Runnable animStartedListener = () -> {
|
||||
// Hide the task view and wait for the window to be resized
|
||||
// TODO: Consider animating in launcher and do an in-place start activity
|
||||
// afterwards
|
||||
mRecentsView.addIgnoreResetTask(mTaskView);
|
||||
mTaskView.setAlpha(0f);
|
||||
mTaskView.getViewTreeObserver().addOnPreDrawListener(SplitScreen.this);
|
||||
launcher.<RecentsView>getOverviewPanel().removeView(taskView);
|
||||
};
|
||||
|
||||
final int[] position = new int[2];
|
||||
taskView.getLocationOnScreen(position);
|
||||
final int width = (int) (taskView.getWidth() * taskView.getScaleX());
|
||||
final int height = (int) (taskView.getHeight() * taskView.getScaleY());
|
||||
thumbnailView.getLocationOnScreen(position);
|
||||
final int width = (int) (thumbnailView.getWidth() * taskView.getScaleX());
|
||||
final int height = (int) (thumbnailView.getHeight() * taskView.getScaleY());
|
||||
final Rect taskBounds = new Rect(position[0], position[1],
|
||||
position[0] + width, position[1] + height);
|
||||
|
||||
Bitmap thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
|
||||
taskBounds.width(), taskBounds.height(), taskView, 1f, Color.BLACK);
|
||||
taskBounds.width(), taskBounds.height(), thumbnailView, 1f,
|
||||
Color.BLACK);
|
||||
AppTransitionAnimationSpecsFuture future =
|
||||
new AppTransitionAnimationSpecsFuture(mHandler) {
|
||||
@Override
|
||||
public List<AppTransitionAnimationSpecCompat> composeSpecs() {
|
||||
return Collections.singletonList(new AppTransitionAnimationSpecCompat(
|
||||
task.key.id, thumbnail, taskBounds));
|
||||
taskId, thumbnail, taskBounds));
|
||||
}
|
||||
};
|
||||
WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
|
||||
@@ -166,6 +186,24 @@ public class TaskSystemShortcut<T extends SystemShortcut> extends SystemShortcut
|
||||
WindowManagerWrapper.getInstance().endProlongedAnimations();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceProfileChanged(DeviceProfile dp) {
|
||||
mActivity.removeOnDeviceProfileChangeListener(this);
|
||||
if (dp.isMultiWindowMode) {
|
||||
mTaskView.getRootView().addOnLayoutChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChange(View v, int l, int t, int r, int b,
|
||||
int oldL, int oldT, int oldR, int oldB) {
|
||||
mTaskView.getRootView().removeOnLayoutChangeListener(this);
|
||||
mRecentsView.removeIgnoreResetTask(mTaskView);
|
||||
|
||||
// Start animating in the side pages once launcher has been resized
|
||||
mRecentsView.dismissTask(mTaskView, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Pin extends TaskSystemShortcut {
|
||||
@@ -178,8 +216,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 +250,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);
|
||||
|
||||
@@ -29,21 +29,14 @@ import java.util.function.Consumer;
|
||||
@FunctionalInterface
|
||||
public interface TouchConsumer extends Consumer<MotionEvent> {
|
||||
|
||||
static boolean isInteractionQuick(@InteractionType int interactionType) {
|
||||
return interactionType == INTERACTION_QUICK_SCRUB ||
|
||||
interactionType == INTERACTION_QUICK_SWITCH;
|
||||
}
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
INTERACTION_NORMAL,
|
||||
INTERACTION_QUICK_SWITCH,
|
||||
INTERACTION_QUICK_SCRUB
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface InteractionType {}
|
||||
int INTERACTION_NORMAL = 0;
|
||||
int INTERACTION_QUICK_SWITCH = 1;
|
||||
int INTERACTION_QUICK_SCRUB = 2;
|
||||
int INTERACTION_QUICK_SCRUB = 1;
|
||||
|
||||
default void reset() { }
|
||||
|
||||
@@ -72,4 +65,6 @@ public interface TouchConsumer extends Consumer<MotionEvent> {
|
||||
default boolean forceToLauncherConsumer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default void onShowOverviewFromAltTab() {}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
@@ -47,7 +48,6 @@ import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.uioverrides.UiFactory;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.recents.IOverviewProxy;
|
||||
@@ -61,7 +61,7 @@ import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class TouchInteractionService extends Service {
|
||||
|
||||
public static final boolean DEBUG_SHOW_OVERVIEW_BUTTON = false;
|
||||
public static final boolean DEBUG_OPEN_OVERVIEW_VIA_ALT_TAB = false;
|
||||
|
||||
private static final SparseArray<String> sMotionEventNames;
|
||||
|
||||
@@ -86,7 +86,7 @@ public class TouchInteractionService extends Service {
|
||||
@Override
|
||||
public void onPreMotionEvent(@HitTarget int downHitTarget) throws RemoteException {
|
||||
TraceHelper.beginSection("SysUiBinder");
|
||||
onBinderPreMotionEvent(downHitTarget);
|
||||
setupTouchConsumer(downHitTarget);
|
||||
TraceHelper.partitionSection("SysUiBinder", "Down target " + downHitTarget);
|
||||
}
|
||||
|
||||
@@ -106,15 +106,7 @@ public class TouchInteractionService extends Service {
|
||||
mRecentsModel.setSystemUiProxy(mISystemUiProxy);
|
||||
RemoteRunnable.executeSafely(() -> mISystemUiProxy.setRecentsOnboardingText(
|
||||
getResources().getString(R.string.recents_swipe_up_onboarding)));
|
||||
Launcher launcher = (Launcher) LauncherAppState.getInstance(
|
||||
TouchInteractionService.this).getModel().getCallback();
|
||||
UiFactory.onLauncherStateOrFocusChanged(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickSwitch() {
|
||||
mEventQueue.onQuickSwitch();
|
||||
TraceHelper.endSection("SysUiBinder", "onQuickSwitch");
|
||||
mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,10 +132,29 @@ public class TouchInteractionService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOverviewShown(boolean triggeredFromAltTab) { }
|
||||
public void onOverviewShown(boolean triggeredFromAltTab) {
|
||||
if (DEBUG_OPEN_OVERVIEW_VIA_ALT_TAB) {
|
||||
if (triggeredFromAltTab) {
|
||||
setupTouchConsumer(HIT_TARGET_NONE);
|
||||
mEventQueue.onOverviewShownFromAltTab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
|
||||
public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
|
||||
if (DEBUG_OPEN_OVERVIEW_VIA_ALT_TAB) {
|
||||
if (triggeredFromAltTab && !triggeredFromHomeKey) {
|
||||
// onOverviewShownFromAltTab initiates quick scrub. Ending it here.
|
||||
mEventQueue.onQuickScrubEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickStep(MotionEvent motionEvent) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private final TouchConsumer mNoOpTouchConsumer = (ev) -> {};
|
||||
@@ -160,6 +171,7 @@ public class TouchInteractionService extends Service {
|
||||
private MainThreadExecutor mMainThreadExecutor;
|
||||
private ISystemUiProxy mISystemUiProxy;
|
||||
private OverviewCommandHelper mOverviewCommandHelper;
|
||||
private OverviewInteractionState mOverviewInteractionState;
|
||||
|
||||
private Choreographer mMainThreadChoreographer;
|
||||
private Choreographer mBackgroundThreadChoreographer;
|
||||
@@ -173,6 +185,7 @@ public class TouchInteractionService extends Service {
|
||||
mOverviewCommandHelper = new OverviewCommandHelper(this);
|
||||
mMainThreadChoreographer = Choreographer.getInstance();
|
||||
mEventQueue = new MotionEventQueue(mMainThreadChoreographer, mNoOpTouchConsumer);
|
||||
mOverviewInteractionState = OverviewInteractionState.getInstance(this);
|
||||
|
||||
sConnected = true;
|
||||
|
||||
@@ -193,7 +206,7 @@ public class TouchInteractionService extends Service {
|
||||
return mMyBinder;
|
||||
}
|
||||
|
||||
private void onBinderPreMotionEvent(@HitTarget int downHitTarget) {
|
||||
private void setupTouchConsumer(@HitTarget int downHitTarget) {
|
||||
mEventQueue.reset();
|
||||
TouchConsumer oldConsumer = mEventQueue.getConsumer();
|
||||
if (oldConsumer.deferNextEventToMainThread()) {
|
||||
@@ -221,7 +234,8 @@ public class TouchInteractionService extends Service {
|
||||
tracker = VelocityTracker.obtain();
|
||||
}
|
||||
return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
|
||||
mOverviewCommandHelper.homeIntent, mISystemUiProxy, mMainThreadExecutor,
|
||||
mOverviewCommandHelper.homeIntent,
|
||||
mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor,
|
||||
mBackgroundThreadChoreographer, downHitTarget, tracker);
|
||||
}
|
||||
}
|
||||
@@ -314,14 +328,10 @@ public class TouchInteractionService extends Service {
|
||||
if (mInvalidated) {
|
||||
return;
|
||||
}
|
||||
if (TouchConsumer.isInteractionQuick(interactionType)) {
|
||||
if (interactionType == INTERACTION_QUICK_SCRUB) {
|
||||
Runnable action = () -> {
|
||||
Runnable onComplete = null;
|
||||
if (interactionType == INTERACTION_QUICK_SWITCH) {
|
||||
onComplete = mQuickScrubController::onQuickSwitch;
|
||||
}
|
||||
LauncherState fromState = mLauncher.getStateManager().getState();
|
||||
mLauncher.getStateManager().goToState(FAST_OVERVIEW, true, onComplete);
|
||||
mLauncher.getStateManager().goToState(FAST_OVERVIEW, true);
|
||||
mQuickScrubController.onQuickScrubStart(fromState == NORMAL);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,22 +15,16 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
|
||||
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
|
||||
import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_START_DURATION;
|
||||
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_DURATION;
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
|
||||
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH;
|
||||
import static com.android.quickstep.TouchConsumer.isInteractionQuick;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
|
||||
import static com.android.systemui.shared.recents.utilities.Utilities
|
||||
.postAtFrontOfQueueAsynchronously;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
@@ -41,7 +35,6 @@ import android.graphics.Matrix.ScaleToFit;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.metrics.LogMaker;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -51,16 +44,15 @@ import android.support.annotation.WorkerThread;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver.OnDrawListener;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
@@ -69,8 +61,10 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.util.ViewOnDrawExecutor;
|
||||
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
|
||||
import com.android.quickstep.ActivityControlHelper.LayoutListener;
|
||||
import com.android.quickstep.TouchConsumer.InteractionType;
|
||||
import com.android.quickstep.util.SysuiEventLogger;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -84,42 +78,8 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
|
||||
class EventLogTags {
|
||||
private EventLogTags() {
|
||||
} // don't instantiate
|
||||
|
||||
/** 524292 sysui_multi_action (content|4) */
|
||||
public static final int SYSUI_MULTI_ACTION = 524292;
|
||||
|
||||
public static void writeSysuiMultiAction(Object[] content) {
|
||||
android.util.EventLog.writeEvent(SYSUI_MULTI_ACTION, content);
|
||||
}
|
||||
}
|
||||
|
||||
class MetricsLogger {
|
||||
private static MetricsLogger sMetricsLogger;
|
||||
|
||||
private static MetricsLogger getLogger() {
|
||||
if (sMetricsLogger == null) {
|
||||
sMetricsLogger = new MetricsLogger();
|
||||
}
|
||||
return sMetricsLogger;
|
||||
}
|
||||
|
||||
protected void saveLog(Object[] rep) {
|
||||
EventLogTags.writeSysuiMultiAction(rep);
|
||||
}
|
||||
|
||||
public void write(LogMaker content) {
|
||||
if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) {
|
||||
content.setType(4/*MetricsEvent.TYPE_ACTION*/);
|
||||
}
|
||||
saveLog(content.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
|
||||
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
|
||||
private static final boolean DEBUG_STATES = false;
|
||||
|
||||
@@ -142,9 +102,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
|
||||
// States for quick switch/scrub
|
||||
private static final int STATE_SWITCH_TO_SCREENSHOT_COMPLETE = 1 << 10;
|
||||
private static final int STATE_QUICK_SWITCH = 1 << 11;
|
||||
private static final int STATE_QUICK_SCRUB_START = 1 << 12;
|
||||
private static final int STATE_QUICK_SCRUB_END = 1 << 13;
|
||||
private static final int STATE_QUICK_SCRUB_START = 1 << 11;
|
||||
private static final int STATE_QUICK_SCRUB_END = 1 << 12;
|
||||
|
||||
private static final int LAUNCHER_UI_STATES =
|
||||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE
|
||||
@@ -193,6 +152,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
// The clip rect in source app window coordinates
|
||||
private final Rect mClipRect = new Rect();
|
||||
private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
|
||||
protected Runnable mGestureEndCallback;
|
||||
protected boolean mIsGoingToHome;
|
||||
private DeviceProfile mDp;
|
||||
private int mTransitionDragLength;
|
||||
|
||||
@@ -206,12 +167,14 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
|
||||
private final Context mContext;
|
||||
private final int mRunningTaskId;
|
||||
private final ActivityControlHelper<T> mActivityControlHelper;
|
||||
private final ActivityInitListener mActivityInitListener;
|
||||
|
||||
private MultiStateCallback mStateCallback;
|
||||
private AnimatorPlaybackController mLauncherTransitionController;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private LauncherLayoutListener mLauncherLayoutListener;
|
||||
private T mActivity;
|
||||
private LayoutListener mLayoutListener;
|
||||
private RecentsView mRecentsView;
|
||||
private QuickScrubController mQuickScrubController;
|
||||
|
||||
@@ -232,12 +195,16 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
private Matrix mTmpMatrix = new Matrix();
|
||||
private final long mTouchTimeMs;
|
||||
private long mLauncherFrameDrawnTime;
|
||||
private final MetricsLogger mMetricsLogger = new MetricsLogger();
|
||||
|
||||
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs) {
|
||||
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs,
|
||||
ActivityControlHelper<T> controller) {
|
||||
mContext = context;
|
||||
mRunningTaskId = runningTaskInfo.id;
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mActivityControlHelper = controller;
|
||||
mActivityInitListener = mActivityControlHelper
|
||||
.createActivityInitListener(this::onActivityInit);
|
||||
|
||||
// Register the input consumer on the UI thread, to ensure that it runs after any pending
|
||||
// unregister calls
|
||||
mMainExecutor.execute(mInputConsumer::registerInputConsumer);
|
||||
@@ -283,13 +250,10 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::invalidateHandlerWithLauncher);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SWITCH,
|
||||
this::onQuickInteractionStart);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SCRUB_START,
|
||||
this::onQuickInteractionStart);
|
||||
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SWITCH_TO_SCREENSHOT_COMPLETE
|
||||
| STATE_QUICK_SWITCH, this::switchToFinalAppAfterQuickSwitch);
|
||||
this::onQuickScrubStart);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SCRUB_START
|
||||
| STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SWITCH_TO_SCREENSHOT_COMPLETE
|
||||
| STATE_QUICK_SCRUB_END, this::switchToFinalAppAfterQuickScrub);
|
||||
}
|
||||
@@ -310,7 +274,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
mSourceStackBounds.height() - mSourceInsets.bottom);
|
||||
|
||||
Rect tempRect = new Rect();
|
||||
RecentsView.getPageRect(dp, mContext, tempRect);
|
||||
mTransitionDragLength = mActivityControlHelper
|
||||
.getSwipeUpDestinationAndLength(dp, mContext, tempRect);
|
||||
|
||||
mTargetRect.set(tempRect);
|
||||
mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left,
|
||||
@@ -331,14 +296,15 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
Math.max(mSourceStackBounds.width() - scaledTargetRect.right, 0),
|
||||
Math.max(mSourceStackBounds.height() - scaledTargetRect.bottom, 0));
|
||||
mSourceRect.set(scaledTargetRect);
|
||||
}
|
||||
|
||||
Rect targetInsets = dp.getInsets();
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
|
||||
mTransitionDragLength = dp.hotseatBarSizePx + dp.hotseatBarSidePaddingPx + hotseatInset;
|
||||
} else {
|
||||
mTransitionDragLength = dp.heightPx - tempRect.bottom;
|
||||
}
|
||||
public int getTransitionLength() {
|
||||
return mTransitionDragLength;
|
||||
}
|
||||
|
||||
public RectF getTargetRect(Point outWindowSize) {
|
||||
outWindowSize.set(mDp.widthPx, mDp.heightPx);
|
||||
return mInitialTargetRect;
|
||||
}
|
||||
|
||||
private long getFadeInDuration() {
|
||||
@@ -353,40 +319,39 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean init(final Launcher launcher, boolean alreadyOnHome) {
|
||||
if (launcher == mLauncher) {
|
||||
public void initWhenReady() {
|
||||
mActivityInitListener.register();
|
||||
}
|
||||
|
||||
private boolean onActivityInit(final T activity, Boolean alreadyOnHome) {
|
||||
if (mActivity == activity) {
|
||||
return true;
|
||||
}
|
||||
if (mLauncher != null) {
|
||||
if (mActivity != null) {
|
||||
// The launcher may have been recreated as a result of device rotation.
|
||||
int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
|
||||
initStateCallbacks();
|
||||
mStateCallback.setState(oldState);
|
||||
mLauncherLayoutListener.setHandler(null);
|
||||
mLayoutListener.setHandler(null);
|
||||
}
|
||||
mWasLauncherAlreadyVisible = alreadyOnHome;
|
||||
mLauncher = launcher;
|
||||
mActivity = activity;
|
||||
|
||||
// For the duration of the gesture, lock the screen orientation to ensure that we do not
|
||||
// rotate mid-quickscrub
|
||||
mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK);
|
||||
|
||||
mRecentsView = mLauncher.getOverviewPanel();
|
||||
mRecentsView = activity.getOverviewPanel();
|
||||
mQuickScrubController = mRecentsView.getQuickScrubController();
|
||||
mLauncherLayoutListener = new LauncherLayoutListener(mLauncher);
|
||||
mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity);
|
||||
|
||||
mStateCallback.setState(STATE_LAUNCHER_PRESENT);
|
||||
if (alreadyOnHome) {
|
||||
onLauncherStart(launcher);
|
||||
onLauncherStart(activity);
|
||||
} else {
|
||||
launcher.setOnStartCallback(this::onLauncherStart);
|
||||
activity.setOnStartCallback(this::onLauncherStart);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onLauncherStart(final Launcher launcher) {
|
||||
if (mLauncher != launcher) {
|
||||
private void onLauncherStart(final T activity) {
|
||||
if (mActivity != activity) {
|
||||
return;
|
||||
}
|
||||
if ((mStateCallback.getState() & STATE_HANDLER_INVALIDATED) != 0) {
|
||||
@@ -394,31 +359,20 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
|
||||
mStateCallback.setState(STATE_LAUNCHER_STARTED);
|
||||
LauncherState startState = mLauncher.getStateManager().getState();
|
||||
if (startState.disableRestore) {
|
||||
startState = mLauncher.getStateManager().getRestState();
|
||||
}
|
||||
mLauncher.getStateManager().setRestState(startState);
|
||||
mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible);
|
||||
AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible);
|
||||
|
||||
AbstractFloatingView.closeAllOpenViews(mLauncher, mWasLauncherAlreadyVisible);
|
||||
|
||||
|
||||
if (mWasLauncherAlreadyVisible && !mLauncher.getAppTransitionManager().isAnimating()) {
|
||||
DeviceProfile dp = mLauncher.getDeviceProfile();
|
||||
long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
|
||||
mLauncherTransitionController = mLauncher.getStateManager()
|
||||
.createAnimationToNewWorkspace(OVERVIEW, accuracy);
|
||||
if (mWasLauncherAlreadyVisible) {
|
||||
mLauncherTransitionController = mActivityControlHelper
|
||||
.createControllerForVisibleActivity(activity);
|
||||
mLauncherTransitionController.dispatchOnStart();
|
||||
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
|
||||
|
||||
mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
|
||||
} else {
|
||||
TraceHelper.beginSection("WTS-init");
|
||||
mLauncher.getStateManager().goToState(OVERVIEW, false);
|
||||
TraceHelper.partitionSection("WTS-init", "State changed");
|
||||
|
||||
// TODO: Implement a better animation for fading in
|
||||
View rootView = mLauncher.getRootView();
|
||||
View rootView = activity.getRootView();
|
||||
rootView.setAlpha(0);
|
||||
rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
|
||||
|
||||
@@ -427,21 +381,18 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
TraceHelper.endSection("WTS-init", "Launcher frame is drawn");
|
||||
rootView.post(() ->
|
||||
rootView.getViewTreeObserver().removeOnDrawListener(this));
|
||||
if (launcher != mLauncher) {
|
||||
if (activity != mActivity) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStateCallback.setState(STATE_LAUNCHER_DRAWN);
|
||||
}
|
||||
});
|
||||
|
||||
// Optimization, hide the all apps view to prevent layout while initializing
|
||||
mLauncher.getAppsView().setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
mRecentsView.showTask(mRunningTaskId);
|
||||
mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
|
||||
mLauncherLayoutListener.open();
|
||||
mLayoutListener.open();
|
||||
}
|
||||
|
||||
public void setLauncherOnDrawCallback(Runnable callback) {
|
||||
@@ -449,7 +400,7 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
|
||||
private void launcherFrameDrawn() {
|
||||
View rootView = mLauncher.getRootView();
|
||||
View rootView = mActivity.getRootView();
|
||||
if (rootView.getAlpha() < 1) {
|
||||
if (mGestureStarted) {
|
||||
final MultiStateCallback callback = mStateCallback;
|
||||
@@ -468,19 +419,12 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
|
||||
private void initializeLauncherAnimationController() {
|
||||
mLauncherLayoutListener.setHandler(this);
|
||||
mLayoutListener.setHandler(this);
|
||||
onLauncherLayoutChanged();
|
||||
|
||||
final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs;
|
||||
// Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for
|
||||
// "Recents" activity for app transition tests for the app-to-recents case.
|
||||
final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/);
|
||||
builder.setPackageName("com.android.systemui");
|
||||
builder.addTaggedData(871/*FIELD_CLASS_NAME*/,
|
||||
"com.android.systemui.recents.RecentsActivity");
|
||||
builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/,
|
||||
transitionDelay);
|
||||
mMetricsLogger.write(builder);
|
||||
SysuiEventLogger.writeDummyRecentsTransition(transitionDelay);
|
||||
|
||||
if (LatencyTrackerCompat.isEnabled(mContext)) {
|
||||
LatencyTrackerCompat.logToggleRecents((int) transitionDelay);
|
||||
}
|
||||
@@ -491,23 +435,16 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change interaction type from " + mInteractionType);
|
||||
}
|
||||
if (!isInteractionQuick(interactionType)) {
|
||||
if (interactionType != INTERACTION_QUICK_SCRUB) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change interaction type to " + interactionType);
|
||||
}
|
||||
mInteractionType = interactionType;
|
||||
|
||||
setStateOnUiThread(interactionType == INTERACTION_QUICK_SWITCH
|
||||
? STATE_QUICK_SWITCH : STATE_QUICK_SCRUB_START);
|
||||
setStateOnUiThread(STATE_QUICK_SCRUB_START);
|
||||
|
||||
// Start the window animation without waiting for launcher.
|
||||
animateToProgress(1f, QUICK_SWITCH_START_DURATION);
|
||||
}
|
||||
|
||||
private void onQuickInteractionStart() {
|
||||
mLauncher.getStateManager().goToState(FAST_OVERVIEW,
|
||||
mWasLauncherAlreadyVisible || mGestureStarted);
|
||||
mQuickScrubController.onQuickScrubStart(false);
|
||||
animateToProgress(1f, QUICK_SCRUB_START_DURATION);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@@ -520,32 +457,14 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #mLauncherLayoutListener} when launcher layout changes
|
||||
* Called by {@link #mLayoutListener} when launcher layout changes
|
||||
*/
|
||||
public void onLauncherLayoutChanged() {
|
||||
initTransitionEndpoints(mLauncher.getDeviceProfile());
|
||||
initTransitionEndpoints(mActivity.getDeviceProfile());
|
||||
|
||||
if (!mWasLauncherAlreadyVisible) {
|
||||
float startProgress;
|
||||
AllAppsTransitionController controller = mLauncher.getAllAppsController();
|
||||
|
||||
if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
|
||||
startProgress = 1;
|
||||
} else {
|
||||
float scrollRange = Math.max(controller.getShiftRange(), 1);
|
||||
startProgress = (mTransitionDragLength / scrollRange) + 1;
|
||||
}
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(controller, ALL_APPS_PROGRESS,
|
||||
startProgress, OVERVIEW.getVerticalProgress(mLauncher));
|
||||
shiftAnim.setInterpolator(LINEAR);
|
||||
anim.play(shiftAnim);
|
||||
|
||||
// TODO: Link this animation to state animation, so that it is cancelled
|
||||
// automatically on state change
|
||||
anim.setDuration(mTransitionDragLength * 2);
|
||||
mLauncherTransitionController =
|
||||
AnimatorPlaybackController.wrap(anim, mTransitionDragLength * 2);
|
||||
mLauncherTransitionController = mActivityControlHelper
|
||||
.createControllerForHiddenActivity(mActivity, mTransitionDragLength);
|
||||
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
|
||||
}
|
||||
}
|
||||
@@ -558,7 +477,12 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
if (mRecentsAnimationWrapper.controller != null) {
|
||||
RectF currentRect;
|
||||
synchronized (mTargetRect) {
|
||||
currentRect = mRectFEvaluator.evaluate(shift, mSourceRect, mTargetRect);
|
||||
Interpolator interpolator = mInteractionType == INTERACTION_QUICK_SCRUB
|
||||
? ACCEL_2 : LINEAR;
|
||||
float interpolated = interpolator.getInterpolation(shift);
|
||||
currentRect = mRectFEvaluator.evaluate(interpolated, mSourceRect, mTargetRect);
|
||||
// Stay lined up with the center of the target, since it moves for quick scrub.
|
||||
currentRect.offset(mTargetRect.centerX() - currentRect.centerX(), 0);
|
||||
}
|
||||
|
||||
mClipRect.left = (int) (mSourceWindowClipInsets.left * shift);
|
||||
@@ -598,13 +522,18 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
View firstTask = mRecentsView.getPageAt(0);
|
||||
int scrollForFirstTask = mRecentsView.getScrollForPage(0);
|
||||
int offsetFromFirstTask = (scrollForFirstTask - mRecentsView.getScrollX());
|
||||
if (offsetFromFirstTask != 0) {
|
||||
synchronized (mTargetRect) {
|
||||
mTargetRect.set(mInitialTargetRect);
|
||||
Utilities.scaleRectFAboutCenter(mTargetRect, firstTask.getScaleX());
|
||||
float offsetX = offsetFromFirstTask + firstTask.getTranslationX();
|
||||
mTargetRect.offset(offsetX, 0);
|
||||
}
|
||||
synchronized (mTargetRect) {
|
||||
mTargetRect.set(mInitialTargetRect);
|
||||
Utilities.scaleRectFAboutCenter(mTargetRect, firstTask.getScaleX());
|
||||
float offsetX = offsetFromFirstTask + firstTask.getTranslationX();
|
||||
float offsetY = mRecentsView.getTranslationY();
|
||||
mTargetRect.offset(offsetX, offsetY);
|
||||
}
|
||||
if (mRecentsAnimationWrapper.controller != null) {
|
||||
|
||||
// TODO: This logic is spartanic!
|
||||
mRecentsAnimationWrapper.controller.setAnimationTargetsBehindSystemBars(
|
||||
shift < 0.12f);
|
||||
}
|
||||
};
|
||||
if (Looper.getMainLooper() == Looper.myLooper()) {
|
||||
@@ -652,14 +581,13 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mRecentsAnimationWrapper.setController(controller, apps);
|
||||
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
}
|
||||
|
||||
public void onRecentsAnimationCanceled() {
|
||||
mRecentsAnimationWrapper.setController(null, null);
|
||||
clearReference();
|
||||
mActivityInitListener.unregister();
|
||||
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
@@ -675,9 +603,10 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
* on both background and UI threads
|
||||
*/
|
||||
private void notifyGestureStarted() {
|
||||
final Launcher curLauncher = mLauncher;
|
||||
if (curLauncher != null) {
|
||||
curLauncher.onQuickstepGestureStarted(mWasLauncherAlreadyVisible);
|
||||
final T curActivity = mActivity;
|
||||
if (curActivity != null) {
|
||||
mActivityControlHelper.onQuickstepGestureStarted(
|
||||
curActivity, mWasLauncherAlreadyVisible);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,25 +690,20 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
|
||||
clearReference();
|
||||
mActivityInitListener.unregister();
|
||||
mInputConsumer.unregisterInputConsumer();
|
||||
}
|
||||
|
||||
private void invalidateHandlerWithLauncher() {
|
||||
mLauncherTransitionController = null;
|
||||
mLauncherLayoutListener.setHandler(null);
|
||||
mLauncherLayoutListener.close(false);
|
||||
|
||||
// Restore the requested orientation to the user preference after the gesture has ended
|
||||
mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE);
|
||||
mLayoutListener.finish();
|
||||
|
||||
mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
|
||||
}
|
||||
|
||||
private void resetStateForAnimationCancel() {
|
||||
LauncherState startState = mLauncher.getStateManager().getRestState();
|
||||
boolean animate = mWasLauncherAlreadyVisible || mGestureStarted;
|
||||
mLauncher.getStateManager().goToState(startState, animate);
|
||||
boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted;
|
||||
mActivityControlHelper.onTransitionCancelled(mActivity, wasVisible);
|
||||
}
|
||||
|
||||
public void layoutListenerClosed() {
|
||||
@@ -808,17 +732,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
if (taskView != null) {
|
||||
// Defer finishing the animation until the next launcher frame with the
|
||||
// new thumbnail
|
||||
ViewOnDrawExecutor executor = new ViewOnDrawExecutor() {
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
if (!isCompleted()) {
|
||||
runAllTasks();
|
||||
}
|
||||
}
|
||||
};
|
||||
executor.attachTo(mLauncher, taskView,
|
||||
false /* waitForLoadAnimation */);
|
||||
executor.execute(finishTransitionRunnable);
|
||||
mActivityControlHelper.executeOnNextDraw(mActivity, taskView,
|
||||
finishTransitionRunnable);
|
||||
finishTransitionPosted = true;
|
||||
}
|
||||
}
|
||||
@@ -834,8 +749,7 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
}
|
||||
|
||||
private void setupLauncherUiAfterSwipeUpAnimation() {
|
||||
// Re apply state in case we did something funky during the transition.
|
||||
mLauncher.getStateManager().reapplyState();
|
||||
mActivityControlHelper.onSwipeUpComplete(mActivity);
|
||||
|
||||
// Animate the first icon.
|
||||
mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, true /* animate */);
|
||||
@@ -843,21 +757,13 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
reset();
|
||||
}
|
||||
|
||||
public void onQuickScrubEnd() {
|
||||
setStateOnUiThread(STATE_QUICK_SCRUB_END);
|
||||
private void onQuickScrubStart() {
|
||||
mActivityControlHelper.onQuickInteractionStart(mActivity, mWasLauncherAlreadyVisible);
|
||||
mQuickScrubController.onQuickScrubStart(false);
|
||||
}
|
||||
|
||||
private void switchToFinalAppAfterQuickSwitch() {
|
||||
mQuickScrubController.onQuickSwitch();
|
||||
}
|
||||
|
||||
private void switchToFinalAppAfterQuickScrub() {
|
||||
mQuickScrubController.onQuickScrubEnd();
|
||||
|
||||
// Normally this is handled in reset(), but since we are still scrubbing after the
|
||||
// transition into recents, we need to defer the handler invalidation for quick scrub until
|
||||
// after the gesture ends
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
private void onFinishedTransitionToQuickScrub() {
|
||||
mQuickScrubController.onFinishedTransitionToQuickScrub();
|
||||
}
|
||||
|
||||
public void onQuickScrubProgress(float progress) {
|
||||
@@ -870,6 +776,19 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
mQuickScrubController.onQuickScrubProgress(progress);
|
||||
}
|
||||
|
||||
public void onQuickScrubEnd() {
|
||||
setStateOnUiThread(STATE_QUICK_SCRUB_END);
|
||||
}
|
||||
|
||||
private void switchToFinalAppAfterQuickScrub() {
|
||||
mQuickScrubController.onQuickScrubEnd();
|
||||
|
||||
// Normally this is handled in reset(), but since we are still scrubbing after the
|
||||
// transition into recents, we need to defer the handler invalidation for quick scrub until
|
||||
// after the gesture ends
|
||||
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
private void debugNewState(int stateFlag) {
|
||||
if (!DEBUG_STATES) {
|
||||
return;
|
||||
@@ -889,4 +808,8 @@ public class WindowTransformSwipeHandler extends BaseSwipeInteractionHandler {
|
||||
Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding " + stateFlagStr + " to "
|
||||
+ currentStateStr);
|
||||
}
|
||||
|
||||
public void setGestureEndCallback(Runnable gestureEndCallback) {
|
||||
mGestureEndCallback = gestureEndCallback;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.quickstep.util;
|
||||
|
||||
import android.metrics.LogMaker;
|
||||
import android.util.EventLog;
|
||||
|
||||
/**
|
||||
* Utility class for writing logs on behalf of systemUI
|
||||
*/
|
||||
public class SysuiEventLogger {
|
||||
|
||||
/** 524292 sysui_multi_action (content|4) */
|
||||
public static final int SYSUI_MULTI_ACTION = 524292;
|
||||
|
||||
private static void write(LogMaker content) {
|
||||
if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) {
|
||||
content.setType(4/*MetricsEvent.TYPE_ACTION*/);
|
||||
}
|
||||
EventLog.writeEvent(SYSUI_MULTI_ACTION, content.serialize());
|
||||
}
|
||||
|
||||
public static void writeDummyRecentsTransition(long transitionDelay) {
|
||||
// Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for
|
||||
// "Recents" activity for app transition tests for the app-to-recents case.
|
||||
final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/);
|
||||
builder.setPackageName("com.android.systemui");
|
||||
builder.addTaggedData(871/*FIELD_CLASS_NAME*/,
|
||||
"com.android.systemui.recents.RecentsActivity");
|
||||
builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/,
|
||||
transitionDelay);
|
||||
write(builder);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.MotionEvent;
|
||||
@@ -21,11 +23,14 @@ import android.view.MotionEvent;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.quickstep.ActivityControlHelper.LayoutListener;
|
||||
import com.android.quickstep.WindowTransformSwipeHandler;
|
||||
|
||||
/**
|
||||
* Floating view which shows the task snapshot allowing it to be dragged and placed.
|
||||
*/
|
||||
public class LauncherLayoutListener extends AbstractFloatingView implements Insettable {
|
||||
public class LauncherLayoutListener extends AbstractFloatingView
|
||||
implements Insettable, LayoutListener {
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private WindowTransformSwipeHandler mHandler;
|
||||
@@ -36,6 +41,7 @@ public class LauncherLayoutListener extends AbstractFloatingView implements Inse
|
||||
setVisibility(INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHandler(WindowTransformSwipeHandler handler) {
|
||||
mHandler = handler;
|
||||
}
|
||||
@@ -65,6 +71,7 @@ public class LauncherLayoutListener extends AbstractFloatingView implements Inse
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
if (!mIsOpen) {
|
||||
mLauncher.getDragLayer().addView(this);
|
||||
@@ -86,4 +93,11 @@ public class LauncherLayoutListener extends AbstractFloatingView implements Inse
|
||||
protected boolean isOfType(int type) {
|
||||
return (type & TYPE_QUICKSTEP_PREVIEW) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
setHandler(null);
|
||||
close(false);
|
||||
mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE);
|
||||
}
|
||||
}
|
||||
@@ -17,20 +17,12 @@ package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.Shader.TileMode;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
@@ -41,13 +33,40 @@ import com.android.launcher3.R;
|
||||
/**
|
||||
* {@link RecentsView} used in Launcher activity
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class LauncherRecentsView extends RecentsView<Launcher> implements Insettable {
|
||||
|
||||
private Bitmap mScrim;
|
||||
private Paint mFadePaint;
|
||||
private Shader mFadeShader;
|
||||
private Matrix mFadeMatrix;
|
||||
private boolean mScrimOnLeft;
|
||||
public static final FloatProperty<LauncherRecentsView> TRANSLATION_X_FACTOR =
|
||||
new FloatProperty<LauncherRecentsView>("translationXFactor") {
|
||||
|
||||
@Override
|
||||
public void setValue(LauncherRecentsView view, float v) {
|
||||
view.setTranslationXFactor(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(LauncherRecentsView view) {
|
||||
return view.mTranslationXFactor;
|
||||
}
|
||||
};
|
||||
|
||||
public static final FloatProperty<LauncherRecentsView> TRANSLATION_Y_FACTOR =
|
||||
new FloatProperty<LauncherRecentsView>("translationYFactor") {
|
||||
|
||||
@Override
|
||||
public void setValue(LauncherRecentsView view, float v) {
|
||||
view.setTranslationYFactor(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(LauncherRecentsView view) {
|
||||
return view.mTranslationYFactor;
|
||||
}
|
||||
};
|
||||
|
||||
private float mTranslationXFactor;
|
||||
private float mTranslationYFactor;
|
||||
private Rect mPagePadding = new Rect();
|
||||
|
||||
public LauncherRecentsView(Context context) {
|
||||
this(context, null);
|
||||
@@ -59,6 +78,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
|
||||
|
||||
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setContentAlpha(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,64 +91,39 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
|
||||
setLayoutParams(lp);
|
||||
|
||||
setPadding(padding.left, padding.top, padding.right, 0);
|
||||
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
boolean wasScrimOnLeft = mScrimOnLeft;
|
||||
mScrimOnLeft = dp.isSeascape();
|
||||
|
||||
if (mScrim == null || wasScrimOnLeft != mScrimOnLeft) {
|
||||
Drawable scrim = getContext().getDrawable(mScrimOnLeft
|
||||
? R.drawable.recents_horizontal_scrim_left
|
||||
: R.drawable.recents_horizontal_scrim_right);
|
||||
if (scrim instanceof BitmapDrawable) {
|
||||
mScrim = ((BitmapDrawable) scrim).getBitmap();
|
||||
mFadePaint = new Paint();
|
||||
mFadePaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
|
||||
mFadeShader = new BitmapShader(mScrim, TileMode.CLAMP, TileMode.REPEAT);
|
||||
mFadeMatrix = new Matrix();
|
||||
} else {
|
||||
mScrim = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mScrim = null;
|
||||
mFadePaint = null;
|
||||
mFadeShader = null;
|
||||
mFadeMatrix = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mScrim == null) {
|
||||
super.draw(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
|
||||
|
||||
int length = mScrim.getWidth();
|
||||
int height = getHeight();
|
||||
int saveCount = canvas.getSaveCount();
|
||||
|
||||
int scrimLeft;
|
||||
if (mScrimOnLeft) {
|
||||
scrimLeft = getScrollX();
|
||||
} else {
|
||||
scrimLeft = getScrollX() + getWidth() - length;
|
||||
}
|
||||
canvas.saveLayer(scrimLeft, 0, scrimLeft + length, height, null, flags);
|
||||
super.draw(canvas);
|
||||
|
||||
mFadeMatrix.setTranslate(scrimLeft, 0);
|
||||
mFadeShader.setLocalMatrix(mFadeMatrix);
|
||||
mFadePaint.setShader(mFadeShader);
|
||||
canvas.drawRect(scrimLeft, 0, scrimLeft + length, height, mFadePaint);
|
||||
canvas.restoreToCount(saveCount);
|
||||
mPagePadding.set(padding);
|
||||
mPagePadding.top += getResources().getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAllTasksRemoved() {
|
||||
mActivity.getStateManager().goToState(NORMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
int width = right - left;
|
||||
setTranslationX(mTranslationXFactor * (mIsRtl ? -width : width));
|
||||
setTranslationYFactor(mTranslationYFactor);
|
||||
}
|
||||
|
||||
public void setTranslationXFactor(float translationFactor) {
|
||||
mTranslationXFactor = translationFactor;
|
||||
setTranslationX(translationFactor * (mIsRtl ? -getWidth() : getWidth()));
|
||||
}
|
||||
|
||||
public float getTranslationXFactor() {
|
||||
return mTranslationXFactor;
|
||||
}
|
||||
|
||||
public void setTranslationYFactor(float translationFactor) {
|
||||
mTranslationYFactor = translationFactor;
|
||||
setTranslationY(mTranslationYFactor * (mPagePadding.bottom - mPagePadding.top));
|
||||
}
|
||||
|
||||
public float getTranslationYFactor() {
|
||||
return mTranslationYFactor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
@@ -30,8 +31,11 @@ import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
@@ -40,6 +44,7 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.quickstep.PendingAnimation;
|
||||
import com.android.quickstep.QuickScrubController;
|
||||
@@ -62,7 +67,23 @@ import java.util.ArrayList;
|
||||
public abstract class RecentsView<T extends BaseActivity>
|
||||
extends PagedView implements OnSharedPreferenceChangeListener {
|
||||
|
||||
public static final FloatProperty<RecentsView> CONTENT_ALPHA =
|
||||
new FloatProperty<RecentsView>("contentAlpha") {
|
||||
|
||||
|
||||
@Override
|
||||
public void setValue(RecentsView recentsView, float v) {
|
||||
recentsView.setContentAlpha(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(RecentsView recentsView) {
|
||||
return recentsView.mContentAlpha;
|
||||
}
|
||||
};
|
||||
|
||||
private static final String PREF_FLIP_RECENTS = "pref_flip_recents";
|
||||
private static final int DISMISS_TASK_DURATION = 300;
|
||||
|
||||
private static final Rect sTempStableInsets = new Rect();
|
||||
|
||||
@@ -104,6 +125,11 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
|
||||
private PendingAnimation mPendingAnimation;
|
||||
|
||||
private float mContentAlpha = 1;
|
||||
|
||||
// Keeps track of task views whose visual state should not be reset
|
||||
private ArraySet<TaskView> mIgnoreResetTaskViews = new ArraySet<>();
|
||||
|
||||
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
|
||||
@@ -261,7 +287,10 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
|
||||
public void resetTaskVisuals() {
|
||||
for (int i = getChildCount() - 1; i >= 0; i--) {
|
||||
((TaskView) getChildAt(i)).resetVisualProperties();
|
||||
TaskView taskView = (TaskView) getChildAt(i);
|
||||
if (!mIgnoreResetTaskViews.contains(taskView)) {
|
||||
taskView.resetVisualProperties();
|
||||
}
|
||||
}
|
||||
|
||||
updateCurveProperties();
|
||||
@@ -294,12 +323,10 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
|
||||
float overviewHeight, overviewWidth;
|
||||
if (profile.isVerticalBarLayout()) {
|
||||
float scrimLength = context.getResources()
|
||||
.getDimension(R.dimen.recents_page_fade_length);
|
||||
float maxPadding = Math.max(padding.left, padding.right);
|
||||
|
||||
// Use the same padding on both sides for symmetry.
|
||||
float availableWidth = taskWidth - 2 * Math.max(maxPadding, scrimLength);
|
||||
float availableWidth = taskWidth - 2 * maxPadding;
|
||||
float availableHeight = profile.availableHeightPx - padding.top - padding.bottom
|
||||
- sTempStableInsets.top;
|
||||
float scaledRatio = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
|
||||
@@ -512,7 +539,16 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
public float linearInterpolation;
|
||||
}
|
||||
|
||||
public PendingAnimation createTaskDismissAnimation(TaskView taskView, long duration) {
|
||||
public void addIgnoreResetTask(TaskView taskView) {
|
||||
mIgnoreResetTaskViews.add(taskView);
|
||||
}
|
||||
|
||||
public void removeIgnoreResetTask(TaskView taskView) {
|
||||
mIgnoreResetTaskViews.remove(taskView);
|
||||
}
|
||||
|
||||
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
|
||||
boolean removeTask, long duration) {
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
|
||||
throw new IllegalStateException("Another pending animation is still running");
|
||||
}
|
||||
@@ -543,9 +579,11 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child == taskView) {
|
||||
addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim);
|
||||
addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()),
|
||||
duration, LINEAR, anim);
|
||||
if (animateTaskView) {
|
||||
addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim);
|
||||
addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()),
|
||||
duration, LINEAR, anim);
|
||||
}
|
||||
} else {
|
||||
int scrollDiff = newScroll[i] - oldScroll[i] + maxScrollDiff;
|
||||
if (scrollDiff != 0) {
|
||||
@@ -563,12 +601,16 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
}
|
||||
|
||||
// Add a tiny bit of translation Z, so that it draws on top of other views
|
||||
taskView.setTranslationZ(0.1f);
|
||||
if (animateTaskView) {
|
||||
taskView.setTranslationZ(0.1f);
|
||||
}
|
||||
|
||||
mPendingAnimation = pendingAnimation;
|
||||
mPendingAnimation.addEndListener((isSuccess) -> {
|
||||
if (isSuccess) {
|
||||
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
|
||||
if (removeTask) {
|
||||
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
|
||||
}
|
||||
removeView(taskView);
|
||||
if (getChildCount() == 0) {
|
||||
onAllTasksRemoved();
|
||||
@@ -585,4 +627,85 @@ public abstract class RecentsView<T extends BaseActivity>
|
||||
anim.setDuration(duration).setInterpolator(interpolator);
|
||||
set.play(anim);
|
||||
}
|
||||
|
||||
private void snapToPageRelative(int delta) {
|
||||
snapToPage((getNextPage() + getPageCount() + delta) % getPageCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibilityAggregated(boolean isVisible) {
|
||||
super.onVisibilityAggregated(isVisible);
|
||||
if (isVisible && !isFocused()) {
|
||||
// Having focus, even in touch mode, keeps us from losing [Alt+]Tab by preventing
|
||||
// switching to keyboard mode.
|
||||
requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissTask(TaskView taskView, boolean animateTaskView, boolean removeTask) {
|
||||
PendingAnimation pendingAnim = createTaskDismissAnimation(taskView, animateTaskView,
|
||||
removeTask, DISMISS_TASK_DURATION);
|
||||
AnimatorPlaybackController controller = AnimatorPlaybackController.wrap(
|
||||
pendingAnim.anim, DISMISS_TASK_DURATION);
|
||||
controller.dispatchOnStart();
|
||||
controller.setEndAction(() -> pendingAnim.finish(true));
|
||||
controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
|
||||
controller.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
switch (event.getKeyCode()) {
|
||||
case KeyEvent.KEYCODE_TAB:
|
||||
snapToPageRelative(event.isShiftPressed() ? -1 : 1);
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
snapToPageRelative(mIsRtl ? -1 : 1);
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
snapToPageRelative(mIsRtl ? 1 : -1);
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_DEL:
|
||||
case KeyEvent.KEYCODE_FORWARD_DEL:
|
||||
dismissTask((TaskView) getChildAt(getNextPage()), true /*animateTaskView*/,
|
||||
true /*removeTask*/);
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_NUMPAD_DOT:
|
||||
if (event.isAltPressed()) {
|
||||
// Numpad DEL pressed while holding Alt.
|
||||
dismissTask((TaskView) getChildAt(getNextPage()), true /*animateTaskView*/,
|
||||
true /*removeTask*/);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
public void snapToTaskAfterNext() {
|
||||
snapToPageRelative(1);
|
||||
}
|
||||
|
||||
public void launchNextTask() {
|
||||
final TaskView nextTask = (TaskView) getChildAt(getNextPage());
|
||||
nextTask.launchTask(true);
|
||||
}
|
||||
|
||||
public void setContentAlpha(float alpha) {
|
||||
if (mContentAlpha == alpha) {
|
||||
return;
|
||||
}
|
||||
mContentAlpha = alpha;
|
||||
for (int i = getChildCount() - 1; i >= 0; i--) {
|
||||
getChildAt(i).setAlpha(alpha);
|
||||
}
|
||||
setVisibility(alpha > 0 ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
child.setAlpha(mContentAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,7 +28,7 @@ import android.view.ViewOutlineProvider;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.views.RecentsView.PageCallbacks;
|
||||
import com.android.quickstep.views.RecentsView.ScrollState;
|
||||
@@ -54,6 +54,11 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
|
||||
*/
|
||||
private static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
|
||||
|
||||
/**
|
||||
* How much to scale down pages near the edge of the screen.
|
||||
*/
|
||||
private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f;
|
||||
|
||||
private static final long SCALE_ICON_DURATION = 120;
|
||||
|
||||
private Task mTask;
|
||||
@@ -91,6 +96,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
|
||||
mTask = task;
|
||||
mSnapshotView.bind();
|
||||
task.addCallback(this);
|
||||
setContentDescription(task.titleDescription);
|
||||
}
|
||||
|
||||
public Task getTask() {
|
||||
@@ -110,7 +116,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);
|
||||
}
|
||||
@@ -164,6 +171,16 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
|
||||
CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
|
||||
|
||||
mSnapshotView.setDimAlpha(1 - curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
|
||||
|
||||
float scale = 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlappingRendering() {
|
||||
// TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final class TaskOutlineProvider extends ViewOutlineProvider {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="2dp"
|
||||
android:width="16dp"
|
||||
android:viewportHeight="2.0"
|
||||
android:viewportWidth="16.0">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M1,0h14c0.55,0,1,0.45,1,1s-0.45,1-1,1H1C0.45,2,0,1.55,0,1S0.45,0,1,0z"/>
|
||||
</vector>
|
||||
@@ -21,8 +21,8 @@
|
||||
android:id="@+id/fast_scroller_popup"
|
||||
style="@style/FastScrollerPopup"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@+id/search_container_all_apps"
|
||||
android:layout_marginEnd="@dimen/fastscroll_popup_margin" />
|
||||
android:layout_marginEnd="@dimen/fastscroll_popup_margin"
|
||||
android:layout_marginTop="@dimen/all_apps_search_bar_field_height_and_margin" />
|
||||
|
||||
<com.android.launcher3.views.RecyclerViewFastScroller
|
||||
android:id="@+id/fast_scroller"
|
||||
@@ -30,8 +30,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@+id/search_container_all_apps"
|
||||
android:layout_marginEnd="@dimen/fastscroll_end_margin"
|
||||
android:layout_marginTop="@dimen/all_apps_search_bar_field_height_and_margin"
|
||||
launcher:canThumbDetach="true" />
|
||||
|
||||
</merge>
|
||||
@@ -18,10 +18,10 @@
|
||||
android:id="@+id/all_apps_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/search_container_all_apps"
|
||||
android:layout_marginTop="@dimen/all_apps_search_bar_field_height_and_margin"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="@dimen/all_apps_header_top_padding"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/all_apps_header_top_padding" >
|
||||
|
||||
<com.android.launcher3.allapps.PersonalWorkSlidingTabStrip
|
||||
android:id="@+id/tabs"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
android:id="@+id/apps_list_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/search_container_all_apps"
|
||||
android:layout_marginTop="@dimen/all_apps_search_bar_field_height_and_margin"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:focusable="true" />
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
android:id="@+id/all_apps_tabs_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/search_container_all_apps"
|
||||
android:layout_gravity="center_horizontal|top"
|
||||
android:layout_marginTop="@dimen/all_apps_header_tab_height"
|
||||
android:layout_marginTop="@dimen/all_apps_tabs_top_margin"
|
||||
android:clipChildren="true"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
android:theme="@style/HomeScreenElementTheme"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drag_indicator"
|
||||
android:layout_width="@dimen/hotseat_drag_indicator_height"
|
||||
android:layout_height="@dimen/hotseat_drag_indicator_height"
|
||||
android:src="@drawable/ic_drag_indicator"
|
||||
android:tint="?attr/workspaceTextColor"
|
||||
android:scaleType="centerInside"
|
||||
android:layout_gravity="top|center_horizontal"/>
|
||||
|
||||
<com.android.launcher3.CellLayout
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -44,13 +44,6 @@
|
||||
layout="@layout/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- DO NOT CHANGE THE ID -->
|
||||
<include
|
||||
android:id="@+id/hotseat"
|
||||
layout="@layout/hotseat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<!-- Keep these behind the workspace so that they are not visible when
|
||||
we go into AllApps -->
|
||||
<com.android.launcher3.pageindicators.WorkspacePageIndicator
|
||||
@@ -69,6 +62,13 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<!-- DO NOT CHANGE THE ID -->
|
||||
<include
|
||||
android:id="@+id/hotseat"
|
||||
layout="@layout/hotseat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</com.android.launcher3.dragndrop.DragLayer>
|
||||
|
||||
</com.android.launcher3.LauncherRootView>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<com.android.launcher3.views.HighlightableListView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:cacheColorHint="@android:color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:drawSelectorOnTop="false"
|
||||
android:orientation="vertical"
|
||||
android:scrollbarAlwaysDrawVerticalTrack="true"
|
||||
android:scrollbarStyle="outsideOverlay" />
|
||||
@@ -31,7 +31,6 @@
|
||||
android:layout_height="@dimen/widget_section_height"
|
||||
android:background="?android:attr/colorPrimary"
|
||||
android:drawablePadding="@dimen/widget_section_horizontal_padding"
|
||||
android:ellipsize="end"
|
||||
android:focusable="true"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingBottom="@dimen/widget_section_vertical_padding"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?android:attr/colorAccent"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
@@ -42,6 +43,7 @@
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_gravity="right"
|
||||
android:contentDescription="@string/bottom_work_tab_user_education_close_button"
|
||||
android:src="@drawable/ic_close"/>
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Kon geen programme kry wat by \"<xliff:g id="QUERY">%1$s</xliff:g>\" pas nie"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Soek meer programme"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Kennisgewings"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Niks meer spasie op die tuisskerm nie."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Geen plek meer in die Gunstelinge-laai nie"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Programmelys"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Lys persoonlike programme"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Lys werkprogramme"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Tuis"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Verwyder"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Deïnstalleer"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Muurpapiere"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Home-instellings"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gedeaktiveer deur jou administrateur"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Oorsig"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Laat toe dat tuisskerm gedraai word"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Wanneer foon gedraai word"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Huidige vertooninstelling laat nie rotasie toe nie"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Kennisgewingkolle"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aan"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Af"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Kennisgewingtoegang word benodig"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Skakel programkennisgewings vir <xliff:g id="NAME">%1$s</xliff:g> aan om kennisgewingkolle te sien"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Verander instellings"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Wys kennisgewingkolle"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Voeg ikoon by tuisskerm"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Vir nuwe programme"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Verander ikoon se vorm"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"op tuisskerm"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Gebruik stelselverstek"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Vierkant"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Sirkelvierkant"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Skep vouer met: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Vouer geskep"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Skuif na tuisskerm"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Skuif skerm na links"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Skuif skerm na regs"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Skerm is geskuif"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Verander grootte"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Vermeerder breedte"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Vermeerder hoogte"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Werk"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Werkprofiel"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Kry werkprogramme hier"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Elke werkprogram het \'n kenteken en word deur jou organisasie veilig gehou. Skuif programme na jou tuisskerm toe vir makliker toegang."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Bestuur deur jou organisasie"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Kennisgewings en programme is af"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Maak toe"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Toe"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"<xliff:g id="QUERY">%1$s</xliff:g> sorğusuna uyğun tətbiq tapılmadı"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Daha çox tətbiq üçün axtarış edin"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Bildirişlər"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Bu Əsas ekranda boş yer yoxdur."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Favoritlər-də yer yoxdur"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Tətbiq siyahısı"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Şəxsi tətbiqlərin siyahısı"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"İş tətbiqlərinin siyahısı"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Əsas səhifə"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Silin"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Sistemdən sil"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Divar kağızları"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Home ayarları"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Admininiz tərəfindən deaktiv edilib"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"İcmal"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Əsas ekranın firlanmağına icazə verin"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefon çevrilən zaman"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Cari Ekran ayarı fırlatmağa icazə vermir"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Bildiriş nişanı"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktiv"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Deaktiv"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Bildiriş girişi tələb edilir"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Bildiriş Nöqtələrini göstərmək üçün <xliff:g id="NAME">%1$s</xliff:g> bildirişlərini aktiv edin"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Ayarları dəyişin"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Bildiriş nöqtələrini göstərin"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Əsas ekrana ikona əlavə edin"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Yeni tətbiqlər üçün"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"İkona formasını dəyişin"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"Əsas səhifə ekranında"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Sistem defoltu istifadə edin"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Kənarları dairəvi kvadrat"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Qovluq yaradın: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Qovluq yaradıldı"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Əsas ekrana köçürün"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Ekranı sola köçürün"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Ekranı sağa köçürün"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Ekran köçürülüb"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Ölçüsünü dəyişin"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Eni artırın"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Hündürlüyü artırın"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"İş"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"İş profili"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Burada iş tətbiqləri axtarın"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Hər bir iş tətbiqində təşkilat tərəfindən qorunduğunu göstərən narıncı nişan var. Tətbiqləri daha asan giriş üçün Əsas Səhifə Ekranına köçürün."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Təşkilatınız tərəfindən idarə olunur"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Bildiriş və tətbiqlər deaktivdir"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Bağlayın"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Bağlıdır"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Няма намерени приложения, съответстващи на „<xliff:g id="QUERY">%1$s</xliff:g>“"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Търсене на още приложения"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Известия"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"На този начален екран няма повече място."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Няма повече място в областта с любимите"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Списък с приложения"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Списък с лични приложения"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Списък със служебни приложения"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Начало"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Премахване"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Деинсталиране"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тапети"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Настройки за Google Home"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Деактивирано от администратора ви"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Общ преглед"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Разрешаване на завъртането на началния екран"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"При завъртане на телефона"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Текущата настройка на екрана не разрешава завъртане"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Точки за известия"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Включено"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Изключено"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Необходим е достъп до известията"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"За да се показват точки за известия, включете известията за приложението <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Промяна на настройките"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Показване на точките за известия"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Добавяне на икона към началния екран"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови приложения"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Промяна на формата на иконите"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"на началния екран"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Използване на стандартната системна настройка"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Квадрат"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Комбинация от кръг и квадрат"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Създаване на папка с елемента „<xliff:g id="NAME">%1$s</xliff:g>“"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Папката е създадена"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Преместване към началния екран"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Преместване на екрана наляво"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Преместване на екрана надясно"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Екранът е преместен"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Преоразмеряване"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Увеличаване на ширината"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Увеличаване на височината"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Служебни"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Служебен потребителски профил"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Тук можете да намерите служебните приложения"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Всяко служебно приложение има значка и организацията ви се грижи за сигурността му. За по-лесен достъп преместете приложенията на началния си екран."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Управлява се от организацията ви"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Известията и приложенията са изключени"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Затваряне"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Затворено"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" এর সাথে মেলে এমন কোনো অ্যাপ পাওয়া যায়নি"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"আরও অ্যাপ্লিকেশানের জন্য খুঁজুন"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"বিজ্ঞপ্তি"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"এই হোম স্ক্রীনে আর কোনো জায়গা নেই৷"</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"পছন্দসই ট্রে-তে আর কোনো জায়গা নেই"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"অ্যাপ্লিকেশানগুলির তালিকা"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"ব্যক্তিগত অ্যাপের তালিকা"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"কাজের অ্যাপের তালিকা"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"হোম"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"সরান"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"আনইনস্টল করুন"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"ওয়ালপেপারগুলি"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"হোম এর সেটিংস"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"এক নজরে"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"হোমস্ক্রীন ঘোরানোর অনুমতি দিন"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"যখন ফোনটি ঘোরানো হয়"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"বর্তমান প্রদর্শনের সেটিংস ঘোরানোর মঞ্জুরি দেয় না"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"বিজ্ঞপ্তি ডট"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"চালু হয়েছে"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"বন্ধ আছে"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, <xliff:g id="NAME">%1$s</xliff:g> এর অ্যাপ বিজ্ঞপ্তি চালু করুন"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"সেটিংস পরিবর্তন করুন"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"বিজ্ঞপ্তির ডট দেখুন"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"হোম স্ক্রিনে আইকন যোগ করুন"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"নতুন অ্যাপ্লিকেশানগুলির জন্যে"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"আইকনের আকৃতি পরিবর্তন করুন"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"হোম স্ক্রিনে"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"সিস্টেমের ডিফল্ট মান ব্যবহার করুন"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"চৌকো"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"চৌকো-গোলাকার"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"এর সাথে ফোল্ডার তৈরি করুন: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"ফোল্ডার তৈরি করা হয়েছে"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"হোম স্ক্রীনে সরান"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"স্ক্রীন বাঁ দিকে সরান"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"স্ক্রীন ডান দিকে সরান"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"স্ক্রীন সরানো হয়েছে"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"আবার আকার দিন"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"প্রস্থ বাড়ান"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"উচ্চতা বাড়ান"</string>
|
||||
@@ -137,8 +138,11 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"অফিস"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"অফিসের প্রোফাইল"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"এখানে কাজের অ্যাপ্সগুলি খুঁজুন"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"প্রতিটি কাজের অ্যাপে একটি করে ব্যাজ রয়েছে এবং অ্যাপগুলি আপনার প্রতিষ্ঠানের দ্বারা সুরক্ষিত। সহজে অ্যাক্সেস করার জন্য অ্যাপগুলি হোম স্ক্রিনে রাখুন।"</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"আপনার প্রতিষ্ঠানের দ্বারা পরিচালিত"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"বিজ্ঞপ্তি এবং অ্যাপ বন্ধ আছে"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_close_button (4224492243977802135) -->
|
||||
<skip />
|
||||
<!-- no translation found for bottom_work_tab_user_education_closed (1098340939861869465) -->
|
||||
<skip />
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No s\'ha trobat cap aplicació que coincideixi amb \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Cerca més aplicacions"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notificacions"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Ja no queda espai en aquesta pantalla d\'inici."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No hi ha més espai a la safata Preferits."</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Llista d\'aplicacions"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Llista d\'aplicacions personals"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Llista d\'aplicacions per a la feina"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inici"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Suprimeix"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstal·la"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fons de pantalla"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Configuració de la pantalla d\'inici"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Desactivada per l\'administrador"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Visió general"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Permet la rotació de la pantalla d\'inici"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"En girar el telèfon"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"La configuració actual de la pantalla no permet la rotació"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Punts de notificació"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activat"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Desactivat"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Cal que tingui accés a les notificacions"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per veure els punts de notificació, activa les notificacions de l\'aplicació <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Canvia la configuració"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Mostra els punts de notificació"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Afegeix la icona a la pantalla d\'inici"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per a les aplicacions noves"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Canvia la forma de les icones"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"a la pantalla d\'inici"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Utilitza l\'opció predeterminada del sistema"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Quadrat"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Quadrat arrodonit"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Crea una carpeta amb: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Desplaça a la pantalla d\'inici"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Desplaça pantalla a l\'esquerra"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Desplaça pantalla a la dreta"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"S\'ha desplaçat la pantalla"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Canvia la mida"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Augmenta l\'amplada"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Augmenta l\'alçada"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Feina"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil professional"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Cerca aplicacions per a la feina aquí"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Totes les aplicacions per a la feina tenen una insígnia que indica que estan protegides per la teva organització. Mou les aplicacions a la pantalla d\'inici per poder-hi accedir més fàcilment."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Gestionat per la teva organització"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Les notificacions i les aplicacions estan desactivades"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Tanca"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Tancada"</string>
|
||||
</resources>
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Der er ikke mere plads på denne startskærm."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Der er ikke mere plads i bakken Foretrukne"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Liste med apps"</string>
|
||||
<!-- no translation found for all_apps_button_personal_label (1315764287305224468) -->
|
||||
<skip />
|
||||
<!-- no translation found for all_apps_button_work_label (7270707118948892488) -->
|
||||
<skip />
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Startskærm"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Fjern"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Afinstaller"</string>
|
||||
@@ -77,19 +81,18 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Baggrunde"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Indstillinger for startskærmen"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Deaktiveret af din administrator"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Oversigt"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Tillad rotation af startskærmen"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Når telefonen roteres"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Den aktuelle indstilling for visning tillader ikke rotation"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Underretningscirkler"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Til"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Fra"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Kræver adgang til underretninger"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Hvis du vil se underretningscirkler, skal du aktivere appunderretninger for <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Skift indstillinger"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Vis underretningscirkler"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Føj ikon til startskærmen"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For nye apps"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Skift ikonform"</string>
|
||||
<!-- no translation found for icon_shape_override_label_location (3841607380657692863) -->
|
||||
<skip />
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Brug systemstandarden"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Kvadrat"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Kvadrat med runde hjørner"</string>
|
||||
@@ -119,9 +122,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Opret mappe med: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Mappen blev oprettet"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Flyt til startskærmen"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Flyt skærmen til venstre"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Flyt skærmen til højre"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Skærmen er flyttet"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Tilpas størrelse"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Øg bredden"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Øg højden"</string>
|
||||
@@ -137,8 +137,7 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Arbejde"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Arbejdsprofil"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Find arbejdsapps her"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Alle arbejdsapps har et badge og beskyttes af din organisation. Flyt apps til din startskærm, så du nemmere kan få adgang til dem."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Administreret af din organisation"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Underretninger og apps er slået fra"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Δεν βρέθηκαν εφαρμογές αντιστοίχισης για \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Αναζήτηση περισσότερων εφαρμογών"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Ειδοποιήσεις"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Δεν υπάρχει χώρος σε αυτήν την αρχική οθόνη."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Δεν υπάρχει επιπλέον χώρος στην περιοχή Αγαπημένα"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Λίστα εφαρμογών"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Λίστα προσωπικών εφαρμογών"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Λίστα εφαρμογών εργασίας"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Αρχική οθόνη"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Κατάργηση"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Απεγκατάσταση"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Ταπετσαρίες"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Ρυθμίσεις Αρχικής σελίδας"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Απενεργοποιήθηκε από τον διαχειριστή σας"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Επισκόπηση"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Να επιτρέπεται η περιστροφή της αρχικής οθόνης"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Όταν το τηλέφωνο περιστρέφεται"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Η τρέχουσα ρύθμιση οθόνης δεν επιτρέπει την περιστροφή"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Κουκκίδες ειδοποίησης"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Ενεργή"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Ανενεργή"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Απαιτείται πρόσβαση στις ειδοποιήσεις"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Για να εμφανιστούν οι Κουκκίδες ειδοποίησης, ενεργοποιήστε τις κουκκίδες εφαρμογής για την εφαρμογή <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Αλλαγή ρυθμίσεων"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Εμφάνιση κουκκίδων ειδοποίησης"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Προσθήκη εικονιδίου στην Αρχική οθόνη"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Για νέες εφαρμογές"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Αλλαγή σχήματος εικονιδίου"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"στην Αρχική οθόνη"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Χρήση προεπιλογής συστήματος"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Τετράγωνο"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Στρογγυλεμένο τετράγωνο"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Δημιουργία φακέλου με: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Δημιουργήθηκε φάκελος"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Μετακίνηση Αρχικής οθόνης"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Μετακίνηση οθόνης αριστερά"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Μετακίνηση οθόνης δεξιά"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Η οθόνη μετακινήθηκε"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Προσαρμογή μεγέθους"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Αύξηση του πλάτους"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Αύξηση του ύψους"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Εργασίας"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Προφίλ εργασίας"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Βρείτε όλες τις εφαρμογές εργασίας εδώ"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Κάθε εφαρμογή εργασίας φέρει ένα σήμα και διατηρείται ασφαλής από τον οργανισμό σας. Μετακινήστε τις εφαρμογές εργασίας στην Αρχική οθόνη, για να έχετε πιο εύκολη πρόσβαση."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Διαχειριζόμενο από τον οργανισμό σας"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Οι ειδοποιήσεις και οι εφαρμογές είναι απενεργοποιημένες"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Κλείσιμο"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Κλειστή"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Personal apps list"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Work apps list"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Remove"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Overview"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Current display setting doesn\'t permit rotation"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Notification dots"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"On"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Off"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Show notification dots"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Change icon shape"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"on Home screen"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Use system default"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Square"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Move screen to left"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Move screen to right"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Screen moved"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Work"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Work profile"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Find work apps here"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Each work app has a badge and is kept secure by your organisation. Move apps to your Home screen for easier access."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Managed by your organisation"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Personal apps list"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Work apps list"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Remove"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Overview"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Current display setting doesn\'t permit rotation"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Notification dots"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"On"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Off"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Show notification dots"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Change icon shape"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"on Home screen"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Use system default"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Square"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Move screen to left"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Move screen to right"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Screen moved"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Work"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Work profile"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Find work apps here"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Each work app has a badge and is kept secure by your organisation. Move apps to your Home screen for easier access."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Managed by your organisation"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No apps found matching \'<xliff:g id="QUERY">%1$s</xliff:g>\'"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Search for more apps"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notifications"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"No more room on this Home screen."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"No more room in the Favourites tray"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Apps list"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Personal apps list"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Work apps list"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Remove"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstall"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpapers"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Home settings"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disabled by your admin"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Overview"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Allow Homescreen rotation"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"When phone is rotated"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Current display setting doesn\'t permit rotation"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Notification dots"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"On"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Off"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Notification access needed"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"To show Notification Dots, turn on app notifications for <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Change settings"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Show notification dots"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Add icon to Home screen"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"For new apps"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Change icon shape"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"on Home screen"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Use system default"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Square"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Create folder with: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Folder created"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Move to Home screen"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Move screen to left"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Move screen to right"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Screen moved"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Re-size"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Increase width"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Increase height"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Work"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Work profile"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Find work apps here"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Each work app has a badge and is kept secure by your organisation. Move apps to your Home screen for easier access."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Managed by your organisation"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifications and apps are off"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Close"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Closed"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"No se han encontrado aplicaciones que contengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Buscar más aplicaciones"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notificaciones"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"No queda espacio en la pantalla de inicio."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"La bandeja de favoritos está completa"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de aplicaciones"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Lista de aplicaciones personales"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Lista de aplicaciones del trabajo"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inicio"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Quitar"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Ajustes de Home"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Inhabilitada por el administrador"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Visión general"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir rotación de la pantalla de inicio"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Al girar el teléfono"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"La configuración de pantalla actual no permite girar la pantalla"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Puntos de notificación"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activada"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Desactivada"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Se necesita acceso a las notificaciones"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para mostrar burbujas de notificación, activa las notificaciones de <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar ajustes"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar burbujas de notificación"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Añadir icono a la pantalla de inicio"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para aplicaciones nuevas"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Cambiar forma de los iconos"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"en la pantalla de inicio"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Usar opción predeterminada del sistema"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Cuadrado"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Cuadrado con esquinas redondeadas"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Crear carpeta con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Carpeta creada"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Mover a la pantalla de inicio"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Mover pantalla a la izquierda"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Mover pantalla a la derecha"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Pantalla movida"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Modificar tamaño"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar ancho"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Trabajo"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de trabajo"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Aplicaciones de trabajo"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Cada aplicación de trabajo tiene una insignia y está protegida por tu organización. Mueve las aplicaciones a la pantalla de inicio para acceder a ellas más fácilmente."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Administrada por tu organización"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Las notificaciones y las aplicaciones están desactivadas"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Cerrar"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Cerrada"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Päringule „<xliff:g id="QUERY">%1$s</xliff:g>” ei vastanud ükski rakendus"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Otsi rohkem rakendusi"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Märguanded"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Sellel avaekraanil pole enam ruumi."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Salves Lemmikud pole rohkem ruumi"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Rakenduste loend"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Isiklike rakenduste loend"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Töörakenduste loend"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Avaekraan"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Eemalda"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalli"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustapildid"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Avalehe seaded"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Keelas administraator"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Ülevaade"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Luba avaekraani pööramine"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kui telefoni pööratakse"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Praegune kuvaseade ei luba pööramist"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Märguandetäpid"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Sees"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Väljas"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Vaja on juurdepääsu märguannetele"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Märguandetäppide kuvamiseks lülitage sisse rakenduse <xliff:g id="NAME">%1$s</xliff:g> märguanded"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Seadete muutmine"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Kuva märguandetäpid"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Lisa ikoon avaekraanile"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Uute rakenduste puhul"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Ikooni kuju muutmine"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"avaekraanil"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Kasuta süsteemi vaikeseadet"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Ruut"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Ümarate nurkadega ruut"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Kausta loomine nimega <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Kaust on loodud"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Teisalda avaekraanile"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Teisalda ekraan vasakule"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Teisalda ekraan paremale"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Ekraan teisaldati"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Muuda suurust"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Suurenda laiust"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Suurenda kõrgust"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Töö"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Tööprofiil"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Töörakendused leiate siit"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Igal töörakendusel on märk ja teie organisatsioon tagab selle turvalisuse. Teisaldage rakendused avaekraanile, et neile oleks lihtsam juurde pääseda."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Haldab teie organisatsioon"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Märguanded ja rakendused on välja lülitatud"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Sule"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Suletud"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Ez da aurkitu \"<xliff:g id="QUERY">%1$s</xliff:g>\" bilaketaren emaitzarik"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Bilatu aplikazio gehiago"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Jakinarazpenak"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Hasierako pantaila honetan ez dago toki gehiago."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Ez dago toki gehiago Gogokoak erretiluan"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Aplikazioen zerrenda"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Aplikazio pertsonalen zerrenda"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Laneko aplikazioen zerrenda"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Hasiera"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Kendu"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalatu"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Horma-paperak"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Hasierako pantailaren ezarpenak"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Administratzaileak desgaitu du"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Ikuspegi orokorra"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Baimendu hasierako pantaila biratzea"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Telefonoa biratzen denean"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Uneko pantaila-ezarpenak ez du onartzen ikuspegia biratzea"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Jakinarazteko biribiltxoak"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktibatuta"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Desaktibatuta"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Jakinarazpenetarako sarbidea behar da"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Jakinarazteko biribiltxoak ikusteko, aktibatu <xliff:g id="NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Aldatu ezarpenak"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Erakutsi jakinarazteko biribiltxoak"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Gehitu ikonoa hasierako pantailan"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Aplikazio berrietan"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Aldatu ikonoaren forma"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"Hasierako pantailan"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Erabili sistemaren balio lehenetsiak"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Karratua"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Ertz biribilduko karratua"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Sortu karpeta <xliff:g id="NAME">%1$s</xliff:g> elementuarekin"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Karpeta sortu da"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Eraman hasierako pantailara"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Eraman pantaila ezkerrera"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Eraman pantaila eskuinera"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Mugitu da pantaila"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Aldatu tamaina"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Handitu zabalera"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Handitu altuera"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Lanekoak"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Laneko profila"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Hemen dituzu laneko aplikazioak"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Laneko aplikazio bakoitzak bereizgarri bat dauka eta erakundeak babesten du. Aplikazioak errazago atzitzeko, eraman itzazu hasierako pantailara."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Erakundeak kudeatzen du"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Jakinarazpenak eta aplikazioak desaktibatuta daude"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Itxi"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Itxita"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"<xliff:g id="QUERY">%1$s</xliff:g> ei palauttanut sovelluksia."</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Hae lisää sovelluksia"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Ilmoitukset"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Tässä aloitusruudussa ei ole enää tilaa."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Suosikit-valikossa ei ole enää tilaa"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Sovellusluettelo"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Omat sovellukset ‑luettelo"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Työsovellusluettelo"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Aloitusruutu"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Poista"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Poista asennus"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Taustakuvat"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Kotiasetukset"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Järjestelmänvalvoja on poistanut toiminnon käytöstä."</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Yleiskatsaus"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Salli aloitusnäytön kiertäminen"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Kun puhelinta kierretään"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Nykyiset näyttöasetukset eivät salli näytön kiertämistä."</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Pistemerkit"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Käytössä"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Pois käytöstä"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Ilmoituksien käyttöoikeus tarvitaan"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"<xliff:g id="NAME">%1$s</xliff:g> tarvitsee ilmoitusten käyttöoikeuden, jotta pistemerkkejä voidaan näyttää."</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Muuta asetuksia"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Näytä ilmoituksista kertovat pistemerkit"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Lisää kuvake aloitusruutuun"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Uusille sovelluksille"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Muuta kuvakkeen muotoa"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"aloitusnäytöllä"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Käytä järjestelmän oletusarvoa"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Neliö"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Ympyräneliö"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Luo kansio, jossa on <xliff:g id="NAME">%1$s</xliff:g>."</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Kansio on luotu."</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Siirrä aloitusnäytölle"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Siirrä näyttöä vasemmalle"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Siirrä näyttöä oikealle"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Näyttö siirrettiin."</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Muuta kokoa"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Lisää leveyttä"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Lisää korkeutta"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Työsovellukset"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Työprofiili"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Etsi työsovelluksia tästä"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Kaikki työsovellukset on merkitty, ja organisaatiosi vastaa niiden suojaamisesta. Voit siirtää työsovelluksia aloitusnäytölle käytön helpottamiseksi."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Organisaatiosi hallinnoima"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Ilmoitukset ja sovellukset ovat poissa käytöstä"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Sulje"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Suljettu"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Non se atoparon aplicacións que coincidan con \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Buscar máis aplicacións"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notificacións"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Non hai máis espazo nesta pantalla de inicio."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Non hai máis espazo na bandexa de favoritos"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Lista de aplicacións"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Lista de aplicacións persoais"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Lista de aplicacións de traballo"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Inicio"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Eliminar"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalar"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Fondos de pantalla"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Configuración de inicio"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Función desactivada polo administrador"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Visión xeral"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Permitir xirar a pantalla de inicio"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Ao xirar o teléfono"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"A configuración de visualización actual non permite xirar a pantalla"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Puntos de notificacións"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Activado"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Desactivado"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Necesítase acceso ás notificacións"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Para que se mostren os puntos de notificacións, activa as notificacións da aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Cambiar configuración"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Mostrar puntos de notificación"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Engadir icona á pantalla de inicio"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicacións"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Cambiar forma das iconas"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"na pantalla de inicio"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Usar valores predeterminados do sistema"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Cadrado"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Cadrado de bordos redondeados"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Crear cartafol con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Creouse o cartafol"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Mover á pantalla de inicio"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Mover pantalla á esquerda"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Mover pantalla á dereita"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Moveuse a pantalla"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Cambiar tamaño"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Aumentar ancho"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Aumentar altura"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Traballo"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Perfil de traballo"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Buscar aplicacións do traballo aquí"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"As aplicacións do traballo teñen unha insignia e están protexidas pola túa organización. Traslada as aplicacións á pantalla de inicio para acceder a elas de forma máis fácil."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Perfil xestionado pola túa organización"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"As notificacións e as aplicacións están desactivadas"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Pechar"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Pechado"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\"થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"વધુ ઍપ્લિકેશનો શોધો"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"નોટિફિકેશનો"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"મનપસંદ ટ્રે પર વધુ જગ્યા નથી"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"ઍપ્લિકેશનોની સૂચિ"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"વ્યક્તિગત ઍપની સૂચિ"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"કાર્યસ્થળની ઍપની સૂચિ"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"હોમ"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"દૂર કરો"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"અનઇન્સ્ટોલ કરો"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"વૉલપેપર્સ"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"હોમ સેટિંગ્સ"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"ઝલક"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"જ્યારે ફોન ફેરવવામાં આવે ત્યારે"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"વર્તમાન પ્રદર્શન સેટિંગ ફેરવવાની પરવાનગી આપતી નથી"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"સૂચના બિંદુઓ"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"ચાલુ"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"બંધ"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"નોટિફિકેશનનો ઍક્સેસની જરૂરી છે"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, <xliff:g id="NAME">%1$s</xliff:g> માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"સેટિંગ્સ બદલો"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"નોટિફિકેશન માટેનું ચિહ્ન બતાવો"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"હોમ સ્ક્રીન પર આઇકન ઉમેરો"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"નવી ઍપ્લિકેશનો માટે"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"આઇકનનો આકાર બદલો"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"હોમ સ્ક્રીન પર"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"સિસ્ટમ ડિફૉલ્ટનો ઉપયોગ કરો"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"ચોરસ"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"ચોરસ જેવું ગોળ"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"આની સાથે ફોલ્ડર બનાવો: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"ફોલ્ડર બનાવ્યું"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"હોમ સ્ક્રીન પર ખસેડો"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"સ્ક્રીનને ડાબી બાજુ ખસેડો"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"સ્ક્રીનને જમણી બાજુ ખસેડો"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"સ્ક્રીન ખસેડી"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"આકાર બદલો"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"પહોળાઈ વધારો"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"ઊંચાઈ વધારો"</string>
|
||||
@@ -137,8 +138,11 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"કાર્યાલયની ઍપ"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"કાર્યાલયની પ્રોફાઇલ"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"કાર્ય ઍપને અહીંથી મેળવો"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"દરેક કાર્ય ઍપ પાસે એક બૅજ હોય છે અને તમારી સંસ્થા દ્વારા તેને સુરક્ષિત રાખવામાં આવે છે. વધુ સરળ ઍક્સેસ માટે ઍપને તમારી હોમ સ્ક્રીન પર ખસેડો."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"તમારી સંસ્થા દ્વારા મેનેજ કરેલ"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"નોટિફિકેશન અને ઍપ બંધ છે"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_close_button (4224492243977802135) -->
|
||||
<skip />
|
||||
<!-- no translation found for bottom_work_tab_user_education_closed (1098340939861869465) -->
|
||||
<skip />
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nem található alkalmazás a(z) „<xliff:g id="QUERY">%1$s</xliff:g>” lekérdezésre"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"További alkalmazások keresése"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Értesítések"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Nincs több hely ezen a kezdőképernyőn."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Nincs több hely a Kedvencek tálcán"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Alkalmazások listája"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Személyes alkalmazások listája"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Munkahelyi alkalmazások listája"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Főoldal"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Törlés"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Eltávolítás"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Háttérképek"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"A Home beállításai"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"A rendszergazda letiltotta"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Áttekintés"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"A kezdőképernyő elforgatásának engedélyezése"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"A telefon elforgatásakor"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"A jelenlegi kijelzőbeállítások nem teszik lehetővé az elforgatást"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Értesítési pöttyök"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Bekapcsolva"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Kikapcsolva"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Értesítésekhez való hozzáférésre van szükség"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Az értesítési pöttyök megjelenítéséhez kapcsolja be a(z) <xliff:g id="NAME">%1$s</xliff:g> alkalmazás értesítéseit"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Beállítások módosítása"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Értesítési pöttyök megjelenítése"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Ikon hozzáadása a kezdőképernyőhöz"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Új alkalmazásoknál"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Ikon formájának módosítása"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"a kezdőképernyőn"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Alapértelmezett érték használata"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Négyzet"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Squircle"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Mappa létrehozása a következővel: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Mappa létrehozva"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Áthelyezés a kezdőképernyőre"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Képernyő mozgatása balra"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Képernyő mozgatása jobbra"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Képernyő áthelyezve"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Átméretezés"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Szélesség növelése"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Magasság növelése"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Munkahelyi"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Munkaprofil"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Itt kereshet munkahelyi alkalmazásokat"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"A munkahelyi alkalmazásoknál jelvény található, és biztonságukról az Ön szervezete gondoskodik. A könnyebb hozzáférés érdekében helyezze át az alkalmazásokat a kezdőképernyőre."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Az Ön szervezete kezeli"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Az értesítések és az alkalmazások ki vannak kapcsolva"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Bezárás"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Bezárva"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Tidak ditemukan aplikasi yang cocok dengan \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Telusuri aplikasi lainnya"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notifikasi"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Tidak ada ruang lagi pada layar Utama ini."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Tidak ada ruang tersisa di baki Favorit"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Daftar aplikasi"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Daftar aplikasi pribadi"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Daftar aplikasi kantor"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Layar Utama"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Hapus"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Uninstal"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Wallpaper"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Setelan layar Utama"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Dinonaktifkan oleh admin"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Ringkasan"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Izinkan layar Utama diputar"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Saat ponsel diputar"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Setelan Tampilan Saat Ini tidak memungkinkan putaran"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Titik notifikasi"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Aktif"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Nonaktif"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Perlu akses notifikasi"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Guna menampilkan Titik Notifikasi, aktifkan notifikasi aplikasi untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Ubah setelan"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Tampilkan titik notifikasi"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Tambahkan ikon ke Layar utama"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Untuk aplikasi baru"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Ubah bentuk ikon"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"di layar Utama"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Gunakan default sistem"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Persegi"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Persegi bundar"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Buat folder dengan: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Folder dibuat"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Pindahkan ke layar Utama"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Pindahkan layar ke kiri"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Pindahkan layar ke kanan"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Layar dipindahkan"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Ubah ukuran"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Tambahi lebar"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Tambahi tinggi"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Kantor"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Profil kerja"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Temukan aplikasi kerja di sini"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Setiap aplikasi kerja memiliki badge dan dibuat tetap aman oleh organisasi. Pindahkan aplikasi ke Layar utama untuk memudahkan akses."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Dikelola oleh organisasi"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Notifikasi dan aplikasi nonaktif"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Tutup"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Ditutup"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"Nessuna app trovata corrispondente a \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Cerca altre app"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Notifiche"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Spazio nella schermata Home esaurito."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Spazio esaurito nella barra dei Preferiti"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Elenco di app"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Elenco di app personali"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Elenco di app di lavoro"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Home page"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Rimuovi"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Disinstalla"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Sfondi"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Impostazioni Home"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Disattivata dall\'amministratore"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Panoramica"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Consenti rotazione della schermata Home"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Con il telefono ruotato"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"L\'impostazione corrente del display non consente la rotazione"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Indicatori notifica"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Attiva"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Non attiva"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Accesso alle notifiche necessario"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Per mostrare gli indicatori di notifica, attiva le notifiche per l\'app <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Modifica impostazioni"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Mostra indicatori di notifica"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Aggiungi icone alla schermata Home"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Per le nuove app"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Cambia la forma delle icone"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"nella schermata Home"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Usa impostazione predefinita di sistema"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Quadrato"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Supercerchio"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Crea cartella con: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Cartella creata"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Sposta nella schermata Home"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Sposta schermata a sinistra"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Sposta schermata a destra"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Schermata spostata"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Ridimensiona"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Aumenta larghezza"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Aumenta altezza"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Lavoro"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Profilo di lavoro"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Qui puoi trovare le tue app di lavoro"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Ogni app di lavoro è contrassegnata da un badge e viene tenuta al sicuro dalla tua organizzazione. Sposta le app nella schermata Home per accedervi più facilmente."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Gestito dalla tua organizzazione"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Le notifiche e le app non sono attive"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Chiudi"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Chiusa"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"「<xliff:g id="QUERY">%1$s</xliff:g>」に一致するアプリは見つかりませんでした"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"他のアプリを検索"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"通知"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"このホーム画面に空きスペースがありません。"</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"お気に入りトレイに空きスペースがありません"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"アプリのリスト"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"個人用アプリのリスト"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"仕事用アプリのリスト"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"ホーム"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"削除"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"アンインストール"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"壁紙"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"ホームの設定"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"管理者により無効にされています"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"概要"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"ホーム画面の回転を許可"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"スマートフォンが回転したとき"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"現在の [ディスプレイ] 設定では回転を使用できません"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"通知ドット"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"ON"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"OFF"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"通知へのアクセス権限が必要"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"通知ドットを表示するには、「<xliff:g id="NAME">%1$s</xliff:g>」のアプリ通知を ON にしてください"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"設定を変更"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"通知ドットの表示"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ホーム画面にアイコンを追加"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"新しいアプリをダウンロードしたとき"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"アイコンの形の変更"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"ホーム画面上"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"システムのデフォルトを使用"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"スクエア"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"スクワークル"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"「<xliff:g id="NAME">%1$s</xliff:g>」フォルダを作成"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"フォルダを作成しました"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"ホーム画面に移動"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"画面を左に移動"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"画面を右に移動"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"画面を移動しました"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"サイズを変更"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"幅を広くする"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"高さを高くする"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"仕事用"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"仕事用プロファイル"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"ここには仕事用アプリが表示されます"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"仕事用アプリにはバッジが表示され、組織によって安全に保護されています。仕事用アプリをホーム画面に移動すると、簡単にアクセスできます。"</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"組織によって管理されています"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"通知とアプリは OFF です"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"閉じる"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"終了"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"„<xliff:g id="QUERY">%1$s</xliff:g>“-ის თანხვედრი აპები არ მოიძებნა"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"მეტი აპის პოვნა"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"შეტყობინებები"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"ამ მთავარ ეკრანზე ადგილი აღარ არის."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"რჩეულების თაროზე ადგილი არ არის"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"აპების სია"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"პერსონალური აპების სია"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"სამსახურის აპების სია"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"მთავარი"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"ამოშლა"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"დეინსტალაცია"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"ფონები"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"მთავარი გვერდის პარამეტრები"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"გათიშულია თქვენი ადმინისტრატორის მიერ"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"მიმოხილვა"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"მთავარი ეკრანის შეტრიალების დაშვება"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"ტელეფონის შეტრიალებისას"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"ბრუნვა დაუშვებელია ჩვენების მიმდინარე პარამეტრებით"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"შეტყობინების ნიშნულები"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"ჩართული"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"გამორთული"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"საჭიროა შეტყობინებებზე წვდომა"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები <xliff:g id="NAME">%1$s</xliff:g>-ისთვის"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"პარამეტრების შეცვლა"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"შეტყობინების ნიშნულების ჩვენება"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ხატულას მთავარ ეკრანზე დამატება"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ახალი აპებისთვის"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"ხატულას ფორმის შეცვლა"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"მთავარ ეკრანზე"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"ნაგულისხმევი სისტემური პარამეტრების გამოყენება"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"კვადრატი"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"წრეკუთხედი"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"საქაღალდის შექმნა ერთეულით: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"საქაღალდე შექმნილია"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"მთავარ ეკრანზე გადატანა"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"ეკრანის გადატანა მარცხნივ"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"ეკრანის გადატანა მარჯვნით"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"ეკრანი გადაადგილდა"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"ზომის შეცვლა"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"სიგანის გაზრდა"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"სიმაღლის გაზრდა"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"სამსახური"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"სამსახურის პროფილი"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"აქ თავმოყრილია სამსახურის აპები"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"სამსახურის თითოეულ აპს აქვს ბეჯი, რაც ნიშნავს, რომ მათ უსაფრთხოებას თქვენი ორგანიზაცია უზრუნველყოფს. მარტივი წვდომისთვის, შეგიძლიათ სამსახურის აპები მთავარი ეკრანზე გადაიტანოთ."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"იმართება თქვენი ორგანიზაციის მიერ"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"შეტყობინებები და აპები გამორთულია"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"დახურვა"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"დახურული"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" сұрауына сәйкес келетін қолданбалар жоқ"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Қосымша қолданбалар іздеу"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Хабарландырулар"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Бұл Негізгі экранда орын қалмады."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Қалаулылар науасында орын қалмады"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Қолданбалар тізімі"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Жеке қолданбалар тізімі"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Жұмыс қолданбаларының тізімі"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Негізгі"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Жою"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Жою"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тұсқағаздар"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Негізгі экран параметрлері"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Әкімші өшірді"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Шолу"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Негізгі экранның бұрылуына рұқсат ету"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон бұрылғанда"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Экранның ағымдағы параметрі айналуға рұқсат бермейді"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Хабарландыру белгілері"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Қосулы"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Өшірулі"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Хабарландыруға кіру рұқсаты қажет"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Хабарландыру белгілерін көрсету үшін <xliff:g id="NAME">%1$s</xliff:g> қолданбасының қолданба хабарландыруларын қосыңыз"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Параметрлерді өзгерту"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Хабарландыру белгілерін көрсету"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Негізгі экранға белгіше енгізу"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңа қолданбаларға арналған"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Белгіше пішінін өзгерту"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"Негізгі экранда"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Жүйенің әдепкі параметрін пайдалану"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Шаршы"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Жұмыр төртбұрыш"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Мына бар қалтаны жасау: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Қалта жасалды"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Негізгі экранға жылжыту"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Экранды солға жылжыту"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Экранды оңға жылжыту"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Экран жылжытылды"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Өлшемін өзгерту"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Енін арттыру"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Биіктігін арттыру"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Жұмыс"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Жұмыс профилі"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Жұмыс қолданбалары осы жерде берілген"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Әрбір жұмыс қолданбасында танымбелгі бар. Ол оның қауіпсіздігі ұйым арқылы қамтамасыз етілетінін білдіреді. Жұмыс қолданбаларына оңай кіру үшін, оларды Негізгі экранға жылжытуға болады."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Ұйым арқылы басқарылады"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Хабарландырулар мен қолданбалар өшірулі"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Жабу"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Жабық"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"រកមិនឃើញកម្មវិធីដែលត្រូវគ្នាជាមួយ \"<xliff:g id="QUERY">%1$s</xliff:g>\" ទេ"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"ស្វែងរកកម្មវិធីច្រើនទៀត"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"ការជូនដំណឹង"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"គ្មានបន្ទប់នៅលើអេក្រង់ដើមនេះទៀតទេ។"</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"គ្មានបន្ទប់ក្នុងថាសនិយមប្រើ"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"បញ្ជីកម្មវិធី"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"បញ្ជីកម្មវិធីផ្ទាល់ខ្លួន"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"បញ្ជីកម្មវិធីការងារ"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"ដើម"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"យកចេញ"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"លុបការដំឡើង"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"ផ្ទាំងរូបភាព"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"ការកំណត់ទំព័រដើម"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"សង្ខេប"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"អនុញ្ញាតការបងិ្វលអេក្រង់ដើម"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"ការកំណត់អេក្រង់បច្ចុប្បន្នមិនអនុញ្ញាតការបង្វិលទេ"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"ស្លាកជូនដំណឹង"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"បើក"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"បិទ"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"តម្រូវឲ្យមានសិទ្ធិចូលប្រើប្រាស់ការជូនដំណឹង"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"ប្ដូរការកំណត់"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"បង្ហាញស្លាកជូនដំណឹង"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"បញ្ចូលរូបតំណាងទៅអេក្រង់ដើម"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"សម្រាប់កម្មវិធីថ្មី"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"ប្តូររូបរាងរូបតំណាង"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"នៅលើអេក្រង់ដើម"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"ប្រើលំនាំដើមរបស់ប្រព័ន្ធ"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"ការ៉េ"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"ការ៉េជ្រុងកោង"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"បង្កើតថតឯកសារជាមួយ៖ <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"បានបង្កើតថតឯកសារ"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"ផ្លាស់ទៅអេក្រង់ដើម"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"រំកិលអេក្រង់ទៅខាងឆ្វេង"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"រំកិលអេក្រង់ទៅខាងស្តាំ"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"អេក្រង់ដែលបានផ្លាស់ទី"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"ប្ដូរទំហំ"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"បង្កើនទទឹង"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"បង្កើនកម្ពស់"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"ការងារ"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"កម្រងព័ត៌មានការងារ"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"ស្វែងរកកម្មវិធីការងារនៅទីនេះ"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"កម្មវិធីការងារនីមួយៗមានស្លាកមួយ និងត្រូវបានរក្សាទុកយ៉ាងមានសុវត្ថិភាពដោយស្ថាប័នរបស់អ្នក។ សូមផ្លាស់ទីកម្មវិធីទៅកាន់អេក្រង់ដើមរបស់អ្នក ដើម្បីងាយស្រួលចូលប្រើជាងមុន។"</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"គ្រប់គ្រងដោយស្ថាប័នរបស់អ្នក"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"ការជូនដំណឹង និងកម្មវិធីត្រូវបានបិទ"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"បិទ"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"បានបិទ"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"ಮತ್ತಷ್ಟು ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಹುಡುಕಿ"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"ಅಧಿಸೂಚನೆಗಳು"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಹೆಚ್ಚು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ಮೆಚ್ಚಿನವುಗಳ ಟ್ರೇನಲ್ಲಿ ಹೆಚ್ಚಿನ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"ಅಪ್ಲಿಕೇಶನ್ಗಳ ಪಟ್ಟಿ"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"ವೈಯಕ್ತಿಕ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಪಟ್ಟಿ"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಪಟ್ಟಿ"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"ಮುಖಪುಟ"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"ತೆಗೆದುಹಾಕಿ"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ಅನ್ಇನ್ಸ್ಟಾಲ್"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"ವಾಲ್ಪೇಪರ್ಗಳು"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"ಅವಲೋಕನ"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"ಫೋನ್ ತಿರುಗಿಸಿದಾಗ"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"ಪ್ರಸ್ತುತ ಪ್ರದರ್ಶನ ಸೆಟ್ಟಿಂಗ್ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳು"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"ಆನ್"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"ಆಫ್"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, <xliff:g id="NAME">%1$s</xliff:g> ಗೆ ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್ ಮಾಡಿ"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"ಅಧಿಸೂಚನೆ ಡಾಟ್ಗಳನ್ನು ತೋರಿಸಿ"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ಮುಖಪುಟದ ಪರದೆಗೆ ಐಕಾನ್ ಸೇರಿಸಿ"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ಹೊಸ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"ಐಕಾನ್ ಆಕಾರವನ್ನು ಬದಲಿಸಿ"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"ಮುಖಪುಟ ಪರದೆಯಲ್ಲಿ"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"ಸಿಸ್ಟಂ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"ಚೌಕ"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"ಚೌಕವೃತ್ತ"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"ಇದನ್ನು ಬಳಸಿಕೊಂಡು ಫೋಲ್ಡರ್ ರಚಿಸಿ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"ಫೋಲ್ಡರ್ ರಚಿಸಲಾಗಿದೆ"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"ಮುಖಪುಟಕ್ಕೆ ಸರಿಸಿ"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"ಪರದೆಯನ್ನು ಎಡಕ್ಕೆ ಸರಿಸಿ"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"ಪರದೆಯನ್ನು ಬಲಕ್ಕೆ ಸರಿಸಿ"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"ಪರದೆ ಸರಿಸಲಾಗಿದೆ"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"ಮರುಗಾತ್ರ"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"ಅಗಲವನ್ನು ಹೆಚ್ಚು ಮಾಡಿ"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"ಎತ್ತರವನ್ನು ಹೆಚ್ಚು ಮಾಡಿ"</string>
|
||||
@@ -137,8 +138,11 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"ಕೆಲಸ"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಇಲ್ಲಿ ಹುಡುಕಿ"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"ಕೆಲಸದ ಪ್ರತಿ ಅಪ್ಲಿಕೇಶನ್ ಬ್ಯಾಡ್ಜ್ ಹೊಂದಿದೆ ಮತ್ತು ನಿಮ್ಮ ಸಂಸ್ಥೆಯಿಂದ ಸುರಕ್ಷಿತವಾಗಿ ಇರಿಸಲಾಗುತ್ತದೆ. ಸುಲಭ ಪ್ರವೇಶಕ್ಕಾಗಿ ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್ಗೆ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಸರಿಸಿ."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗಿದೆ"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್ಗಳು ಆಫ್ ಆಗಿವೆ"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_close_button (4224492243977802135) -->
|
||||
<skip />
|
||||
<!-- no translation found for bottom_work_tab_user_education_closed (1098340939861869465) -->
|
||||
<skip />
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\'<xliff:g id="QUERY">%1$s</xliff:g>\'과(와) 일치하는 앱이 없습니다."</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"더 많은 앱 검색"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"알림"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"홈 화면에 더 이상 공간이 없습니다."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"즐겨찾기 트레이에 더 이상 공간이 없습니다."</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"앱 목록"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"개인 앱 목록"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"업무용 앱 목록"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"홈"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"삭제"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"제거"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"배경화면"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"홈 설정"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"개요"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"홈 화면 회전 허용"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"휴대전화 회전 시"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"현재 표시 설정에는 회전 기능이 허용되지 않습니다."</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"알림 표시 점"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"사용"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"사용 안함"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"알림 액세스 권한 필요"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"알림 표시점을 표시하려면 <xliff:g id="NAME">%1$s</xliff:g>의 앱 알림을 사용 설정하세요."</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"설정 변경"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"알림 표시 점 보기"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"홈 화면에 아이콘 추가"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"새로 설치한 앱에 적용"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"아이콘 모양 변경"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"홈 화면에 표시"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"시스템 기본값 사용"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"정사각형"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"모서리가 둥근 정사각형"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"다음이 포함된 폴더 만들기: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"폴더를 만들었습니다."</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"홈 화면으로 이동"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"화면을 왼쪽으로 이동"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"화면을 오른쪽으로 이동"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"화면 이동됨"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"크기 조정"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"폭 늘리기"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"높이 늘리기"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"직장"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"직장 프로필"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"여기에서 업무용 앱 찾기"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"각 업무용 앱에는 배지가 있으며 업무용 앱은 조직에서 안전하게 보호됩니다. 앱을 홈 화면으로 이동하여 더 간편하게 사용하세요."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"조직에서 관리"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"알림 및 앱 사용 중지됨"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"닫기"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"종료됨"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" сурамына дал келген колдонмолор табылган жок"</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"Көбүрөөк колдонмолорду издөө"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"Эскертмелер"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"Бул Үй экранында бош орун жок."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"Тандамалдар тайпасында орун калган жок"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"Колдонмолор тизмеси"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"Жеке колдономолордун тизмеси"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"Жумуш колдонмолорунун тизмеси"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"Үйгө"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"Алып салуу"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"Чыгарып салуу"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"Тушкагаздар"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"Башкы беттин жөндөөлөрү"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"Администраторуңуз өчүрүп койгон"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"Көз жүгүртүү"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"Башкы экранды айлантууга уруксат берүү"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"Телефон айланганда"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"Экранды айлантуу параметри өчүрүлгөн"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"Эскертме белгилери"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"Күйүк"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"Өчүк"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"Эскертмелерге уруксат берилиши керек"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"Эскертме белгилерин көрсөтүү максатында, <xliff:g id="NAME">%1$s</xliff:g> үчүн колдонмонун эскертмелерин күйгүзүү керек"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"Жөндөөлөрдү өзгөртүү"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"Эскертме белгилерин көрсөтүү"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"Башкы экранга сүрөтчө кошуу"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Жаңы колдонмолор үчүн"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"Сүрөтчөнүн формасын өзгөртүү"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"Башкы экранда"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"Тутум сушунтаган демейкисин колдонуу"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"Чарчы"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"Бурчтары жумуру төрт бурчтук"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"Төмөнкү менен куржун түзүү: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"Куржун түзүлдү"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"Башкы экранга жылдыруу"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"Экранды солго жылдыруу"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"Экранды оңго жылдыруу"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"Экран жылдырылды"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"Өлчөмүн өзгөртүү"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"Кеңейтүү"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"Бийиктетүү"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"Жумуш колдонмолору"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"Жумуш профили"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"Жумуш колдонмолорун бул жерден таап алыңыз"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"Ар бир жумуш колдонмосунун бейджиги бар жана ал уюмуңуз тарабынан коопсуз сакталат. Колдонмолорго тез өтүү үчүн аларды Башкы экранга кошуп алыңыз."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"Уюмуңуз тарабынан башкарылат"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"Билдирүүлөр жана колдонмолор өчүрүлгөн"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"Жабуу"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"Жабык"</string>
|
||||
</resources>
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
<string name="all_apps_no_search_results" msgid="3200346862396363786">"ບໍ່ພົບແອັບທີ່ກົງກັບ \"<xliff:g id="QUERY">%1$s</xliff:g>\""</string>
|
||||
<string name="all_apps_search_market_message" msgid="1366263386197059176">"ຊອກຫາແອັບເພີ່ມເຕີມ"</string>
|
||||
<string name="notifications_header" msgid="1404149926117359025">"ການແຈ້ງເຕືອນ"</string>
|
||||
<!-- no translation found for long_press_shortcut_to_add (4524750017792716791) -->
|
||||
<skip />
|
||||
<!-- no translation found for long_accessible_way_to_add_shortcut (3327314059613154633) -->
|
||||
<skip />
|
||||
<string name="out_of_space" msgid="4691004494942118364">"ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກນີ້."</string>
|
||||
<string name="hotseat_out_of_space" msgid="7448809638125333693">"ບໍ່ມີບ່ອນຫວ່າງໃນຖາດສຳລັບເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ"</string>
|
||||
<string name="all_apps_button_label" msgid="8130441508702294465">"ລາຍຊື່ແອັບ"</string>
|
||||
<string name="all_apps_button_personal_label" msgid="1315764287305224468">"ລາຍຊື່ແອັບສ່ວນຕົວ"</string>
|
||||
<string name="all_apps_button_work_label" msgid="7270707118948892488">"ລາຍຊື່ແອັບເຮັດວຽກ"</string>
|
||||
<string name="all_apps_home_button_label" msgid="252062713717058851">"ໜ້າຫຼັກ"</string>
|
||||
<string name="remove_drop_target_label" msgid="7812859488053230776">"ເອົາອອກ"</string>
|
||||
<string name="uninstall_drop_target_label" msgid="4722034217958379417">"ຖອນການຕິດຕັ້ງ"</string>
|
||||
@@ -77,19 +83,17 @@
|
||||
<string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
|
||||
<string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າ Home"</string>
|
||||
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
|
||||
<string name="accessibility_action_overview" msgid="6257665857640347026">"ພາບຮວມ"</string>
|
||||
<string name="allow_rotation_title" msgid="7728578836261442095">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້"</string>
|
||||
<string name="allow_rotation_desc" msgid="8662546029078692509">"ເມື່ອໝຸນໂທລະສັບ"</string>
|
||||
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"ການຕັ້ງຄ່າສະແດງຜົນປັດຈຸບັນບໍ່ອະນຸຍາດໃຫ້ໝຸນໄດ້"</string>
|
||||
<string name="icon_badging_title" msgid="874121399231955394">"ຈຸດການແຈ້ງເຕືອນ"</string>
|
||||
<string name="icon_badging_desc_on" msgid="2627952638544674079">"ເປີດ"</string>
|
||||
<string name="icon_badging_desc_off" msgid="5503319969924580241">"ປິດ"</string>
|
||||
<string name="title_missing_notification_access" msgid="7503287056163941064">"ຕ້ອງໃຊ້ການເຂົ້າເຖິງການແຈ້ງເຕືອນ"</string>
|
||||
<string name="msg_missing_notification_access" msgid="281113995110910548">"ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="title_change_settings" msgid="1376365968844349552">"ບັນທຶກການຕັ້ງຄ່າ"</string>
|
||||
<string name="icon_badging_service_title" msgid="2309733118428242174">"ສະແດງຈຸດການແຈ້ງເຕືອນ"</string>
|
||||
<string name="auto_add_shortcuts_label" msgid="8222286205987725611">"ເພີ່ມໄອຄອນໃສ່ໜ້າຈໍຫຼັກ"</string>
|
||||
<string name="auto_add_shortcuts_description" msgid="7117251166066978730">"ສຳລັບແອັບໃໝ່"</string>
|
||||
<string name="icon_shape_override_label" msgid="2977264953998281004">"ປ່ຽນຮູບຮ່າງໄອຄອນ"</string>
|
||||
<string name="icon_shape_override_label_location" msgid="3841607380657692863">"ຢູ່ໜ້າຈໍຫຼັກ"</string>
|
||||
<string name="icon_shape_system_default" msgid="1709762974822753030">"ໃຊ້ຄ່າເລີ່ມຕົ້ນລະບົບ"</string>
|
||||
<string name="icon_shape_square" msgid="633575066111622774">"ສີ່ຫຼ່ຽມຈັດຕຸລັດ"</string>
|
||||
<string name="icon_shape_squircle" msgid="5658049910802669495">"ສີ່ຫຼ່ຽມຂອບມົນ"</string>
|
||||
@@ -119,9 +123,6 @@
|
||||
<string name="create_folder_with" msgid="4050141361160214248">"ສ້າງໂຟລເດີກັບ: <xliff:g id="NAME">%1$s</xliff:g>"</string>
|
||||
<string name="folder_created" msgid="6409794597405184510">"ສ້າງໂຟລເດີແລ້ວ"</string>
|
||||
<string name="action_move_to_workspace" msgid="1603837886334246317">"ຍ້າຍໄປໃສ່ໜ້າຈໍຫຼັກ"</string>
|
||||
<string name="action_move_screen_left" msgid="8854216831569401665">"ຍ້າຍໜ້າຈໍໄປທາງຊ້າຍ"</string>
|
||||
<string name="action_move_screen_right" msgid="329334910274311123">"ຍ້າຍໜ້າຈໍໄປທາງຂວາ"</string>
|
||||
<string name="screen_moved" msgid="266230079505650577">"ຍ້າຍໜ້າຈໍແລ້ວ"</string>
|
||||
<string name="action_resize" msgid="1802976324781771067">"ປັບຂະໜາດ"</string>
|
||||
<string name="action_increase_width" msgid="8773715375078513326">"ເພີ່ມລວງກ້ວາງຂຶ້ນ"</string>
|
||||
<string name="action_increase_height" msgid="459390020612501122">"ເພີ່ມລວງສູງຂຶ້ນ"</string>
|
||||
@@ -137,8 +138,9 @@
|
||||
<string name="all_apps_work_tab" msgid="4884822796154055118">"ວຽກ"</string>
|
||||
<string name="work_profile_toggle_label" msgid="3081029915775481146">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
|
||||
<string name="bottom_work_tab_user_education_title" msgid="5785851780786322825">"ຊອກຫາແອັບວຽກຢູ່ບ່ອນນີ້"</string>
|
||||
<!-- no translation found for bottom_work_tab_user_education_body (2818107472360579152) -->
|
||||
<skip />
|
||||
<string name="bottom_work_tab_user_education_body" msgid="2818107472360579152">"ແຕ່ລະແອັບວຽກຈະມີປ້າຍ ແລະ ຖືກຈັດເກັບໄວ້ຢ່າງປອດໄພໂດຍອົງກອນຂອງທ່ານ. ທ່ານສາມາດຍ້າຍແອັບໄປໃສ່ໜ້າຈໍຫຼັກເພື່ອໃຫ້ເຂົ້າໃຊ້ງ່າຍຂຶ້ນໄດ້."</string>
|
||||
<string name="work_mode_on_label" msgid="4781128097185272916">"ຈັດການໂດຍອົງກອນຂອງທ່ານ"</string>
|
||||
<string name="work_mode_off_label" msgid="3194894777601421047">"ການແຈ້ງເຕືອນ ແລະ ແອັບຖືກປິດໄວ້"</string>
|
||||
<string name="bottom_work_tab_user_education_close_button" msgid="4224492243977802135">"ປິດ"</string>
|
||||
<string name="bottom_work_tab_user_education_closed" msgid="1098340939861869465">"ປິດແລ້ວ"</string>
|
||||
</resources>
|
||||
|
||||