Implement InputBarButton

This commit is contained in:
Niels Andriesse
2021-06-15 14:05:32 +10:00
parent acc472bbad
commit 5755f4150a
11 changed files with 182 additions and 58 deletions

View File

@@ -4,11 +4,15 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import android.widget.RelativeLayout
import kotlinx.android.synthetic.main.view_input_bar.view.*
import network.loki.messenger.R
class InputBar : LinearLayout {
private val attachmentsButton by lazy { InputBarButton(context, R.drawable.ic_plus_24) }
private val microphoneButton by lazy { InputBarButton(context, R.drawable.ic_microphone) }
// region Lifecycle
constructor(context: Context) : super(context) {
setUpViewHierarchy()
@@ -24,7 +28,11 @@ class InputBar : LinearLayout {
private fun setUpViewHierarchy() {
LayoutInflater.from(context).inflate(R.layout.view_input_bar, this)
attachmentsButtonContainer.addView(attachmentsButton)
attachmentsButton.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
attachmentsButton.setOnClickListener { }
microphoneButtonContainer.addView(microphoneButton)
microphoneButton.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
microphoneButton.setOnClickListener { }
}
// endregion

View File

@@ -0,0 +1,100 @@
package org.thoughtcrime.securesms.conversation.v2.input_bar
import android.animation.PointFEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.PointF
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.annotation.DrawableRes
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
import org.thoughtcrime.securesms.loki.views.InputBarButtonImageViewContainer
class InputBarButton : RelativeLayout {
@DrawableRes private var iconID = 0
companion object {
val animationDuration = 250.toLong()
}
private val expandedImageViewPosition by lazy { PointF(0.0f, 0.0f) }
private val collapsedImageViewPosition by lazy { PointF((expandedSize - collapsedSize) / 2, (expandedSize - collapsedSize) / 2) }
val expandedSize by lazy { resources.getDimension(R.dimen.input_bar_button_expanded_size) }
val collapsedSize by lazy { resources.getDimension(R.dimen.input_bar_button_collapsed_size) }
private val imageViewContainer by lazy {
val result = InputBarButtonImageViewContainer(context)
val size = collapsedSize.toInt()
result.layoutParams = LayoutParams(size, size)
result.setBackgroundResource(R.drawable.input_bar_button_background)
result.mainColor = resources.getColorWithID(R.color.input_bar_button_background, context.theme)
result
}
private val imageView by lazy {
val result = ImageView(context)
val size = toPx(16, resources)
result.layoutParams = LayoutParams(size, size)
result.scaleType = ImageView.ScaleType.CENTER_INSIDE
result.setImageResource(iconID)
result.imageTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.text, context.theme))
result
}
constructor(context: Context) : super(context) { throw IllegalAccessException("Use InputBarButton(context:iconID:) instead.") }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { throw IllegalAccessException("Use InputBarButton(context:iconID:) instead.") }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { throw IllegalAccessException("Use InputBarButton(context:iconID:) instead.") }
constructor(context: Context, @DrawableRes iconID: Int) : super(context) {
this.iconID = iconID
val size = resources.getDimension(R.dimen.input_bar_button_expanded_size).toInt()
val layoutParams = LayoutParams(size, size)
this.layoutParams = layoutParams
addView(imageViewContainer)
imageViewContainer.x = collapsedImageViewPosition.x
imageViewContainer.y = collapsedImageViewPosition.y
imageViewContainer.addView(imageView)
val imageViewLayoutParams = imageView.layoutParams as LayoutParams
imageViewLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT)
imageView.layoutParams = imageViewLayoutParams
gravity = Gravity.TOP or Gravity.LEFT // Intentionally not Gravity.START
}
fun expand() {
GlowViewUtilities.animateColorChange(context, imageViewContainer, R.color.input_bar_button_background, R.color.accent)
imageViewContainer.animateSizeChange(R.dimen.input_bar_button_collapsed_size, R.dimen.input_bar_button_expanded_size, animationDuration)
animateImageViewContainerPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
}
fun collapse() {
GlowViewUtilities.animateColorChange(context, imageViewContainer, R.color.accent, R.color.input_bar_button_background)
imageViewContainer.animateSizeChange(R.dimen.input_bar_button_expanded_size, R.dimen.input_bar_button_collapsed_size, animationDuration)
animateImageViewContainerPositionChange(expandedImageViewPosition, collapsedImageViewPosition)
}
private fun animateImageViewContainerPositionChange(startPosition: PointF, endPosition: PointF) {
val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition)
animation.duration = animationDuration
animation.addUpdateListener { animator ->
val point = animator.animatedValue as PointF
imageViewContainer.x = point.x
imageViewContainer.y = point.y
}
animation.start()
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> { expand() }
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { collapse() }
}
return true
}
}

View File

@@ -7,9 +7,12 @@ import android.graphics.*
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.appcompat.widget.AppCompatImageView
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.loki.utilities.toPx
@@ -155,4 +158,36 @@ class PathDotView : View, GlowView {
super.onDraw(c)
}
// endregion
}
}
class InputBarButtonImageViewContainer : RelativeLayout, GlowView {
@ColorInt override var mainColor: Int = 0
set(newValue) { field = newValue; paint.color = newValue }
@ColorInt override var sessionShadowColor: Int = 0 // Unused
private val paint: Paint by lazy {
val result = Paint()
result.style = Paint.Style.FILL
result.isAntiAlias = true
result
}
// region Lifecycle
constructor(context: Context) : super(context) { }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { }
init {
setWillNotDraw(false)
}
// endregion
// region Updating
override fun onDraw(c: Canvas) {
val w = width.toFloat()
val h = height.toFloat()
c.drawCircle(w / 2, h / 2, w / 2, paint)
super.onDraw(c)
}
// endregion
}