在android中以编程方式滑动以回复聊天消息,例如whats应用程序

问题描述

我目前正在开发聊天应用程序。我需要滑动才能以编程方式在 android 中回复像 WhatsApp 这样的特定消息。请帮助我实现这一目标。提前致谢。

链接我指的是 https://github.com/shainsingh89/SwipeToReply

swipe to reply

解决方法

好吧,我将在这里列出建议解决方案的主要挑战,您可以在 github over here 上找到整个项目:

挑战 1:带有引用文本的新布局

  1. 为发送者和接收者添加了两个新的聊天消息布局 send_message_quoted_rowreceived_message_quoted_row ->> 布局可能比这更好,但现在没什么大不了的。>

  2. 修改 MessageAdapter 以接受它们作为新类型,并更新 onBindViewHolder 中的引用文本:

    private fun getItemViewType(message: Message): Int {
        return if (message.type == MessageType.SEND)
            if (message.quotePos == -1) R.layout.send_message_row
            else R.layout.send_message_quoted_row
        else
            if (message.quotePos == -1) R.layout.received_message_row
            else R.layout.received_message_quoted_row
    }

    override fun onBindViewHolder(holder: MessageViewHolder,position: Int) {
        val message = messageList[position]
        holder.txtSendMsg.text = message.body
        holder.txtQuotedMsg?.text = message.quote
    }

    class MessageViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var txtSendMsg = view.txtBody!!
        var txtQuotedMsg: TextView? = view.textQuote
    }
  1. Message数据类添加新的构造函数以接受原始消息的引用和位置(在当前消息中被引用
data class Message(var body: String,var time: Long,var type: Int) {

    var quote: String = ""
    var quotePos: Int = -1

    constructor(
        body: String,time: Long,type: Int,quote: String,quotePos: Int
    ) : this(body,time,type) {
        this.quote = quote
        this.quotePos = quotePos
    }

}

object MessageType {
    const val SEND = 1
    const val RECEIVED = 2
}
  1. 添加示例引用消息以在 SampleMessages 中进行测试

挑战 2:将引用布局嵌入到像 WhatsApp 一样动画的回复布局中

在 WhatsApp 中:引用布局作为回复布局的一部分出现,在原始布局后面从下到上逐渐出现。同样,当按下取消按钮时,它会将动画反转到底部。

  • 通过使用自定义 Animation 类更改引用的 TextView 的高度,然后使用 View.Gone/Visible 来显示布局来解决。
class ResizeAnim(var view: View,private val startHeight: Int,private val targetHeight: Int) :
    Animation() {

    override fun applyTransformation(interpolatedTime: Float,t: Transformation) {
        if (startHeight == 0 || targetHeight == 0) {
            view.layoutParams.height =
                (startHeight + (targetHeight - startHeight) * interpolatedTime).toInt()
        } else {
            view.layoutParams.height = (startHeight + targetHeight * interpolatedTime).toInt()
        }
        view.requestLayout()
    }

    override fun willChangeBounds(): Boolean {
        return true
    }
}

并在活动 showQuotedMessage() & hideReplyLayout()

中处理此动画
private fun hideReplyLayout() {

    val resizeAnim = ResizeAnim(reply_layout,mainActivityViewModel.currentMessageHeight,0)
    resizeAnim.duration = ANIMATION_DURATION

    Handler().postDelayed({
        reply_layout.layout(0,-reply_layout.height,reply_layout.width,0)
        reply_layout.requestLayout()
        reply_layout.forceLayout()
        reply_layout.visibility = View.GONE

    },ANIMATION_DURATION - 50)

    reply_layout.startAnimation(resizeAnim)
    mainActivityViewModel.currentMessageHeight = 0

    resizeAnim.setAnimationListener(object : Animation.AnimationListener {
        override fun onAnimationStart(animation: Animation?) {
        }

        override fun onAnimationEnd(animation: Animation?) {
            val params = reply_layout.layoutParams
            params.height = 0
            reply_layout.layoutParams = params
        }

        override fun onAnimationRepeat(animation: Animation?) {
        }
    })

}

private fun showQuotedMessage(message: Message) {
    edit_message.requestFocus()
    val inputMethodManager =
        getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.showSoftInput(edit_message,InputMethodManager.SHOW_IMPLICIT)

    textQuotedMessage.text = message.body
    val height = textQuotedMessage.getActualHeight()
    val startHeight = mainActivityViewModel.currentMessageHeight

    if (height != startHeight) {

        if (reply_layout.visibility == View.GONE)
            Handler().postDelayed({
                reply_layout.visibility = View.VISIBLE
            },50)

        val targetHeight = height - startHeight

        val resizeAnim =
            ResizeAnim(
                reply_layout,startHeight,targetHeight
            )

        resizeAnim.duration = ANIMATION_DURATION
        reply_layout.startAnimation(resizeAnim)

        mainActivityViewModel.currentMessageHeight = height

    }

}

private fun TextView.getActualHeight(): Int {
    textQuotedMessage.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED)
    return this.measuredHeight
}

挑战 3:计算新引用的文本高度的实际值

特别是当用户在当前有引用消息的情况下滑动另一条不同高度的消息时需要扩展/缩小引用文本高度时。

  • 通过使用 getHeight() 函数以编程方式膨胀引用的 TextView 并将其文本设置为新文本,将其高度与旧文本的高度进行比较,并相应地处理动画.

  • 这已经在顶级方法中介绍过了,我使用 currentMessageHeight 整数跟踪了 ViewModel 中的旧高度。

挑战 4:在引用的消息中添加 OnClickListener

  • 所以要到引用消息的原始位置,我们在Message类中将其注册为一个字段,当它为-1时,则不是引用消息;否则为引用消息。
  • 点击侦听器由 QuoteClickListener 中的自定义 MessageAdapter 接口处理

预览:

添加新消息:

,

您应该阅读此内容以滑动以回复聊天消息希望它会帮助您 https://medium.com/mindorks/swipe-to-reply-android-recycler-view-ui-c11365f8999f

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...