diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt index bcc095ad2d..ea91b3a6d0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt @@ -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 diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt new file mode 100644 index 0000000000..0a311c9b1a --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/views/GlowView.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/views/GlowView.kt index e48a67fbc9..e99e6f601a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/views/GlowView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/views/GlowView.kt @@ -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 -} \ No newline at end of file +} + +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 +} diff --git a/app/src/main/res/drawable/input_bar_button_background.xml b/app/src/main/res/drawable/input_bar_button_background.xml index 68f8684bc1..4de519558a 100644 --- a/app/src/main/res/drawable/input_bar_button_background.xml +++ b/app/src/main/res/drawable/input_bar_button_background.xml @@ -1,17 +1,4 @@ - - - - - - - - - - - - - \ No newline at end of file + android:shape="oval" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_conversation_v2_action_bar.xml b/app/src/main/res/layout/activity_conversation_v2_action_bar.xml index 04e4013170..4716171f50 100644 --- a/app/src/main/res/layout/activity_conversation_v2_action_bar.xml +++ b/app/src/main/res/layout/activity_conversation_v2_action_bar.xml @@ -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" /> \ No newline at end of file diff --git a/app/src/main/res/layout/view_conversation.xml b/app/src/main/res/layout/view_conversation.xml index 55dbbff04b..c661335caa 100644 --- a/app/src/main/res/layout/view_conversation.xml +++ b/app/src/main/res/layout/view_conversation.xml @@ -1,5 +1,6 @@ - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_input_bar.xml b/app/src/main/res/layout/view_input_bar.xml index 4250c3c8be..997122f190 100644 --- a/app/src/main/res/layout/view_input_bar.xml +++ b/app/src/main/res/layout/view_input_bar.xml @@ -1,7 +1,6 @@ @@ -16,23 +15,12 @@ android:layout_height="match_parent"> - - - - + android:layout_marginStart="@dimen/small_spacing" /> - - - - + android:layout_marginEnd="@dimen/small_spacing" /> diff --git a/app/src/main/res/layout/view_input_bar_button.xml b/app/src/main/res/layout/view_input_bar_button.xml new file mode 100644 index 0000000000..096c616ab6 --- /dev/null +++ b/app/src/main/res/layout/view_input_bar_button.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-notnight-v21/colors.xml b/app/src/main/res/values-notnight-v21/colors.xml index 95021ff8b0..2a82dabd1d 100644 --- a/app/src/main/res/values-notnight-v21/colors.xml +++ b/app/src/main/res/values-notnight-v21/colors.xml @@ -21,7 +21,7 @@ #0D000000 #FFFFFF #FCFCFC - #0D000000 + #F2F2F2 #ffffff #fcfcfc diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e61ab9ccac..b1ad8d9715 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -28,7 +28,7 @@ #0DFFFFFF #000000 #171717 - #0DFFFFFF + #0D0D0D #5ff8b0 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index fd05d71d76..0afc835242 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -37,6 +37,8 @@ 8dp 16dp 56dp + 40dp + 48dp 8dp