Canvasの画像保存とその利用を教えて欲しい!!!!
前提
AndroidStudioでKotlinを用いてルーレットの画像を作成し回転させるアプリを作っています。
回転に関してはある程度できたのですが、画像作成をした後の保存の部分がよくわかりません。
色々なことを調べてみてプログラム上ではエラーの表示はありませんが、仮想デバイス上でアプリを開いた時に”RouletteImage keeps stopping”(RouletteImageはアプリ名)というアラートダイアログが表示されアプリが開始されません。
実現したいこと
1,ルーレットの各項目の割合を所得しCanvasに円グラフのような画像を作成する
2,Canvas上の画像をアプリ内にPNGとして保存する
3,保存した画像を回転させる
現状2ができていないためその部分を質問しております。
そのため、1ができているか確認できていません。
3はサンプルの画像を回転させることができたので、ここは変えたいと考えておりません。
発生している問題・エラーメッセージ
仮想デバイスのアラートダイアログ上で以下のように通知されます。
AndroidStudio側ではエラー文は表示されていません。
該当のソースコード
package com.example.rouletteimage
import android.content.Context
import android.content.Intent
import android.graphics.*
import android.graphics.Bitmap.CompressFormat
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.View
import android.widget.Button
import android.widget.EditText
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import kotlin.properties.Delegates
class MainActivity : AppCompatActivity() {
private var paint: Paint = TODO()
private val paint1 = Paint()
private val paint2 = Paint()
private val paint3 = Paint()
private val paint4 = Paint()
private val paint5 = Paint()
private val paint6 = Paint()
private val paint7 = Paint()
private val paint8 = Paint()
private val paint9 = Paint()
private val paint10 = Paint()
private val dm = DisplayMetrics()
private val width = dm.widthPixels
private val height = dm.heightPixels
private var sum by Delegates.notNull<Float>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main)
val myView = MyView(this)
setContentView(myView)
val editTextTextPersonName = findViewById<EditText>(R.id.editTextTextPersonName)
val editTextNumber1 = findViewById<EditText>(R.id.editTextNumber1)
val editTextNumber2 = findViewById<EditText>(R.id.editTextNumber2)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val intent = Intent(this, RouletteScreen::class.java)
val etText1 = editTextTextPersonName.text.toString()
val etText2 = editTextNumber1.text.toString()
val etText3 = editTextNumber2.text.toString()
//intent変数をつなげる(第一引数はキー,第二引数は渡したい変数)
intent.putExtra("key1",etText1)
intent.putExtra("key2",etText2)
intent.putExtra("key3",etText3)
startActivity(intent)
finish()
}
}
// Viewを継承したクラス
internal inner class MyView(context: Context) : View(context) {
// init {
// }
@RequiresApi(Build.VERSION_CODES.N)
override fun onDraw(canvas: Canvas){
rouletteMaking(canvas,1f,1f,2f,1f,1f,5f,4f,1f,1f,1f)
}
}
@RequiresApi(Build.VERSION_CODES.N)
fun rouletteMaking(canvas: Canvas, a:Float, b:Float?, c:Float?, d:Float?, e:Float?, f:Float?, g:Float?, h:Float?, i:Float?, j:Float?) {
// 背景、半透明
canvas.drawColor(Color.argb(0, 0, 0, 0))
// 円
paint.color = Color.argb(255, 0, 0, 0)
paint.strokeWidth = 5f
paint.isAntiAlias = true
paint.style = Paint.Style.STROKE
// 分岐
if (height >= width) {
// 円
// (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径
canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), (width / 2.5).toFloat(), paint)
// 各項目
val rect = RectF((width / 10).toFloat(), (height / 2 - 2 * width / 5).toFloat(), (9 * width / 10).toFloat(), (height / 2 + 2 * width / 5).toFloat())
itemRation(canvas,rect, a, b, c, d, e, f, g, h, i, j)
} else {
// 円
canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), (height / 2.5).toFloat(), paint)
// 各項目
val rect = RectF((width / 2 - 2 * height / 5).toFloat(), (height / 10).toFloat(), (width / 2 + 2 * height / 5).toFloat(), (9 * height / 10).toFloat())
itemRation(canvas,rect,a, b, c, d, e, f, g, h, i, j)
}
//保存用Bitmap準備
val image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
//新しいcanvasに保存用Bitmapをセット
Canvas(image)
//canvasに対して描画
try {
//出力ファイルを準備
val fos = FileOutputStream(File("sample.png"))
//PNG形式で出力
image.compress(CompressFormat.PNG, 100, fos)
fos.close()
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun itemRation(canvas: Canvas, rect: RectF, a:Float, b:Float?, c:Float?, d:Float?, e:Float?, f:Float?, g:Float?, h:Float?, i:Float?, j:Float?){
if (b != null && c != null && d != null && e != null && f != null && g != null && h != null && i != null && j != null) {
sum = a + b + c + d + e + f + g + h + i + j
} else if(b != null && c != null && d != null && e != null && f != null && g != null && h != null && i != null){
sum = a + b + c + d + e + f + g + h + i
} else if(b != null && c != null && d != null && e != null && f != null && g != null && h != null){
sum = a + b + c + d + e + f + g + h
} else if(b != null && c != null && d != null && e != null && f != null && g != null){
sum = a + b + c + d + e + f + g
} else if(b != null && c != null && d != null && e != null && f != null){
sum = a + b + c + d + e + f
} else if(b != null && c != null && d != null && e != null){
sum = a + b + c + d + e
} else if(b != null && c != null && d != null){
sum = a + b + c + d
} else if(b != null && c != null){
sum = a + b + c
} else if(b != null){
sum = a + b
} else{
sum = a
}
val a0 : Float = a/sum
val b0 : Float? = b?.div(sum)
val c0 : Float? = c?.div(sum)
val d0 : Float? = d?.div(sum)
val e0 : Float? = e?.div(sum)
val f0 : Float? = f?.div(sum)
val g0 : Float? = g?.div(sum)
val h0 : Float? = h?.div(sum)
val i0 : Float? = i?.div(sum)
val j0 : Float? = j?.div(sum)
paint1.color = Color.argb(195, 233, 58, 36)
canvas.drawArc(rect, -90F, a0*360, true, paint1)
paint2.color = Color.argb(195, 234, 97, 25)
if (b0 != null) {
canvas.drawArc(rect, -90F+a0*360, b0*360, true, paint2)
}
paint3.color = Color.argb(195, 252, 202, 0)
if (c0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!)*360, c0*360, true, paint3)
}
paint4.color = Color.argb(195, 184, 198, 1)
if (d0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!)*360, d0*360, true, paint4)
}
paint5.color = Color.argb(195, 58, 149, 42)
if (e0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!+ d0!!)*360, e0*360, true, paint5)
}
paint6.color = Color.argb(195, 10, 151, 114)
if (f0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!+ d0!!+ e0!!)*360, f0*360, true, paint6)
}
paint7.color = Color.argb(195, 24, 158, 151)
if (g0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!+ d0!!+ e0!!+ f0!!)*360, g0*360, true, paint7)
}
paint8.color = Color.argb(195, 89, 113, 157)
if (h0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!+ d0!!+ e0!!+ f0!!+ g0!!)*360, h0*360, true, paint8)
}
paint9.color = Color.argb(195, 104, 68, 126)
if (i0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!+ d0!!+ e0!!+ f0!!+ g0!!+ h0!!)*360, i0*360, true, paint9)
}
paint10.color = Color.argb(195, 224, 61, 114)
if (j0 != null) {
canvas.drawArc(rect, -90F+(a0+ b0!!+ c0!!+ d0!!+ e0!!+ f0!!+ g0!!+ h0!!+ i0!!)*360, j0*360, true, paint10)
}
}
}
試したこと
onCreate内のEditTextの定義文からbuttonのクリックリスナー部分をコメントアウトした状態で実行しても同様のエラーが出力されます。
補足情報(FW/ツールのバージョンなど)
Android Studio Chipmunk | 2021.2.1 Patch 1
Kotlin 1.7.0
macOS monterey 12.5.1
以下調べた内容などです
https://bluefish.orz.hm/sdoc/android_canvas.html
http://taketoma-labo.blogspot.com/2012/10/android.html
https://akira-watson.com/android/kotlin/canvas.html