Merge "Adding experiment for app-info pane."
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
public void setGlowAlpha(float);
|
public void setGlowAlpha(float);
|
||||||
public void setGlowScale(float);
|
public void setGlowScale(float);
|
||||||
}
|
}
|
||||||
-keep class com.android.systemui.recents.views.TaskIconView {
|
-keep class com.android.systemui.recents.views.TaskInfoView {
|
||||||
public void setCircularClipRadius(float);
|
public void setCircularClipRadius(float);
|
||||||
public float getCircularClipRadius();
|
public float getCircularClipRadius();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,21 @@
|
|||||||
android:id="@+id/task_view_thumbnail"
|
android:id="@+id/task_view_thumbnail"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
<com.android.systemui.recents.views.TaskInfoView
|
||||||
|
android:id="@+id/task_view_info_pane"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="invisible"
|
||||||
|
android:background="#e6444444">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/task_view_app_info_button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_gravity="top|center_horizontal"
|
||||||
|
android:text="@string/recents_app_info_button_label" />
|
||||||
|
</com.android.systemui.recents.views.TaskInfoView>
|
||||||
<com.android.systemui.recents.views.TaskBarView
|
<com.android.systemui.recents.views.TaskBarView
|
||||||
android:id="@+id/task_view_bar"
|
android:id="@+id/task_view_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -31,15 +46,15 @@
|
|||||||
android:id="@+id/application_icon"
|
android:id="@+id/application_icon"
|
||||||
android:layout_width="@dimen/recents_task_view_application_icon_size"
|
android:layout_width="@dimen/recents_task_view_application_icon_size"
|
||||||
android:layout_height="@dimen/recents_task_view_application_icon_size"
|
android:layout_height="@dimen/recents_task_view_application_icon_size"
|
||||||
android:layout_gravity="center_vertical|left"
|
android:layout_gravity="center_vertical|start"
|
||||||
android:padding="8dp" />
|
android:padding="8dp" />
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/activity_description"
|
android:id="@+id/activity_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical|left"
|
android:layout_gravity="center_vertical|left"
|
||||||
android:layout_marginLeft="@dimen/recents_task_view_application_icon_size"
|
android:layout_marginStart="@dimen/recents_task_view_application_icon_size"
|
||||||
android:layout_marginRight="@dimen/recents_task_view_activity_icon_size"
|
android:layout_marginEnd="@dimen/recents_task_view_activity_icon_size"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textColor="#ffffffff"
|
android:textColor="#ffffffff"
|
||||||
android:text="@string/recents_empty_message"
|
android:text="@string/recents_empty_message"
|
||||||
@@ -52,7 +67,7 @@
|
|||||||
android:id="@+id/activity_icon"
|
android:id="@+id/activity_icon"
|
||||||
android:layout_width="@dimen/recents_task_view_activity_icon_size"
|
android:layout_width="@dimen/recents_task_view_activity_icon_size"
|
||||||
android:layout_height="@dimen/recents_task_view_activity_icon_size"
|
android:layout_height="@dimen/recents_task_view_activity_icon_size"
|
||||||
android:layout_gravity="center_vertical|right"
|
android:layout_gravity="center_vertical|end"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:visibility="invisible" />
|
android:visibility="invisible" />
|
||||||
</com.android.systemui.recents.views.TaskBarView>
|
</com.android.systemui.recents.views.TaskBarView>
|
||||||
|
|||||||
@@ -114,6 +114,8 @@
|
|||||||
<integer name="recents_filter_animate_new_views_min_duration">125</integer>
|
<integer name="recents_filter_animate_new_views_min_duration">125</integer>
|
||||||
<!-- The min animation duration for animating views that are newly visible. -->
|
<!-- The min animation duration for animating views that are newly visible. -->
|
||||||
<integer name="recents_animate_task_bar_enter_duration">200</integer>
|
<integer name="recents_animate_task_bar_enter_duration">200</integer>
|
||||||
|
<!-- The animation duration for animating in the info pane. -->
|
||||||
|
<integer name="recents_animate_task_view_info_pane_duration">150</integer>
|
||||||
|
|
||||||
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
|
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
|
||||||
card. -->
|
card. -->
|
||||||
|
|||||||
@@ -239,6 +239,9 @@
|
|||||||
<!-- The size of the activity icon in the recents task view. -->
|
<!-- The size of the activity icon in the recents task view. -->
|
||||||
<dimen name="recents_task_view_activity_icon_size">60dp</dimen>
|
<dimen name="recents_task_view_activity_icon_size">60dp</dimen>
|
||||||
|
|
||||||
|
<!-- The amount of space a user has to scroll to dismiss any info panes. -->
|
||||||
|
<dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
|
||||||
|
|
||||||
<!-- Used to calculate the translation animation duration, the expected amount of movement
|
<!-- Used to calculate the translation animation duration, the expected amount of movement
|
||||||
in dps over one second of time. -->
|
in dps over one second of time. -->
|
||||||
<dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
|
<dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
|
||||||
|
|||||||
@@ -509,6 +509,8 @@
|
|||||||
|
|
||||||
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
|
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
|
||||||
<string name="recents_empty_message">RECENTS</string>
|
<string name="recents_empty_message">RECENTS</string>
|
||||||
|
<!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="recents_app_info_button_label">Application Info</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
|
<!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ public class Constants {
|
|||||||
public static class App {
|
public static class App {
|
||||||
public static final boolean EnableTaskFiltering = true;
|
public static final boolean EnableTaskFiltering = true;
|
||||||
public static final boolean EnableTaskStackClipping = false;
|
public static final boolean EnableTaskStackClipping = false;
|
||||||
public static final boolean EnableToggleNewRecentsActivity = false;
|
public static final boolean EnableInfoPane = true;
|
||||||
// This disables the bitmap and icon caches to
|
|
||||||
|
// This disables the bitmap and icon caches
|
||||||
public static final boolean DisableBackgroundCache = false;
|
public static final boolean DisableBackgroundCache = false;
|
||||||
// For debugging, this enables us to create mock recents tasks
|
// For debugging, this enables us to create mock recents tasks
|
||||||
public static final boolean EnableSystemServicesProxy = false;
|
public static final boolean EnableSystemServicesProxy = false;
|
||||||
|
|||||||
@@ -50,11 +50,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
|||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
Console.log(Constants.DebugFlags.App.SystemUIHandshake,
|
Console.log(Constants.DebugFlags.App.SystemUIHandshake,
|
||||||
"[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
|
"[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
|
||||||
if (action.equals(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY)) {
|
if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
|
||||||
if (Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
} else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
|
|
||||||
// Try and unfilter and filtered stacks
|
// Try and unfilter and filtered stacks
|
||||||
if (!mRecentsView.unfilterFilteredStacks()) {
|
if (!mRecentsView.unfilterFilteredStacks()) {
|
||||||
// If there are no filtered stacks, dismiss recents and launch the first task
|
// If there are no filtered stacks, dismiss recents and launch the first task
|
||||||
@@ -190,7 +186,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
|||||||
// Register the broadcast receiver to handle messages from our service
|
// Register the broadcast receiver to handle messages from our service
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
|
filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
|
||||||
filter.addAction(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY);
|
|
||||||
registerReceiver(mServiceBroadcastReceiver, filter);
|
registerReceiver(mServiceBroadcastReceiver, filter);
|
||||||
|
|
||||||
// Register the broadcast receiver to handle messages when the screen is turned off
|
// Register the broadcast receiver to handle messages when the screen is turned off
|
||||||
@@ -224,11 +219,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
|||||||
Console.AnsiRed);
|
Console.AnsiRed);
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
|
||||||
// Finish the current recents activity after we have launched a task
|
|
||||||
if (mTaskLaunched && Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
mVisible = false;
|
mVisible = false;
|
||||||
mTaskLaunched = false;
|
mTaskLaunched = false;
|
||||||
}
|
}
|
||||||
@@ -250,8 +240,18 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if (!mRecentsView.unfilterFilteredStacks()) {
|
boolean interceptedByInfoPanelClose = false;
|
||||||
super.onBackPressed();
|
|
||||||
|
// Try and return from any open info panes
|
||||||
|
if (Constants.DebugFlags.App.EnableInfoPane) {
|
||||||
|
interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't been intercepted already, then unfilter any stacks
|
||||||
|
if (!interceptedByInfoPanelClose) {
|
||||||
|
if (!mRecentsView.unfilterFilteredStacks()) {
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ public class RecentsConfiguration {
|
|||||||
public int filteringCurrentViewsMinAnimDuration;
|
public int filteringCurrentViewsMinAnimDuration;
|
||||||
public int filteringNewViewsMinAnimDuration;
|
public int filteringNewViewsMinAnimDuration;
|
||||||
public int taskBarEnterAnimDuration;
|
public int taskBarEnterAnimDuration;
|
||||||
|
public int taskStackScrollDismissInfoPaneDistance;
|
||||||
|
public int taskViewInfoPaneAnimDuration;
|
||||||
|
|
||||||
public boolean launchedWithThumbnailAnimation;
|
public boolean launchedWithThumbnailAnimation;
|
||||||
|
|
||||||
@@ -81,6 +83,10 @@ public class RecentsConfiguration {
|
|||||||
res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
|
res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
|
||||||
taskBarEnterAnimDuration =
|
taskBarEnterAnimDuration =
|
||||||
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
|
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
|
||||||
|
taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
|
||||||
|
R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
|
||||||
|
taskViewInfoPaneAnimDuration =
|
||||||
|
res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the system insets */
|
/** Updates the system insets */
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ class SystemUIMessageHandler extends Handler {
|
|||||||
|
|
||||||
/* Service */
|
/* Service */
|
||||||
public class RecentsService extends Service {
|
public class RecentsService extends Service {
|
||||||
final static String ACTION_FINISH_RECENTS_ACTIVITY = "action_finish_recents_activity";
|
|
||||||
final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
|
final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
|
||||||
|
|
||||||
Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
|
Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
|
||||||
|
|||||||
@@ -17,13 +17,16 @@
|
|||||||
package com.android.systemui.recents.views;
|
package com.android.systemui.recents.views;
|
||||||
|
|
||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
|
import android.app.TaskStackBuilder;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import com.android.systemui.recents.Console;
|
import com.android.systemui.recents.Console;
|
||||||
@@ -179,6 +182,21 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Closes any open info panes */
|
||||||
|
public boolean closeOpenInfoPanes() {
|
||||||
|
if (mBSP != null) {
|
||||||
|
// Get the first stack view
|
||||||
|
int childCount = getChildCount();
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
TaskStackView stackView = (TaskStackView) getChildAt(i);
|
||||||
|
if (stackView.closeOpenInfoPanes()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Unfilters any filtered stacks */
|
/** Unfilters any filtered stacks */
|
||||||
public boolean unfilterFilteredStacks() {
|
public boolean unfilterFilteredStacks() {
|
||||||
if (mBSP != null) {
|
if (mBSP != null) {
|
||||||
@@ -206,6 +224,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
|||||||
mCb.onTaskLaunching();
|
mCb.onTaskLaunching();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close any open info panes
|
||||||
|
closeOpenInfoPanes();
|
||||||
|
|
||||||
final Runnable launchRunnable = new Runnable() {
|
final Runnable launchRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -283,4 +304,15 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
|||||||
tv.animateOnLeavingRecents(launchRunnable);
|
tv.animateOnLeavingRecents(launchRunnable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskAppInfoLaunched(Task t) {
|
||||||
|
// Create a new task stack with the application info details activity
|
||||||
|
Intent baseIntent = t.key.baseIntent;
|
||||||
|
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||||
|
Uri.fromParts("package", baseIntent.getComponent().getPackageName(), null));
|
||||||
|
intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
|
||||||
|
TaskStackBuilder.create(getContext())
|
||||||
|
.addNextIntentWithParentStack(intent).startActivities();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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.systemui.recents.views;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.recents.BakedBezierInterpolator;
|
||||||
|
import com.android.systemui.recents.Utilities;
|
||||||
|
|
||||||
|
|
||||||
|
/* The task info view */
|
||||||
|
class TaskInfoView extends FrameLayout {
|
||||||
|
|
||||||
|
Button mAppInfoButton;
|
||||||
|
|
||||||
|
// Circular clip animation
|
||||||
|
boolean mCircularClipEnabled;
|
||||||
|
Path mClipPath = new Path();
|
||||||
|
float mClipRadius;
|
||||||
|
float mMaxClipRadius;
|
||||||
|
Point mClipOrigin = new Point();
|
||||||
|
ObjectAnimator mCircularClipAnimator;
|
||||||
|
|
||||||
|
public TaskInfoView(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskInfoView(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
this(context, attrs, defStyleAttr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
// Initialize the buttons on the info panel
|
||||||
|
mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates the positions of each of the items to fit in the rect specified */
|
||||||
|
void updateContents(Rect visibleRect) {
|
||||||
|
// Offset the app info button
|
||||||
|
LayoutParams lp = (LayoutParams) mAppInfoButton.getLayoutParams();
|
||||||
|
lp.topMargin = visibleRect.top +
|
||||||
|
(visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2;
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the circular clip radius on this panel */
|
||||||
|
public void setCircularClipRadius(float r) {
|
||||||
|
mClipRadius = r;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the circular clip radius on this panel */
|
||||||
|
public float getCircularClipRadius() {
|
||||||
|
return mClipRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Animates the circular clip radius on the icon */
|
||||||
|
void animateCircularClip(Point o, float fromRadius, float toRadius,
|
||||||
|
final Runnable postRunnable, boolean animateInContent) {
|
||||||
|
if (mCircularClipAnimator != null) {
|
||||||
|
mCircularClipAnimator.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the max clip radius to each of the corners
|
||||||
|
int w = getMeasuredWidth() - o.x;
|
||||||
|
int h = getMeasuredHeight() - o.y;
|
||||||
|
// origin to tl, tr, br, bl
|
||||||
|
mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
|
||||||
|
mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
|
||||||
|
mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
|
||||||
|
mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
|
||||||
|
|
||||||
|
mClipOrigin.set(o.x, o.y);
|
||||||
|
mClipRadius = fromRadius;
|
||||||
|
int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
|
||||||
|
mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
|
||||||
|
mCircularClipAnimator.setDuration(duration);
|
||||||
|
mCircularClipAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
|
||||||
|
mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
mCircularClipEnabled = false;
|
||||||
|
if (postRunnable != null) {
|
||||||
|
postRunnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mCircularClipAnimator.start();
|
||||||
|
mCircularClipEnabled = true;
|
||||||
|
|
||||||
|
if (animateInContent) {
|
||||||
|
animateAppInfoButtonIn(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cancels the circular clip animation. */
|
||||||
|
void cancelCircularClipAnimation() {
|
||||||
|
if (mCircularClipAnimator != null) {
|
||||||
|
mCircularClipAnimator.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void animateAppInfoButtonIn(int duration) {
|
||||||
|
mAppInfoButton.setScaleX(0.75f);
|
||||||
|
mAppInfoButton.setScaleY(0.75f);
|
||||||
|
mAppInfoButton.animate()
|
||||||
|
.scaleX(1f)
|
||||||
|
.scaleY(1f)
|
||||||
|
.setDuration(duration)
|
||||||
|
.setInterpolator(BakedBezierInterpolator.INSTANCE)
|
||||||
|
.withLayer()
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
int saveCount = 0;
|
||||||
|
if (mCircularClipEnabled) {
|
||||||
|
saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
|
||||||
|
mClipPath.reset();
|
||||||
|
mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
|
||||||
|
Path.Direction.CW);
|
||||||
|
canvas.clipPath(mClipPath);
|
||||||
|
}
|
||||||
|
super.draw(canvas);
|
||||||
|
if (mCircularClipEnabled) {
|
||||||
|
canvas.restoreToCount(saveCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,11 +52,12 @@ import java.util.HashMap;
|
|||||||
/* The visual representation of a task stack view */
|
/* The visual representation of a task stack view */
|
||||||
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
|
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
|
||||||
TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
|
TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
|
||||||
View.OnClickListener {
|
View.OnClickListener, View.OnLongClickListener {
|
||||||
|
|
||||||
/** The TaskView callbacks */
|
/** The TaskView callbacks */
|
||||||
interface TaskStackViewCallbacks {
|
interface TaskStackViewCallbacks {
|
||||||
public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
|
public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
|
||||||
|
public void onTaskAppInfoLaunched(Task t);
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskStack mStack;
|
TaskStack mStack;
|
||||||
@@ -75,6 +76,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
int mMinScroll;
|
int mMinScroll;
|
||||||
int mMaxScroll;
|
int mMaxScroll;
|
||||||
int mStashedScroll;
|
int mStashedScroll;
|
||||||
|
int mLastInfoPaneStackScroll;
|
||||||
OverScroller mScroller;
|
OverScroller mScroller;
|
||||||
ObjectAnimator mScrollAnimator;
|
ObjectAnimator mScrollAnimator;
|
||||||
|
|
||||||
@@ -281,6 +283,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
public void setStackScroll(int value) {
|
public void setStackScroll(int value) {
|
||||||
mStackScroll = value;
|
mStackScroll = value;
|
||||||
requestSynchronizeStackViewsWithModel();
|
requestSynchronizeStackViewsWithModel();
|
||||||
|
|
||||||
|
// Close any open info panes if the user has scrolled away from them
|
||||||
|
boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
|
||||||
|
if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
|
||||||
|
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||||
|
if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
|
||||||
|
config.taskStackScrollDismissInfoPaneDistance) {
|
||||||
|
// Close any open info panes
|
||||||
|
closeOpenInfoPanes();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/** Sets the current stack scroll without synchronizing the stack view with the model */
|
/** Sets the current stack scroll without synchronizing the stack view with the model */
|
||||||
public void setStackScrollRaw(int value) {
|
public void setStackScrollRaw(int value) {
|
||||||
@@ -300,19 +313,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
// Enable hw layers on the stack
|
// Enable hw layers on the stack
|
||||||
addHwLayersRefCount("animateBoundScroll");
|
addHwLayersRefCount("animateBoundScroll");
|
||||||
|
|
||||||
// Abort any current animations
|
|
||||||
abortScroller();
|
|
||||||
abortBoundScrollAnimation();
|
|
||||||
|
|
||||||
// Start a new scroll animation
|
// Start a new scroll animation
|
||||||
animateScroll(curScroll, newScroll);
|
animateScroll(curScroll, newScroll, new Runnable() {
|
||||||
mScrollAnimator.start();
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Disable hw layers on the stack
|
||||||
|
decHwLayersRefCount("animateBoundScroll");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return mScrollAnimator;
|
return mScrollAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Animates the stack scroll */
|
/** Animates the stack scroll */
|
||||||
void animateScroll(int curScroll, int newScroll) {
|
void animateScroll(int curScroll, int newScroll, final Runnable postRunnable) {
|
||||||
|
// Abort any current animations
|
||||||
|
abortScroller();
|
||||||
|
abortBoundScrollAnimation();
|
||||||
|
|
||||||
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
|
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
|
||||||
mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
|
mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
|
||||||
curScroll, 250));
|
curScroll, 250));
|
||||||
@@ -326,20 +344,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
mScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
mScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
// Disable hw layers on the stack
|
if (postRunnable != null) {
|
||||||
decHwLayersRefCount("animateBoundScroll");
|
postRunnable.run();
|
||||||
|
}
|
||||||
|
mScrollAnimator.removeAllListeners();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mScrollAnimator.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Aborts any current stack scrolls */
|
/** Aborts any current stack scrolls */
|
||||||
void abortBoundScrollAnimation() {
|
void abortBoundScrollAnimation() {
|
||||||
if (mScrollAnimator != null) {
|
if (mScrollAnimator != null) {
|
||||||
mScrollAnimator.cancel();
|
mScrollAnimator.cancel();
|
||||||
mScrollAnimator.removeAllListeners();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Aborts the scroller and any current fling */
|
||||||
void abortScroller() {
|
void abortScroller() {
|
||||||
if (!mScroller.isFinished()) {
|
if (!mScroller.isFinished()) {
|
||||||
// Abort the scroller
|
// Abort the scroller
|
||||||
@@ -407,6 +428,21 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Closes any open info panes. */
|
||||||
|
boolean closeOpenInfoPanes() {
|
||||||
|
if (!Constants.DebugFlags.App.EnableInfoPane) return false;
|
||||||
|
|
||||||
|
int childCount = getChildCount();
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
TaskView tv = (TaskView) getChildAt(i);
|
||||||
|
if (tv.isInfoPaneVisible()) {
|
||||||
|
tv.hideInfoPane();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Enables the hw layers and increments the hw layer requirement ref count */
|
/** Enables the hw layers and increments the hw layer requirement ref count */
|
||||||
void addHwLayersRefCount(String reason) {
|
void addHwLayersRefCount(String reason) {
|
||||||
Console.log(Constants.DebugFlags.UI.HwLayers,
|
Console.log(Constants.DebugFlags.UI.HwLayers,
|
||||||
@@ -644,7 +680,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
|
requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the animations for all the children views that need to be removed or to move views
|
* Creates the animations for all the children views that need to be removed or to move views
|
||||||
* to their un/filtered position when we are un/filtering a stack, and returns the duration
|
* to their un/filtered position when we are un/filtering a stack, and returns the duration
|
||||||
@@ -789,6 +824,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
@Override
|
@Override
|
||||||
public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
|
public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
|
||||||
Task filteredTask) {
|
Task filteredTask) {
|
||||||
|
// Close any open info panes
|
||||||
|
closeOpenInfoPanes();
|
||||||
|
|
||||||
// Stash the scroll and filtered task for us to restore to when we unfilter
|
// Stash the scroll and filtered task for us to restore to when we unfilter
|
||||||
mStashedScroll = getStackScroll();
|
mStashedScroll = getStackScroll();
|
||||||
|
|
||||||
@@ -813,6 +851,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
|
public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
|
||||||
|
// Close any open info panes
|
||||||
|
closeOpenInfoPanes();
|
||||||
|
|
||||||
// Calculate the current task transforms
|
// Calculate the current task transforms
|
||||||
final ArrayList<TaskViewTransform> curTaskTransforms =
|
final ArrayList<TaskViewTransform> curTaskTransforms =
|
||||||
getStackTransforms(curTasks, getStackScroll(), null, true);
|
getStackTransforms(curTasks, getStackScroll(), null, true);
|
||||||
@@ -892,6 +933,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
|
|
||||||
// Set the callbacks and listeners for this new view
|
// Set the callbacks and listeners for this new view
|
||||||
tv.setOnClickListener(this);
|
tv.setOnClickListener(this);
|
||||||
|
if (Constants.DebugFlags.App.EnableInfoPane) {
|
||||||
|
tv.setOnLongClickListener(this);
|
||||||
|
}
|
||||||
tv.setCallbacks(this);
|
tv.setCallbacks(this);
|
||||||
} else {
|
} else {
|
||||||
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
|
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
|
||||||
@@ -926,6 +970,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskInfoPanelShown(TaskView tv) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskInfoPanelHidden(TaskView tv) {
|
||||||
|
// Unset the saved scroll
|
||||||
|
mLastInfoPaneStackScroll = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskAppInfoClicked(TaskView tv) {
|
||||||
|
if (mCb != null) {
|
||||||
|
mCb.onTaskAppInfoLaunched(tv.getTask());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**** View.OnClickListener Implementation ****/
|
/**** View.OnClickListener Implementation ****/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -935,10 +997,51 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
Console.log(Constants.DebugFlags.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
|
Console.log(Constants.DebugFlags.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
|
||||||
task + " cb: " + mCb);
|
task + " cb: " + mCb);
|
||||||
|
|
||||||
|
// Close any open info panes if the user taps on another task
|
||||||
|
if (closeOpenInfoPanes()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mCb != null) {
|
if (mCb != null) {
|
||||||
mCb.onTaskLaunched(this, tv, mStack, task);
|
mCb.onTaskLaunched(this, tv, mStack, task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
if (!Constants.DebugFlags.App.EnableInfoPane) return false;
|
||||||
|
|
||||||
|
TaskView tv = (TaskView) v;
|
||||||
|
|
||||||
|
// Close any other task info panels if we launch another info pane
|
||||||
|
closeOpenInfoPanes();
|
||||||
|
|
||||||
|
// Scroll the task view so that it is maximally visible
|
||||||
|
float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
|
||||||
|
int taskIndex = mStack.indexOfTask(tv.getTask());
|
||||||
|
int curScroll = getStackScroll();
|
||||||
|
int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
|
||||||
|
TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
|
||||||
|
Rect nonOverlapRect = new Rect(transform.rect);
|
||||||
|
if (taskIndex < (mStack.getTaskCount() - 1)) {
|
||||||
|
nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: Use HW Layers
|
||||||
|
if (transform.t < 0f) {
|
||||||
|
animateScroll(curScroll, newScroll, null);
|
||||||
|
} else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
|
||||||
|
// Check if we are out of bounds, if so, just scroll it in such that the bottom of the
|
||||||
|
// task view is visible
|
||||||
|
newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
|
||||||
|
animateScroll(curScroll, newScroll, null);
|
||||||
|
}
|
||||||
|
mLastInfoPaneStackScroll = newScroll;
|
||||||
|
|
||||||
|
// Show the info pane for this task view
|
||||||
|
tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles touch events */
|
/* Handles touch events */
|
||||||
@@ -1153,9 +1256,10 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
|||||||
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
|
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
|
||||||
int x = (int) ev.getX(activePointerIndex);
|
int x = (int) ev.getX(activePointerIndex);
|
||||||
int y = (int) ev.getY(activePointerIndex);
|
int y = (int) ev.getY(activePointerIndex);
|
||||||
|
int yTotal = Math.abs(y - mInitialMotionY);
|
||||||
int deltaY = mLastMotionY - y;
|
int deltaY = mLastMotionY - y;
|
||||||
if (!mIsScrolling) {
|
if (!mIsScrolling) {
|
||||||
if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
|
if (yTotal > mScrollTouchSlop) {
|
||||||
mIsScrolling = true;
|
mIsScrolling = true;
|
||||||
// Initialize the velocity tracker
|
// Initialize the velocity tracker
|
||||||
initOrResetVelocityTracker();
|
initOrResetVelocityTracker();
|
||||||
@@ -1277,6 +1381,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
|||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.requestDisallowInterceptTouchEvent(true);
|
parent.requestDisallowInterceptTouchEvent(true);
|
||||||
}
|
}
|
||||||
|
// If the info panel is currently showing on this view, then we need to dismiss it
|
||||||
|
if (Constants.DebugFlags.App.EnableInfoPane) {
|
||||||
|
TaskView tv = (TaskView) v;
|
||||||
|
if (tv.isInfoPaneVisible()) {
|
||||||
|
tv.hideInfoPane();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -17,8 +17,10 @@
|
|||||||
package com.android.systemui.recents.views;
|
package com.android.systemui.recents.views;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -29,18 +31,26 @@ import com.android.systemui.recents.model.Task;
|
|||||||
|
|
||||||
|
|
||||||
/* A task view */
|
/* A task view */
|
||||||
public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
|
public class TaskView extends FrameLayout implements View.OnClickListener,
|
||||||
|
Task.TaskCallbacks {
|
||||||
/** The TaskView callbacks */
|
/** The TaskView callbacks */
|
||||||
interface TaskViewCallbacks {
|
interface TaskViewCallbacks {
|
||||||
public void onTaskIconClicked(TaskView tv);
|
public void onTaskIconClicked(TaskView tv);
|
||||||
|
public void onTaskInfoPanelShown(TaskView tv);
|
||||||
|
public void onTaskInfoPanelHidden(TaskView tv);
|
||||||
|
public void onTaskAppInfoClicked(TaskView tv);
|
||||||
|
|
||||||
// public void onTaskViewReboundToTask(TaskView tv, Task t);
|
// public void onTaskViewReboundToTask(TaskView tv, Task t);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task mTask;
|
Task mTask;
|
||||||
boolean mTaskDataLoaded;
|
boolean mTaskDataLoaded;
|
||||||
|
boolean mTaskInfoPaneVisible;
|
||||||
|
Point mLastTouchDown = new Point();
|
||||||
|
|
||||||
TaskThumbnailView mThumbnailView;
|
TaskThumbnailView mThumbnailView;
|
||||||
TaskBarView mBarView;
|
TaskBarView mBarView;
|
||||||
|
TaskInfoView mInfoView;
|
||||||
TaskViewCallbacks mCb;
|
TaskViewCallbacks mCb;
|
||||||
|
|
||||||
|
|
||||||
@@ -65,12 +75,24 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
// Bind the views
|
// Bind the views
|
||||||
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
|
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
|
||||||
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
|
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
|
||||||
mBarView.mApplicationIcon.setOnClickListener(this);
|
mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
|
||||||
|
|
||||||
if (mTaskDataLoaded) {
|
if (mTaskDataLoaded) {
|
||||||
onTaskDataLoaded(false);
|
onTaskDataLoaded(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||||
|
switch (ev.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
mLastTouchDown.set((int) ev.getX(), (int) ev.getY());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return super.onInterceptTouchEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
/** Set callback */
|
/** Set callback */
|
||||||
void setCallbacks(TaskViewCallbacks cb) {
|
void setCallbacks(TaskViewCallbacks cb) {
|
||||||
mCb = cb;
|
mCb = cb;
|
||||||
@@ -189,6 +211,63 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
return outRect;
|
return outRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether this task has an info pane visible */
|
||||||
|
boolean isInfoPaneVisible() {
|
||||||
|
return mTaskInfoPaneVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Shows the info pane if it is not visible. */
|
||||||
|
void showInfoPane(Rect taskVisibleRect) {
|
||||||
|
if (mTaskInfoPaneVisible) return;
|
||||||
|
|
||||||
|
// Remove the bar view from the visible rect and update the info pane contents
|
||||||
|
taskVisibleRect.top += mBarView.getMeasuredHeight();
|
||||||
|
mInfoView.updateContents(taskVisibleRect);
|
||||||
|
|
||||||
|
// Show the info pane and animate it into view
|
||||||
|
mInfoView.setVisibility(View.VISIBLE);
|
||||||
|
mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
|
||||||
|
mInfoView.setOnClickListener(this);
|
||||||
|
mTaskInfoPaneVisible = true;
|
||||||
|
|
||||||
|
// Notify any callbacks
|
||||||
|
if (mCb != null) {
|
||||||
|
mCb.onTaskInfoPanelShown(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Hides the info pane if it is visible. */
|
||||||
|
void hideInfoPane() {
|
||||||
|
if (!mTaskInfoPaneVisible) return;
|
||||||
|
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||||
|
|
||||||
|
// Cancel any circular clip animation
|
||||||
|
mInfoView.cancelCircularClipAnimation();
|
||||||
|
|
||||||
|
// Animate the info pane out
|
||||||
|
mInfoView.animate()
|
||||||
|
.alpha(0f)
|
||||||
|
.setDuration(config.taskViewInfoPaneAnimDuration)
|
||||||
|
.setInterpolator(BakedBezierInterpolator.INSTANCE)
|
||||||
|
.withLayer()
|
||||||
|
.withEndAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mInfoView.setVisibility(View.INVISIBLE);
|
||||||
|
mInfoView.setOnClickListener(null);
|
||||||
|
|
||||||
|
mInfoView.setAlpha(1f);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
mTaskInfoPaneVisible = false;
|
||||||
|
|
||||||
|
// Notify any callbacks
|
||||||
|
if (mCb != null) {
|
||||||
|
mCb.onTaskInfoPanelHidden(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Enable the hw layers on this task view */
|
/** Enable the hw layers on this task view */
|
||||||
void enableHwLayers() {
|
void enableHwLayers() {
|
||||||
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||||
@@ -209,27 +288,39 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskDataLoaded(boolean reloadingTaskData) {
|
public void onTaskDataLoaded(boolean reloadingTaskData) {
|
||||||
if (mThumbnailView != null && mBarView != null) {
|
if (mThumbnailView != null && mBarView != null && mInfoView != null) {
|
||||||
// Bind each of the views to the new task data
|
// Bind each of the views to the new task data
|
||||||
mThumbnailView.rebindToTask(mTask, reloadingTaskData);
|
mThumbnailView.rebindToTask(mTask, reloadingTaskData);
|
||||||
mBarView.rebindToTask(mTask, reloadingTaskData);
|
mBarView.rebindToTask(mTask, reloadingTaskData);
|
||||||
|
// Rebind any listeners
|
||||||
|
mBarView.mApplicationIcon.setOnClickListener(this);
|
||||||
|
mInfoView.mAppInfoButton.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
mTaskDataLoaded = true;
|
mTaskDataLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskDataUnloaded() {
|
public void onTaskDataUnloaded() {
|
||||||
if (mThumbnailView != null && mBarView != null) {
|
if (mThumbnailView != null && mBarView != null && mInfoView != null) {
|
||||||
// Unbind each of the views from the task data and remove the task callback
|
// Unbind each of the views from the task data and remove the task callback
|
||||||
mTask.setCallbacks(null);
|
mTask.setCallbacks(null);
|
||||||
mThumbnailView.unbindFromTask();
|
mThumbnailView.unbindFromTask();
|
||||||
mBarView.unbindFromTask();
|
mBarView.unbindFromTask();
|
||||||
|
// Unbind any listeners
|
||||||
|
mBarView.mApplicationIcon.setOnClickListener(null);
|
||||||
|
mInfoView.mAppInfoButton.setOnClickListener(null);
|
||||||
}
|
}
|
||||||
mTaskDataLoaded = false;
|
mTaskDataLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
mCb.onTaskIconClicked(this);
|
if (v == mInfoView) {
|
||||||
|
// Do nothing
|
||||||
|
} else if (v == mBarView.mApplicationIcon) {
|
||||||
|
mCb.onTaskIconClicked(this);
|
||||||
|
} else if (v == mInfoView.mAppInfoButton) {
|
||||||
|
mCb.onTaskAppInfoClicked(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user