Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ru.brightos.emoji.view
- import android.content.Context
- import android.content.res.TypedArray
- import android.graphics.Bitmap
- import android.util.AttributeSet
- import android.util.TypedValue
- import android.view.View
- import android.view.ViewGroup
- import android.widget.ImageView
- import android.widget.TextView
- import androidx.appcompat.content.res.AppCompatResources
- import androidx.core.content.ContextCompat
- import androidx.core.content.res.ResourcesCompat
- import androidx.core.view.marginBottom
- import androidx.core.view.marginLeft
- import androidx.core.view.marginRight
- import androidx.core.view.marginTop
- import ru.brightos.emoji.R
- import kotlin.math.roundToInt
- class MessageView(
- context: Context,
- attrs: AttributeSet? = null
- ) : ViewGroup(context, attrs) {
- val avatar: ImageView
- val author: TextView
- val message: TextView
- val flexBoxLayout: FlexBoxLayout
- val messageBackground: View
- var isLeftGravity = false
- val plusView = ImageView(context)
- init {
- inflate(context, R.layout.message_view_group, this)
- avatar = findViewById(R.id.avatar)
- author = findViewById(R.id.author)
- message = findViewById(R.id.text)
- flexBoxLayout = findViewById(R.id.flexbox)
- messageBackground = findViewById(R.id.message_background)
- author.apply {
- typeface = ResourcesCompat.getFont(context, R.font.inter_regular)
- setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
- }
- message.apply {
- typeface = ResourcesCompat.getFont(context, R.font.inter_regular)
- setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
- }
- initStyledAttributes(
- typedArray = context.obtainStyledAttributes(
- attrs,
- R.styleable.MessageView
- )
- )
- plusView.apply {
- background = AppCompatResources.getDrawable(context, R.drawable.ic_add)
- visibility = View.INVISIBLE
- }
- messageBackground.background =
- AppCompatResources.getDrawable(context, R.drawable.emoji_deselected)
- background = ContextCompat.getDrawable(context, R.drawable.emoji_selected)
- }
- fun setAvatarImageBitmap(bm: Bitmap) {
- avatar.setImageBitmap(bm)
- requestLayout()
- }
- private fun setAvatar(image: Int) {
- avatar.setImageDrawable(AppCompatResources.getDrawable(context, image))
- requestLayout()
- }
- fun setAuthor(text: String) {
- author.text = text
- requestLayout()
- }
- fun setMessage(text: String) {
- message.text = text
- requestLayout()
- }
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- if (isLeftGravity) {
- measureChildWithMargins(
- avatar,
- widthMeasureSpec,
- 0,
- heightMeasureSpec,
- 0
- )
- measureChildWithMargins(
- messageBackground,
- widthMeasureSpec,
- avatar.measuredWidthWithMargins + messageBackground.marginLeft,
- heightMeasureSpec,
- 0
- )
- measureChildWithMargins(
- author,
- widthMeasureSpec,
- avatar.measuredWidthWithMargins + messageBackground.marginLeft + author.marginLeft,
- heightMeasureSpec,
- messageBackground.marginTop
- )
- measureChildWithMargins(
- message,
- widthMeasureSpec,
- avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.marginLeft,
- heightMeasureSpec,
- author.measuredHeight + messageBackground.marginTop
- )
- measureChildWithMargins(
- flexBoxLayout,
- widthMeasureSpec,
- 0,
- heightMeasureSpec,
- maxOf(
- author.measuredHeightWithMargins + message.measuredHeightWithMargins,
- avatar.measuredHeightWithMargins
- )
- )
- } else {
- measureChildWithMargins(
- avatar,
- widthMeasureSpec,
- MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidth,
- heightMeasureSpec,
- 0
- )
- measureChildWithMargins(
- messageBackground,
- widthMeasureSpec,
- MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidthWithMargins - messageBackground.measuredWidthWithMargins,
- heightMeasureSpec,
- 0
- )
- measureChildWithMargins(
- author,
- widthMeasureSpec,
- MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidthWithMargins - messageBackground.measuredWidthWithMargins - messageBackground.marginLeft,
- heightMeasureSpec,
- messageBackground.marginTop
- )
- measureChildWithMargins(
- message,
- widthMeasureSpec,
- MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidthWithMargins - messageBackground.measuredWidthWithMargins - messageBackground.marginLeft,
- heightMeasureSpec,
- author.measuredHeight + messageBackground.marginTop
- )
- measureChildWithMargins(
- flexBoxLayout,
- widthMeasureSpec,
- messageBackground.left,
- heightMeasureSpec,
- maxOf(
- messageBackground.measuredHeightWithMargins,
- avatar.measuredHeightWithMargins
- )
- )
- }
- val contentWidth = avatar.measuredWidthWithMargins + messageBackground.measuredWidthWithMargins
- val contentHeight = flexBoxLayout.height + messageBackground.measuredHeightWithMargins
- setMeasuredDimension(
- resolveSize(contentWidth, widthMeasureSpec),
- resolveSize(contentHeight, heightMeasureSpec)
- )
- }
- override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
- if (isLeftGravity) {
- avatar.layout(
- avatar.marginLeft,
- avatar.marginTop,
- avatar.measuredWidth + avatar.marginLeft,
- avatar.marginTop + avatar.measuredHeight
- )
- messageBackground.layout(
- l + avatar.measuredWidthWithMargins + messageBackground.marginLeft,
- messageBackground.marginTop,
- l + avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.measuredWidthWithMargins + messageBackground.marginRight,
- message.bottom + messageBackground.marginTop
- )
- author.layout(
- avatar.measuredWidthWithMargins + messageBackground.marginLeft + author.marginLeft,
- author.marginTop + messageBackground.marginTop,
- avatar.measuredWidthWithMargins + messageBackground.marginLeft + author.measuredWidth + author.marginLeft,
- author.marginTop + author.measuredHeight + messageBackground.marginTop
- )
- val messageTop = author.marginTop + author.measuredHeight + message.marginTop
- message.layout(
- avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.marginLeft,
- messageTop + messageBackground.marginTop,
- avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.measuredWidth + author.marginLeft,
- messageTop + message.measuredHeight + messageBackground.marginTop
- )
- flexBoxLayout.layout(
- flexBoxLayout.marginLeft,
- messageBackground.marginTop + author.measuredHeight + author.marginTop + author.marginBottom + message.measuredHeight + message.marginTop + message.marginBottom + messageBackground.marginBottom + flexBoxLayout.marginTop,
- avatar.measuredWidthWithMargins + messageBackground.measuredWidthWithMargins,
- messageBackground.measuredHeightWithMargins + flexBoxLayout.marginTop + flexBoxLayout.measuredHeight
- )
- } else {
- avatar.layout(
- r - avatar.measuredWidthWithMargins,
- avatar.marginTop,
- r - avatar.marginRight,
- avatar.marginTop + avatar.measuredHeight
- )
- messageBackground.layout(
- r - avatar.measuredWidthWithMargins - message.measuredWidthWithMargins - message.marginLeft,
- messageBackground.marginTop,
- r - avatar.measuredWidthWithMargins - message.marginRight - messageBackground.marginRight,
- message.bottom + messageBackground.marginTop
- )
- author.layout(
- r - avatar.measuredWidthWithMargins - message.measuredWidthWithMargins,
- author.marginTop + messageBackground.marginTop,
- r - avatar.measuredWidthWithMargins - message.marginRight,
- author.marginTop + author.measuredHeight + messageBackground.marginTop
- )
- val messageTop = author.marginTop + author.measuredHeight + message.marginTop
- message.layout(
- r - avatar.measuredWidthWithMargins - message.measuredWidthWithMargins,
- messageTop + messageBackground.marginTop,
- r - avatar.measuredWidthWithMargins - message.marginRight,
- messageTop + message.measuredHeight + messageBackground.marginTop
- )
- val flexBoxLayoutTop = maxOf(
- avatar.marginTop + avatar.measuredHeight,
- messageTop + message.measuredHeight + messageBackground.marginTop
- ) + flexBoxLayout.marginTop
- flexBoxLayout.layout(
- flexBoxLayout.marginLeft,
- flexBoxLayoutTop,
- avatar.measuredWidthWithMargins + messageBackground.measuredWidthWithMargins,
- flexBoxLayoutTop + flexBoxLayout.measuredHeight
- )
- }
- }
- private fun initStyledAttributes(typedArray: TypedArray) {
- setMessage(typedArray.getString(R.styleable.MessageView_message) ?: "")
- setAuthor(typedArray.getString(R.styleable.MessageView_author) ?: "")
- setAvatar(
- typedArray.getInteger(
- R.styleable.MessageView_image,
- R.drawable.ic_launcher_background
- )
- )
- isLeftGravity = typedArray.getBoolean(R.styleable.MessageView_isLeftGravity, false)
- }
- fun setupPlusClickListener(action: () -> Unit = {}) {
- plusView.apply {
- setOnClickListener {
- it.isSelected = !it.isSelected
- action()
- it.isSelected = !it.isSelected
- }
- }
- }
- fun addNewEmoji(
- count: Int,
- emojiText: String,
- isClicked: Boolean,
- onEmojiClicked: () -> Unit = {},
- onEmojiNotClicked: () -> Unit = {}
- ) {
- val view = EmojiView(context)
- view.apply {
- text = emojiText
- if (emojiText.isNotEmpty()) {
- tapCount = count
- setOnClickListener {
- it.isSelected = !it.isSelected
- }
- emojiSelectedAction = onEmojiClicked
- emojiDeselectedAction = onEmojiNotClicked
- isSelected = isClicked
- if (isClicked) tapCount--
- addCustomEmoji(this)
- }
- }
- requestLayout()
- if (plusView.visibility == View.INVISIBLE)
- flexBoxLayout.also {
- plusView.visibility = View.VISIBLE
- plusView.layoutParams = LayoutParams(view.height, view.height)
- it.addView(plusView, it.childCount)
- it.requestLayout()
- }
- }
- fun addCustomEmoji(view: EmojiView) {
- flexBoxLayout.also {
- it.addView(view, 0)
- it.requestLayout()
- }
- }
- override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams =
- MarginLayoutParams(context, attrs)
- override fun checkLayoutParams(p: LayoutParams): Boolean =
- p is MarginLayoutParams
- override fun generateLayoutParams(p: LayoutParams): LayoutParams =
- MarginLayoutParams(p)
- private val View.measuredWidthWithMargins: Int
- get() {
- val params = layoutParams as MarginLayoutParams
- return measuredWidth + params.rightMargin + params.leftMargin
- }
- private val View.measuredHeightWithMargins: Int
- get() {
- val params = layoutParams as MarginLayoutParams
- return measuredHeight + params.topMargin + params.bottomMargin
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement