mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Bubble: move overlay view to MessageBubbleView (and fix corner radius)
This commit is contained in:
parent
c14eb050b1
commit
b79a5fd4f4
6 changed files with 82 additions and 47 deletions
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue