Skip to content

Commit

Permalink
* Implement multi brush color for Graphics note
Browse files Browse the repository at this point in the history
* Do not resize/push up layout when opening soft keyboard to prevent views being overlapped
* Modify Paste text's ripple effect
  • Loading branch information
tuancoltech committed Jun 25, 2024
1 parent e0d33d8 commit 22e81ab
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 35 deletions.
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
tools:targetApi="31">
<activity
android:name=".ui.activities.MainActivity"
android:windowSoftInputMode="adjustResize"
android:windowSoftInputMode="adjustNothing"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/graphics/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dev.arkbuilders.arkmemo.graphics

enum class Color(val code: Int, val value: String) {

BLACK(ColorCode.black, "black"),

GRAY(ColorCode.gray, "gray"),

RED(ColorCode.red, "red"),

ORANGE(ColorCode.orange, "orange"),

GREEN(ColorCode.green, "green"),

BLUE(ColorCode.blue, "blue"),

PURPLE(ColorCode.purple, "purple")
}
11 changes: 11 additions & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/graphics/ColorCode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.arkbuilders.arkmemo.graphics

object ColorCode {
val black by lazy { android.graphics.Color.parseColor("#000000") }
val gray by lazy { android.graphics.Color.parseColor("#667085") }
val red by lazy { android.graphics.Color.parseColor("#F04438") }
val orange by lazy { android.graphics.Color.parseColor("#F79009") }
val green by lazy { android.graphics.Color.parseColor("#17B26A") }
val blue by lazy { android.graphics.Color.parseColor("#0BA5EC") }
val purple by lazy { android.graphics.Color.parseColor("#7A5AF8") }
}
95 changes: 71 additions & 24 deletions app/src/main/java/dev/arkbuilders/arkmemo/graphics/SVG.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.arkbuilders.arkmemo.graphics

import android.graphics.Color
import android.graphics.Paint
import android.util.Log
import android.graphics.Path as AndroidDrawPath
Expand All @@ -12,22 +11,48 @@ import kotlin.io.path.reader
import kotlin.io.path.writer

class SVG {
private var strokeColor = "black"
private var strokeColor = Color.BLACK.value
private var fill = "none"
private var viewBox = ViewBox()
private val commands = ArrayDeque<SVGCommand>()
private val paths = ArrayDeque<DrawPath>()

private val paint
get() = Paint().also {
it.color = Color.parseColor(strokeColor)
it.color = strokeColor.getColorCode()
it.style = Paint.Style.STROKE
it.strokeWidth = 10f
it.strokeCap = Paint.Cap.ROUND
it.strokeJoin = Paint.Join.ROUND
it.isAntiAlias = true
}

fun Int.getStrokeColor(): String {
return when (this) {
Color.BLACK.code -> Color.BLACK.value
Color.GRAY.code -> Color.GRAY.value
Color.RED.code -> Color.RED.value
Color.GREEN.code -> Color.GREEN.value
Color.BLUE.code -> Color.BLUE.value
Color.PURPLE.code -> Color.PURPLE.value
Color.ORANGE.code -> Color.ORANGE.value
else -> Color.BLACK.value
}
}

private fun String.getColorCode(): Int {
return when (this) {
Color.BLACK.value -> Color.BLACK.code
Color.GRAY.value -> Color.GRAY.code
Color.RED.value -> Color.RED.code
Color.GREEN.value -> Color.GREEN.code
Color.BLUE.value -> Color.BLUE.code
Color.PURPLE.value -> Color.PURPLE.code
Color.ORANGE.value -> Color.ORANGE.code
else -> Color.BLACK.code
}
}

fun addCommand(command: SVGCommand) {
commands.addLast(command)
}
Expand Down Expand Up @@ -80,6 +105,7 @@ class SVG {
if (paths.isNotEmpty()) paths.clear()
var path = AndroidDrawPath()
commands.forEach { command ->
strokeColor = command.paintColor
when (command) {
is SVGCommand.MoveTo -> {
path = AndroidDrawPath()
Expand All @@ -94,7 +120,7 @@ class SVG {
path.lineTo(command.x, command.y)
}
}
paths.addLast(DrawPath(path, paint))
paths.addLast(DrawPath(path, paint.apply { color = strokeColor.getColorCode() }))
}
}
}
Expand Down Expand Up @@ -139,15 +165,31 @@ class SVG {
pathData.split(COMMA).forEach {
val command = it.trim()
if (command.isEmpty()) return@forEach
val commandElements = command.split(" ")
when (command.first()) {
SVGCommand.MoveTo.CODE -> {
commands.addLast(SVGCommand.MoveTo.fromString(command))
if (commandElements.size > 3) {
strokeColor = commandElements[3]
}
commands.addLast(SVGCommand.MoveTo.fromString(command).apply {
paintColor = strokeColor
})
}
SVGCommand.AbsLineTo.CODE -> {
commands.addLast(SVGCommand.MoveTo.fromString(command))
if (commandElements.size > 3) {
strokeColor = commandElements[3]
}
commands.addLast(SVGCommand.MoveTo.fromString(command).apply {
paintColor = strokeColor
})
}
SVGCommand.AbsQuadTo.CODE -> {
commands.addLast(SVGCommand.AbsQuadTo.fromString(command))
if (commandElements.size > 6) {
strokeColor = commandElements[5]
}
commands.addLast(SVGCommand.AbsQuadTo.fromString(command).apply {
paintColor = strokeColor
})
}
else -> {}
}
Expand Down Expand Up @@ -193,20 +235,23 @@ data class ViewBox(

sealed class SVGCommand {

var paintColor = Color.BLACK.value

class MoveTo(
val x: Float,
val y: Float
) : SVGCommand() {
override fun toString(): String = "$CODE $x $y"
override fun toString(): String = "$CODE $x $y $paintColor"

companion object {
const val CODE = 'M'

fun fromString(string: String): SVGCommand {
val coords = string.removePrefix("$CODE").trim().split(" ")
val x = coords[0].toFloat()
val y = coords[1].toFloat()
return MoveTo(x, y)
val params = string.removePrefix("$CODE").trim().split(" ")
val x = params[0].toFloat()
val y = params[1].toFloat()
val colorCode = if (params.size > 2) params[0] else Color.BLACK.value
return MoveTo(x, y).apply { paintColor = colorCode }
}
}
}
Expand All @@ -215,16 +260,17 @@ sealed class SVGCommand {
val x: Float,
val y: Float
) : SVGCommand() {
override fun toString(): String = "$CODE $x $y"
override fun toString(): String = "$CODE $x $y $paintColor"

companion object {
const val CODE = 'L'

fun fromString(string: String): SVGCommand {
val coords = string.removePrefix("$CODE").trim().split(" ")
val x = coords[0].toFloat()
val y = coords[1].toFloat()
return AbsLineTo(x, y)
val params = string.removePrefix("$CODE").trim().split(" ")
val x = params[0].toFloat()
val y = params[1].toFloat()
val colorCode = if (params.size > 2) params[0] else Color.BLACK.value
return AbsLineTo(x, y).apply { paintColor = colorCode}
}
}
}
Expand All @@ -235,18 +281,19 @@ sealed class SVGCommand {
val x2: Float,
val y2: Float
) : SVGCommand() {
override fun toString(): String = "$CODE $x1 $y1 $x2 $y2"
override fun toString(): String = "$CODE $x1 $y1 $x2 $y2 $paintColor"

companion object {
const val CODE = 'Q'

fun fromString(string: String): SVGCommand {
val coords = string.removePrefix("$CODE").trim().split(" ")
val x1 = coords[0].toFloat()
val y1 = coords[1].toFloat()
val x2 = coords[2].toFloat()
val y2 = coords[3].toFloat()
return AbsQuadTo(x1, y1, x2, y2)
val params = string.removePrefix("$CODE").trim().split(" ")
val x1 = params[0].toFloat()
val y1 = params[1].toFloat()
val x2 = params[2].toFloat()
val y2 = params[3].toFloat()
val colorCode = if (params.size > 4) params[0] else Color.BLACK.value
return AbsQuadTo(x1, y1, x2, y2).apply { paintColor = colorCode }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import dev.arkbuilders.arkmemo.R
import dev.arkbuilders.arkmemo.models.GraphicNote
import dev.arkbuilders.arkmemo.models.Note
import dev.arkbuilders.arkmemo.ui.adapters.BrushAdapter
import dev.arkbuilders.arkmemo.ui.adapters.BrushColor
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorBlack
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorBlue
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorGreen
Expand Down Expand Up @@ -231,6 +232,7 @@ class EditGraphicNotesFragment: BaseEditNoteFragment() {
},
onItemClick = { attribute, pos ->
Log.v(TAG, "onColorSelected: " + attribute)
graphicNotesViewModel.setPaintColor(attribute as BrushColor)
}
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package dev.arkbuilders.arkmemo.ui.viewmodels

import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.arkbuilders.arkmemo.models.GraphicNote
import dev.arkbuilders.arkmemo.graphics.SVG
import dev.arkbuilders.arkmemo.models.GraphicNote
import dev.arkbuilders.arkmemo.ui.adapters.BrushColor
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorBlack
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorBlue
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorGreen
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorGrey
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorOrange
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorPurple
import dev.arkbuilders.arkmemo.ui.adapters.BrushColorRed
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
Expand All @@ -20,7 +27,7 @@ class GraphicNotesViewModel @Inject constructor(): ViewModel() {

private val _notes = MutableStateFlow(listOf<GraphicNote>())
val notes: StateFlow<List<GraphicNote>> = _notes
private var paintColor = Color.BLACK
private var paintColor = dev.arkbuilders.arkmemo.graphics.Color.BLACK.code

private var strokeWidth = 10f

Expand Down Expand Up @@ -64,9 +71,21 @@ class GraphicNotesViewModel @Inject constructor(): ViewModel() {
fun paths(): Collection<DrawPath> = editPaths

fun svg(): SVG = svg

fun setPaintColor(color: BrushColor) {
paintColor = when (color) {
is BrushColorBlack -> dev.arkbuilders.arkmemo.graphics.Color.BLACK.code
is BrushColorGrey -> dev.arkbuilders.arkmemo.graphics.Color.GRAY.code
is BrushColorRed -> dev.arkbuilders.arkmemo.graphics.Color.RED.code
is BrushColorOrange -> dev.arkbuilders.arkmemo.graphics.Color.ORANGE.code
is BrushColorGreen -> dev.arkbuilders.arkmemo.graphics.Color.GREEN.code
is BrushColorBlue -> dev.arkbuilders.arkmemo.graphics.Color.BLUE.code
is BrushColorPurple -> dev.arkbuilders.arkmemo.graphics.Color.PURPLE.code
}
}
}

data class DrawPath(
val path: Path,
val paint: Paint
val paint: Paint,
)
14 changes: 10 additions & 4 deletions app/src/main/java/dev/arkbuilders/arkmemo/ui/views/NotesCanvas.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class NotesCanvas(context: Context, attrs: AttributeSet): View(context, attrs) {
val paths = viewModel.paths()
if (paths.isNotEmpty()) {
paths.forEach {
canvas.drawPath(it.path, it.paint)
canvas.drawPath(it.path, it.paint.apply { color = it.paint.color })
}
}
}
Expand All @@ -34,7 +34,9 @@ class NotesCanvas(context: Context, attrs: AttributeSet): View(context, attrs) {
MotionEvent.ACTION_DOWN -> {
path.moveTo(x, y)
viewModel.svg().apply {
addCommand(SVGCommand.MoveTo(x, y))
addCommand(SVGCommand.MoveTo(x, y).apply {
paintColor = viewModel.paint.color.getStrokeColor()
})
}
currentX = x
currentY = y
Expand All @@ -44,7 +46,9 @@ class NotesCanvas(context: Context, attrs: AttributeSet): View(context, attrs) {
val y2 = (currentY + y) / 2
path.quadTo(currentX, currentY, x2, y2)
viewModel.svg().apply {
addCommand(SVGCommand.AbsQuadTo(currentX, currentY, x2, y2))
addCommand(SVGCommand.AbsQuadTo(currentX, currentY, x2, y2).apply {
paintColor = viewModel.paint.color.getStrokeColor()
})
}
currentX = x
currentY = y
Expand All @@ -53,7 +57,9 @@ class NotesCanvas(context: Context, attrs: AttributeSet): View(context, attrs) {
path = Path()
}
}
val drawPath = DrawPath(path, viewModel.paint)
val drawPath = DrawPath(path, viewModel.paint.apply {
color = viewModel.paint.color
})
viewModel.onDrawPath(drawPath)
invalidate()
return true
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/fragment_edit_notes_v2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
<TextView
android:id="@+id/tv_paste"
style="@style/ActionTextView"
android:background="?attr/selectableItemBackgroundBorderless"
android:background="?attr/selectableItemBackground"
android:foreground="@null"
android:drawablePadding="6dp"
android:text="@string/paste"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<color name="bg_tag">#FFFAEB</color>
<color name="fg_secondary">#344054</color>
<color name="bg_error">#F04438</color>
<color name="brush_color_black">#101828</color>
<color name="brush_color_black">#000000</color>
<color name="brush_color_grey">#667085</color>
<color name="brush_color_red">#F04438</color>
<color name="brush_color_orange">#F79009</color>
Expand Down

0 comments on commit 22e81ab

Please sign in to comment.