Bubble: move overlay view to MessageBubbleView (and fix corner radius)

This commit is contained in:
ganfra 2022-01-28 15:09:43 +01:00
parent c14eb050b1
commit b79a5fd4f4
6 changed files with 82 additions and 47 deletions

View file

@ -89,7 +89,6 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
holder.mediaContentView.onClick(attributes.itemClickListener)
holder.mediaContentView.setOnLongClickListener(attributes.itemLongClickListener)
holder.playContentView.visibility = if (playable) View.VISIBLE else View.GONE
holder.overlayView.isVisible = messageLayout is TimelineMessageLayout.Bubble && messageLayout.timestampAsOverlay
}
override fun unbind(holder: Holder) {
@ -108,7 +107,6 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
val imageView by bind<ImageView>(R.id.messageThumbnailView)
val playContentView by bind<ImageView>(R.id.messageMediaPlayView)
val mediaContentView by bind<ViewGroup>(R.id.messageContentMedia)
val overlayView by bind<View>(R.id.messageMediaOverlayView)
}
companion object {

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* 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 im.vector.app.features.home.room.detail.timeline.style
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.ShapeAppearanceModel
fun TimelineMessageLayout.Bubble.shapeAppearanceModel(cornerRadius: Float): ShapeAppearanceModel {
val (topCornerFamily, topRadius) = if (isFirstFromThisSender) {
Pair(CornerFamily.ROUNDED, cornerRadius)
} else {
Pair(CornerFamily.CUT, 0f)
}
val (bottomCornerFamily, bottomRadius) = if (isLastFromThisSender) {
Pair(CornerFamily.ROUNDED, cornerRadius)
} else {
Pair(CornerFamily.CUT, 0f)
}
val shapeAppearanceModelBuilder = ShapeAppearanceModel().toBuilder()
if (isIncoming) {
shapeAppearanceModelBuilder
.setTopRightCorner(CornerFamily.ROUNDED, cornerRadius)
.setBottomRightCorner(CornerFamily.ROUNDED, cornerRadius)
.setTopLeftCorner(topCornerFamily, topRadius)
.setBottomLeftCorner(bottomCornerFamily, bottomRadius)
} else {
shapeAppearanceModelBuilder
.setTopLeftCorner(CornerFamily.ROUNDED, cornerRadius)
.setBottomLeftCorner(CornerFamily.ROUNDED, cornerRadius)
.setTopRightCorner(topCornerFamily, topRadius)
.setBottomRightCorner(bottomCornerFamily, bottomRadius)
}
return shapeAppearanceModelBuilder.build()
}

View file

@ -20,6 +20,7 @@ import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
@ -27,15 +28,14 @@ import android.widget.RelativeLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.content.ContextCompat
import androidx.core.content.withStyledAttributes
import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.google.android.material.shape.CornerFamily
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel
import im.vector.app.R
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewMessageBubbleBinding
import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
import im.vector.app.features.home.room.detail.timeline.style.shapeAppearanceModel
import im.vector.app.features.themes.ThemeUtils
import timber.log.Timber
@ -103,6 +103,12 @@ class MessageBubbleView @JvmOverloads constructor(context: Context, attrs: Attri
}
applyTo(views.bubbleView)
}
if (messageLayout.timestampAsOverlay) {
views.messageOverlayView.isVisible = true
(views.messageOverlayView.background as? GradientDrawable)?.cornerRadii = messageLayout.cornerRadii(cornerRadius)
} else {
views.messageOverlayView.isVisible = false
}
if (messageLayout.isPseudoBubble && messageLayout.timestampAsOverlay) {
views.viewStubContainer.root.setPadding(0, 0, 0, 0)
} else {
@ -125,41 +131,24 @@ class MessageBubbleView @JvmOverloads constructor(context: Context, attrs: Attri
}
}
private fun TimelineMessageLayout.Bubble.cornerRadii(cornerRadius: Float): FloatArray {
val topRadius = if (isFirstFromThisSender) cornerRadius else 0f
val bottomRadius = if (isLastFromThisSender) cornerRadius else 0f
return if (isIncoming) {
floatArrayOf(topRadius, topRadius, cornerRadius, cornerRadius, cornerRadius, cornerRadius, bottomRadius, bottomRadius)
} else {
floatArrayOf(cornerRadius, cornerRadius, topRadius, topRadius, bottomRadius, bottomRadius, cornerRadius, cornerRadius)
}
}
private fun createBackgroundDrawable(messageLayout: TimelineMessageLayout.Bubble): Drawable {
val (topCornerFamily, topRadius) = if (messageLayout.isFirstFromThisSender) {
Pair(CornerFamily.ROUNDED, cornerRadius)
} else {
Pair(CornerFamily.CUT, 0f)
}
val (bottomCornerFamily, bottomRadius) = if (messageLayout.isLastFromThisSender) {
Pair(CornerFamily.ROUNDED, cornerRadius)
} else {
Pair(CornerFamily.CUT, 0f)
}
val shapeAppearanceModelBuilder = ShapeAppearanceModel().toBuilder()
val backgroundColor: Int
if (isIncoming) {
backgroundColor = ThemeUtils.getColor(context, R.attr.vctr_message_bubble_inbound)
shapeAppearanceModelBuilder
.setTopRightCorner(CornerFamily.ROUNDED, cornerRadius)
.setBottomRightCorner(CornerFamily.ROUNDED, cornerRadius)
.setTopLeftCorner(topCornerFamily, topRadius)
.setBottomLeftCorner(bottomCornerFamily, bottomRadius)
} else {
backgroundColor = ThemeUtils.getColor(context, R.attr.vctr_message_bubble_outbound)
//val alpha = if (ThemeUtils.isLightTheme(context)) 0x0E else 0x26
//backgroundColor = ColorUtils.setAlphaComponent(resolvedColor, alpha)
shapeAppearanceModelBuilder
.setTopLeftCorner(CornerFamily.ROUNDED, cornerRadius)
.setBottomLeftCorner(CornerFamily.ROUNDED, cornerRadius)
.setTopRightCorner(topCornerFamily, topRadius)
.setBottomRightCorner(bottomCornerFamily, bottomRadius)
}
val shapeAppearanceModel = shapeAppearanceModelBuilder.build()
val shapeAppearanceModel = messageLayout.shapeAppearanceModel(cornerRadius)
return MaterialShapeDrawable(shapeAppearanceModel).apply {
fillColor = if (messageLayout.isPseudoBubble) {
ColorStateList.valueOf(Color.TRANSPARENT)
} else {
val backgroundColorAttr = if (isIncoming) R.attr.vctr_message_bubble_inbound else R.attr.vctr_message_bubble_outbound
val backgroundColor = ThemeUtils.getColor(context, backgroundColorAttr)
ColorStateList.valueOf(backgroundColor)
}
}

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="@dimen/chat_bubble_corner_radius"/>
<gradient
android:type="linear"
android:angle="270"

View file

@ -18,17 +18,6 @@
tools:layout_height="300dp"
tools:src="@tools:sample/backgrounds/scenic" />
<View
android:id="@+id/messageMediaOverlayView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/overlay_bubble_media"
android:elevation="2dp"
app:layout_constraintStart_toStartOf="@id/messageThumbnailView"
app:layout_constraintEnd_toEndOf="@id/messageThumbnailView"
app:layout_constraintTop_toTopOf="@id/messageThumbnailView"
app:layout_constraintBottom_toBottomOf="@id/messageThumbnailView"/>
<ImageView
android:id="@+id/messageMediaPlayView"
android:layout_width="40dp"

View file

@ -105,6 +105,18 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="@dimen/chat_bubble_fixed_size" />
<View
android:id="@+id/messageOverlayView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/overlay_bubble_media"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintStart_toStartOf="@id/viewStubContainer"
app:layout_constraintEnd_toEndOf="@id/viewStubContainer"
app:layout_constraintTop_toTopOf="@id/viewStubContainer"
app:layout_constraintBottom_toBottomOf="@id/viewStubContainer"/>
<TextView
android:id="@+id/messageTimeView"
android:layout_width="wrap_content"