Загрузка данных
package com.example.drawingboard
import android.content.ContentValues
import android.graphics.Bitmap
import android.graphics.Paint
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.asAndroidPath
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import java.io.OutputStream
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
DrawingScreen()
}
}
}
}
data class DrawPath(
val path: Path,
val color: Color
)
@Composable
fun DrawingScreen() {
val context = LocalContext.current
val paths = remember { mutableStateListOf<DrawPath>() }
var currentPath by remember {
mutableStateOf(Path())
}
var currentColor by remember {
mutableStateOf(Color.Black)
}
var showDialog by remember {
mutableStateOf(false)
}
Column(
modifier = Modifier.fillMaxSize()
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(onClick = {
saveDrawing(context, paths)
}) {
Text("Сохранить")
}
Button(onClick = {
paths.clear()
}) {
Text("Очистить")
}
}
Canvas(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
// Касания
.pointerInput(Unit) {
detectTapGestures(
onTap = {
paths.clear()
},
onLongPress = {
showDialog = true
}
)
}
// Рисование
.pointerInput(Unit) {
detectDragGestures(
onDragStart = { offset ->
currentPath = Path().apply {
moveTo(offset.x, offset.y)
}
paths.add(
DrawPath(currentPath, currentColor)
)
},
onDrag = { change, _ ->
currentPath.lineTo(
change.position.x,
change.position.y
)
}
)
}
) {
paths.forEach { drawPath ->
drawPath(
path = drawPath.path,
color = drawPath.color,
style = androidx.compose.ui.graphics.drawscope.Stroke(
width = 8f
)
)
}
}
}
// Диалог выбора цвета
if (showDialog) {
AlertDialog(
onDismissRequest = {
showDialog = false
},
title = {
Text("Выберите цвет")
},
text = {
Column {
ColorButton("Красный", Color.Red) {
currentColor = Color.Red
showDialog = false
}
ColorButton("Синий", Color.Blue) {
currentColor = Color.Blue
showDialog = false
}
ColorButton("Зелёный", Color.Green) {
currentColor = Color.Green
showDialog = false
}
ColorButton("Чёрный", Color.Black) {
currentColor = Color.Black
showDialog = false
}
}
},
confirmButton = {}
)
}
}
@Composable
fun ColorButton(
text: String,
color: Color,
onClick: () -> Unit
) {
Button(
onClick = onClick,
colors = ButtonDefaults.buttonColors(
containerColor = color
),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
) {
Text(text)
}
}
fun saveDrawing(
context: android.content.Context,
paths: List<DrawPath>
) {
val bitmap = Bitmap.createBitmap(
1080,
1920,
Bitmap.Config.ARGB_8888
)
val canvas = android.graphics.Canvas(bitmap)
canvas.drawColor(android.graphics.Color.WHITE)
val paint = Paint().apply {
style = Paint.Style.STROKE
strokeWidth = 8f
isAntiAlias = true
}
paths.forEach {
paint.color = when (it.color) {
Color.Red -> android.graphics.Color.RED
Color.Blue -> android.graphics.Color.BLUE
Color.Green -> android.graphics.Color.GREEN
else -> android.graphics.Color.BLACK
}
canvas.drawPath(
it.path.asAndroidPath(),
paint
)
}
val resolver = context.contentResolver
val contentValues = ContentValues().apply {
put(
MediaStore.MediaColumns.DISPLAY_NAME,
"drawing_${System.currentTimeMillis()}.png"
)
put(
MediaStore.MediaColumns.MIME_TYPE,
"image/png"
)
put(
MediaStore.MediaColumns.RELATIVE_PATH,
"Pictures/DrawingBoard"
)
}
val imageUri = resolver.insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
imageUri?.let {
val outputStream: OutputStream? =
resolver.openOutputStream(it)
outputStream?.use { stream ->
bitmap.compress(
Bitmap.CompressFormat.PNG,
100,
stream
)
}
Toast.makeText(
context,
"Изображение сохранено",
Toast.LENGTH_SHORT
).show()
}
}