Split NotificationHeaderView's text content into NotificationTopLineView
Test: atest SystemUITests Test: manual testing of various notification types Change-Id: I80173501b2c5902bab83c2f620daabbd943fc473
This commit is contained in:
@@ -43,16 +43,11 @@ import java.util.ArrayList;
|
||||
public class NotificationHeaderView extends ViewGroup {
|
||||
private final int mChildMinWidth;
|
||||
private final int mContentEndMargin;
|
||||
private View mAppName;
|
||||
private View mHeaderText;
|
||||
private View mSecondaryHeaderText;
|
||||
private OnClickListener mExpandClickListener;
|
||||
private OnClickListener mFeedbackListener;
|
||||
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
|
||||
private NotificationTopLineView mTopLineView;
|
||||
private NotificationExpandButton mExpandButton;
|
||||
private CachingIconView mIcon;
|
||||
private View mProfileBadge;
|
||||
private View mFeedbackIcon;
|
||||
private int mHeaderTextMarginEnd;
|
||||
private Drawable mBackground;
|
||||
private boolean mEntireHeaderClickable;
|
||||
@@ -94,13 +89,9 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mAppName = findViewById(R.id.app_name_text);
|
||||
mHeaderText = findViewById(R.id.header_text);
|
||||
mSecondaryHeaderText = findViewById(R.id.header_text_secondary);
|
||||
mExpandButton = findViewById(R.id.expand_button);
|
||||
mIcon = findViewById(R.id.icon);
|
||||
mProfileBadge = findViewById(R.id.profile_badge);
|
||||
mFeedbackIcon = findViewById(R.id.feedback);
|
||||
mTopLineView = findViewById(R.id.notification_top_line);
|
||||
mExpandButton = findViewById(R.id.expand_button);
|
||||
setClipToPadding(false);
|
||||
}
|
||||
|
||||
@@ -127,7 +118,7 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
lp.topMargin + lp.bottomMargin, lp.height);
|
||||
child.measure(childWidthSpec, childHeightSpec);
|
||||
// Icons that should go at the end
|
||||
if (child == mExpandButton || child == mProfileBadge || child == mFeedbackIcon) {
|
||||
if (child == mExpandButton) {
|
||||
iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
|
||||
} else {
|
||||
totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
|
||||
@@ -138,16 +129,9 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
int endMargin = Math.max(mHeaderTextMarginEnd, iconWidth);
|
||||
if (totalWidth > givenWidth - endMargin) {
|
||||
int overFlow = totalWidth - givenWidth + endMargin;
|
||||
// We are overflowing, lets shrink the app name first
|
||||
overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
|
||||
// We are overflowing; shrink the top line
|
||||
shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mTopLineView,
|
||||
mChildMinWidth);
|
||||
|
||||
// still overflowing, we shrink the header text
|
||||
overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mHeaderText, 0);
|
||||
|
||||
// still overflowing, finally we shrink the secondary header text
|
||||
shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
|
||||
0);
|
||||
}
|
||||
setMeasuredDimension(givenWidth, givenHeight);
|
||||
}
|
||||
@@ -183,7 +167,7 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
int top = (int) (getPaddingTop() + (ownHeight - childHeight) / 2.0f);
|
||||
int bottom = top + childHeight;
|
||||
// Icons that should go at the end
|
||||
if (child == mExpandButton || child == mProfileBadge || child == mFeedbackIcon) {
|
||||
if (child == mExpandButton) {
|
||||
if (end == getMeasuredWidth()) {
|
||||
layoutRight = end - mContentEndMargin;
|
||||
} else {
|
||||
@@ -251,7 +235,7 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
}
|
||||
|
||||
private void updateTouchListener() {
|
||||
if (mExpandClickListener == null && mFeedbackListener == null) {
|
||||
if (mExpandClickListener == null) {
|
||||
setOnTouchListener(null);
|
||||
return;
|
||||
}
|
||||
@@ -259,15 +243,6 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
mTouchListener.bindTouchRects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets onclick listener for feedback icon.
|
||||
*/
|
||||
public void setFeedbackOnClickListener(OnClickListener l) {
|
||||
mFeedbackListener = l;
|
||||
mFeedbackIcon.setOnClickListener(mFeedbackListener);
|
||||
updateTouchListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClickListener(@Nullable OnClickListener l) {
|
||||
mExpandClickListener = l;
|
||||
@@ -302,7 +277,6 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
|
||||
private final ArrayList<Rect> mTouchRects = new ArrayList<>();
|
||||
private Rect mExpandButtonRect;
|
||||
private Rect mFeedbackRect;
|
||||
private int mTouchSlop;
|
||||
private boolean mTrackGesture;
|
||||
private float mDownX;
|
||||
@@ -315,7 +289,6 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
mTouchRects.clear();
|
||||
addRectAroundView(mIcon);
|
||||
mExpandButtonRect = addRectAroundView(mExpandButton);
|
||||
mFeedbackRect = addRectAroundView(mFeedbackIcon);
|
||||
addWidthRect();
|
||||
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
}
|
||||
@@ -376,11 +349,11 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mTrackGesture) {
|
||||
if (mFeedbackIcon.isVisibleToUser()
|
||||
&& (mFeedbackRect.contains((int) x, (int) y)
|
||||
|| mFeedbackRect.contains((int) mDownX, (int) mDownY))) {
|
||||
mFeedbackIcon.performClick();
|
||||
return true;
|
||||
float topLineX = mTopLineView.getX();
|
||||
float topLineY = mTopLineView.getY();
|
||||
if (mTopLineView.onTouchUp(x - topLineX, y - topLineY,
|
||||
mDownX - topLineX, mDownY - topLineY)) {
|
||||
break;
|
||||
}
|
||||
mExpandButton.performClick();
|
||||
}
|
||||
@@ -402,7 +375,9 @@ public class NotificationHeaderView extends ViewGroup {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
float topLineX = x - mTopLineView.getX();
|
||||
float topLineY = y - mTopLineView.getY();
|
||||
return mTopLineView.isInTouchRect(topLineX, topLineY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
344
core/java/android/view/NotificationTopLineView.java
Normal file
344
core/java/android/view/NotificationTopLineView.java
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 android.view;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The top line of content in a notification view.
|
||||
* This includes the text views and badges but excludes the icon and the expander.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RemoteViews.RemoteView
|
||||
public class NotificationTopLineView extends ViewGroup {
|
||||
private final int mChildMinWidth;
|
||||
private final int mContentEndMargin;
|
||||
private View mAppName;
|
||||
private View mHeaderText;
|
||||
private View mSecondaryHeaderText;
|
||||
private OnClickListener mFeedbackListener;
|
||||
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
|
||||
private View mProfileBadge;
|
||||
private View mFeedbackIcon;
|
||||
private int mHeaderTextMarginEnd;
|
||||
private List<View> mIconsAtEnd;
|
||||
|
||||
public NotificationTopLineView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public NotificationTopLineView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public NotificationTopLineView(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public NotificationTopLineView(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
Resources res = getResources();
|
||||
mChildMinWidth = res.getDimensionPixelSize(R.dimen.notification_header_shrink_min_width);
|
||||
mContentEndMargin = res.getDimensionPixelSize(R.dimen.notification_content_margin_end);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mAppName = findViewById(R.id.app_name_text);
|
||||
mHeaderText = findViewById(R.id.header_text);
|
||||
mSecondaryHeaderText = findViewById(R.id.header_text_secondary);
|
||||
mProfileBadge = findViewById(R.id.profile_badge);
|
||||
mFeedbackIcon = findViewById(R.id.feedback);
|
||||
mIconsAtEnd = Arrays.asList(mProfileBadge, mFeedbackIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
final int givenWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
final int givenHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int wrapContentWidthSpec = MeasureSpec.makeMeasureSpec(givenWidth,
|
||||
MeasureSpec.AT_MOST);
|
||||
int wrapContentHeightSpec = MeasureSpec.makeMeasureSpec(givenHeight,
|
||||
MeasureSpec.AT_MOST);
|
||||
int totalWidth = getPaddingStart();
|
||||
int iconWidth = getPaddingEnd();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
// We'll give it the rest of the space in the end
|
||||
continue;
|
||||
}
|
||||
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
|
||||
int childWidthSpec = getChildMeasureSpec(wrapContentWidthSpec,
|
||||
lp.leftMargin + lp.rightMargin, lp.width);
|
||||
int childHeightSpec = getChildMeasureSpec(wrapContentHeightSpec,
|
||||
lp.topMargin + lp.bottomMargin, lp.height);
|
||||
child.measure(childWidthSpec, childHeightSpec);
|
||||
// Icons that should go at the end
|
||||
if (mIconsAtEnd.contains(child)) {
|
||||
iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
|
||||
} else {
|
||||
totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there is at least enough space for the icons
|
||||
int endMargin = Math.max(mHeaderTextMarginEnd, iconWidth);
|
||||
if (totalWidth > givenWidth - endMargin) {
|
||||
int overFlow = totalWidth - givenWidth + endMargin;
|
||||
// We are overflowing, lets shrink the app name first
|
||||
overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
|
||||
mChildMinWidth);
|
||||
|
||||
// still overflowing, we shrink the header text
|
||||
overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mHeaderText, 0);
|
||||
|
||||
// still overflowing, finally we shrink the secondary header text
|
||||
shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
|
||||
0);
|
||||
}
|
||||
setMeasuredDimension(givenWidth, givenHeight);
|
||||
}
|
||||
|
||||
private int shrinkViewForOverflow(int heightSpec, int overFlow, View targetView,
|
||||
int minimumWidth) {
|
||||
final int oldWidth = targetView.getMeasuredWidth();
|
||||
if (overFlow > 0 && targetView.getVisibility() != GONE && oldWidth > minimumWidth) {
|
||||
// we're still too big
|
||||
int newSize = Math.max(minimumWidth, oldWidth - overFlow);
|
||||
int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
|
||||
targetView.measure(childWidthSpec, heightSpec);
|
||||
overFlow -= oldWidth - newSize;
|
||||
}
|
||||
return overFlow;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int left = getPaddingStart();
|
||||
int end = getMeasuredWidth();
|
||||
int childCount = getChildCount();
|
||||
int ownHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
int childHeight = child.getMeasuredHeight();
|
||||
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
|
||||
int layoutLeft;
|
||||
int layoutRight;
|
||||
int top = (int) (getPaddingTop() + (ownHeight - childHeight) / 2.0f);
|
||||
int bottom = top + childHeight;
|
||||
// Icons that should go at the end
|
||||
if (mIconsAtEnd.contains(child)) {
|
||||
if (end == getMeasuredWidth()) {
|
||||
layoutRight = end - mContentEndMargin;
|
||||
} else {
|
||||
layoutRight = end - params.getMarginEnd();
|
||||
}
|
||||
layoutLeft = layoutRight - child.getMeasuredWidth();
|
||||
end = layoutLeft - params.getMarginStart();
|
||||
} else {
|
||||
left += params.getMarginStart();
|
||||
int right = left + child.getMeasuredWidth();
|
||||
layoutLeft = left;
|
||||
layoutRight = right;
|
||||
left = right + params.getMarginEnd();
|
||||
}
|
||||
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
|
||||
int ltrLeft = layoutLeft;
|
||||
layoutLeft = getWidth() - layoutRight;
|
||||
layoutRight = getWidth() - ltrLeft;
|
||||
}
|
||||
child.layout(layoutLeft, top, layoutRight, bottom);
|
||||
}
|
||||
updateTouchListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new MarginLayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
private void updateTouchListener() {
|
||||
if (mFeedbackListener == null) {
|
||||
setOnTouchListener(null);
|
||||
return;
|
||||
}
|
||||
setOnTouchListener(mTouchListener);
|
||||
mTouchListener.bindTouchRects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets onclick listener for feedback icon.
|
||||
*/
|
||||
public void setFeedbackOnClickListener(OnClickListener l) {
|
||||
mFeedbackListener = l;
|
||||
mFeedbackIcon.setOnClickListener(mFeedbackListener);
|
||||
updateTouchListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the margin end for the text portion of the header, excluding right-aligned elements
|
||||
*
|
||||
* @param headerTextMarginEnd margin size
|
||||
*/
|
||||
public void setHeaderTextMarginEnd(int headerTextMarginEnd) {
|
||||
if (mHeaderTextMarginEnd != headerTextMarginEnd) {
|
||||
mHeaderTextMarginEnd = headerTextMarginEnd;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current margin end value for the header text
|
||||
*
|
||||
* @return margin size
|
||||
*/
|
||||
public int getHeaderTextMarginEnd() {
|
||||
return mHeaderTextMarginEnd;
|
||||
}
|
||||
|
||||
private class HeaderTouchListener implements OnTouchListener {
|
||||
|
||||
private Rect mFeedbackRect;
|
||||
private int mTouchSlop;
|
||||
private boolean mTrackGesture;
|
||||
private float mDownX;
|
||||
private float mDownY;
|
||||
|
||||
HeaderTouchListener() {
|
||||
}
|
||||
|
||||
public void bindTouchRects() {
|
||||
mFeedbackRect = getRectAroundView(mFeedbackIcon);
|
||||
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
}
|
||||
|
||||
private Rect getRectAroundView(View view) {
|
||||
float size = 48 * getResources().getDisplayMetrics().density;
|
||||
float width = Math.max(size, view.getWidth());
|
||||
float height = Math.max(size, view.getHeight());
|
||||
final Rect r = new Rect();
|
||||
if (view.getVisibility() == GONE) {
|
||||
view = getFirstChildNotGone();
|
||||
r.left = (int) (view.getLeft() - width / 2.0f);
|
||||
} else {
|
||||
r.left = (int) ((view.getLeft() + view.getRight()) / 2.0f - width / 2.0f);
|
||||
}
|
||||
r.top = (int) ((view.getTop() + view.getBottom()) / 2.0f - height / 2.0f);
|
||||
r.bottom = (int) (r.top + height);
|
||||
r.right = (int) (r.left + width);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
switch (event.getActionMasked() & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mTrackGesture = false;
|
||||
if (isInside(x, y)) {
|
||||
mDownX = x;
|
||||
mDownY = y;
|
||||
mTrackGesture = true;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (mTrackGesture) {
|
||||
if (Math.abs(mDownX - x) > mTouchSlop
|
||||
|| Math.abs(mDownY - y) > mTouchSlop) {
|
||||
mTrackGesture = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mTrackGesture && onTouchUp(x, y, mDownX, mDownY)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return mTrackGesture;
|
||||
}
|
||||
|
||||
private boolean onTouchUp(float upX, float upY, float downX, float downY) {
|
||||
if (mFeedbackIcon.isVisibleToUser()
|
||||
&& (mFeedbackRect.contains((int) upX, (int) upY)
|
||||
|| mFeedbackRect.contains((int) downX, (int) downY))) {
|
||||
mFeedbackIcon.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isInside(float x, float y) {
|
||||
return mFeedbackRect.contains((int) x, (int) y);
|
||||
}
|
||||
}
|
||||
|
||||
private View getFirstChildNotGone() {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() != GONE) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlappingRendering() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given point is touching an active part of the top line.
|
||||
*/
|
||||
public boolean isInTouchRect(float x, float y) {
|
||||
if (mFeedbackListener == null) {
|
||||
return false;
|
||||
}
|
||||
return mTouchListener.isInside(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a click on an active part of the top line, if touching.
|
||||
*/
|
||||
public boolean onTouchUp(float upX, float upY, float downX, float downY) {
|
||||
if (mFeedbackListener == null) {
|
||||
return false;
|
||||
}
|
||||
return mTouchListener.onTouchUp(upX, upY, downX, downY);
|
||||
}
|
||||
}
|
||||
@@ -38,81 +38,7 @@
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
</FrameLayout>
|
||||
<TextView
|
||||
android:id="@+id/app_name_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_app_name_margin_start"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:visibility="?attr/notificationHeaderAppNameVisibility"
|
||||
android:singleLine="true"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/header_text_secondary_divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:text="@string/notification_header_divider_symbol"
|
||||
android:visibility="gone"/>
|
||||
<TextView
|
||||
android:id="@+id/header_text_secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:visibility="gone"
|
||||
android:singleLine="true"/>
|
||||
<TextView
|
||||
android:id="@+id/header_text_divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:text="@string/notification_header_divider_symbol"
|
||||
android:visibility="gone"/>
|
||||
<TextView
|
||||
android:id="@+id/header_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:visibility="gone"
|
||||
android:singleLine="true"/>
|
||||
<TextView
|
||||
android:id="@+id/time_divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:text="@string/notification_header_divider_symbol"
|
||||
android:singleLine="true"
|
||||
android:visibility="gone"/>
|
||||
<DateTimeView
|
||||
android:id="@+id/time"
|
||||
android:textAppearance="@style/TextAppearance.Material.Notification.Time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:showRelative="true"
|
||||
android:singleLine="true"
|
||||
android:visibility="gone" />
|
||||
<ViewStub
|
||||
android:id="@+id/chronometer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:layout="@layout/notification_template_part_chronometer"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
<include layout="@layout/notification_template_top_line" />
|
||||
<com.android.internal.widget.NotificationExpandButton
|
||||
android:id="@+id/expand_button"
|
||||
android:background="@null"
|
||||
@@ -123,42 +49,5 @@
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/expand_button_content_description_collapsed"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/alerted_icon"
|
||||
android:layout_width="@dimen/notification_alerted_size"
|
||||
android:layout_height="@dimen/notification_alerted_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="4dp"
|
||||
android:paddingTop="1dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_alerted_content_description"
|
||||
android:src="@drawable/ic_notifications_alerted"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/feedback"
|
||||
android:layout_width="@dimen/notification_feedback_size"
|
||||
android:layout_height="@dimen/notification_feedback_size"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_feedback_indicator"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_feedback_indicator"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/profile_badge"
|
||||
android:layout_width="@dimen/notification_badge_size"
|
||||
android:layout_height="@dimen/notification_badge_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="4dp"
|
||||
android:paddingTop="1dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_work_profile_content_description"
|
||||
/>
|
||||
</NotificationHeaderView>
|
||||
|
||||
|
||||
139
core/res/res/layout/notification_template_top_line.xml
Normal file
139
core/res/res/layout/notification_template_top_line.xml
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 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
|
||||
-->
|
||||
<!-- extends ViewGroup -->
|
||||
<NotificationTopLineView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:theme="@style/Theme.DeviceDefault.Notification"
|
||||
android:id="@+id/notification_top_line"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/notification_header_height"
|
||||
android:clipChildren="false"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/app_name_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_app_name_margin_start"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:visibility="?attr/notificationHeaderAppNameVisibility"
|
||||
android:singleLine="true"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/header_text_secondary_divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:text="@string/notification_header_divider_symbol"
|
||||
android:visibility="gone"/>
|
||||
<TextView
|
||||
android:id="@+id/header_text_secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:visibility="gone"
|
||||
android:singleLine="true"/>
|
||||
<TextView
|
||||
android:id="@+id/header_text_divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:text="@string/notification_header_divider_symbol"
|
||||
android:visibility="gone"/>
|
||||
<TextView
|
||||
android:id="@+id/header_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:visibility="gone"
|
||||
android:singleLine="true"/>
|
||||
<TextView
|
||||
android:id="@+id/time_divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/notificationHeaderTextAppearance"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:text="@string/notification_header_divider_symbol"
|
||||
android:singleLine="true"
|
||||
android:visibility="gone"/>
|
||||
<DateTimeView
|
||||
android:id="@+id/time"
|
||||
android:textAppearance="@style/TextAppearance.Material.Notification.Time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:showRelative="true"
|
||||
android:singleLine="true"
|
||||
android:visibility="gone" />
|
||||
<ViewStub
|
||||
android:id="@+id/chronometer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_marginEnd="@dimen/notification_header_separating_margin"
|
||||
android:layout="@layout/notification_template_part_chronometer"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/alerted_icon"
|
||||
android:layout_width="@dimen/notification_alerted_size"
|
||||
android:layout_height="@dimen/notification_alerted_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="4dp"
|
||||
android:paddingTop="1dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_alerted_content_description"
|
||||
android:src="@drawable/ic_notifications_alerted"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/feedback"
|
||||
android:layout_width="@dimen/notification_feedback_size"
|
||||
android:layout_height="@dimen/notification_feedback_size"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:paddingTop="2dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_feedback_indicator"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_feedback_indicator"
|
||||
/>
|
||||
<ImageView
|
||||
android:id="@+id/profile_badge"
|
||||
android:layout_width="@dimen/notification_badge_size"
|
||||
android:layout_height="@dimen/notification_badge_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="4dp"
|
||||
android:paddingTop="1dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_work_profile_content_description"
|
||||
/>
|
||||
</NotificationTopLineView>
|
||||
|
||||
@@ -2850,6 +2850,7 @@
|
||||
<java-symbol type="id" name="header_text_secondary" />
|
||||
<java-symbol type="id" name="expand_button" />
|
||||
<java-symbol type="id" name="notification_header" />
|
||||
<java-symbol type="id" name="notification_top_line" />
|
||||
<java-symbol type="id" name="time_divider" />
|
||||
<java-symbol type="id" name="header_text_divider" />
|
||||
<java-symbol type="id" name="header_text_secondary_divider" />
|
||||
|
||||
@@ -22,8 +22,10 @@ import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.util.ArraySet;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.NotificationTopLineView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -44,7 +46,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Wraps a notification header view.
|
||||
* Wraps a notification view which may or may not include a header.
|
||||
*/
|
||||
public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
|
||||
@@ -56,6 +58,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
private CachingIconView mIcon;
|
||||
private NotificationExpandButton mExpandButton;
|
||||
protected NotificationHeaderView mNotificationHeader;
|
||||
protected NotificationTopLineView mNotificationTopLine;
|
||||
private TextView mHeaderText;
|
||||
private TextView mAppNameText;
|
||||
private ImageView mWorkProfileImage;
|
||||
@@ -107,14 +110,15 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
|
||||
mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
|
||||
mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
|
||||
mNotificationTopLine = mView.findViewById(com.android.internal.R.id.notification_top_line);
|
||||
mAudiblyAlertedIcon = mView.findViewById(com.android.internal.R.id.alerted_icon);
|
||||
mFeedbackIcon = mView.findViewById(com.android.internal.R.id.feedback);
|
||||
}
|
||||
|
||||
private void addFeedbackOnClickListener(ExpandableNotificationRow row) {
|
||||
View.OnClickListener listener = row.getFeedbackOnClickListener();
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.setFeedbackOnClickListener(listener);
|
||||
if (mNotificationTopLine != null) {
|
||||
mNotificationTopLine.setFeedbackOnClickListener(listener);
|
||||
}
|
||||
if (mFeedbackIcon != null) {
|
||||
mFeedbackIcon.setOnClickListener(listener);
|
||||
@@ -158,13 +162,11 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
mAppNameText.setTextAppearance(
|
||||
com.android.internal.R.style
|
||||
.TextAppearance_DeviceDefault_Notification_Conversation_AppName);
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mAppNameText.getLayoutParams();
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mAppNameText.getLayoutParams();
|
||||
layoutParams.setMarginStart(0);
|
||||
}
|
||||
if (mIconContainer != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIconContainer.getLayoutParams();
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mIconContainer.getLayoutParams();
|
||||
layoutParams.width =
|
||||
mIconContainer.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.conversation_content_start);
|
||||
@@ -174,8 +176,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
layoutParams.setMarginStart(marginStart * -1);
|
||||
}
|
||||
if (mIcon != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIcon.getLayoutParams();
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mIcon.getLayoutParams();
|
||||
layoutParams.setMarginEnd(0);
|
||||
}
|
||||
}
|
||||
@@ -187,21 +188,18 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
com.android.internal.R.attr.notificationHeaderTextAppearance,
|
||||
com.android.internal.R.style.TextAppearance_DeviceDefault_Notification_Info);
|
||||
mAppNameText.setTextAppearance(textAppearance);
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mAppNameText.getLayoutParams();
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mAppNameText.getLayoutParams();
|
||||
final int marginStart = mAppNameText.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_header_app_name_margin_start);
|
||||
layoutParams.setMarginStart(marginStart);
|
||||
}
|
||||
if (mIconContainer != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIconContainer.getLayoutParams();
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mIconContainer.getLayoutParams();
|
||||
layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
layoutParams.setMarginStart(0);
|
||||
}
|
||||
if (mIcon != null) {
|
||||
ViewGroup.MarginLayoutParams layoutParams =
|
||||
(ViewGroup.MarginLayoutParams) mIcon.getLayoutParams();
|
||||
MarginLayoutParams layoutParams = (MarginLayoutParams) mIcon.getLayoutParams();
|
||||
final int marginEnd = mIcon.getContext().getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.notification_header_icon_margin_end);
|
||||
layoutParams.setMarginEnd(marginEnd);
|
||||
@@ -261,6 +259,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
@Override
|
||||
public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {
|
||||
mExpandButton.setVisibility(expandable ? View.VISIBLE : View.GONE);
|
||||
mExpandButton.setOnClickListener(expandable ? onClickListener : null);
|
||||
if (mNotificationHeader != null) {
|
||||
mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user