WebView と JvmOverloads
@JvmOverloads とそれによって発生しうる問題
Android で Custom View を作ろうとすると、複数のコンストラクタを実装する必要がありますが、Kotlin を使用している場合は @JvmOverloads
アノテーションを使うことで簡単に作成することができます。
class MyCustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : WebView(context, attrs, defStyleAttr)
このように記述することで、attrs
や defStyleAttr
が無い場合のオーバーロードコンストラクタも生成されます。基本的には問題ないのですが、一部のViewでは期待した挙動にならないことがあります。
その一つはKotlinでcustom viewを実装する時の注意点 - Qiitaでも書かれているように EditText です。defStyleAttr
が0で初期化されることにより、Context と AttributeSet を受け取るコンストラクタで指定されているデフォルトのスタイルが適用されず、意図した動作となりません。こういった View はそれなりに存在しており、少し古い記事になりますがY.A.M の 雑記帳: Android スタイルメモでその一覧が示されています。
このようなViewに遭遇したとき、実際にどのように調査するかの備忘録です。
原因調査
今回私が遭遇した View は WebView なのですが、@JvmOverloads
によりデフォルトスタイルが適用されない場合、表示した Web ページのテキストボックスをクリックしてもキーボードが表示されません。
非公式ではありますが、有志の方が公開しているAndroidソースコード検索サービス - Developer Collaboration Projectというものがあります。
public WebView(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.webViewStyle);
}
WebView 内では上記のように定義されているので、任意の Andoid バージョンのソースコードで webViewStyle
というキーワードで検索してみると、なにやら Widget.WebView
が影響していそうです。
さらに Widget.WebView
で検索すると、以下のようなコードが見つかりました。Theme 内で focusable
を指定しており、それが設定されないことにより、キーボードが現れない現象が発生していました。
<style name="Widget.WebView">
<item name="focusable">true</item>
<item name="focusableInTouchMode">true</item>
<item name="scrollbars">horizontal|vertical</item>
</style>
問題が発生する View への対処
実際にこういった View にどうアプローチするかを考えると、3引数(あるいは4引数)のコンストラクタを使う機会はそれほどないはずなので、2引数で @JvmOverloads
を使うのが一番楽だと思います。そこで問題が起きた際には改めて複数のコンストラクタを生成する、と言った形でも問題ないでしょう。
Discussion