Merge "Merge "Notification MessagingStyle: Add handset views" into nyc-dev am: 4db2f1f" into nyc-dev-plus-aosp
This commit is contained in:
committed by
Android (Google) Code Review
commit
34f82ca733
@@ -29,6 +29,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
@@ -43,6 +44,7 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
@@ -588,8 +590,8 @@ public class Notification implements Parcelable
|
||||
private static final int COLOR_INVALID = 1;
|
||||
|
||||
/**
|
||||
* Sphere of visibility of this notification, which affects how and when the SystemUI reveals
|
||||
* the notification's presence and contents in untrusted situations (namely, on the secure
|
||||
* Sphere of visibility of this notification, which affects how and when the SystemUI reveals
|
||||
* the notification's presence and contents in untrusted situations (namely, on the secure
|
||||
* lockscreen).
|
||||
*
|
||||
* The default level, {@link #VISIBILITY_PRIVATE}, behaves exactly as notifications have always
|
||||
@@ -2227,7 +2229,8 @@ public class Notification implements Parcelable
|
||||
Log.d(TAG, "Unknown style class: " + templateClass);
|
||||
} else {
|
||||
try {
|
||||
final Constructor<? extends Style> ctor = styleClass.getConstructor();
|
||||
final Constructor<? extends Style> ctor =
|
||||
styleClass.getDeclaredConstructor();
|
||||
ctor.setAccessible(true);
|
||||
final Style style = ctor.newInstance();
|
||||
style.restoreFromExtras(mN.extras);
|
||||
@@ -3126,6 +3129,18 @@ public class Notification implements Parcelable
|
||||
* @param hasProgress whether the progress bar should be shown and set
|
||||
*/
|
||||
private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
|
||||
final Bundle ex = mN.extras;
|
||||
|
||||
CharSequence title = processLegacyText(ex.getCharSequence(EXTRA_TITLE));
|
||||
CharSequence text = processLegacyText(ex.getCharSequence(EXTRA_TEXT));
|
||||
return applyStandardTemplate(resId, hasProgress, title, text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hasProgress whether the progress bar should be shown and set
|
||||
*/
|
||||
private RemoteViews applyStandardTemplate(int resId, boolean hasProgress,
|
||||
CharSequence title, CharSequence text) {
|
||||
RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
|
||||
|
||||
resetStandardTemplate(contentView);
|
||||
@@ -3134,17 +3149,15 @@ public class Notification implements Parcelable
|
||||
|
||||
bindNotificationHeader(contentView);
|
||||
bindLargeIcon(contentView);
|
||||
if (ex.getCharSequence(EXTRA_TITLE) != null) {
|
||||
if (title != null) {
|
||||
contentView.setViewVisibility(R.id.title, View.VISIBLE);
|
||||
contentView.setTextViewText(R.id.title,
|
||||
processLegacyText(ex.getCharSequence(EXTRA_TITLE)));
|
||||
contentView.setTextViewText(R.id.title, title);
|
||||
}
|
||||
boolean showProgress = handleProgressBar(hasProgress, contentView, ex);
|
||||
if (ex.getCharSequence(EXTRA_TEXT) != null) {
|
||||
if (text != null) {
|
||||
int textId = showProgress ? com.android.internal.R.id.text_line_1
|
||||
: com.android.internal.R.id.text;
|
||||
contentView.setTextViewText(textId, processLegacyText(
|
||||
ex.getCharSequence(EXTRA_TEXT)));
|
||||
contentView.setTextViewText(textId, text);
|
||||
contentView.setViewVisibility(textId, View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -3749,6 +3762,10 @@ public class Notification implements Parcelable
|
||||
return R.layout.notification_template_material_inbox;
|
||||
}
|
||||
|
||||
private int getMessagingLayoutResource() {
|
||||
return R.layout.notification_template_material_messaging;
|
||||
}
|
||||
|
||||
private int getActionLayoutResource() {
|
||||
return R.layout.notification_material_action;
|
||||
}
|
||||
@@ -4375,13 +4392,100 @@ public class Notification implements Parcelable
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public RemoteViews makeBigContentView() {
|
||||
// TODO handset to write implementation
|
||||
RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
|
||||
@Override
|
||||
public RemoteViews makeContentView() {
|
||||
Message m = findLatestIncomingMessage();
|
||||
CharSequence title = mConversationTitle != null
|
||||
? mConversationTitle
|
||||
: (m == null) ? null : m.mSender;
|
||||
CharSequence text = (m == null)
|
||||
? null
|
||||
: mConversationTitle != null ? makeMessageLine(m) : m.mText;
|
||||
|
||||
return mBuilder.applyStandardTemplate(mBuilder.getBaseLayoutResource(),
|
||||
false /* hasProgress */,
|
||||
title,
|
||||
text);
|
||||
}
|
||||
|
||||
private Message findLatestIncomingMessage() {
|
||||
for (int i = mMessages.size() - 1; i >= 0; i--) {
|
||||
Message m = mMessages.get(i);
|
||||
// Incoming messages have a non-empty sender.
|
||||
if (!TextUtils.isEmpty(m.mSender)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public RemoteViews makeBigContentView() {
|
||||
CharSequence title = !TextUtils.isEmpty(super.mBigContentTitle)
|
||||
? super.mBigContentTitle
|
||||
: mConversationTitle;
|
||||
boolean hasTitle = !TextUtils.isEmpty(title);
|
||||
|
||||
RemoteViews contentView = mBuilder.applyStandardTemplate(
|
||||
mBuilder.getMessagingLayoutResource(),
|
||||
false /* hasProgress */,
|
||||
title,
|
||||
null /* text */);
|
||||
|
||||
int[] rowIds = {R.id.inbox_text0, R.id.inbox_text1, R.id.inbox_text2, R.id.inbox_text3,
|
||||
R.id.inbox_text4, R.id.inbox_text5, R.id.inbox_text6};
|
||||
|
||||
// Make sure all rows are gone in case we reuse a view.
|
||||
for (int rowId : rowIds) {
|
||||
contentView.setViewVisibility(rowId, View.GONE);
|
||||
}
|
||||
|
||||
int i=0;
|
||||
int titlePadding = mBuilder.mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.notification_messaging_spacing);
|
||||
contentView.setViewLayoutMarginBottom(R.id.line1, hasTitle ? titlePadding : 0);
|
||||
contentView.setInt(R.id.notification_messaging, "setNumIndentLines",
|
||||
mBuilder.mN.mLargeIcon == null ? 0 : (hasTitle ? 1 : 2));
|
||||
|
||||
int firstMessage = Math.max(0, mMessages.size() - rowIds.length);
|
||||
while (firstMessage + i < mMessages.size() && i < rowIds.length) {
|
||||
Message m = mMessages.get(firstMessage + i);
|
||||
int rowId = rowIds[i];
|
||||
|
||||
contentView.setViewVisibility(rowId, View.VISIBLE);
|
||||
contentView.setTextViewText(rowId, makeMessageLine(m));
|
||||
|
||||
i++;
|
||||
}
|
||||
return contentView;
|
||||
}
|
||||
|
||||
private CharSequence makeMessageLine(Message m) {
|
||||
BidiFormatter bidi = BidiFormatter.getInstance();
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
if (TextUtils.isEmpty(m.mSender)) {
|
||||
CharSequence replyName = mUserDisplayName == null ? "" : mUserDisplayName;
|
||||
sb.append(bidi.unicodeWrap(replyName),
|
||||
makeFontColorSpan(mBuilder.resolveContrastColor()),
|
||||
0 /* flags */);
|
||||
} else {
|
||||
sb.append(bidi.unicodeWrap(m.mSender),
|
||||
makeFontColorSpan(Color.BLACK),
|
||||
0 /* flags */);
|
||||
}
|
||||
CharSequence text = m.mText == null ? "" : m.mText;
|
||||
sb.append(" ").append(bidi.unicodeWrap(text));
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static TextAppearanceSpan makeFontColorSpan(int color) {
|
||||
return new TextAppearanceSpan(null, 0, 0,
|
||||
ColorStateList.valueOf(color), null);
|
||||
}
|
||||
|
||||
public static final class Message implements Parcelable {
|
||||
|
||||
private final CharSequence mText;
|
||||
|
||||
@@ -1856,6 +1856,7 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
public static final int LAYOUT_MARGIN_END = 1;
|
||||
/** Set width */
|
||||
public static final int LAYOUT_WIDTH = 2;
|
||||
public static final int LAYOUT_MARGIN_BOTTOM = 3;
|
||||
|
||||
/**
|
||||
* @param viewId ID of the view alter
|
||||
@@ -1898,6 +1899,12 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
target.setLayoutParams(layoutParams);
|
||||
}
|
||||
break;
|
||||
case LAYOUT_MARGIN_BOTTOM:
|
||||
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
|
||||
((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = value;
|
||||
target.setLayoutParams(layoutParams);
|
||||
}
|
||||
break;
|
||||
case LAYOUT_WIDTH:
|
||||
layoutParams.width = value;
|
||||
target.setLayoutParams(layoutParams);
|
||||
@@ -2869,6 +2876,16 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END, endMargin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to setting {@link android.view.ViewGroup.MarginLayoutParams#bottomMargin}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void setViewLayoutMarginBottom(int viewId, int bottomMargin) {
|
||||
addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM,
|
||||
bottomMargin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to setting {@link android.view.ViewGroup.LayoutParams#width}.
|
||||
* @hide
|
||||
|
||||
@@ -16,13 +16,18 @@
|
||||
|
||||
package com.android.internal.widget;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.BoringLayout;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.RemotableViewMethod;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.TextView;
|
||||
@@ -35,7 +40,8 @@ import android.widget.TextView;
|
||||
@RemoteViews.RemoteView
|
||||
public class ImageFloatingTextView extends TextView {
|
||||
|
||||
private boolean mHasImage;
|
||||
/** Number of lines from the top to indent */
|
||||
private int mIndentLines;
|
||||
|
||||
public ImageFloatingTextView(Context context) {
|
||||
this(context, null);
|
||||
@@ -69,10 +75,16 @@ public class ImageFloatingTextView extends TextView {
|
||||
.setEllipsizedWidth(ellipsisWidth)
|
||||
.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
|
||||
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
|
||||
// we set the endmargin on the first 2 lines. this works just in our case but that's
|
||||
// sufficient for now.
|
||||
int endMargin = (int) (getResources().getDisplayMetrics().density * 52);
|
||||
int[] margins = mHasImage ? new int[] {endMargin, endMargin, 0} : null;
|
||||
// we set the endmargin on the requested number of lines.
|
||||
int endMargin = getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.notification_content_picture_margin);
|
||||
int[] margins = null;
|
||||
if (mIndentLines > 0) {
|
||||
margins = new int[mIndentLines + 1];
|
||||
for (int i = 0; i < mIndentLines; i++) {
|
||||
margins[i] = endMargin;
|
||||
}
|
||||
}
|
||||
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
|
||||
builder.setIndents(margins, null);
|
||||
} else {
|
||||
@@ -84,8 +96,22 @@ public class ImageFloatingTextView extends TextView {
|
||||
|
||||
@RemotableViewMethod
|
||||
public void setHasImage(boolean hasImage) {
|
||||
mHasImage = hasImage;
|
||||
mIndentLines = hasImage ? 2 : 0;
|
||||
// The new layout will be automatically created when the text is
|
||||
// set again by the notification.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lines the number of lines at the top that should be indented by indentEnd
|
||||
* @return whether a change was made
|
||||
*/
|
||||
public boolean setNumIndentLines(int lines) {
|
||||
if (mIndentLines != lines) {
|
||||
mIndentLines = lines;
|
||||
// Invalidate layout.
|
||||
setHint(getHint());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
278
core/java/com/android/internal/widget/MessagingLinearLayout.java
Normal file
278
core/java/com/android/internal/widget/MessagingLinearLayout.java
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.internal.widget;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.RemotableViewMethod;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
/**
|
||||
* A custom-built layout for the Notification.MessagingStyle.
|
||||
*
|
||||
* Evicts children until they all fit.
|
||||
*/
|
||||
@RemoteViews.RemoteView
|
||||
public class MessagingLinearLayout extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Spacing to be applied between views.
|
||||
*/
|
||||
private int mSpacing;
|
||||
|
||||
/**
|
||||
* The maximum height allowed.
|
||||
*/
|
||||
private int mMaxHeight;
|
||||
|
||||
private int mIndentLines;
|
||||
|
||||
public MessagingLinearLayout(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.MessagingLinearLayout, 0,
|
||||
0);
|
||||
|
||||
final int N = a.getIndexCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
int attr = a.getIndex(i);
|
||||
switch (attr) {
|
||||
case R.styleable.MessagingLinearLayout_maxHeight:
|
||||
mMaxHeight = a.getDimensionPixelSize(i, 0);
|
||||
break;
|
||||
case R.styleable.MessagingLinearLayout_spacing:
|
||||
mSpacing = a.getDimensionPixelSize(i, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMaxHeight <= 0) {
|
||||
throw new IllegalStateException(
|
||||
"MessagingLinearLayout: Must specify positive maxHeight");
|
||||
}
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// This is essentially a bottom-up linear layout that only adds children that fit entirely
|
||||
// up to a maximum height.
|
||||
|
||||
switch (MeasureSpec.getMode(heightMeasureSpec)) {
|
||||
case MeasureSpec.AT_MOST:
|
||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
|
||||
Math.min(mMaxHeight, MeasureSpec.getSize(heightMeasureSpec)),
|
||||
MeasureSpec.AT_MOST);
|
||||
break;
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
|
||||
mMaxHeight,
|
||||
MeasureSpec.AT_MOST);
|
||||
break;
|
||||
case MeasureSpec.EXACTLY:
|
||||
break;
|
||||
}
|
||||
final int targetHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
final int count = getChildCount();
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
final View child = getChildAt(i);
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
lp.hide = true;
|
||||
}
|
||||
|
||||
int totalHeight = mPaddingTop + mPaddingBottom;
|
||||
boolean first = true;
|
||||
|
||||
// Starting from the bottom: we measure every view as if it were the only one. If it still
|
||||
// fits, we take it, otherwise we stop there.
|
||||
for (int i = count - 1; i >= 0 && totalHeight < targetHeight; i--) {
|
||||
if (getChildAt(i).getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
final View child = getChildAt(i);
|
||||
LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
|
||||
|
||||
if (child instanceof ImageFloatingTextView) {
|
||||
// Pretend we need the image padding for all views, we don't know which
|
||||
// one will end up needing to do this (might end up not using all the space,
|
||||
// but calculating this exactly would be more expensive).
|
||||
((ImageFloatingTextView) child).setNumIndentLines(mIndentLines);
|
||||
}
|
||||
|
||||
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
|
||||
|
||||
final int childHeight = child.getMeasuredHeight();
|
||||
int newHeight = Math.max(totalHeight, totalHeight + childHeight + lp.topMargin +
|
||||
lp.bottomMargin + (first ? 0 : mSpacing));
|
||||
first = false;
|
||||
|
||||
if (newHeight <= targetHeight) {
|
||||
totalHeight = newHeight;
|
||||
lp.hide = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know which views to take, fix up the indents and see what width we get.
|
||||
int measuredWidth = mPaddingLeft + mPaddingRight;
|
||||
int imageLines = mIndentLines;
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (child.getVisibility() == GONE || lp.hide) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child instanceof ImageFloatingTextView) {
|
||||
ImageFloatingTextView textChild = (ImageFloatingTextView) child;
|
||||
if (imageLines == 2 && textChild.getLineCount() > 2) {
|
||||
// HACK: If we need indent for two lines, and they're coming from the same
|
||||
// view, we need extra spacing to compensate for the lack of margins,
|
||||
// so add an extra line of indent.
|
||||
imageLines = 3;
|
||||
}
|
||||
boolean changed = textChild.setNumIndentLines(Math.max(0, imageLines));
|
||||
if (changed) {
|
||||
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
|
||||
}
|
||||
imageLines -= textChild.getLineCount();
|
||||
}
|
||||
|
||||
measuredWidth = Math.max(measuredWidth,
|
||||
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin
|
||||
+ mPaddingLeft + mPaddingRight);
|
||||
}
|
||||
|
||||
|
||||
setMeasuredDimension(
|
||||
resolveSize(Math.max(getSuggestedMinimumWidth(), measuredWidth),
|
||||
widthMeasureSpec),
|
||||
resolveSize(Math.max(getSuggestedMinimumHeight(), totalHeight),
|
||||
heightMeasureSpec));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
final int paddingLeft = mPaddingLeft;
|
||||
|
||||
int childTop;
|
||||
|
||||
// Where right end of child should go
|
||||
final int width = right - left;
|
||||
final int childRight = width - mPaddingRight;
|
||||
|
||||
final int layoutDirection = getLayoutDirection();
|
||||
final int count = getChildCount();
|
||||
|
||||
childTop = mPaddingTop;
|
||||
|
||||
boolean first = true;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (child.getVisibility() == GONE || lp.hide) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int childWidth = child.getMeasuredWidth();
|
||||
final int childHeight = child.getMeasuredHeight();
|
||||
|
||||
int childLeft;
|
||||
if (layoutDirection == LAYOUT_DIRECTION_RTL) {
|
||||
childLeft = childRight - childWidth - lp.rightMargin;
|
||||
} else {
|
||||
childLeft = paddingLeft + lp.leftMargin;
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
childTop += mSpacing;
|
||||
}
|
||||
|
||||
childTop += lp.topMargin;
|
||||
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
||||
|
||||
childTop += childHeight + lp.bottomMargin;
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
if (lp.hide) {
|
||||
return true;
|
||||
}
|
||||
return super.drawChild(canvas, child, drawingTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new LayoutParams(mContext, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateDefaultLayoutParams() {
|
||||
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
|
||||
LayoutParams copy = new LayoutParams(lp.width, lp.height);
|
||||
if (lp instanceof MarginLayoutParams) {
|
||||
copy.copyMarginsFrom((MarginLayoutParams) lp);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@RemotableViewMethod
|
||||
/**
|
||||
* Sets how many lines should be indented to avoid a floating image.
|
||||
*/
|
||||
public void setNumIndentLines(int numberLines) {
|
||||
mIndentLines = numberLines;
|
||||
}
|
||||
|
||||
public static class LayoutParams extends MarginLayoutParams {
|
||||
|
||||
boolean hide = false;
|
||||
|
||||
public LayoutParams(Context c, AttributeSet attrs) {
|
||||
super(c, attrs);
|
||||
}
|
||||
|
||||
public LayoutParams(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2016 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
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/status_bar_latest_event_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="messaging"
|
||||
>
|
||||
<include layout="@layout/notification_template_header" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="top"
|
||||
android:layout_marginTop="@dimen/notification_content_margin_top"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/notification_main_column"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:paddingStart="@dimen/notification_content_margin_start"
|
||||
android:paddingEnd="@dimen/notification_content_margin_end"
|
||||
android:minHeight="@dimen/notification_min_content_height"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
<include layout="@layout/notification_template_part_line1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.android.internal.widget.MessagingLinearLayout
|
||||
android:id="@+id/notification_messaging"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/notification_content_margin_bottom"
|
||||
android:spacing="@dimen/notification_messaging_spacing"
|
||||
android:maxHeight="212dp">
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text0"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text1"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text2"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text3"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text4"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text5"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text6"
|
||||
style="@style/Widget.Material.Notification.MessagingText"
|
||||
/>
|
||||
</com.android.internal.widget.MessagingLinearLayout>
|
||||
</LinearLayout>
|
||||
<include layout="@layout/notification_material_action_list" />
|
||||
</LinearLayout>
|
||||
<include layout="@layout/notification_template_right_icon" />
|
||||
</FrameLayout>
|
||||
@@ -16,9 +16,9 @@
|
||||
-->
|
||||
|
||||
<ImageView android:id="@+id/right_icon" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_width="@dimen/notification_large_icon_width"
|
||||
android:layout_height="@dimen/notification_large_icon_width"
|
||||
android:layout_marginEnd="@dimen/notification_content_margin_end"
|
||||
android:layout_marginTop="36dp"
|
||||
android:layout_gravity="top|end"
|
||||
android:scaleType="centerCrop"
|
||||
|
||||
@@ -8129,6 +8129,11 @@ i
|
||||
<attr name="maxCollapsedHeightSmall" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MessagingLinearLayout">
|
||||
<attr name="maxHeight" />
|
||||
<attr name="spacing" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="ResolverDrawerLayout_LayoutParams">
|
||||
<attr name="layout_alwaysShow" format="boolean" />
|
||||
<attr name="layout_ignoreOffset" format="boolean" />
|
||||
|
||||
@@ -162,9 +162,9 @@
|
||||
<dimen name="notification_min_height">92dp</dimen>
|
||||
|
||||
<!-- The width of the big icons in notifications. -->
|
||||
<dimen name="notification_large_icon_width">64dp</dimen>
|
||||
<dimen name="notification_large_icon_width">40dp</dimen>
|
||||
<!-- The width of the big icons in notifications. -->
|
||||
<dimen name="notification_large_icon_height">64dp</dimen>
|
||||
<dimen name="notification_large_icon_height">40dp</dimen>
|
||||
|
||||
<!-- The minimum width of the app name in the header if it shrinks -->
|
||||
<dimen name="notification_header_shrink_min_width">72dp</dimen>
|
||||
@@ -181,6 +181,9 @@
|
||||
<!-- The margin of the content to an image-->
|
||||
<dimen name="notification_content_image_margin_end">8dp</dimen>
|
||||
|
||||
<!-- The spacing between messages in Notification.MessagingStyle -->
|
||||
<dimen name="notification_messaging_spacing">6dp</dimen>
|
||||
|
||||
<!-- Preferred width of the search view. -->
|
||||
<dimen name="search_view_preferred_width">320dip</dimen>
|
||||
|
||||
|
||||
@@ -456,6 +456,14 @@ please see styles_device_defaults.xml.
|
||||
|
||||
<style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
|
||||
|
||||
<style name="Widget.Material.Notification.MessagingText" parent="Widget.Material.Light.TextView">
|
||||
<item name="layout_width">match_parent</item>
|
||||
<item name="layout_height">wrap_content</item>
|
||||
<item name="ellipsize">end</item>
|
||||
<item name="visibility">gone</item>
|
||||
<item name="textAppearance">@style/TextAppearance.Material.Notification</item>
|
||||
</style>
|
||||
|
||||
<!-- Widget Styles -->
|
||||
|
||||
<style name="Material"/>
|
||||
|
||||
@@ -2494,6 +2494,8 @@
|
||||
<java-symbol type="bool" name="config_strongAuthRequiredOnBoot" />
|
||||
|
||||
<java-symbol type="layout" name="app_anr_dialog" />
|
||||
<java-symbol type="layout" name="notification_template_material_messaging" />
|
||||
|
||||
<java-symbol type="id" name="aerr_wait" />
|
||||
|
||||
<java-symbol type="id" name="notification_content_container" />
|
||||
@@ -2523,12 +2525,16 @@
|
||||
<java-symbol type="string" name="carrier_app_notification_text" />
|
||||
<java-symbol type="string" name="negative_duration" />
|
||||
|
||||
<java-symbol type="dimen" name="notification_messaging_spacing" />
|
||||
|
||||
<!-- WallpaperManager config -->
|
||||
<java-symbol type="string" name="config_wallpaperCropperPackage" />
|
||||
|
||||
<java-symbol type="id" name="textSpacerNoTitle" />
|
||||
<java-symbol type="id" name="titleDividerNoCustom" />
|
||||
|
||||
<java-symbol type="id" name="notification_messaging" />
|
||||
|
||||
<java-symbol type="bool" name="config_sustainedPerformanceModeSupported" />
|
||||
|
||||
<!-- Wearable input extract edit view -->
|
||||
|
||||
Reference in New Issue
Block a user