session-android/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt

148 lines
5.8 KiB
Kotlin
Raw Normal View History

2021-06-16 06:50:41 +02:00
package org.thoughtcrime.securesms.conversation.v2.input_bar
2021-06-16 07:49:39 +02:00
import android.animation.FloatEvaluator
2021-06-17 03:24:54 +02:00
import android.animation.IntEvaluator
2021-06-16 07:49:39 +02:00
import android.animation.ValueAnimator
2021-06-16 06:50:41 +02:00
import android.content.Context
2021-06-17 07:20:19 +02:00
import android.os.Handler
import android.os.Looper
2021-06-16 06:50:41 +02:00
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.RelativeLayout
2021-06-17 06:01:43 +02:00
import androidx.core.content.res.ResourcesCompat
2021-06-16 07:49:39 +02:00
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.view_input_bar_recording.view.*
2021-06-16 06:50:41 +02:00
import network.loki.messenger.R
2021-07-09 05:18:48 +02:00
import org.thoughtcrime.securesms.util.animateSizeChange
import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.toPx
2021-06-17 07:20:19 +02:00
import org.thoughtcrime.securesms.util.DateUtils
import java.util.*
2021-06-16 06:50:41 +02:00
class InputBarRecordingView : RelativeLayout {
2021-06-17 07:20:19 +02:00
private var startTimestamp = 0L
private val snHandler = Handler(Looper.getMainLooper())
private var dotViewAnimation: ValueAnimator? = null
private var pulseAnimation: ValueAnimator? = null
var delegate: InputBarRecordingViewDelegate? = null
2021-06-16 06:50:41 +02:00
constructor(context: Context) : super(context) { initialize() }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() }
private fun initialize() {
LayoutInflater.from(context).inflate(R.layout.view_input_bar_recording, this)
2021-06-17 02:53:56 +02:00
inputBarMiddleContentContainer.disableClipping()
inputBarCancelButton.setOnClickListener { hide() }
2021-06-16 06:50:41 +02:00
}
2021-06-16 07:49:39 +02:00
fun show() {
2021-06-17 07:20:19 +02:00
startTimestamp = Date().time
recordButtonOverlayImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_microphone, context.theme))
2021-06-18 01:51:44 +02:00
inputBarCancelButton.alpha = 0.0f
inputBarMiddleContentContainer.alpha = 1.0f
lockView.alpha = 1.0f
2021-06-16 07:49:39 +02:00
isVisible = true
alpha = 0.0f
val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f)
animation.duration = 250L
animation.addUpdateListener { animator ->
alpha = animator.animatedValue as Float
}
animation.start()
2021-06-16 07:54:00 +02:00
animateDotView()
2021-06-16 07:49:39 +02:00
pulse()
2021-06-17 03:24:54 +02:00
animateLockViewUp()
2021-06-17 07:20:19 +02:00
updateTimer()
2021-06-16 07:49:39 +02:00
}
fun hide() {
alpha = 1.0f
val animation = ValueAnimator.ofObject(FloatEvaluator(), 1.0f, 0.0f)
animation.duration = 250L
animation.addUpdateListener { animator ->
alpha = animator.animatedValue as Float
if (animator.animatedFraction == 1.0f) {
isVisible = false
dotViewAnimation?.repeatCount = 0
pulseAnimation?.removeAllUpdateListeners()
}
}
animation.start()
2021-06-18 07:54:24 +02:00
delegate?.handleVoiceMessageUIHidden()
}
2021-06-16 07:54:00 +02:00
private fun animateDotView() {
val animation = ValueAnimator.ofObject(FloatEvaluator(), 1.0f, 0.0f)
dotViewAnimation = animation
2021-06-16 07:54:00 +02:00
animation.duration = 500L
animation.addUpdateListener { animator ->
dotView.alpha = animator.animatedValue as Float
}
animation.repeatCount = ValueAnimator.INFINITE
animation.repeatMode = ValueAnimator.REVERSE
animation.start()
}
2021-06-16 07:49:39 +02:00
private fun pulse() {
val collapsedSize = toPx(80.0f, resources)
val expandedSize = toPx(104.0f, resources)
pulseView.animateSizeChange(collapsedSize, expandedSize, 1000)
val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.5, 0.0f)
pulseAnimation = animation
2021-06-16 07:49:39 +02:00
animation.duration = 1000L
animation.addUpdateListener { animator ->
pulseView.alpha = animator.animatedValue as Float
if (animator.animatedFraction == 1.0f && isVisible) { pulse() }
2021-06-16 07:49:39 +02:00
}
animation.start()
}
2021-06-17 03:24:54 +02:00
private fun animateLockViewUp() {
val startMarginBottom = toPx(32, resources)
val endMarginBottom = toPx(72, resources)
val layoutParams = lockView.layoutParams as LayoutParams
layoutParams.bottomMargin = startMarginBottom
lockView.layoutParams = layoutParams
val animation = ValueAnimator.ofObject(IntEvaluator(), startMarginBottom, endMarginBottom)
animation.duration = 250L
animation.addUpdateListener { animator ->
layoutParams.bottomMargin = animator.animatedValue as Int
lockView.layoutParams = layoutParams
}
animation.start()
}
2021-06-17 06:01:43 +02:00
2021-06-17 07:20:19 +02:00
private fun updateTimer() {
val duration = (Date().time - startTimestamp) / 1000L
recordingViewDurationTextView.text = DateUtils.formatElapsedTime(duration)
snHandler.postDelayed({ updateTimer() }, 500)
}
2021-06-17 06:01:43 +02:00
fun lock() {
val fadeOutAnimation = ValueAnimator.ofObject(FloatEvaluator(), 1.0f, 0.0f)
fadeOutAnimation.duration = 250L
fadeOutAnimation.addUpdateListener { animator ->
inputBarMiddleContentContainer.alpha = animator.animatedValue as Float
lockView.alpha = animator.animatedValue as Float
}
fadeOutAnimation.start()
val fadeInAnimation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f)
fadeInAnimation.duration = 250L
fadeInAnimation.addUpdateListener { animator ->
inputBarCancelButton.alpha = animator.animatedValue as Float
}
fadeInAnimation.start()
recordButtonOverlayImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_arrow_up, context.theme))
recordButtonOverlay.setOnClickListener { delegate?.sendVoiceMessage() }
inputBarCancelButton.setOnClickListener { delegate?.cancelVoiceMessage() }
2021-06-17 06:01:43 +02:00
}
2021-06-16 06:50:41 +02:00
}
interface InputBarRecordingViewDelegate {
2021-06-18 07:54:24 +02:00
fun handleVoiceMessageUIHidden()
fun sendVoiceMessage()
fun cancelVoiceMessage()
}