証券フロンティア事業部の割子田です。2022年の4月に新卒として入社し、Androidアプリの開発を主に行っております。最近、Androidのアプリ開発でシークバーの部品を使う機会がありました。動画の再生位置を調整するときによく使われるあれです。Androidではandroid.widgetパッケージにSeekBarというウィジェット部品があるのでそれを使って開発を行ったのですが、開発者向けドキュメントを読んだ際に、SeekBarクラスがProgressBarクラスを継承しているという点が目に入りました。プログレスバーは処理の進捗度合いを表すときによく見るものですね。たしかに、プログレスバーを拡張すればシークバーも実現できそうです。具体的にどのように実装されているのかが気になったので、そのソースコードを読んでみることにしました。この記事はその過程のメモ的な記事になります。Androidはオープンソースですので、誰でもソースコードを見ることができます。Project(AOSP)と呼ばれています。GitというGoogleのGitリポジトリ上からソースコードを見ることにします。SeekBarクラスとProgressBarクラスについてandroid.widgetパッケージのSeekBarクラスはAbsSeekBarというクラスを継承していて、それがさらにProgressBarクラスを継承しています。ちなみになぜAbsSeekBarクラスを挟んでいるのかという点ですが、SeekBarの他に、RatingBarというグルメサイトの星とかに使われそうな部品もAbsSeekBarクラスを継承しているためだと思われます。今回は一番重要なAbsSeekBar.javaの実装を見てみます。android.googlesource.com今回読むのはIOや難しいグラフィック処理等の部分ではなく、Viewウィジェットという高レイヤで表層的、かつ既存のものを拡張したクラスなので、OSやハードウェアに関する深い知識がなくても追えそうです。コードを読む前にプログレスバーとシークバーの違いを考えてみる一般論として、プログレスバーとシークバーの違いとして思いつくのが次の2点でしょうか。プログレスバーはタッチで操作できないが、シークバーはタッチでユーザーが操作できるプログレスバーは●が必要ないが、シークバーは●がある(●のことをAndroidではthumbと呼んでいる)この2点に注目しながらソースコードを追ってみたいと思います。実際にソースコードを読むフィールドを眺めるまずフィールド回りを眺めてみます。Rect();mTempRectやthumb、mThumbRectがシークバーの●に使われていそうです。mIsUserSeekableはシークの可否、mIsDraggingはドラッグの判定に使われていそうですね。28)以降に追加されたもので、非SDKインターフェースの制限というものを意味するようです。リフレクションやJNIを使って対象のフィールドやメソッドに直接アクセスしていなければ問題ありません。シークバーの●について続いてシークバーの●(thumb)について見てみます。setThumb(thumb);AbsSeekBarのコンストラクタでthumbとして使うdrawableを設定しています。TypedArrayとしてXMLの属性値を取り出し、そこからthumbのdrawableを取り出しているようです。}継承元のProgressBarクラスからonVisualProgressChanged()メソッドをオーバーライドしています。progressの値が変わったタイミングでthumbの位置も変えているのがわかります。0.5f);setThumbPos()メソッドでは、シークバーの幅、padding、scale(進捗率)から座標を求めていました。ここまでがシークバーの●(thumb)に関する処理です。タッチ操作について次にProgressBarにはないタッチ操作について見ていきます。}onTouchEvent()メソッドをオーバーライドしてタッチイベントの種類ごとにSwitch文で分岐させています。想像していたよりもシンプルでした!mIsDraggingでドラッグ中か否かを管理して、trackTouchEvent()メソッドを呼んでいます。}trackTouchEvent()メソッド内でタッチイベントの座標やシークバーの座標から進捗率を算出し、setProgressInternal()メソッドを呼んでいます。setProgressInternal()メソッドはProgressBarクラスに実装されているもので、実際に進捗率を変更します。想像していたよりもシンプルな実装でした。最初に予想したプログレスバーとシークバーの2点の違いについて、予想通りの機能が追加実装されているのが確認できました。今後、継承関係の設計をするときやオリジナルのシークバーを実装するときに役立ちそうですね。アプリを開発する時に、その土台となるOSのソースコードを読むことができるのはありがたいです。今回はViewのウィジェットという最も表層にあり、かつ既存のものを拡張したクラスだったためかなり理解しやすいものでした。今後はもっと難しい部分のAOSPコードリーディングにもチャレンジしていきたいと思います。