Use pseudo-bubbles for for ImageVideo items
Pseudo-bubbles: align like bubbles, but don't draw the actual bubbles. Closes #8. Change-Id: I8ff281858f67ed8a3ee5e4530e3ce02aa786b955
This commit is contained in:
parent
0d7c0bc29c
commit
037a333c37
|
@ -25,11 +25,9 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.core.view.children
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import kotlin.math.max
|
||||
import kotlin.math.round
|
||||
|
@ -84,7 +82,17 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
holder.avatarImageView.setOnLongClickListener(attributes.itemLongClickListener)
|
||||
holder.memberNameView.setOnLongClickListener(attributes.itemLongClickListener)
|
||||
holder.bubbleMemberNameView.setOnLongClickListener(attributes.itemLongClickListener)
|
||||
if (contentInBubble) {
|
||||
if (hideSenderInformation()) {
|
||||
holder.memberNameView.visibility = View.GONE
|
||||
holder.timeView.visibility = View.GONE
|
||||
holder.bubbleMemberNameView.visibility = View.GONE
|
||||
holder.bubbleTimeView.visibility = View.GONE
|
||||
if (attributes.informationData.isDirect) {
|
||||
holder.avatarImageView.visibility = View.GONE
|
||||
} else {
|
||||
holder.avatarImageView.visibility = View.VISIBLE
|
||||
}
|
||||
} else if (contentInBubble) {
|
||||
holder.memberNameView.visibility = View.GONE
|
||||
holder.timeView.visibility = View.GONE
|
||||
holder.bubbleMemberNameView.visibility = View.VISIBLE
|
||||
|
@ -109,7 +117,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
holder.timeView.visibility = View.GONE
|
||||
holder.avatarImageView.setOnLongClickListener(null)
|
||||
holder.memberNameView.setOnLongClickListener(null)
|
||||
if (attributes.informationData.showInformation /* && contentInBubble && attributes.informationData.sentByMe */) {
|
||||
if (attributes.informationData.showInformation && !hideSenderInformation()/* && contentInBubble && attributes.informationData.sentByMe */) {
|
||||
holder.bubbleTimeView.visibility = View.VISIBLE
|
||||
holder.bubbleTimeView.text = attributes.informationData.time
|
||||
holder.bubbleMemberNameView.visibility = View.VISIBLE
|
||||
|
@ -203,13 +211,18 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
}
|
||||
|
||||
private fun infoInBubbles(context: Context): Boolean {
|
||||
return messageBubbleAllowed(context) && BubbleThemeUtils.getBubbleStyle(context) == BubbleThemeUtils.BUBBLE_STYLE_BOTH
|
||||
return BubbleThemeUtils.getBubbleStyle(context) == BubbleThemeUtils.BUBBLE_STYLE_BOTH &&
|
||||
(messageBubbleAllowed(context) || pseudoBubbleAllowed())
|
||||
}
|
||||
|
||||
override fun shouldReverseBubble(): Boolean {
|
||||
return attributes.informationData.sentByMe
|
||||
}
|
||||
|
||||
private fun hideSenderInformation(): Boolean {
|
||||
return pseudoBubbleAllowed() && false
|
||||
}
|
||||
|
||||
open fun getBubbleMargin(density: Float, reverseBubble: Boolean): Int {
|
||||
return round(96*density).toInt()
|
||||
}
|
||||
|
@ -231,7 +244,13 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
*/
|
||||
bubbleView.setPadding(0, 0, 0, 0)
|
||||
}
|
||||
BubbleThemeUtils.BUBBLE_STYLE_START, BubbleThemeUtils.BUBBLE_STYLE_BOTH -> {
|
||||
BubbleThemeUtils.BUBBLE_STYLE_START,
|
||||
BubbleThemeUtils.BUBBLE_STYLE_BOTH,
|
||||
BubbleThemeUtils.BUBBLE_STYLE_BOTH_HIDDEN,
|
||||
BubbleThemeUtils.BUBBLE_STYLE_START_HIDDEN -> {
|
||||
val longPadding: Int
|
||||
val shortPadding: Int
|
||||
if (BubbleThemeUtils.drawsActualBubbles(bubbleStyle)) {
|
||||
if (attributes.informationData.showInformation) {
|
||||
bubbleView.setBackgroundResource(if (reverseBubble) R.drawable.msg_bubble_outgoing else R.drawable.msg_bubble_incoming)
|
||||
} else {
|
||||
|
@ -244,6 +263,12 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
)
|
||||
)
|
||||
bubbleView.backgroundTintList = tintColor
|
||||
longPadding = 20
|
||||
shortPadding = 8
|
||||
} else {
|
||||
longPadding = 10
|
||||
shortPadding = 0//if (attributes.informationData.showInformation && !hideSenderInformation()) { 8 } else { 0 }
|
||||
}
|
||||
val density = bubbleView.resources.displayMetrics.density
|
||||
// TODO 96 = 2 * avatar size?
|
||||
if (reverseBubble) {
|
||||
|
@ -261,17 +286,17 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
// TODO padding?
|
||||
if (reverseBubble) {
|
||||
bubbleView.setPaddingRelative(
|
||||
round(8 * density).toInt(),
|
||||
round(8 * density).toInt(),
|
||||
round(20 * density).toInt(),
|
||||
round(8 * density).toInt()
|
||||
round(shortPadding * density).toInt(),
|
||||
round(shortPadding * density).toInt(),
|
||||
round(longPadding * density).toInt(),
|
||||
round(shortPadding * density).toInt()
|
||||
)
|
||||
} else {
|
||||
bubbleView.setPaddingRelative(
|
||||
round(20 * density).toInt(),
|
||||
round(8 * density).toInt(),
|
||||
round(8 * density).toInt(),
|
||||
round(8 * density).toInt()
|
||||
round(longPadding * density).toInt(),
|
||||
round(shortPadding * density).toInt(),
|
||||
round(shortPadding * density).toInt(),
|
||||
round(shortPadding * density).toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,8 +102,21 @@ abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
|||
|
||||
fun updateMessageBubble(holder: H) {
|
||||
val bubbleStyleSetting = BubbleThemeUtils.getBubbleStyle(holder.checkableBackground.context)
|
||||
val bubbleStyle = if (messageBubbleAllowed(holder.checkableBackground.context)) bubbleStyleSetting else BubbleThemeUtils.BUBBLE_STYLE_NONE
|
||||
val reverseBubble = shouldReverseBubble() && bubbleStyle == BubbleThemeUtils.BUBBLE_STYLE_BOTH
|
||||
val bubbleStyle = when {
|
||||
messageBubbleAllowed(holder.checkableBackground.context) -> {
|
||||
bubbleStyleSetting
|
||||
}
|
||||
bubbleStyleSetting == BubbleThemeUtils.BUBBLE_STYLE_BOTH && pseudoBubbleAllowed() -> {
|
||||
BubbleThemeUtils.BUBBLE_STYLE_BOTH_HIDDEN
|
||||
}
|
||||
bubbleStyleSetting == BubbleThemeUtils.BUBBLE_STYLE_START && pseudoBubbleAllowed() -> {
|
||||
BubbleThemeUtils.BUBBLE_STYLE_START_HIDDEN
|
||||
}
|
||||
else -> {
|
||||
BubbleThemeUtils.BUBBLE_STYLE_NONE
|
||||
}
|
||||
}
|
||||
val reverseBubble = shouldReverseBubble() && BubbleThemeUtils.drawsDualSide(bubbleStyle)
|
||||
|
||||
setBubbleLayout(holder, bubbleStyle, bubbleStyleSetting, reverseBubble)
|
||||
}
|
||||
|
@ -116,6 +129,10 @@ abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
|||
return false
|
||||
}
|
||||
|
||||
open fun pseudoBubbleAllowed(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
open fun setBubbleLayout(holder: H, bubbleStyle: String, bubbleStyleSetting: String, reverseBubble: Boolean) {
|
||||
val defaultDirection = holder.readReceiptsView.resources.configuration.layoutDirection;
|
||||
|
@ -123,7 +140,7 @@ abstract class BaseEventItem<H : BaseEventItem.BaseHolder> : VectorEpoxyModel<H>
|
|||
val reverseDirection = if (defaultRtl) View.LAYOUT_DIRECTION_LTR else View.LAYOUT_DIRECTION_RTL
|
||||
|
||||
// Always keep read receipts of others on other side for dual side bubbles
|
||||
val dualBubbles = bubbleStyleSetting == BubbleThemeUtils.BUBBLE_STYLE_BOTH
|
||||
val dualBubbles = BubbleThemeUtils.drawsDualSide(bubbleStyleSetting)
|
||||
|
||||
val receiptParent = holder.readReceiptsView.parent
|
||||
if (receiptParent is LinearLayout) {
|
||||
|
|
|
@ -84,6 +84,10 @@ abstract class MessageImageVideoItem : AbsMessageItem<MessageImageVideoItem.Hold
|
|||
override fun getViewType() = STUB_ID
|
||||
|
||||
override fun messageBubbleAllowed(context: Context): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun pseudoBubbleAllowed(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,13 @@ object BubbleThemeUtils {
|
|||
const val BUBBLE_STYLE_NONE = "none"
|
||||
const val BUBBLE_STYLE_START = "start"
|
||||
const val BUBBLE_STYLE_BOTH = "both"
|
||||
|
||||
// Special case of BUBBLE_STYLE_BOTH, to allow non-bubble items align to the sender either way
|
||||
// (not meant for user setting, but internal use)
|
||||
const val BUBBLE_STYLE_BOTH_HIDDEN = "both_hidden"
|
||||
// As above, so for single bubbles side
|
||||
const val BUBBLE_STYLE_START_HIDDEN = "start_hidden"
|
||||
|
||||
private var mBubbleStyle: String = ""
|
||||
|
||||
fun getBubbleStyle(context: Context): String {
|
||||
|
@ -21,6 +28,14 @@ object BubbleThemeUtils {
|
|||
return mBubbleStyle
|
||||
}
|
||||
|
||||
fun drawsActualBubbles(bubbleStyle: String): Boolean {
|
||||
return bubbleStyle == BUBBLE_STYLE_START || bubbleStyle == BUBBLE_STYLE_BOTH
|
||||
}
|
||||
|
||||
fun drawsDualSide(bubbleStyle: String): Boolean {
|
||||
return bubbleStyle == BUBBLE_STYLE_BOTH || bubbleStyle == BUBBLE_STYLE_BOTH_HIDDEN
|
||||
}
|
||||
|
||||
fun invalidateBubbleStyle() {
|
||||
mBubbleStyle = ""
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue