[Notif] Add custom view to made undo text push button down

Added a custom FrameLayout that computes the correct height if the text
overlaps with the button and re-positions the button to be below the
text as necessary.

Test: Manually tested w/ different text, including layout bounds + RTL
Change-Id: I80b0eb4ce3a108d350924d6a7b964cd0b59f1cac
Fixes: 77810898
Bug: 109839789
This commit is contained in:
Rohan Shah
2018-06-13 20:17:42 -07:00
parent 594c88f79c
commit 482193f224
2 changed files with 149 additions and 9 deletions

View File

@@ -161,30 +161,31 @@
style="@style/TextAppearance.NotificationInfo.Button"/>
</LinearLayout>
</LinearLayout>
<RelativeLayout
<com.android.systemui.statusbar.NotificationUndoLayout
android:id="@+id/confirmation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:layout_marginStart="@dimen/notification_guts_button_side_margin"
android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
android:visibility="gone"
android:orientation="horizontal" >
<TextView
android:id="@+id/confirmation_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="start|center_vertical"
android:layout_marginStart="@*android:dimen/notification_content_margin_start"
android:layout_marginEnd="@*android:dimen/notification_content_margin_start"
android:text="@string/notification_channel_disabled"
style="@style/TextAppearance.NotificationInfo.Confirmation"/>
<TextView
android:id="@+id/undo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
android:layout_marginStart="@dimen/notification_guts_button_side_margin"
android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
android:layout_gravity="end|center_vertical"
android:text="@string/inline_undo"
style="@style/TextAppearance.NotificationInfo.Button"/>
</RelativeLayout>
</com.android.systemui.statusbar.NotificationUndoLayout>
</com.android.systemui.statusbar.NotificationInfo>

View File

@@ -0,0 +1,139 @@
/*
* 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.systemui.statusbar;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.R;
/**
* Custom view for the NotificationInfo confirmation views so that the confirmation text can
* occupy the full width of the notification and push the undo button down to the next line if
* necessary.
*
* @see NotificationInfo
*/
public class NotificationUndoLayout extends FrameLayout {
/**
* View for the prompt/confirmation text to tell the user the previous action was successful.
*/
private View mConfirmationTextView;
/** Undo button (actionable text) view. */
private View mUndoView;
/**
* Whether {@link #mConfirmationTextView} is multiline and will require the full width of the
* parent (which causes the {@link #mUndoView} to push down).
*/
private boolean mIsMultiline = false;
private int mMultilineTopMargin;
public NotificationUndoLayout(Context context) {
this(context, null);
}
public NotificationUndoLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NotificationUndoLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mConfirmationTextView = findViewById(R.id.confirmation_text);
mUndoView = findViewById(R.id.undo);
mMultilineTopMargin = getResources().getDimensionPixelOffset(
com.android.internal.R.dimen.notification_content_margin_start);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LayoutParams confirmationLayoutParams =
(LayoutParams) mConfirmationTextView.getLayoutParams();
LayoutParams undoLayoutParams =(LayoutParams) mUndoView.getLayoutParams();
int measuredWidth = getMeasuredWidth();
// Ignore the left margin on the undo button - no need for additional extra space between
// the text and the button.
int requiredWidth = mConfirmationTextView.getMeasuredWidth()
+ confirmationLayoutParams.rightMargin
+ confirmationLayoutParams.leftMargin
+ mUndoView.getMeasuredWidth()
+ undoLayoutParams.rightMargin;
// If the measured width isn't enough to accommodate both the undo button and the text in
// the same line, we'll need to adjust the view to be multi-line. Otherwise, we're done.
if (requiredWidth > measuredWidth) {
mIsMultiline = true;
// Update height requirement to the text height and the button's height (along with
// additional spacing for the top of the text).
int updatedHeight = mMultilineTopMargin
+ mConfirmationTextView.getMeasuredHeight()
+ mUndoView.getMeasuredHeight()
+ undoLayoutParams.topMargin
+ undoLayoutParams.bottomMargin;
setMeasuredDimension(measuredWidth, updatedHeight);
} else {
mIsMultiline = false;
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// If the text view and undo view don't fit on the same line, we'll need to manually lay
// out the content.
if (mIsMultiline) {
// Re-align parent right/bottom values. Left and top are considered to be 0.
int parentBottom = getMeasuredHeight();
int parentRight = getMeasuredWidth();
LayoutParams confirmationLayoutParams =
(LayoutParams) mConfirmationTextView.getLayoutParams();
LayoutParams undoLayoutParams = (LayoutParams) mUndoView.getLayoutParams();
// The confirmation text occupies the full width as computed earlier. Both side margins
// are equivalent, so we only need to grab the left one here.
mConfirmationTextView.layout(
confirmationLayoutParams.leftMargin,
mMultilineTopMargin,
confirmationLayoutParams.leftMargin + mConfirmationTextView.getMeasuredWidth(),
mMultilineTopMargin + mConfirmationTextView.getMeasuredHeight());
// The undo button is aligned bottom|end with the parent in the case of multiline text.
int undoViewLeft = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
? undoLayoutParams.rightMargin
: parentRight - mUndoView.getMeasuredWidth() - undoLayoutParams.rightMargin;
mUndoView.layout(
undoViewLeft,
parentBottom - mUndoView.getMeasuredHeight() - undoLayoutParams.bottomMargin,
undoViewLeft + mUndoView.getMeasuredWidth(),
parentBottom - undoLayoutParams.bottomMargin);
} else {
super.onLayout(changed, left, top, right, bottom);
}
}
}