问题描述
我目前正在开发聊天应用程序。我需要滑动才能以编程方式在 android 中回复像 WhatsApp 这样的特定消息。请帮助我实现这一目标。提前致谢。
链接我指的是 https://github.com/shainsingh89/SwipeToReply。
解决方法
好吧,我将在这里列出建议解决方案的主要挑战,您可以在 github over here 上找到整个项目:
挑战 1:带有引用文本的新布局
为发送者和接收者添加了两个新的聊天消息布局
send_message_quoted_row
和received_message_quoted_row
->> 布局可能比这更好,但现在没什么大不了的。>-
修改
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
}
- 向
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
}
- 添加示例引用消息以在
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