3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Android強化月間 - Androidアプリ開発の知見を共有しよう -

【Android】アプリアイコンをさくっと作成する方法

Posted at

アプリのアイコンが付いていないとコードを書く気が出ない・・・そんなときに、とりあえずそれっぽいアイコンをさくっく作成する方法です。先日、iOSでやったので、今回はAndroidでもやってみました。
image.png
↑ やる気がでないやつ

アプリアイコンの作成の流れ

  1. アイコン画像を表示するViewを作成
  2. Viewのスナップショットをファイルに保存(PNG)
  3. Android Studioでアイコン画像を設定

アイコン画像を表示するViewの作成

Jetpack Composeでマテリアルアイコンを使って適当なアイコンをViewに表示して、背景色にグラデーションをかけるだけです。
image.png

AppIconView.kt
@Composable
fun AppIconView(iconVector: ImageVector, baseColor: Color, modifier: Modifier = Modifier) {
    val endColor = baseColor.copy(alpha = 0.7f)

    BoxWithConstraints(
        modifier = modifier
    ) {
        val boxWith = constraints.maxWidth.toFloat()
        val boxHeight = constraints.maxHeight.toFloat()

        val gradientBrush = Brush.linearGradient(
            colors = listOf(baseColor, endColor),
            start = Offset(boxWith / 2, boxHeight / 2),
            end = Offset(boxWith / 2, 0f))

        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(brush = gradientBrush),
            contentAlignment = Alignment.Center
        ) {
            Icon(
                imageVector = iconVector,
                contentDescription = null,
                tint = Color.White,
                modifier = Modifier.fillMaxSize(0.4f)
            )
        }
    }
}

@Preview(showBackground = true)
@Composable
fun IconViewPreview() {
    Column {
        AppIconView(
            iconVector = Icons.Default.Draw,
            baseColor = Color(235, 78, 61),
            modifier = Modifier.size(200.dp).padding(8.dp)
        )
        AppIconView(
            iconVector = Icons.Default.Train,
            baseColor = Color(101, 196, 102),
            modifier = Modifier.size(200.dp).padding(8.dp)
        )
        AppIconView(
            iconVector = Icons.Default.Sailing,
            baseColor = Color(52, 120, 246),
            modifier = Modifier.size(200.dp).padding(8.dp)
        )
    }
}

すべてのマテリアルアイコンを使用できるようにする

デフォルトではCoreライブラリに入っている基本アイコンのみのため、すべてのマテリアルアイコンを使用するためには追加パッケージが必要です。

build.gradle.kts
implementation("androidx.compose.material:material-icons-extended")

Transportationの例:
image.png

Viewのキャプチャをファイルに保存

ファイル保存用のボタンを設置し、 アイコンのキャプチャをファイルに保存します。キャプチャ対象をAppIconViewだけに絞るために、AndroidViewでラップしViewのインスタンスを取得します。画像ファイルは端末の画像フォルダーに保存されます(エミュレータ時のファイルパスは後述)。

アイコンや色を変えるUIは今回用意していなので、コード上のiconとbaseColorを直接書き換えます。

MainActivity.kt
@Composable
fun MainView() {
    val scope = rememberCoroutineScope()
    val context = LocalContext.current
    val density = LocalDensity.current
    var composeViewRef by remember { mutableStateOf<ComposeView?>(null) }
    var isGranted by remember { mutableStateOf(true) }
    val icon: ImageVector = Icons.Default.Draw
    val requestPermissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) {
        if (it) {
            isGranted = true
        } else {
            Toast.makeText(context, "Permission denied", Toast.LENGTH_SHORT).show()
        }
    }

    isGranted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        true
    } else {
        ContextCompat.checkSelfPermission(
            context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        contentAlignment = Alignment.Center
    ) {

        Column(
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            // キャプチャ時にインスタンスを取得するために、AndroidViewでアイコンを描画
            AndroidView(
                factory = { ctx ->
                    ComposeView(ctx).apply {
                        layoutParams = ViewGroup.LayoutParams(
                            (300 * density.density).toInt(),
                            (300 * density.density).toInt()
                        )
                        setContent {
                            AppIconView(
                                iconVector = icon,
                                baseColor = Color(235, 149, 0),
                                modifier = Modifier
                                    .size(300.dp)
                                    .background(Color.White)
                            )
                        }
                        composeViewRef = this
                    }
                }
            )

            Text(icon.name)
        }

        Button(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(top = 16.dp),
            onClick = {
                if (isGranted) {
                    val view = composeViewRef
                    view?.let {
                        val bitmap = it.drawToBitmap()
                        scope.launch {
                            saveImageToGallery(context, bitmap)
                        }
                    }
                } else {
                    requestPermissionLauncher.launch(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                }
            }
        ) {
            Text("Save Image")
        }
    }
}

fun saveImageToGallery(context: Context, bitmap: Bitmap) {
    val contentValues = ContentValues().apply {
        put(MediaStore.MediaColumns.DISPLAY_NAME, "Icon_${System.currentTimeMillis()}.png")
        put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
        put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
    }
    val uri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
    uri?.let {
        val outputStream: OutputStream? = context.contentResolver.openOutputStream(it)
        outputStream.use { stream ->
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
            Toast.makeText(context, "Image file saved to: " + it.path, Toast.LENGTH_LONG).show()
        }
    }
}

エミュレータで実行している場合の保存場所

Androidエミュレータでアプリを実行すると、アプリの画像ファイルはAndroid StudioのDevice Explorerで参照できます。
storage > emulated > 0 > Picturesに保存されているので、pngファイルを右クリックしてダウンロードフォルダーなどに保存します。
image.png

画像ファイルをAndroid StudioのImage Assetに設定

  1. Android StudioのFileメニューから、New > Image Asset を選択して Asset Studio を起動します。
  2. 画像ファイルをPathに設定します。上書きするかの警告は無視して問題ありません。
  3. あとはデフォルトのまま Next > Finish と進めると完了です。
    image.png

完成サンプル

いい感じにできました。
image.png

おしまい〜!

サンプルコード一式

iOS版はこちら

【iOS】アプリアイコンをさくっと作成する方法

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?