概要
custom view を作成した際に、onTouchEvent() をオーバーライドしたが performClick()
をオーバーライドしていない場合に、以下のような警告が表示されます。1
Custom view XxxView overrides onTouchEvent but not performClick
performClick() について
まずは performClick() から読み解いてみようと思います。
◆ javadoc
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
ざっくりこんな感じですね。
- OnClickListener が定義されていればそれを呼び出す。
- クリックに関連するすべての通常の処理(accessibility event の報告や音声再生など)を実行する。
◆ 解釈
これを言い換えると、
- クリック時の処理は OnClickListener に含まれる。
- クリックに関連する OnClickListener 以外の処理は performClick() に含まれる。
のようなことが言えると思います。
別の見方をすると、
- custom view の外部から動的に設定される機能は OnClickListener で実行される。
- custom view として固定のクリック音やクリック時のUI効果、デザイン上の決まり事である accessibility event の報告、などは performClick() 上で実行される。
とも言えそうです。
◆ Viewのコード
View#performClick() のコードでは
li.mOnClickListener.onClick(this)
のように OnClickListener の処理が呼び出され、
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED
のように accessibility 系のコードも呼び出されているということがわかります。
ということで、performClick() を叩けば OnClickListener やら accessibility 系などすべて含んだクリック処理を行ってくれるってことですね。
◆ performClick() まとめ
クリック処理は、常に performClick() 経由で実行しましょう。
onTouchEvent() について
◆ javadoc
以下が onTouchEvent() の javadoc の内容。
Implement this method to handle touch screen motion events.
If this method is used to detect click actions, it is recommended that the actions be performed by implementing and calling performClick(). This will ensure consistent system behavior, including:
・obeying click sound preferences
・dispatching OnClickListener calls
・handling ACTION_CLICK when accessibility features are enabled
第一パラグラフは普通にタッチイベントを扱うという話。
第二パラグラフの2文目以降は performClick() の話で、既に前項で扱った話。
ということで、重要なのは残った以下の文章。
If this method is used to detect click actions, it is recommended that the actions be performed by implementing and calling performClick().
『このメソッドがクリック処理を検出するために使われるのであれば、performClick() を実装してそれを呼び出すことを推奨する』ということですが、逆を言えば、クリック処理を検出するために使われない場合には performClick() を実装して呼び出す必要はないという事になります。
◆ 補足
補足ですが、Accessibility 系のオプションを有効にしている場合など、タッチ関連の通知経路が変わることがあります。
具体的な例としては、普段は onTouchEvent() にてクリックの判断をしている場合に、端末の TalkBack を on にしていると、Accessibility 系の仕組み経由でクリックの判断が行われるため、onTouchEvent() が発生せずにいきなり performClick() が呼び出されることがあり、その場合は onTouchEvent() 内部に書かれた処理は一切実行されません。
まとめ
Custom view XxxView overrides onTouchEvent but not performClick って怒られるケースについてという文脈でまとめると、以下のようになるのかなと思います:
- onTouchEvent() がクリック処理を検出するために使われない場合
- performClick() を実装して呼び出す必要はない。← 警告を suppress しちゃってOKだと思われ。
- onTouchEvent() がクリック処理を検出するために使われる場合
- クリックを検出した箇所で、クリックに関する処理はすべて performClick() に丸投げしましょう。2
以上。