Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DroidKaigi2022 Jetpack Composeを用いて、Canvasを直接触るよ...

kkkkan
October 04, 2022

DroidKaigi2022 Jetpack Composeを用いて、Canvasを直接触るようなコンポーネントを作成する方法

DroidKaigi2022に参加した際の発表資料です。

発表時との相違点
・動画のURLのQRの中央に動画アイコンを追加
・「最終目標」として動画を再掲しているページに、動画のURLとQRを追加
・Androidロボットの権利表記を追加 (DroidKaigi実行委員会の方より表記必要なことご指摘いただきました。ありがとうございます。)

・2023/01/09 : p109-p134 にスライドを追加しました。(「DstOverだけだと背景が透明な画像の時に上手く動かない件」について)

・2023/01/12 : 追加スライド内(p124)のURLリンクが間違っていたので修正

-------------------------------

Jetpack Composeは、ライブラリにあるコンポーネントでアプリを組むのは従来のAndroid Viewに比べて簡単で開発時間の短縮にもつながる優れたUIツールキットです。

一方、Android View時代だったら、Viewを継承して、オーバーライドしたonDraw()に処理をガリガリ書いていたであろう完全なオリジナルコンポーネントを作成しようとした時、どうしたらよいのか悩まれる方もいるのではないでしょうか。

私は去年 Jetpack Composeを用いて、そのようなコンポーネントを持つアプリをリリースしました。
ユーザーから受け取った端末内画像を表示し、その上を指でなぞると軌跡が切り取られて透明表示のレイヤーが表示されるようなアプリです。

そのアプリで使用しているコードを例に、jetpack Composeを用いて完全なオリジナルコンポーネントを作成する際にヒントにできるような内容をお話しする予定です。

kkkkan

October 04, 2022
Tweet

More Decks by kkkkan

Other Decks in Technology

Transcript

  1. - drawArc…円弧を描く - drawCircle…正円を描く - drawImage…画像を描く - drawLine…直線を描く - drawOval…楕円を描く

    - drawPath…線を描く - drawPoints…点を描写する - drawRect…矩形を描く - drawRoundRect…角の丸い矩形を描く
  2. // グラデーションの色 // 円弧の始点の度数 // 扇形の終点の度数 // 円の中心を通すか // 360度描いた場合に円周の通る軌道のx座標とy座標の最小値

    // スタイル(塗りつぶすか、外周だけか) // 縦方向の直径と横方向の直径 // 透過度 // 上書くカラーフィルター // 同じCanvasに描かれた他のもの が重なった時の描写設定 https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope#drawArc(androidx.compose .ui.graphics.Brush,kotlin.Float,kotlin.Float,kotlin.Boolean,androidx.compose.ui.geometry.Offset,androidx.compose.ui.geometry.Si ze,kotlin.Float,androidx.compose.ui.graphics.drawscope.DrawStyle,androidx.compose.ui.graphics.ColorFilter,androidx.compose. ui.graphics.BlendMode) アクセス日 : 2022/09/01
  3. // グラデーションの色 // スタイル(塗りつぶすか、外周だけか) // 半径 // 透過度 // 上書くカラーフィルター

    // 同じCanvasに描かれた他のものが重なった時の 描写設定 // 中心 https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope#drawCircle(androidx.compo se.ui.graphics.Brush,kotlin.Float,androidx.compose.ui.geometry.Offset,kotlin.Float,androidx.compose.ui.graphics.drawscope.Dra wStyle,androidx.compose.ui.graphics.ColorFilter,androidx.compose.ui.graphics.BlendMode) アクセス日 : 2022/09/01
  4. https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope#drawImage(androidx.comp ose.ui.graphics.ImageBitmap,androidx.compose.ui.unit.IntOffset,androidx.compose.ui.unit.IntSize,androidx.compose.ui.unit.IntOff set,androidx.compose.ui.unit.IntSize,kotlin.Float,androidx.compose.ui.graphics.drawscope.DrawStyle,androidx.compose.ui.graphi cs.ColorFilter,androidx.compose.ui.graphics.BlendMode,androidx.compose.ui.graphics.FilterQuality) // 画像ソース // ソースのオフセット // 透過度

    // 上からかけるカラーフィルター // 同じCanvasに描かれた他のものが重なった時の 描写設定 // 描く場所の領域 // 描く場所のオフセット // ソース画像の描く領域 // 描く画質のきれいさ // スタイル(塗りつぶすか、線で囲うだけか) ・styleは変更しても描写に変更ないように見えた。なんの為にあるか不明。 ご存知の方いましたら教えてください .... ・大まか設定verはdstOffsetがtopLeftという名前で存在していて、それ以外の大きさや位置関係の設定はでき ない アクセス日 : 2022/09/01
  5. // グラデーションの色 // 円周の通る軌道のx座標とy座標の最小値 // スタイル(塗りつぶすか、外周だけか) // 楕円が収まる矩形の大きさ // 透過度

    // 上書くカラーフィルター // 同じCanvasに描かれた他のものが重なった時の 描写設定 https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope#drawOval(androidx.compos e.ui.graphics.Brush,androidx.compose.ui.geometry.Offset,androidx.compose.ui.geometry.Size,kotlin.Float,androidx.compose.ui.g raphics.drawscope.DrawStyle,androidx.compose.ui.graphics.ColorFilter,androidx.compose.ui.graphics.BlendMode) アクセス日 : 2022/09/01
  6. https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope#drawPoints(kotlin.collection s.List,androidx.compose.ui.graphics.PointMode,androidx.compose.ui.graphics.Brush,kotlin.Float,androidx.compose.ui.graphics.S trokeCap,androidx.compose.ui.graphics.PathEffect,kotlin.Float,androidx.compose.ui.graphics.ColorFilter,androidx.compose.ui.gr aphics.BlendMode) // グラデーションの色 // ポイントモード(点にするかつなげて線として描写するか ) //

    透過度 // 上書くカラーフィルター // 同じCanvasに描かれた他のもの が重なった時の描写設定 // 線や点の太さ // 線や点の端点の形 // 線のスタイル(破線などを作れる) // 描写する点のリスト ・pointModeが PointMode.Pointsの時はPathEffectを設定してもなにも起きないようです。 アクセス日 : 2022/09/01
  7. // 下端の角度 // 右端の座標 https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope#(androidx.compose.ui.grap hics.drawscope.DrawScope).clipRect(kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,androidx.compose.ui.graphics.ClipOp,kotlin. Function1) // 左端の座標 //

    上端の座標 // 描写反映領域を指定した座標の中にするか外にするか ・clipOpをClipOp.Differenceとすると指定した領域外の部分のみ描写を反映するようになる アクセス日 : 2022/09/01
  8. Composeでの回避策② - とはいえ、alphaを設定する作戦よりはハードウェア アクセラレーション をオフにしてやる方式の方がまだより本質的 & 確実そうでより不安が少 ないので、ComposeでもAndroidViewでも、alpha設定よりハードウェア アクセラレーションをオフにしてやる方がいいかも? -

    ハードウェア アクセラレーションに関しても結局もっと深い部分を見て確 認したわけではないので不確実要素はかなりあるけど - OSのバージョンによって挙動が違うなどありそうだし - ただ、ハードウェア アクセラレーションは描写パフォーマンスを考えて導 入されているものなので、描写が重い部分では全体のハードウェア アク セラレーションをオフにしてしまうのではなくalpha方式の方がいいかも。
  9. - Jetpack ComposeにもCanvasはあります - DrawScopeを公開してくれるので、そこに描き込んでいく形です - Canvasの大きさを超えて描き込むことができてしまうので注意 - insetを使用すると描画領域を新しく展開できて便利です -

    はみ出したくない領域があるときはclipRectを使用しましょう - Jetpack Composeでタッチイベントを取得したいときは Modifier.pointerInteropFilterを使用します