Advertisement
BrightOS

Untitled

Mar 16th, 2022
772
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 13.04 KB | None | 0 0
  1. package ru.brightos.emoji.view
  2.  
  3. import android.content.Context
  4. import android.content.res.TypedArray
  5. import android.graphics.Bitmap
  6. import android.util.AttributeSet
  7. import android.util.TypedValue
  8. import android.view.View
  9. import android.view.ViewGroup
  10. import android.widget.ImageView
  11. import android.widget.TextView
  12. import androidx.appcompat.content.res.AppCompatResources
  13. import androidx.core.content.ContextCompat
  14. import androidx.core.content.res.ResourcesCompat
  15. import androidx.core.view.marginBottom
  16. import androidx.core.view.marginLeft
  17. import androidx.core.view.marginRight
  18. import androidx.core.view.marginTop
  19. import ru.brightos.emoji.R
  20. import kotlin.math.roundToInt
  21.  
  22. class MessageView(
  23.     context: Context,
  24.     attrs: AttributeSet? = null
  25. ) : ViewGroup(context, attrs) {
  26.  
  27.     val avatar: ImageView
  28.     val author: TextView
  29.     val message: TextView
  30.     val flexBoxLayout: FlexBoxLayout
  31.     val messageBackground: View
  32.     var isLeftGravity = false
  33.  
  34.     val plusView = ImageView(context)
  35.  
  36.     init {
  37.         inflate(context, R.layout.message_view_group, this)
  38.  
  39.         avatar = findViewById(R.id.avatar)
  40.         author = findViewById(R.id.author)
  41.         message = findViewById(R.id.text)
  42.         flexBoxLayout = findViewById(R.id.flexbox)
  43.         messageBackground = findViewById(R.id.message_background)
  44.  
  45.         author.apply {
  46.             typeface = ResourcesCompat.getFont(context, R.font.inter_regular)
  47.             setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
  48.         }
  49.         message.apply {
  50.             typeface = ResourcesCompat.getFont(context, R.font.inter_regular)
  51.             setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
  52.         }
  53.  
  54.         initStyledAttributes(
  55.             typedArray = context.obtainStyledAttributes(
  56.                 attrs,
  57.                 R.styleable.MessageView
  58.             )
  59.         )
  60.  
  61.         plusView.apply {
  62.             background = AppCompatResources.getDrawable(context, R.drawable.ic_add)
  63.             visibility = View.INVISIBLE
  64.         }
  65.  
  66.         messageBackground.background =
  67.             AppCompatResources.getDrawable(context, R.drawable.emoji_deselected)
  68.  
  69.         background = ContextCompat.getDrawable(context, R.drawable.emoji_selected)
  70.     }
  71.  
  72.     fun setAvatarImageBitmap(bm: Bitmap) {
  73.         avatar.setImageBitmap(bm)
  74.         requestLayout()
  75.     }
  76.  
  77.     private fun setAvatar(image: Int) {
  78.         avatar.setImageDrawable(AppCompatResources.getDrawable(context, image))
  79.         requestLayout()
  80.     }
  81.  
  82.     fun setAuthor(text: String) {
  83.         author.text = text
  84.         requestLayout()
  85.     }
  86.  
  87.     fun setMessage(text: String) {
  88.         message.text = text
  89.         requestLayout()
  90.     }
  91.  
  92.     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  93.  
  94.         if (isLeftGravity) {
  95.             measureChildWithMargins(
  96.                 avatar,
  97.                 widthMeasureSpec,
  98.                 0,
  99.                 heightMeasureSpec,
  100.                 0
  101.             )
  102.  
  103.             measureChildWithMargins(
  104.                 messageBackground,
  105.                 widthMeasureSpec,
  106.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft,
  107.                 heightMeasureSpec,
  108.                 0
  109.             )
  110.  
  111.             measureChildWithMargins(
  112.                 author,
  113.                 widthMeasureSpec,
  114.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft + author.marginLeft,
  115.                 heightMeasureSpec,
  116.                 messageBackground.marginTop
  117.             )
  118.  
  119.             measureChildWithMargins(
  120.                 message,
  121.                 widthMeasureSpec,
  122.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.marginLeft,
  123.                 heightMeasureSpec,
  124.                 author.measuredHeight + messageBackground.marginTop
  125.             )
  126.  
  127.             measureChildWithMargins(
  128.                 flexBoxLayout,
  129.                 widthMeasureSpec,
  130.                 0,
  131.                 heightMeasureSpec,
  132.                 maxOf(
  133.                     author.measuredHeightWithMargins + message.measuredHeightWithMargins,
  134.                     avatar.measuredHeightWithMargins
  135.                 )
  136.             )
  137.         } else {
  138.             measureChildWithMargins(
  139.                 avatar,
  140.                 widthMeasureSpec,
  141.                 MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidth,
  142.                 heightMeasureSpec,
  143.                 0
  144.             )
  145.  
  146.             measureChildWithMargins(
  147.                 messageBackground,
  148.                 widthMeasureSpec,
  149.                 MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidthWithMargins - messageBackground.measuredWidthWithMargins,
  150.                 heightMeasureSpec,
  151.                 0
  152.             )
  153.  
  154.             measureChildWithMargins(
  155.                 author,
  156.                 widthMeasureSpec,
  157.                 MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidthWithMargins - messageBackground.measuredWidthWithMargins - messageBackground.marginLeft,
  158.                 heightMeasureSpec,
  159.                 messageBackground.marginTop
  160.             )
  161.  
  162.             measureChildWithMargins(
  163.                 message,
  164.                 widthMeasureSpec,
  165.                 MeasureSpec.getSize(widthMeasureSpec) - avatar.measuredWidthWithMargins - messageBackground.measuredWidthWithMargins - messageBackground.marginLeft,
  166.                 heightMeasureSpec,
  167.                 author.measuredHeight + messageBackground.marginTop
  168.             )
  169.  
  170.             measureChildWithMargins(
  171.                 flexBoxLayout,
  172.                 widthMeasureSpec,
  173.                 messageBackground.left,
  174.                 heightMeasureSpec,
  175.                 maxOf(
  176.                     messageBackground.measuredHeightWithMargins,
  177.                     avatar.measuredHeightWithMargins
  178.                 )
  179.             )
  180.         }
  181.  
  182.         val contentWidth = avatar.measuredWidthWithMargins + messageBackground.measuredWidthWithMargins
  183.         val contentHeight = flexBoxLayout.height + messageBackground.measuredHeightWithMargins
  184.  
  185.         setMeasuredDimension(
  186.             resolveSize(contentWidth, widthMeasureSpec),
  187.             resolveSize(contentHeight, heightMeasureSpec)
  188.         )
  189.     }
  190.  
  191.     override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
  192.  
  193.         if (isLeftGravity) {
  194.             avatar.layout(
  195.                 avatar.marginLeft,
  196.                 avatar.marginTop,
  197.                 avatar.measuredWidth + avatar.marginLeft,
  198.                 avatar.marginTop + avatar.measuredHeight
  199.             )
  200.  
  201.             messageBackground.layout(
  202.                 l + avatar.measuredWidthWithMargins + messageBackground.marginLeft,
  203.                 messageBackground.marginTop,
  204.                 l + avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.measuredWidthWithMargins + messageBackground.marginRight,
  205.                 message.bottom + messageBackground.marginTop
  206.             )
  207.  
  208.             author.layout(
  209.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft + author.marginLeft,
  210.                 author.marginTop + messageBackground.marginTop,
  211.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft + author.measuredWidth + author.marginLeft,
  212.                 author.marginTop + author.measuredHeight + messageBackground.marginTop
  213.             )
  214.  
  215.             val messageTop = author.marginTop + author.measuredHeight + message.marginTop
  216.             message.layout(
  217.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.marginLeft,
  218.                 messageTop + messageBackground.marginTop,
  219.                 avatar.measuredWidthWithMargins + messageBackground.marginLeft + message.measuredWidth  + author.marginLeft,
  220.                 messageTop + message.measuredHeight + messageBackground.marginTop
  221.             )
  222.  
  223.             flexBoxLayout.layout(
  224.                 flexBoxLayout.marginLeft,
  225.                 messageBackground.marginTop + author.measuredHeight + author.marginTop + author.marginBottom + message.measuredHeight + message.marginTop + message.marginBottom + messageBackground.marginBottom + flexBoxLayout.marginTop,
  226.                 avatar.measuredWidthWithMargins + messageBackground.measuredWidthWithMargins,
  227.                 messageBackground.measuredHeightWithMargins + flexBoxLayout.marginTop + flexBoxLayout.measuredHeight
  228.             )
  229.         } else {
  230.             avatar.layout(
  231.                 r - avatar.measuredWidthWithMargins,
  232.                 avatar.marginTop,
  233.                 r - avatar.marginRight,
  234.                 avatar.marginTop + avatar.measuredHeight
  235.             )
  236.  
  237.             messageBackground.layout(
  238.                 r - avatar.measuredWidthWithMargins - message.measuredWidthWithMargins - message.marginLeft,
  239.                 messageBackground.marginTop,
  240.                 r - avatar.measuredWidthWithMargins - message.marginRight - messageBackground.marginRight,
  241.                 message.bottom + messageBackground.marginTop
  242.             )
  243.  
  244.             author.layout(
  245.                 r - avatar.measuredWidthWithMargins - message.measuredWidthWithMargins,
  246.                 author.marginTop + messageBackground.marginTop,
  247.                 r - avatar.measuredWidthWithMargins - message.marginRight,
  248.                 author.marginTop + author.measuredHeight + messageBackground.marginTop
  249.             )
  250.  
  251.             val messageTop = author.marginTop + author.measuredHeight + message.marginTop
  252.             message.layout(
  253.                 r - avatar.measuredWidthWithMargins - message.measuredWidthWithMargins,
  254.                 messageTop + messageBackground.marginTop,
  255.                 r - avatar.measuredWidthWithMargins - message.marginRight,
  256.                 messageTop + message.measuredHeight + messageBackground.marginTop
  257.             )
  258.  
  259.             val flexBoxLayoutTop = maxOf(
  260.                 avatar.marginTop + avatar.measuredHeight,
  261.                 messageTop + message.measuredHeight + messageBackground.marginTop
  262.             ) + flexBoxLayout.marginTop
  263.             flexBoxLayout.layout(
  264.                 flexBoxLayout.marginLeft,
  265.                 flexBoxLayoutTop,
  266.                 avatar.measuredWidthWithMargins + messageBackground.measuredWidthWithMargins,
  267.                 flexBoxLayoutTop + flexBoxLayout.measuredHeight
  268.             )
  269.         }
  270.  
  271.     }
  272.  
  273.     private fun initStyledAttributes(typedArray: TypedArray) {
  274.         setMessage(typedArray.getString(R.styleable.MessageView_message) ?: "")
  275.         setAuthor(typedArray.getString(R.styleable.MessageView_author) ?: "")
  276.         setAvatar(
  277.             typedArray.getInteger(
  278.                 R.styleable.MessageView_image,
  279.                 R.drawable.ic_launcher_background
  280.             )
  281.         )
  282.         isLeftGravity = typedArray.getBoolean(R.styleable.MessageView_isLeftGravity, false)
  283.     }
  284.  
  285.     fun setupPlusClickListener(action: () -> Unit = {}) {
  286.         plusView.apply {
  287.             setOnClickListener {
  288.                 it.isSelected = !it.isSelected
  289.                 action()
  290.                 it.isSelected = !it.isSelected
  291.             }
  292.         }
  293.     }
  294.  
  295.     fun addNewEmoji(
  296.         count: Int,
  297.         emojiText: String,
  298.         isClicked: Boolean,
  299.         onEmojiClicked: () -> Unit = {},
  300.         onEmojiNotClicked: () -> Unit = {}
  301.     ) {
  302.         val view = EmojiView(context)
  303.  
  304.         view.apply {
  305.             text = emojiText
  306.             if (emojiText.isNotEmpty()) {
  307.                 tapCount = count
  308.                 setOnClickListener {
  309.                     it.isSelected = !it.isSelected
  310.                 }
  311.                 emojiSelectedAction = onEmojiClicked
  312.                 emojiDeselectedAction = onEmojiNotClicked
  313.                 isSelected = isClicked
  314.                 if (isClicked) tapCount--
  315.                 addCustomEmoji(this)
  316.             }
  317.         }
  318.  
  319.         requestLayout()
  320.  
  321.         if (plusView.visibility == View.INVISIBLE)
  322.             flexBoxLayout.also {
  323.                 plusView.visibility = View.VISIBLE
  324.                 plusView.layoutParams = LayoutParams(view.height, view.height)
  325.                 it.addView(plusView, it.childCount)
  326.                 it.requestLayout()
  327.             }
  328.     }
  329.  
  330.     fun addCustomEmoji(view: EmojiView) {
  331.         flexBoxLayout.also {
  332.             it.addView(view, 0)
  333.             it.requestLayout()
  334.         }
  335.     }
  336.  
  337.     override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams =
  338.         MarginLayoutParams(context, attrs)
  339.  
  340.     override fun checkLayoutParams(p: LayoutParams): Boolean =
  341.         p is MarginLayoutParams
  342.  
  343.     override fun generateLayoutParams(p: LayoutParams): LayoutParams =
  344.         MarginLayoutParams(p)
  345.  
  346.     private val View.measuredWidthWithMargins: Int
  347.         get() {
  348.             val params = layoutParams as MarginLayoutParams
  349.             return measuredWidth + params.rightMargin + params.leftMargin
  350.         }
  351.  
  352.     private val View.measuredHeightWithMargins: Int
  353.         get() {
  354.             val params = layoutParams as MarginLayoutParams
  355.             return measuredHeight + params.topMargin + params.bottomMargin
  356.         }
  357.  
  358. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement