Загрузка данных


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()
    }
}