diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ImageEditorValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ImageEditorValues.kt index b7579bd576..9510b4d4f5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ImageEditorValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/ImageEditorValues.kt @@ -39,4 +39,4 @@ internal class ImageEditorValues internal constructor(store: KeyValueStore) : Si fun getHighlighterWidthRange(): Pair = Pair(0.03f, 0.08f) fun getBlurWidthRange(): Pair = Pair(0.052f, 0.092f) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/BrushWidthPreviewView.kt b/app/src/main/java/org/thoughtcrime/securesms/scribbles/BrushWidthPreviewView.kt new file mode 100644 index 0000000000..0f3f3538a3 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/BrushWidthPreviewView.kt @@ -0,0 +1,87 @@ +package org.thoughtcrime.securesms.scribbles + +import android.animation.Animator +import android.animation.ObjectAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Rect +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.core.animation.doOnEnd +import org.thoughtcrime.securesms.imageeditor.Bounds +import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations +import org.thoughtcrime.securesms.util.ViewUtil +import org.thoughtcrime.securesms.util.visible + +class BrushWidthPreviewView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + + private val tmpRect = Rect() + + private var animator: Animator? = null + + private val backdropPaint = Paint().apply { + isAntiAlias = true + style = Paint.Style.FILL + color = Color.WHITE + } + + private val brushPaint = Paint().apply { + isAntiAlias = true + style = Paint.Style.FILL + color = Color.WHITE + } + + private var radius: Float = (0.03f * Bounds.FULL_BOUNDS.width() / 2f) + private var isBlur: Boolean = false + + fun setBlur(blur: Boolean) { + isBlur = blur + invalidate() + } + + fun setColor(@ColorInt color: Int) { + brushPaint.color = color + invalidate() + } + + fun setThickness(thickness: Float) { + radius = (thickness * Bounds.FULL_BOUNDS.width()) / 2f + invalidate() + } + + fun show() { + visible = true + animator?.cancel() + animator = ObjectAnimator.ofFloat(this, "alpha", 1f).apply { + interpolator = MediaAnimations.interpolator + duration = 150L + start() + } + } + + fun hide() { + animator?.cancel() + animator = ObjectAnimator.ofFloat(this, "alpha", 0f).apply { + interpolator = MediaAnimations.interpolator + duration = 150L + doOnEnd { visible = false } + start() + } + } + + override fun onDraw(canvas: Canvas) { + canvas.getClipBounds(tmpRect) + canvas.drawCircle(tmpRect.exactCenterX(), tmpRect.exactCenterY(), radius + ViewUtil.dpToPx(1), backdropPaint) + + if (!isBlur) { + canvas.drawCircle(tmpRect.exactCenterX(), tmpRect.exactCenterY(), radius, brushPaint) + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt index c4952e4228..4d2ad97471 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt @@ -68,6 +68,7 @@ class ImageEditorHudV2 @JvmOverloads constructor( private val delete: FrameLayout = findViewById(R.id.image_editor_hud_delete) private val deleteBackground: View = findViewById(R.id.image_editor_hud_delete_bg) private val bottomGuideline: Guideline = findViewById(R.id.image_editor_bottom_guide) + private val brushPreview: BrushWidthPreviewView = findViewById(R.id.image_editor_hud_brush_preview) private val selectableSet: Set = setOf(drawButton, textButton, stickerButton, blurButton) @@ -172,6 +173,7 @@ class ImageEditorHudV2 @JvmOverloads constructor( widthSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { listener?.onBrushWidthChange() + brushPreview.setThickness(getActiveBrushWidth()) when (currentMode) { Mode.DRAW -> SignalStore.imageEditorValues().setMarkerPercentage(progress) @@ -188,8 +190,10 @@ class ImageEditorHudV2 @JvmOverloads constructor( widthSeekBar.setOnTouchListener { v, event -> if (event.action == MotionEvent.ACTION_DOWN) { animateWidthSeekbarIn() + brushPreview.show() } else if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) { animateWidthSeekbarOut() + brushPreview.hide() } v.onTouchEvent(event) @@ -449,6 +453,8 @@ class ImageEditorHudV2 @JvmOverloads constructor( private fun updateColorIndicator() { colorIndicator.drawable.colorFilter = SimpleColorFilter(drawSeekBar.getColor()) colorIndicator.translationX = (drawSeekBar.thumb.bounds.left.toFloat() + ViewUtil.dpToPx(16)) + brushPreview.setColor(drawSeekBar.getColor()) + brushPreview.setBlur(currentMode == Mode.BLUR) } private fun animateModeChange( diff --git a/app/src/main/res/layout/v2_media_image_editor_hud.xml b/app/src/main/res/layout/v2_media_image_editor_hud.xml index 203ef5b9f4..2488ac0c14 100644 --- a/app/src/main/res/layout/v2_media_image_editor_hud.xml +++ b/app/src/main/res/layout/v2_media_image_editor_hud.xml @@ -405,4 +405,12 @@ + \ No newline at end of file