Merge "[13/n] Letterbox Education: change dialog width and handle oveflow cases."
This commit is contained in:
@@ -22,81 +22,101 @@
|
||||
|
||||
<!-- The background of the top-level layout acts as the background dim. -->
|
||||
|
||||
<!-- Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
|
||||
<!-- Vertical margin will be set dynamically since it depends on task bounds.
|
||||
Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
|
||||
enter animation starts. -->
|
||||
<LinearLayout
|
||||
<FrameLayout
|
||||
android:id="@+id/letterbox_education_dialog_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginHorizontal="@dimen/letterbox_education_dialog_margin"
|
||||
android:background="@drawable/letterbox_education_dialog_background"
|
||||
android:padding="24dp"
|
||||
android:alpha="0">
|
||||
android:alpha="0"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintWidth_max="@dimen/letterbox_education_dialog_width"
|
||||
app:layout_constrainedHeight="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/letterbox_education_icon"
|
||||
android:layout_width="@dimen/letterbox_education_dialog_icon_size"
|
||||
android:layout_height="@dimen/letterbox_education_dialog_icon_size"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:src="@drawable/letterbox_education_ic_letterboxed_app"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/letterbox_education_dialog_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="@dimen/letterbox_education_dialog_title_max_width"
|
||||
android:lineSpacingExtra="4sp"
|
||||
android:text="@string/letterbox_education_dialog_title"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/compat_controls_text"
|
||||
android:textSize="24sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:maxWidth="@dimen/letterbox_education_dialog_title_max_width"
|
||||
android:lineSpacingExtra="4sp"
|
||||
android:text="@string/letterbox_education_dialog_subtext"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/letterbox_education_text_secondary"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="48dp">
|
||||
|
||||
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/letterbox_education_ic_screen_rotation"
|
||||
app:text="@string/letterbox_education_screen_rotation_text"/>
|
||||
|
||||
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/letterbox_education_dialog_space_between_actions"
|
||||
app:icon="@drawable/letterbox_education_ic_reposition"
|
||||
app:text="@string/letterbox_education_reposition_text"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/letterbox_education_dialog_dismiss_button"
|
||||
<!-- The ScrollView should only wrap the content of the dialog, otherwise the background
|
||||
corner radius will be cut off when scrolling to the top/bottom. -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:background="@drawable/letterbox_education_dismiss_button_background_ripple"
|
||||
android:text="@string/letterbox_education_got_it"
|
||||
android:textColor="@android:color/system_neutral1_900"
|
||||
android:textAlignment="center"
|
||||
android:contentDescription="@string/letterbox_education_got_it"/>
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/letterbox_education_dialog_icon_size"
|
||||
android:layout_height="@dimen/letterbox_education_dialog_icon_size"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:src="@drawable/letterbox_education_ic_letterboxed_app"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/letterbox_education_dialog_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingExtra="4sp"
|
||||
android:text="@string/letterbox_education_dialog_title"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/compat_controls_text"
|
||||
android:textSize="24sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:lineSpacingExtra="4sp"
|
||||
android:text="@string/letterbox_education_dialog_subtext"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/letterbox_education_text_secondary"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="48dp">
|
||||
|
||||
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/letterbox_education_ic_screen_rotation"
|
||||
app:text="@string/letterbox_education_screen_rotation_text"/>
|
||||
|
||||
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart=
|
||||
"@dimen/letterbox_education_dialog_space_between_actions"
|
||||
app:icon="@drawable/letterbox_education_ic_reposition"
|
||||
app:text="@string/letterbox_education_reposition_text"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/letterbox_education_dialog_dismiss_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="48dp"
|
||||
android:background=
|
||||
"@drawable/letterbox_education_dismiss_button_background_ripple"
|
||||
android:text="@string/letterbox_education_got_it"
|
||||
android:textColor="@android:color/system_neutral1_900"
|
||||
android:textAlignment="center"
|
||||
android:contentDescription="@string/letterbox_education_got_it"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogLayout>
|
||||
|
||||
@@ -225,15 +225,18 @@
|
||||
<!-- The size of an icon in the letterbox education dialog. -->
|
||||
<dimen name="letterbox_education_dialog_icon_size">48dp</dimen>
|
||||
|
||||
<!-- The fixed width of the dialog if there is enough space in the parent. -->
|
||||
<dimen name="letterbox_education_dialog_width">472dp</dimen>
|
||||
|
||||
<!-- The margin between the dialog container and its parent. -->
|
||||
<dimen name="letterbox_education_dialog_margin">16dp</dimen>
|
||||
|
||||
<!-- The width of each action container in the letterbox education dialog -->
|
||||
<dimen name="letterbox_education_dialog_action_width">140dp</dimen>
|
||||
|
||||
<!-- The space between two actions in the letterbox education dialog -->
|
||||
<dimen name="letterbox_education_dialog_space_between_actions">24dp</dimen>
|
||||
|
||||
<!-- The maximum width of the title and subtitle in the letterbox education dialog. -->
|
||||
<dimen name="letterbox_education_dialog_title_max_width">444dp</dimen>
|
||||
|
||||
<!-- The width of the brand image on staring surface. -->
|
||||
<dimen name="starting_surface_brand_image_width">200dp</dimen>
|
||||
|
||||
|
||||
@@ -189,15 +189,18 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSurfacePosition(Rect taskBounds, Rect stableBounds) {
|
||||
@VisibleForTesting
|
||||
public void updateSurfacePosition() {
|
||||
if (mLayout == null) {
|
||||
return;
|
||||
}
|
||||
// Position of the button in the container coordinate.
|
||||
final Rect taskBounds = getTaskBounds();
|
||||
final Rect taskStableBounds = getTaskStableBounds();
|
||||
final int positionX = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
|
||||
? stableBounds.left - taskBounds.left
|
||||
: stableBounds.right - taskBounds.left - mLayout.getMeasuredWidth();
|
||||
final int positionY = stableBounds.bottom - taskBounds.top
|
||||
? taskStableBounds.left - taskBounds.left
|
||||
: taskStableBounds.right - taskBounds.left - mLayout.getMeasuredWidth();
|
||||
final int positionY = taskStableBounds.bottom - taskBounds.top
|
||||
- mLayout.getMeasuredHeight();
|
||||
|
||||
updateSurfacePosition(positionX, positionY);
|
||||
|
||||
@@ -51,15 +51,15 @@ import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
*/
|
||||
public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowManager {
|
||||
|
||||
protected final SyncTransactionQueue mSyncQueue;
|
||||
protected final int mDisplayId;
|
||||
protected final int mTaskId;
|
||||
|
||||
protected Context mContext;
|
||||
protected Configuration mTaskConfig;
|
||||
protected ShellTaskOrganizer.TaskListener mTaskListener;
|
||||
protected DisplayLayout mDisplayLayout;
|
||||
protected final Rect mStableBounds;
|
||||
|
||||
private final SyncTransactionQueue mSyncQueue;
|
||||
private final int mDisplayId;
|
||||
private Configuration mTaskConfig;
|
||||
private ShellTaskOrganizer.TaskListener mTaskListener;
|
||||
private DisplayLayout mDisplayLayout;
|
||||
private final Rect mStableBounds;
|
||||
|
||||
/**
|
||||
* Utility class for adding and releasing a View hierarchy for this {@link
|
||||
@@ -211,7 +211,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
boolean layoutDirectionUpdated =
|
||||
mTaskConfig.getLayoutDirection() != prevTaskConfig.getLayoutDirection();
|
||||
if (boundsUpdated || layoutDirectionUpdated) {
|
||||
updateSurface();
|
||||
onParentBoundsChanged();
|
||||
}
|
||||
|
||||
if (layout != null && layoutDirectionUpdated) {
|
||||
@@ -248,8 +248,9 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
displayLayout.getStableBounds(curStableBounds);
|
||||
mDisplayLayout = displayLayout;
|
||||
if (!prevStableBounds.equals(curStableBounds)) {
|
||||
updateSurface();
|
||||
// mStableBounds should be updated before we call onParentBoundsChanged.
|
||||
mStableBounds.set(curStableBounds);
|
||||
onParentBoundsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,51 +290,39 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
}
|
||||
|
||||
/** Re-layouts the view host and updates the surface position. */
|
||||
public void relayout() {
|
||||
void relayout() {
|
||||
relayout(getWindowLayoutParams());
|
||||
}
|
||||
|
||||
protected void relayout(WindowManager.LayoutParams windowLayoutParams) {
|
||||
if (mViewHost == null) {
|
||||
return;
|
||||
}
|
||||
mViewHost.relayout(getWindowLayoutParams());
|
||||
mViewHost.relayout(windowLayoutParams);
|
||||
updateSurfacePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the surface following a change in the task bounds, display layout stable bounds,
|
||||
* or the layout direction.
|
||||
* Called following a change in the task bounds, display layout stable bounds, or the layout
|
||||
* direction.
|
||||
*/
|
||||
protected void updateSurface() {
|
||||
protected void onParentBoundsChanged() {
|
||||
updateSurfacePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of the surface with respect to the task bounds and display layout
|
||||
* stable bounds.
|
||||
* Updates the position of the surface with respect to the parent bounds.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void updateSurfacePosition() {
|
||||
if (mLeash == null) {
|
||||
return;
|
||||
}
|
||||
// Use stable bounds to prevent controls from overlapping with system bars.
|
||||
final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds();
|
||||
final Rect stableBounds = new Rect();
|
||||
mDisplayLayout.getStableBounds(stableBounds);
|
||||
stableBounds.intersect(taskBounds);
|
||||
|
||||
updateSurfacePosition(taskBounds, stableBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the position of the surface with respect to the given {@code taskBounds} and {@code
|
||||
* stableBounds}.
|
||||
*/
|
||||
protected abstract void updateSurfacePosition(Rect taskBounds, Rect stableBounds);
|
||||
protected abstract void updateSurfacePosition();
|
||||
|
||||
/**
|
||||
* Updates the position of the surface with respect to the given {@code positionX} and {@code
|
||||
* positionY}.
|
||||
*/
|
||||
protected void updateSurfacePosition(int positionX, int positionY) {
|
||||
if (mLeash == null) {
|
||||
return;
|
||||
}
|
||||
mSyncQueue.runInSync(t -> {
|
||||
if (mLeash == null || !mLeash.isValid()) {
|
||||
Log.w(getTag(), "The leash has been released.");
|
||||
@@ -347,6 +336,17 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
return mContext.getResources().getConfiguration().getLayoutDirection();
|
||||
}
|
||||
|
||||
protected Rect getTaskBounds() {
|
||||
return mTaskConfig.windowConfiguration.getBounds();
|
||||
}
|
||||
|
||||
/** Returns the intersection between the task bounds and the display layout stable bounds. */
|
||||
protected Rect getTaskStableBounds() {
|
||||
final Rect result = new Rect(mStableBounds);
|
||||
result.intersect(getTaskBounds());
|
||||
return result;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
SurfaceControlViewHost createSurfaceViewHost() {
|
||||
return new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
|
||||
|
||||
@@ -43,6 +43,8 @@ import com.android.internal.policy.TransitionAnimation;
|
||||
class LetterboxEduAnimationController {
|
||||
private static final String TAG = "LetterboxEduAnimation";
|
||||
|
||||
private static final int ENTER_ANIM_START_DELAY_MILLIS = 500;
|
||||
|
||||
private final TransitionAnimation mTransitionAnimation;
|
||||
private final String mPackageName;
|
||||
@AnyRes
|
||||
@@ -87,6 +89,9 @@ class LetterboxEduAnimationController {
|
||||
mDialogAnimation.getDuration());
|
||||
mBackgroundDimAnimator.addListener(getDimAnimatorListener());
|
||||
|
||||
mDialogAnimation.setStartOffset(ENTER_ANIM_START_DELAY_MILLIS);
|
||||
mBackgroundDimAnimator.setStartDelay(ENTER_ANIM_START_DELAY_MILLIS);
|
||||
|
||||
dialogContainer.startAnimation(mDialogAnimation);
|
||||
mBackgroundDimAnimator.start();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
|
||||
@@ -31,7 +32,7 @@ import com.android.wm.shell.R;
|
||||
* background dim which dismisses the dialog when clicked.
|
||||
*/
|
||||
// TODO(b/215316431): Add tests
|
||||
class LetterboxEduDialogLayout extends FrameLayout {
|
||||
class LetterboxEduDialogLayout extends ConstraintLayout {
|
||||
|
||||
// The alpha of a background is a number between 0 (fully transparent) to 255 (fully opaque).
|
||||
// 204 is simply 255 * 0.8.
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.graphics.Rect;
|
||||
import android.provider.Settings;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
@@ -109,6 +110,7 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
|
||||
protected View createLayout() {
|
||||
setSeenLetterboxEducation();
|
||||
mLayout = inflateLayout();
|
||||
updateDialogMargins();
|
||||
|
||||
mAnimationController.startEnterAnimation(mLayout, /* endCallback= */
|
||||
this::setDismissOnClickListener);
|
||||
@@ -116,6 +118,22 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
|
||||
return mLayout;
|
||||
}
|
||||
|
||||
private void updateDialogMargins() {
|
||||
if (mLayout == null) {
|
||||
return;
|
||||
}
|
||||
final View dialogContainer = mLayout.getDialogContainer();
|
||||
MarginLayoutParams marginParams = (MarginLayoutParams) dialogContainer.getLayoutParams();
|
||||
int verticalMargin = (int) mContext.getResources().getDimension(
|
||||
R.dimen.letterbox_education_dialog_margin);
|
||||
|
||||
final Rect taskBounds = getTaskBounds();
|
||||
final Rect taskStableBounds = getTaskStableBounds();
|
||||
marginParams.topMargin = taskStableBounds.top - taskBounds.top + verticalMargin;
|
||||
marginParams.bottomMargin = taskBounds.bottom - taskStableBounds.bottom + verticalMargin;
|
||||
dialogContainer.setLayoutParams(marginParams);
|
||||
}
|
||||
|
||||
private LetterboxEduDialogLayout inflateLayout() {
|
||||
return (LetterboxEduDialogLayout) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.letterbox_education_dialog_layout, null);
|
||||
@@ -150,20 +168,26 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSurface() {
|
||||
// We need to relayout because the layout dimensions depend on the task bounds.
|
||||
relayout();
|
||||
protected void onParentBoundsChanged() {
|
||||
if (mLayout == null) {
|
||||
return;
|
||||
}
|
||||
// Both the layout dimensions and dialog margins depend on the parent bounds.
|
||||
WindowManager.LayoutParams windowLayoutParams = getWindowLayoutParams();
|
||||
mLayout.setLayoutParams(windowLayoutParams);
|
||||
updateDialogMargins();
|
||||
relayout(windowLayoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSurfacePosition(Rect taskBounds, Rect stableBounds) {
|
||||
protected void updateSurfacePosition() {
|
||||
// Nothing to do, since the position of the surface is fixed to the top left corner (0,0)
|
||||
// of the task (parent surface), which is the default position of a surface.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WindowManager.LayoutParams getWindowLayoutParams() {
|
||||
final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds();
|
||||
final Rect taskBounds = getTaskBounds();
|
||||
return getWindowLayoutParams(/* width= */ taskBounds.width(), /* height= */
|
||||
taskBounds.height());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user