前書き
言いたいことはタイトル通りですが、
私自身そんなにAndroid開発やkotlinについて
詳しくないので定かではないのでこんなタイトルにしました。
とりあえずSurfaceViewのサンプル実装見たかったので、
Google検索で以下のようなワード群で検索しました。
android SurfaceView サンプル
or
android kotlin SurfaceView
引っかかるサイト全般に同じような事をしていて
意味不明だったので記事を書きました。
問題のサンプルコード
問題と思う所のサンプルコードはみんな以下のような状況でした。
察しのいい人はここでわかると思います。
class SampleSurfaceView: SurfaceView, SurfaceHolder.Callback { ... }
<androidx.constraintlayout.widget.ConstraintLayout ... >
<SurfaceView ... />
</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// ここは2パターンあるがどれも無意味だと思っている。
SampleSurfaceView(this) // パターン1
SampleSurfaceView(this, surfaceView) // パターン2
}
}
謎のSurfaceViewの継承
activity_main.xmlのSurfaceViewを定義しているので、
そのオブジェクトを使用すればいいのですが、
なぜか別途継承しオブジェクトを作成しないといけません。同じViewを。。。
同格のオブジェクトを扱うのになぜか継承関係を作ろうとしているサンプルが
たくさんありました。
意味が分かりません。
継承して扱うのであれば、
xmlは以下のようにするのが正しいと思うのですが、
それもしていないので継承している意味が分かりません。
<androidx.constraintlayout.widget.ConstraintLayout ... >
<SampleSurfaceView... />
</androidx.constraintlayout.widget.ConstraintLayout>
単純に描画したいんじゃ
無意味な継承とインスタンス関係性の意味が分からなく、
描画したいだけだったのにすごい時間がかかりました。
以下のようにすればできるよってだけ載せておきます。
手順
- addCallbackに渡すオブジェクトを作成。(SurfaceHolder.Callback)
- 描画先のSurfaceViewのインスタンスを取得。
- SurfaceViewのholderのaddCallbackにコールバックオブジェクト(描画処理を記載)を渡す。
1. addCallbackに渡すオブジェクトを作成。(SurfaceHolder.Callback)
こちらは手っ取り早く以下のようなオブジェクト式で作成するか、
別ファイルでクラスを作成するかはお好みでどうぞ。
import android.view.SurfaceHolder
import ...
class MainActivity: AppCompatActivity() {
// 適当にcallbackのオブジェクトを定義・作成
val surfaceCallback = object : SurfaceHolder.Callback { //(1)
//ここで適当にオーバーライドして、描画したい処理を書く
override fun surfaceCreated(holder: SurfaceHolder) {
val canvas = holder.lockCanvas()
canvas.drawText("TEST SAMPLE", canvas.width / 2.0F, canvas.height / 2.0F, paint)
canvas.drawCircle(100F, 100F, 50F, paint)
// 色々書く
holder.unlockCanvasAndPost(canvas)
}
...
}
}
2. 描画先のSurfaceViewのインスタンスを取得。
class MainActivity: AppCompatActivity() {
val surfaceCallback = object : SurfaceHolder.Callback{...} //(1)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 描画先のSurfaceViewを取ってくる
val surfaceView = findViewById<SurfaceView>(R.id.surfaceView) //(2)
}
}
3. SurfaceViewのholderのaddCallbackにコールバックオブジェクトを渡す。
class MainActivity: AppCompatActivity() {
val surfaceCallback = object : SurfaceHolder.Callback{...} //(1)
override fun onCreate(savedInstanceState: Bundle?) {
...
// 描画先のSurfaceViewを取ってくる
val surfaceView = findViewById<SurfaceView>(R.id.surfaceView) //(2)
surfaceView.holder.addCallback(surfaceCallback) //(3)
// もしくは下のようにしてもいい
surfaceView.holder.addCallback(object: SurfaceHolder.Callback{...})//(1),(3)
}
}
以上になります。
その他の初期化等はあると思いますが、
ただ描画したいだけであればこれだけで
済むのにめちゃくちゃコード書いている人たちが居て
コーディングが好きなんだなぁって思いましたー