Merge pull request #5303 from vector-im/feature/fga/improve_bubble_layout

Feature/fga/improve bubble layout
This commit is contained in:
Benoit Marty 2022-02-22 22:56:09 +01:00 committed by GitHub
commit 6e7aa01437
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 3 deletions

1
changelog.d/5303.misc Normal file
View File

@ -0,0 +1 @@
Improve Bubble layouts rendering.

View File

@ -0,0 +1,124 @@
/*
* 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.view
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewStub
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.marginBottom
import androidx.core.view.marginEnd
import androidx.core.view.marginStart
import androidx.core.view.marginTop
import im.vector.app.R
import im.vector.app.core.resources.LocaleProvider
import im.vector.app.core.resources.getLayoutDirectionFromCurrentLocale
class MessageBubbleContentLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
ConstraintLayout(context, attrs, defStyleAttr) {
private var messageTextView: TextView? = null
private lateinit var contentContainerView: View
private lateinit var timeView: View
private lateinit var contentOverlayView: View
private var localeLayoutDirection: Int = View.LAYOUT_DIRECTION_LOCALE
private val timeViewMeasuredWidthWithMargins: Int
get() = timeView.measuredWidth + timeView.marginStart + timeView.marginEnd
override fun onFinishInflate() {
super.onFinishInflate()
val textViewStub: ViewStub = findViewById(R.id.messageContentTextStub)
contentContainerView = findViewById(R.id.viewStubContainer)
contentOverlayView = findViewById(R.id.messageOverlayView)
timeView = findViewById(R.id.messageTimeView)
textViewStub.setOnInflateListener { _, inflated ->
textViewStub.setOnInflateListener(null)
messageTextView = inflated.findViewById(R.id.messageTextView)
}
localeLayoutDirection = LocaleProvider(resources).getLayoutDirectionFromCurrentLocale()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// Let the ConstraintLayouts measure children
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val messageTextView = this.messageTextView
// Then if we have a text message layout, we can resize ourself so we can position the timeView without losing space.
if (messageTextView != null) {
val width: Int
val height: Int
val textLineCount = messageTextView.lineCount
val maxContentWidth = (contentContainerView.layoutParams as LayoutParams).matchConstraintMaxWidth
val lastLineWidth = if (textLineCount != 0) messageTextView.layout.getLineWidth(textLineCount - 1) else 0f
if (textLineCount == 1 && contentContainerView.measuredWidth + timeViewMeasuredWidthWithMargins < maxContentWidth) {
width = contentContainerView.measuredWidth + timeViewMeasuredWidthWithMargins
height = contentContainerView.measuredHeight
} else if (textLineCount > 1 && lastLineWidth + timeViewMeasuredWidthWithMargins
< contentContainerView.measuredWidth - contentContainerView.paddingEnd) {
width = contentContainerView.measuredWidth
height = contentContainerView.measuredHeight
} else {
width = contentContainerView.measuredWidth
height = contentContainerView.measuredHeight + timeView.measuredHeight
}
setMeasuredDimension(width, height)
}
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
// If we have a text message layout, we want to render it manually, so we don't call super.onLayout
if (messageTextView != null) {
val parentLeft: Int = paddingLeft
val parentRight: Int = right - left - paddingRight
val parentTop: Int = paddingTop
val parentBottom: Int = bottom - top - paddingBottom
if (localeLayoutDirection == LAYOUT_DIRECTION_RTL) {
val contentLeft = parentRight - contentContainerView.measuredWidth - contentContainerView.marginEnd
contentContainerView.layout(
contentLeft,
parentTop + contentContainerView.marginTop,
parentRight - contentContainerView.marginEnd,
parentTop + contentContainerView.marginTop + contentContainerView.measuredHeight
)
timeView.layout(
parentLeft + timeView.marginEnd,
parentBottom - timeView.measuredHeight - timeView.marginBottom,
parentLeft + timeView.measuredWidth + timeView.marginEnd,
parentBottom - timeView.marginBottom
)
} else {
contentContainerView.layout(
parentLeft,
parentTop,
parentLeft + contentContainerView.measuredWidth,
parentTop + contentContainerView.measuredHeight
)
timeView.layout(
parentRight - timeView.measuredWidth - timeView.marginEnd,
parentBottom - timeView.measuredHeight - timeView.marginBottom,
parentRight - timeView.marginEnd,
parentBottom - timeView.marginBottom
)
}
} else {
super.onLayout(changed, left, top, right, bottom)
}
}
}

View File

@ -49,7 +49,7 @@ class MessageBubbleView @JvmOverloads constructor(context: Context, attrs: Attri
private var isIncoming: Boolean = false private var isIncoming: Boolean = false
private val horizontalStubPadding = DimensionConverter(resources).dpToPx(12) private val horizontalStubPadding = DimensionConverter(resources).dpToPx(12)
private val verticalStubPadding = DimensionConverter(resources).dpToPx(4) private val verticalStubPadding = DimensionConverter(resources).dpToPx(8)
private lateinit var views: ViewMessageBubbleBinding private lateinit var views: ViewMessageBubbleBinding
private lateinit var bubbleDrawable: MaterialShapeDrawable private lateinit var bubbleDrawable: MaterialShapeDrawable

View File

@ -12,6 +12,7 @@
style="@style/Widget.Vector.TextView.Body" style="@style/Widget.Vector.TextView.Body"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:textColor="?vctr_content_primary" android:textColor="?vctr_content_primary"
tools:text="@sample/messages.json/data/message" /> tools:text="@sample/messages.json/data/message" />

View File

@ -84,7 +84,7 @@
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false"> android:clipToPadding="false">
<androidx.constraintlayout.widget.ConstraintLayout <im.vector.app.features.home.room.detail.timeline.view.MessageBubbleContentLayout
android:id="@+id/bubbleView" android:id="@+id/bubbleView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -130,7 +130,7 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
tools:text="@tools:sample/date/hhmm" /> tools:text="@tools:sample/date/hhmm" />
</androidx.constraintlayout.widget.ConstraintLayout> </im.vector.app.features.home.room.detail.timeline.view.MessageBubbleContentLayout>
</FrameLayout> </FrameLayout>
<im.vector.app.core.ui.views.SendStateImageView <im.vector.app.core.ui.views.SendStateImageView