diff --git a/res/drawable/compose_background.xml b/res/drawable/compose_background_dark.xml similarity index 62% rename from res/drawable/compose_background.xml rename to res/drawable/compose_background_dark.xml index 18b651b7f..c04badbf7 100644 --- a/res/drawable/compose_background.xml +++ b/res/drawable/compose_background_dark.xml @@ -5,10 +5,10 @@ + android:color="@color/core_dark_70" /> + android:color="@color/core_dark_85" /> diff --git a/res/drawable/compose_background_light.xml b/res/drawable/compose_background_light.xml new file mode 100644 index 000000000..b93c9edb7 --- /dev/null +++ b/res/drawable/compose_background_light.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/message_bubble_background_received_alone.xml b/res/drawable/message_bubble_background_received_alone.xml new file mode 100644 index 000000000..cda641b1d --- /dev/null +++ b/res/drawable/message_bubble_background_received_alone.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/res/drawable/message_bubble_background_received_end.xml b/res/drawable/message_bubble_background_received_end.xml new file mode 100644 index 000000000..3e4e2c056 --- /dev/null +++ b/res/drawable/message_bubble_background_received_end.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/res/drawable/message_bubble_background_received_middle.xml b/res/drawable/message_bubble_background_received_middle.xml new file mode 100644 index 000000000..e3888978a --- /dev/null +++ b/res/drawable/message_bubble_background_received_middle.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/res/drawable/message_bubble_background_received_start.xml b/res/drawable/message_bubble_background_received_start.xml new file mode 100644 index 000000000..4c30cc756 --- /dev/null +++ b/res/drawable/message_bubble_background_received_start.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/res/drawable/message_bubble_background_sent_alone.xml b/res/drawable/message_bubble_background_sent_alone.xml new file mode 100644 index 000000000..6f19f4f16 --- /dev/null +++ b/res/drawable/message_bubble_background_sent_alone.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/message_bubble_background_sent_end.xml b/res/drawable/message_bubble_background_sent_end.xml new file mode 100644 index 000000000..5bc4597c0 --- /dev/null +++ b/res/drawable/message_bubble_background_sent_end.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/message_bubble_background_sent_middle.xml b/res/drawable/message_bubble_background_sent_middle.xml new file mode 100644 index 000000000..aea426453 --- /dev/null +++ b/res/drawable/message_bubble_background_sent_middle.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/res/drawable/message_bubble_background_sent_start.xml b/res/drawable/message_bubble_background_sent_start.xml new file mode 100644 index 000000000..4719d235f --- /dev/null +++ b/res/drawable/message_bubble_background_sent_start.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/res/drawable/sticky_date_header_background.xml b/res/drawable/sticky_date_header_background_dark.xml similarity index 66% rename from res/drawable/sticky_date_header_background.xml rename to res/drawable/sticky_date_header_background_dark.xml index e4fa23267..d5be2c288 100644 --- a/res/drawable/sticky_date_header_background.xml +++ b/res/drawable/sticky_date_header_background_dark.xml @@ -4,5 +4,5 @@ android:shape="rectangle"> - + \ No newline at end of file diff --git a/res/drawable/sticky_date_header_background_light.xml b/res/drawable/sticky_date_header_background_light.xml new file mode 100644 index 000000000..b015b381b --- /dev/null +++ b/res/drawable/sticky_date_header_background_light.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/conversation_fragment.xml b/res/layout/conversation_fragment.xml index 41eac4b70..ab905ae02 100644 --- a/res/layout/conversation_fragment.xml +++ b/res/layout/conversation_fragment.xml @@ -28,7 +28,7 @@ style="@style/Signal.Text.Caption" android:textColor="?attr/conversation_item_sticky_date_text_color" android:textAllCaps="true" - android:background="@drawable/sticky_date_header_background" + android:background="?attr/conversation_item_sticky_date_background" android:elevation="9dp" android:visibility="gone" tools:text="March 1, 2015" /> diff --git a/res/layout/conversation_input_panel.xml b/res/layout/conversation_input_panel.xml index 70e43f220..c06879dc3 100644 --- a/res/layout/conversation_input_panel.xml +++ b/res/layout/conversation_input_panel.xml @@ -27,7 +27,7 @@ android:id="@+id/compose_bubble" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/compose_background" + android:background="?attr/conversation_input_background" android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical"> diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml index 91870ed9a..d5eee08bb 100644 --- a/res/layout/conversation_item_received.xml +++ b/res/layout/conversation_item_received.xml @@ -20,6 +20,8 @@ android:layout_height="wrap_content" android:layout_marginRight="@dimen/conversation_individual_right_gutter" android:layout_marginEnd="@dimen/conversation_individual_right_gutter" + android:paddingLeft="8dp" + android:paddingStart="8dp" android:clipToPadding="false" android:clipChildren="false"> @@ -28,31 +30,28 @@ android:foreground="@drawable/contact_photo_background" android:layout_width="36dp" android:layout_height="36dp" - android:layout_marginLeft="8dp" - android:layout_marginRight="8dp" android:layout_marginBottom="6dp" android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:cropToPadding="true" android:contentDescription="@string/conversation_item_received__contact_photo_description" /> - - - + android:clipChildren="false" + android:background="@color/white" + tools:backgroundTint="@color/conversation_blue"> - - - + - - + + + + + + + + + + + + + + + + + + + app:footer_color="?conversation_item_sent_text_secondary_color"/> - - - - - - - - - - - - - - - - - - - - - - - + - + android:layout_height="wrap_content" + android:orientation="horizontal"> + + + android:layout_marginLeft="8dp" + android:layout_marginStart="8dp" + android:layout_marginRight="8dp" + android:layout_marginEnd="8dp" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" + android:orientation="vertical" + android:layout_weight="1"> - + + android:layout_marginBottom="2dp" + android:orientation="horizontal" + android:gravity="center_vertical" + android:visibility="gone" + tools:visibility="visible"> - - - - - - - - - + - - - + tools:text="The-Amazing-Spider-Man.cba" /> - - - + android:layout_height="wrap_content" + android:layout_marginRight="8dp" + style="@style/Signal.Text.Caption" + android:textColor="@color/core_light_90" + android:paddingTop="4dp" + android:textStyle="italic" + android:visibility="gone" + tools:text="Photo" + tools:visibility="visible" /> - + - - - - - - + android:layout_height="match_parent"> - + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 0b6db57e4..039048083 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -28,8 +28,7 @@ - - + @@ -77,7 +76,7 @@ - + diff --git a/res/values/themes.xml b/res/values/themes.xml index 95936da31..c35309cc0 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -146,8 +146,7 @@ @color/core_white #22000000 #ff111111 - @color/core_light_02 - @color/core_light_10 + @drawable/compose_background_light @drawable/ic_send_sms_insecure @drawable/ic_send_push @color/white @@ -195,7 +194,7 @@ @color/core_light_60 @color/core_light_45 @color/core_light_90 - @color/core_light_02 + @drawable/sticky_date_header_background_light @color/core_light_60 @color/core_light_45 @@ -295,7 +294,7 @@ @color/core_dark_30 @color/core_dark_55 @color/core_dark_05 - @color/core_dark_85 + @drawable/sticky_date_header_background_dark @color/core_dark_30 @color/core_dark_60 @@ -319,8 +318,7 @@ @color/black #22ffffff #ffeeeeee - @color/core_dark_85 - @color/core_dark_70 + @drawable/compose_background_dark @drawable/ic_send_sms_insecure_dark @drawable/ic_send_push @color/black diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 5cad022cf..b6797811a 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -110,16 +110,16 @@ public class ConversationItem extends LinearLayout private Recipient recipient; private GlideRequests glideRequests; - protected CornerMaskingView bodyBubble; - private QuoteView quoteView; - private TextView bodyText; - private ConversationItemFooter footer; - private TextView groupSender; - private TextView groupSenderProfileName; - private View groupSenderHolder; - private AvatarImageView contactPhoto; - private AlertView alertView; - private ViewGroup container; + protected ViewGroup bodyBubble; + private QuoteView quoteView; + private TextView bodyText; + private ConversationItemFooter footer; + private TextView groupSender; + private TextView groupSenderProfileName; + private View groupSenderHolder; + private AvatarImageView contactPhoto; + private AlertView alertView; + private ViewGroup container; private @NonNull Set batchSelected = new HashSet<>(); private @NonNull Recipient conversationRecipient; @@ -203,7 +203,9 @@ public class ConversationItem extends LinearLayout this.recipient.addListener(this); this.conversationRecipient.addListener(this); - setMediaAttributes(messageRecord, nextMessageRecord, previousMessageRecord, conversationRecipient, groupThread); + setGutterSizes(messageRecord, groupThread); + setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread); + setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, conversationRecipient, groupThread); setInteractionState(messageRecord, pulseHighlight); setBodyText(messageRecord); setBubbleState(messageRecord); @@ -213,9 +215,7 @@ public class ConversationItem extends LinearLayout setAuthor(messageRecord, previousMessageRecord, nextMessageRecord, groupThread); setQuote(messageRecord, previousMessageRecord, nextMessageRecord, groupThread); setMessageSpacing(context, messageRecord, nextMessageRecord); - setGutterSizes(messageRecord, groupThread); setFooter(messageRecord, nextMessageRecord, locale, groupThread); - setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread); } @Override @@ -414,6 +414,8 @@ public class ConversationItem extends LinearLayout sharedContactStub.get().setOnClickListener(sharedContactClickListener); sharedContactStub.get().setOnLongClickListener(passthroughClickListener); + setSharedContactCorners(messageRecord, previousRecord, nextRecord, isGroupThread); + ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); footer.setVisibility(GONE); } else if (hasAudio(messageRecord)) { @@ -464,7 +466,7 @@ public class ConversationItem extends LinearLayout mediaThumbnailStub.get().setOnClickListener(passthroughClickListener); mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getDisplayBody())); - setThumbnailOutlineCorners(messageRecord, nextRecord, previousRecord, isGroupThread); + setThumbnailOutlineCorners(messageRecord, previousRecord, nextRecord, isGroupThread); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); footer.setVisibility(VISIBLE); @@ -537,6 +539,18 @@ public class ConversationItem extends LinearLayout mediaThumbnailStub.get().setOutlineCorners(topLeft, topRight, bottomRight, bottomLeft); } + private void setSharedContactCorners(@NonNull MessageRecord current, @NonNull Optional previous, @NonNull Optional next, boolean isGroupThread) { + if (isSingularMessage(current, previous, next, isGroupThread) || isEndOfMessageCluster(current, next, isGroupThread)) { + sharedContactStub.get().setSingularStyle(); + } else { + if (current.isOutgoing()) { + sharedContactStub.get().setClusteredOutgoingStyle(); + } else { + sharedContactStub.get().setClusteredIncomingStyle(); + } + } + } + private void setContactPhoto(@NonNull Recipient recipient) { if (contactPhoto == null) return; @@ -621,18 +635,10 @@ public class ConversationItem extends LinearLayout } private void setGutterSizes(@NonNull MessageRecord current, boolean isGroupThread) { - if (isGroupThread) { - if (current.isOutgoing()) { - ViewUtil.setLeftMargin(container, readDimen(R.dimen.conversation_group_left_gutter)); - } else { - ViewUtil.setLeftMargin(bodyBubble, readDimen(R.dimen.conversation_group_left_gutter)); - } - } else { - if (current.isOutgoing()) { - ViewUtil.setLeftMargin(container, readDimen(R.dimen.conversation_individual_left_gutter)); - } else { - ViewUtil.setLeftMargin(bodyBubble, readDimen(R.dimen.conversation_individual_left_gutter)); - } + if (isGroupThread && current.isOutgoing()) { + ViewUtil.setLeftMargin(container, readDimen(R.dimen.conversation_group_left_gutter)); + } else if (current.isOutgoing()) { + ViewUtil.setLeftMargin(container, readDimen(R.dimen.conversation_individual_left_gutter)); } } @@ -698,7 +704,7 @@ public class ConversationItem extends LinearLayout if (!next.isPresent() || next.get().isUpdate() || !current.getRecipient().getAddress().equals(next.get().getRecipient().getAddress())) { contactPhoto.setVisibility(VISIBLE); } else { - contactPhoto.setVisibility(GONE); + contactPhoto.setVisibility(INVISIBLE); } } else { groupSenderHolder.setVisibility(GONE); @@ -710,45 +716,22 @@ public class ConversationItem extends LinearLayout } private void setMessageShape(@NonNull MessageRecord current, @NonNull Optional previous, @NonNull Optional next, boolean isGroupThread) { + int background; if (isSingularMessage(current, previous, next, isGroupThread)) { - bodyBubble.setRadius(readDimen(R.dimen.message_corner_radius)); + background = current.isOutgoing() ? R.drawable.message_bubble_background_sent_alone + : R.drawable.message_bubble_background_received_alone; } else if (isStartOfMessageCluster(current, previous, isGroupThread)) { - if (current.isOutgoing()) { - bodyBubble.setRadii(readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_collapse_radius), - readDimen(R.dimen.message_corner_radius)); - } else { - bodyBubble.setRadii(readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_collapse_radius)); - } + background = current.isOutgoing() ? R.drawable.message_bubble_background_sent_start + : R.drawable.message_bubble_background_received_start; } else if (isEndOfMessageCluster(current, next, isGroupThread)) { - if (current.isOutgoing()) { - bodyBubble.setRadii(readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_collapse_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius)); - } else { - bodyBubble.setRadii(readDimen(R.dimen.message_corner_collapse_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius)); - } + background = current.isOutgoing() ? R.drawable.message_bubble_background_sent_end + : R.drawable.message_bubble_background_received_end; } else { - if (current.isOutgoing()) { - bodyBubble.setRadii(readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_collapse_radius), - readDimen(R.dimen.message_corner_collapse_radius), - readDimen(R.dimen.message_corner_radius)); - } else { - bodyBubble.setRadii(readDimen(R.dimen.message_corner_collapse_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_radius), - readDimen(R.dimen.message_corner_collapse_radius)); - } + background = current.isOutgoing() ? R.drawable.message_bubble_background_sent_middle + : R.drawable.message_bubble_background_received_middle; } + + bodyBubble.setBackgroundResource(background); } private boolean isStartOfMessageCluster(@NonNull MessageRecord current, @NonNull Optional previous, boolean isGroupThread) { diff --git a/src/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java b/src/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java index 83148e460..4d4356f90 100644 --- a/src/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java +++ b/src/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java @@ -48,6 +48,7 @@ public class ConversationItemThumbnail extends FrameLayout { private ImageView shade; private ConversationItemFooter footer; private Paint outlinePaint; + private CornerMask cornerMask; public ConversationItemThumbnail(Context context) { super(context); @@ -71,6 +72,7 @@ public class ConversationItemThumbnail extends FrameLayout { this.shade = findViewById(R.id.conversation_thumbnail_shade); this.footer = findViewById(R.id.conversation_thumbnail_footer); this.outlinePaint = ThemeUtil.isDarkTheme(getContext()) ? DARK_THEME_OUTLINE_PAINT : LIGHT_THEME_OUTLINE_PAINT; + this.cornerMask = new CornerMask(this); setTouchDelegate(thumbnail.getTouchDelegate()); @@ -87,8 +89,16 @@ public class ConversationItemThumbnail extends FrameLayout { @SuppressWarnings("SuspiciousNameCombination") @Override protected void dispatchDraw(Canvas canvas) { + if (cornerMask.isLegacy()) { + cornerMask.mask(canvas); + } + super.dispatchDraw(canvas); + if (!cornerMask.isLegacy()) { + cornerMask.mask(canvas); + } + final float halfStrokeWidth = outlinePaint.getStrokeWidth() / 2; bounds.left = halfStrokeWidth; @@ -137,6 +147,8 @@ public class ConversationItemThumbnail extends FrameLayout { radii[2] = radii[3] = topRight; radii[4] = radii[5] = bottomRight; radii[6] = radii[7] = bottomLeft; + + cornerMask.setRadii(topLeft, topRight, bottomRight, bottomLeft); } public ConversationItemFooter getFooter() { diff --git a/src/org/thoughtcrime/securesms/components/CornerMask.java b/src/org/thoughtcrime/securesms/components/CornerMask.java new file mode 100644 index 000000000..085df2557 --- /dev/null +++ b/src/org/thoughtcrime/securesms/components/CornerMask.java @@ -0,0 +1,88 @@ +package org.thoughtcrime.securesms.components; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.os.Build; +import android.support.annotation.NonNull; +import android.view.View; + +public class CornerMask { + + private final float[] radii = new float[8]; + private final Paint clearPaint = new Paint(); + private final Path outline = new Path(); + private final Path corners = new Path(); + private final RectF bounds = new RectF(); + + public CornerMask(@NonNull View view) { + if (isLegacy()) { + view.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } else { + view.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + + clearPaint.setColor(Color.BLACK); + clearPaint.setStyle(Paint.Style.FILL); + clearPaint.setAntiAlias(true); + clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } + + public void mask(Canvas canvas) { + bounds.left = 0; + bounds.top = 0; + bounds.right = canvas.getWidth(); + bounds.bottom = canvas.getHeight(); + + corners.reset(); + corners.addRoundRect(bounds, radii, Path.Direction.CW); + + // Note: There's a bug in the P beta where most PorterDuff modes aren't working. But CLEAR does. + // So we find and inverse path and use Mode.CLEAR for versions that support Path.op(). + // See issue https://issuetracker.google.com/issues/111394085. + if (!isLegacy()) { + outline.reset(); + outline.addRect(bounds, Path.Direction.CW); + outline.op(corners, Path.Op.DIFFERENCE); + canvas.drawPath(outline, clearPaint); + } else { + corners.addRoundRect(bounds, radii, Path.Direction.CW); + canvas.clipPath(corners); + } + } + + public boolean isLegacy() { + return Build.VERSION.SDK_INT < 19; + } + + public void setRadius(int radius) { + setRadii(radius, radius, radius, radius); + } + + public void setRadii(int topLeft, int topRight, int bottomRight, int bottomLeft) { + radii[0] = radii[1] = topLeft; + radii[2] = radii[3] = topRight; + radii[4] = radii[5] = bottomRight; + radii[6] = radii[7] = bottomLeft; + } + + public void setTopLeftRadius(int radius) { + radii[0] = radii[1] = radius; + } + + public void setTopRightRadius(int radius) { + radii[2] = radii[3] = radius; + } + + public void setBottomRightRadius(int radius) { + radii[4] = radii[5] = radius; + } + + public void setBottomLeftRadius(int radius) { + radii[6] = radii[7] = radius; + } +} diff --git a/src/org/thoughtcrime/securesms/components/QuoteView.java b/src/org/thoughtcrime/securesms/components/QuoteView.java index c2dbcbc99..8222c1062 100644 --- a/src/org/thoughtcrime/securesms/components/QuoteView.java +++ b/src/org/thoughtcrime/securesms/components/QuoteView.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Canvas; import android.graphics.Color; import android.os.Build; import android.support.annotation.NonNull; @@ -40,25 +41,25 @@ public class QuoteView extends LinearLayout implements RecipientModifiedListener private static final int MESSAGE_TYPE_OUTGOING = 1; private static final int MESSAGE_TYPE_INCOMING = 2; - private CornerMaskingView rootView; - private View backgroundView; - private TextView authorView; - private TextView bodyView; - private ImageView quoteBarView; - private ImageView thumbnailView; - private View attachmentVideoOverlayView; - private ViewGroup attachmentContainerView; - private TextView attachmentNameView; - private ImageView dismissView; + private ViewGroup rootView; + private TextView authorView; + private TextView bodyView; + private ImageView quoteBarView; + private ImageView thumbnailView; + private View attachmentVideoOverlayView; + private ViewGroup attachmentContainerView; + private TextView attachmentNameView; + private ImageView dismissView; - private long id; - private Recipient author; - private String body; - private TextView mediaDescriptionText; - private SlideDeck attachments; - private int messageType; - private int largeCornerRadius; - private int smallCornerRadius; + private long id; + private Recipient author; + private String body; + private TextView mediaDescriptionText; + private SlideDeck attachments; + private int messageType; + private int largeCornerRadius; + private int smallCornerRadius; + private CornerMask cornerMask; public QuoteView(Context context) { @@ -86,7 +87,6 @@ public class QuoteView extends LinearLayout implements RecipientModifiedListener inflate(getContext(), R.layout.quote_view, this); this.rootView = findViewById(R.id.quote_root); - this.backgroundView = findViewById(R.id.quote_background); this.authorView = findViewById(R.id.quote_author); this.bodyView = findViewById(R.id.quote_text); this.quoteBarView = findViewById(R.id.quote_bar); @@ -99,7 +99,8 @@ public class QuoteView extends LinearLayout implements RecipientModifiedListener this.largeCornerRadius = getResources().getDimensionPixelSize(R.dimen.quote_corner_radius_large); this.smallCornerRadius = getResources().getDimensionPixelSize(R.dimen.quote_corner_radius_bottom); - rootView.setRadii(largeCornerRadius, largeCornerRadius, smallCornerRadius, smallCornerRadius); + cornerMask = new CornerMask(this); + cornerMask.setRadii(largeCornerRadius, largeCornerRadius, smallCornerRadius, smallCornerRadius); if (attrs != null) { TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.QuoteView, 0, 0); @@ -117,16 +118,31 @@ public class QuoteView extends LinearLayout implements RecipientModifiedListener if (messageType == MESSAGE_TYPE_PREVIEW) { int radius = getResources().getDimensionPixelOffset(R.dimen.quote_corner_radius_preview); - rootView.setTopLeftRadius(radius); - rootView.setTopRightRadius(radius); + cornerMask.setTopLeftRadius(radius); + cornerMask.setTopRightRadius(radius); } } dismissView.setOnClickListener(view -> setVisibility(GONE)); - setWillNotDraw(false); - if (Build.VERSION.SDK_INT < 18) { - setLayerType(View.LAYER_TYPE_SOFTWARE, null); + if (cornerMask.isLegacy()) { + setWillNotDraw(false); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (cornerMask.isLegacy()) { + cornerMask.mask(canvas); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (!cornerMask.isLegacy()) { + cornerMask.mask(canvas); } } @@ -145,8 +161,8 @@ public class QuoteView extends LinearLayout implements RecipientModifiedListener } public void setTopCornerSizes(boolean topLeftLarge, boolean topRightLarge) { - rootView.setTopLeftRadius(topLeftLarge ? largeCornerRadius : smallCornerRadius); - rootView.setTopRightRadius(topRightLarge ? largeCornerRadius : smallCornerRadius); + cornerMask.setTopLeftRadius(topLeftLarge ? largeCornerRadius : smallCornerRadius); + cornerMask.setTopRightRadius(topRightLarge ? largeCornerRadius : smallCornerRadius); } public void dismiss() { @@ -177,7 +193,7 @@ public class QuoteView extends LinearLayout implements RecipientModifiedListener // We use the raw color resource because Android 4.x was struggling with tints here quoteBarView.setImageResource(author.getColor().toQuoteBarColorResource(getContext(), outgoing)); - backgroundView.setBackgroundColor(author.getColor().toQuoteBackgroundColor(getContext(), outgoing)); + rootView.setBackgroundColor(author.getColor().toQuoteBackgroundColor(getContext(), outgoing)); } private void setQuoteText(@Nullable String body, @NonNull SlideDeck attachments) { diff --git a/src/org/thoughtcrime/securesms/components/SharedContactView.java b/src/org/thoughtcrime/securesms/components/SharedContactView.java index 30af4c725..94435e240 100644 --- a/src/org/thoughtcrime/securesms/components/SharedContactView.java +++ b/src/org/thoughtcrime/securesms/components/SharedContactView.java @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.components; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Canvas; import android.graphics.Color; import android.net.Uri; import android.os.Build; @@ -46,6 +47,9 @@ public class SharedContactView extends LinearLayout implements RecipientModified private Locale locale; private GlideRequests glideRequests; private EventListener eventListener; + private CornerMask cornerMask; + private int bigCornerRadius; + private int smallCornerRadius; private final Map activeRecipients = new HashMap<>(); @@ -79,6 +83,10 @@ public class SharedContactView extends LinearLayout implements RecipientModified actionButtonView = findViewById(R.id.contact_action_button); footer = findViewById(R.id.contact_footer); + cornerMask = new CornerMask(this); + bigCornerRadius = getResources().getDimensionPixelOffset(R.dimen.message_corner_radius); + smallCornerRadius = getResources().getDimensionPixelOffset(R.dimen.message_corner_collapse_radius); + if (attrs != null) { TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.SharedContactView, 0, 0); int titleColor = typedArray.getInt(R.styleable.SharedContactView_contact_titleColor, Color.BLACK); @@ -89,6 +97,26 @@ public class SharedContactView extends LinearLayout implements RecipientModified numberView.setTextColor(captionColor); footer.setColor(captionColor); } + + if (cornerMask.isLegacy()) { + setWillNotDraw(false); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (cornerMask.isLegacy()) { + cornerMask.mask(canvas); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (!cornerMask.isLegacy()) { + cornerMask.mask(canvas); + } } public void setContact(@NonNull Contact contact, @NonNull GlideRequests glideRequests, @NonNull Locale locale) { @@ -104,6 +132,21 @@ public class SharedContactView extends LinearLayout implements RecipientModified presentActionButtons(ContactUtil.getRecipients(getContext(), contact)); } + public void setSingularStyle() { + cornerMask.setBottomLeftRadius(bigCornerRadius); + cornerMask.setBottomRightRadius(bigCornerRadius); + } + + public void setClusteredIncomingStyle() { + cornerMask.setBottomLeftRadius(smallCornerRadius); + cornerMask.setBottomRightRadius(bigCornerRadius); + } + + public void setClusteredOutgoingStyle() { + cornerMask.setBottomLeftRadius(bigCornerRadius); + cornerMask.setBottomRightRadius(smallCornerRadius); + } + public void setEventListener(@NonNull EventListener eventListener) { this.eventListener = eventListener; } diff --git a/src/org/thoughtcrime/securesms/util/ViewUtil.java b/src/org/thoughtcrime/securesms/util/ViewUtil.java index b52cd6b19..8f606103c 100644 --- a/src/org/thoughtcrime/securesms/util/ViewUtil.java +++ b/src/org/thoughtcrime/securesms/util/ViewUtil.java @@ -224,6 +224,7 @@ public class ViewUtil { } else { ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin; } + view.forceLayout(); view.requestLayout(); }