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
}

View File

@ -1,17 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/accent">
<item
android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="@color/white" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="@color/input_bar_button_background" />
</shape>
</item>
</ripple>
android:shape="oval" />

View File

@ -19,6 +19,8 @@
android:text="Elon"
android:textColor="@color/text"
android:textStyle="bold"
android:textSize="@dimen/very_large_font_size" />
android:textSize="@dimen/very_large_font_size"
android:maxLines="1"
android:ellipsize="end" />
</LinearLayout>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -116,13 +117,6 @@
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="@dimen/medium_spacing"
android:background="?android:dividerHorizontal" />
</FrameLayout>
</LinearLayout>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/input_bar_height"
android:orientation="vertical">
@ -16,23 +15,12 @@
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/attachmentsButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:id="@+id/attachmentsButtonContainer"
android:layout_width="@dimen/input_bar_button_expanded_size"
android:layout_height="@dimen/input_bar_button_expanded_size"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/small_spacing"
android:background="@drawable/input_bar_button_background">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:scaleType="centerInside"
android:layout_centerInParent="true"
android:src="@drawable/ic_plus_24"
app:tint="@color/text" />
</RelativeLayout>
android:layout_marginStart="@dimen/small_spacing" />
<TextView
android:layout_width="wrap_content"
@ -43,23 +31,12 @@
android:background="@color/red" />
<RelativeLayout
android:id="@+id/microphoneButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:id="@+id/microphoneButtonContainer"
android:layout_width="@dimen/input_bar_button_expanded_size"
android:layout_height="@dimen/input_bar_button_expanded_size"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/small_spacing"
android:background="@drawable/input_bar_button_background">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:scaleType="centerInside"
android:layout_centerInParent="true"
android:src="@drawable/ic_microphone"
app:tint="@color/text" />
</RelativeLayout>
android:layout_marginEnd="@dimen/small_spacing" />
</RelativeLayout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/inputBarButton"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/input_bar_button_background">
<ImageView
android:id="@+id/inputBarButtonImageView"
android:layout_width="16dp"
android:layout_height="16dp"
android:scaleType="centerInside"
android:layout_centerInParent="true"
android:src="@drawable/ic_plus_24"
app:tint="@color/text" />
</RelativeLayout>

View File

@ -21,7 +21,7 @@
<color name="open_group_chip_color">#0D000000</color>
<color name="message_selected">#FFFFFF</color>
<color name="input_bar_background">#FCFCFC</color>
<color name="input_bar_button_background">#0D000000</color>
<color name="input_bar_button_background">#F2F2F2</color>
<color name="default_background_start">#ffffff</color>
<color name="default_background_end">#fcfcfc</color>

View File

@ -28,7 +28,7 @@
<color name="open_group_chip_color">#0DFFFFFF</color>
<color name="message_selected">#000000</color>
<color name="input_bar_background">#171717</color>
<color name="input_bar_button_background">#0DFFFFFF</color>
<color name="input_bar_button_background">#0D0D0D</color>
<array name="profile_picture_placeholder_colors">
<item>#5ff8b0</item>

View File

@ -37,6 +37,8 @@
<dimen name="path_row_dot_size">8dp</dimen>
<dimen name="path_row_expanded_dot_size">16dp</dimen>
<dimen name="input_bar_height">56dp</dimen>
<dimen name="input_bar_button_collapsed_size">40dp</dimen>
<dimen name="input_bar_button_expanded_size">48dp</dimen>
<!-- Distances -->
<dimen name="small_spacing">8dp</dimen>