Add brush width preview.
This commit is contained in:
parent
f86c1fe508
commit
bd4dd25460
4 changed files with 102 additions and 1 deletions
|
@ -39,4 +39,4 @@ internal class ImageEditorValues internal constructor(store: KeyValueStore) : Si
|
||||||
fun getHighlighterWidthRange(): Pair<Float, Float> = Pair(0.03f, 0.08f)
|
fun getHighlighterWidthRange(): Pair<Float, Float> = Pair(0.03f, 0.08f)
|
||||||
|
|
||||||
fun getBlurWidthRange(): Pair<Float, Float> = Pair(0.052f, 0.092f)
|
fun getBlurWidthRange(): Pair<Float, Float> = Pair(0.052f, 0.092f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,7 @@ class ImageEditorHudV2 @JvmOverloads constructor(
|
||||||
private val delete: FrameLayout = findViewById(R.id.image_editor_hud_delete)
|
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 deleteBackground: View = findViewById(R.id.image_editor_hud_delete_bg)
|
||||||
private val bottomGuideline: Guideline = findViewById(R.id.image_editor_bottom_guide)
|
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<View> = setOf(drawButton, textButton, stickerButton, blurButton)
|
private val selectableSet: Set<View> = setOf(drawButton, textButton, stickerButton, blurButton)
|
||||||
|
|
||||||
|
@ -172,6 +173,7 @@ class ImageEditorHudV2 @JvmOverloads constructor(
|
||||||
widthSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
widthSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||||
listener?.onBrushWidthChange()
|
listener?.onBrushWidthChange()
|
||||||
|
brushPreview.setThickness(getActiveBrushWidth())
|
||||||
|
|
||||||
when (currentMode) {
|
when (currentMode) {
|
||||||
Mode.DRAW -> SignalStore.imageEditorValues().setMarkerPercentage(progress)
|
Mode.DRAW -> SignalStore.imageEditorValues().setMarkerPercentage(progress)
|
||||||
|
@ -188,8 +190,10 @@ class ImageEditorHudV2 @JvmOverloads constructor(
|
||||||
widthSeekBar.setOnTouchListener { v, event ->
|
widthSeekBar.setOnTouchListener { v, event ->
|
||||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||||
animateWidthSeekbarIn()
|
animateWidthSeekbarIn()
|
||||||
|
brushPreview.show()
|
||||||
} else if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) {
|
} else if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) {
|
||||||
animateWidthSeekbarOut()
|
animateWidthSeekbarOut()
|
||||||
|
brushPreview.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
v.onTouchEvent(event)
|
v.onTouchEvent(event)
|
||||||
|
@ -449,6 +453,8 @@ class ImageEditorHudV2 @JvmOverloads constructor(
|
||||||
private fun updateColorIndicator() {
|
private fun updateColorIndicator() {
|
||||||
colorIndicator.drawable.colorFilter = SimpleColorFilter(drawSeekBar.getColor())
|
colorIndicator.drawable.colorFilter = SimpleColorFilter(drawSeekBar.getColor())
|
||||||
colorIndicator.translationX = (drawSeekBar.thumb.bounds.left.toFloat() + ViewUtil.dpToPx(16))
|
colorIndicator.translationX = (drawSeekBar.thumb.bounds.left.toFloat() + ViewUtil.dpToPx(16))
|
||||||
|
brushPreview.setColor(drawSeekBar.getColor())
|
||||||
|
brushPreview.setBlur(currentMode == Mode.BLUR)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun animateModeChange(
|
private fun animateModeChange(
|
||||||
|
|
|
@ -405,4 +405,12 @@
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.scribbles.BrushWidthPreviewView
|
||||||
|
android:id="@+id/image_editor_hud_brush_preview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
|
android:alpha="0"
|
||||||
|
tools:alpha="1" />
|
||||||
</merge>
|
</merge>
|
Loading…
Add table
Reference in a new issue