Kotlin dilinde bir paint çizim uygulaması yapıyorum. Çizim, renklendirme, geri alma, temizleme, kaydetme vs. her şey çalışıyor. Ancak çizim yaparken formu değiştirdiğimde yaptığım çizimler kayboluyor. Biraz çizip başka bir forma geçip geri gelmek istiyorum ama çizimlerim silinmesin.
Kodlarım aşağıda
`package com.coding.curvedbottomnavigationapp
import android.content.Context
import android.graphics.*
import android.os.Environment
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.Toast // Toast kütüphanesi eklendi
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
class PaintView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private var currentPaint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
strokeWidth = 10f
color = Color.BLACK // Varsayılan renk siyah
}
private var strokeWidth = 10f
private var paintColor = Color.BLACK
// Her bir çizim yolunu ve ona karşılık gelen Paint nesnesini saklayacağımız yapı
private val paths = mutableListOf<Pair<Path, Paint>>()
private var currentPath: Path? = null
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// Tüm yolları ve onların kendi boyama stillerini çiz
for ((path, paint) in paths) {
canvas.drawPath(path, paint)
}
// Halen çizilmekte olan yolu çiz
currentPath?.let { canvas.drawPath(it, currentPaint) }
}
override fun onTouchEvent(event: MotionEvent): Boolean {
val point = PointF(event.x, event.y)
when (event.action) {
MotionEvent.ACTION_DOWN -> {
// Yeni bir yol oluştur ve onu mevcut boyama ayarlarıyla başlat
currentPath = Path().apply {
moveTo(point.x, point.y)
}
return true
}
MotionEvent.ACTION_MOVE -> {
// Yolu güncelle
currentPath?.lineTo(point.x, point.y)
}
MotionEvent.ACTION_UP -> {
// Çizim bitince yolu ve boyama ayarlarını sakla
currentPath?.let {
paths.add(Pair(it, Paint(currentPaint))) // Paint nesnesini kopyalayarak sakla
currentPath = null
}
}
}
invalidate() // Ekranı güncelle
return true
}
// Renk değiştirme fonksiyonu
fun setPaintColor(color: Int) {
paintColor = color
currentPaint.color = color // Mevcut boyama stiline yeni rengi uygula
invalidate()
}
// Kalem genişliği değiştirme fonksiyonu
fun setStrokeWidth(width: Float) {
strokeWidth = width
currentPaint.strokeWidth = width // Mevcut boyama stiline yeni kalem genişliğini uygula
invalidate()
}
// Geri alma fonksiyonu
fun undo() {
if (paths.isNotEmpty()) {
paths.removeAt(paths.size - 1)
invalidate()
}
}
// Tüm çizimleri temizleme fonksiyonu
fun clear() {
paths.clear()
invalidate()
}
// Çizimi kaydetme fonksiyonu
fun saveDrawing() {
// Çizimi bitmap olarak oluştur
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
draw(canvas) // Çizimi bitmape çiz
// Kaydetme işlemi
val file = File(context.getExternalFilesDir(null), "drawing_${System.currentTimeMillis()}.png")
try {
FileOutputStream(file).use { output ->
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output)
Toast.makeText(context, "Çizim kaydedildi: ${file.absolutePath}", Toast.LENGTH_LONG).show()
}
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(context, "Kaydetme işlemi başarısız.", Toast.LENGTH_SHORT).show()
}
}
}
package com.coding.curvedbottomnavigationapp.fragments
import android.Manifest
import android.content.pm.PackageManager
import android.graphics.Color
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.SeekBar
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.coding.curvedbottomnavigationapp.MainActivity
import com.coding.curvedbottomnavigationapp.R
import com.coding.curvedbottomnavigationapp.PaintView
import java.util.*
class HomeFragment : Fragment(), TextToSpeech.OnInitListener {
private lateinit var paintView: PaintView
private lateinit var buttonUndo: Button
private lateinit var buttonClear: Button
private lateinit var buttonSave: Button
private lateinit var seekBarStrokeWidth: SeekBar
private lateinit var tts: TextToSpeech // TTS tanımlandı
companion object {
private const val STORAGE_PERMISSION_CODE = 1001
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
paintView = view.findViewById(R.id.paintView)
buttonUndo = view.findViewById(R.id.buttonUndo)
buttonClear = view.findViewById(R.id.buttonClear)
buttonSave = view.findViewById(R.id.buttonSave)
seekBarStrokeWidth = view.findViewById(R.id.seekBarStrokeWidth)
// Text-to-Speech başlatma
tts = TextToSpeech(context, this)
// İzinleri kontrol et
requestStoragePermissions()
// Geri alma işlemi
buttonUndo.setOnClickListener {
paintView.undo()
playColorExplanation("Çizim geri alındı")
}
// Temizleme işlemi
buttonClear.setOnClickListener {
paintView.clear()
playColorExplanation("Ekran temizlendi")
}
// Kalem kalınlığını ayarlama
seekBarStrokeWidth.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
paintView.setStrokeWidth(progress.toFloat())
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
// Kaydetme işlemi
buttonSave.setOnClickListener {
paintView.saveDrawing() // Çizimi kaydet
playColorExplanation("Muhteşem bir resim kaydettin")
}
// Renk seçimi butonları için tıklama olaylarını ekleme
view.findViewById<Button>(R.id.buttonRed).setOnClickListener {
paintView.setPaintColor(Color.RED)
playColorExplanation("Kırmızı renk seçildi") // Sesli uyarı
}
view.findViewById<Button>(R.id.buttonGreen).setOnClickListener {
paintView.setPaintColor(Color.GREEN)
playColorExplanation("Yeşil renk seçildi") // Sesli uyarı
}
view.findViewById<Button>(R.id.buttonBlue).setOnClickListener {
paintView.setPaintColor(Color.BLUE)
playColorExplanation("Mavi renk seçildi") // Sesli uyarı
}
view.findViewById<Button>(R.id.buttonYellow).setOnClickListener {
paintView.setPaintColor(Color.YELLOW)
playColorExplanation("Sarı renk seçildi") // Sesli uyarı
}
view.findViewById<Button>(R.id.buttonBlack).setOnClickListener {
paintView.setPaintColor(Color.BLACK)
playColorExplanation("Siyah renk seçildi") // Sesli uyarı
}
}
// TTS başlatıldığında bu fonksiyon çalışır
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
// Dil olarak Türkçe seçiyoruz
val result = tts.setLanguage(Locale("tr", "TR"))
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
speakOut("Bu dil desteklenmiyor")
}
} else {
speakOut("Text to Speech başlatılamadı")
}
}
// Sesli mesaj oynatma fonksiyonu
private fun speakOut(message: String) {
tts.speak(message, TextToSpeech.QUEUE_FLUSH, null, "")
}
// Text-to-Speech ile renk seçimi açıklaması yaparken müziği durdurma ve yeniden başlatma
private fun playColorExplanation(message: String) {
(activity as? MainActivity)?.let { mainActivity ->
val wasPlaying = mainActivity.isMusicPlaying() // mediaPlayer yerine getter kullanılıyor
mainActivity.pauseMusic()
speakOut(message)
tts.setOnUtteranceCompletedListener {
// Eğer müzik başlangıçta çalıyorduysa tekrar başlat
if (wasPlaying) {
mainActivity.playMusic()
}
}
}
}
override fun onDestroy() {
// TTS kaynağını serbest bırak
if (tts != null) {
tts.stop()
tts.shutdown()
}
super.onDestroy()
}
private fun requestStoragePermissions() {
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), STORAGE_PERMISSION_CODE)
}
}
}`