RelativeLayout
を拡張して作成したウィジェット/コントロールを再利用できるように作成しました。次に、アクティビティの1つで、これらのウィジェットの束をループで作成しました。しかし、各ウィジェットがクリックに応答するようにしたいときに問題が発生しました。
OnTouchListener
の設定が機能することがわかりました。
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
//Triggers debug message
}
});
しかし、OnClickListener
はしません:
this.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
//Doesn't trigger debug message
}
});
どうしてこれなの?
ビューがクリック可能であることを確認するために確認することがいくつかあります。
View.setClickable()
View.setEnabled()
View.setFocusable()
View.setFocusableInTouchMode()
取得したい正確な動作に応じて、それらの1つ以上をオンに設定する必要があります。 onTouchイベントを取得しているので、setClickableが必要だと思います。しかし、確かにビュー作成コードを確認する必要があります。
TouchListenerがタッチイベントを「消費」していないことを確認する必要があります。 onTouch()
メソッドからtrueを返すと、Androidは消費されたと見なし、他のさまざまなタッチハンドラー(ClickListenerが含まれると想定しています)に渡されません。 。
やったほうがいい:
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
//Triggers debug message
return false;
}
});
ブール値のonTouch値を正しく返していますか?
ドキュメントから:
onTouch()-これは、リスナーがこのイベントを消費するかどうかを示すブール値を返します。重要なことは、このイベントが互いに続く複数のアクションを持つことができるということです。したがって、ダウンアクションイベントを受信したときにfalseを返す場合は、イベントを消費しておらず、このイベントからの後続のアクションにも関心がないことを示します。したがって、指のジェスチャーや最終的なアップアクションイベントなど、イベント内の他のアクションが要求されることはありません。
[〜#〜]編集[〜#〜]
この 質問 で解決策を見つけて、自分で試してみました。
このreturn super.onTouchEvent(event);
をonTouchEventコードで使用する必要があります。これを追加した後、OnClickListenerが機能し始めました。
これを実行するには、次のようにonTouch()
でfalseを返します。
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
return false;
}
});
OnTouchListenerを介してonClickListenerを実装できます。
webView.setOnTouchListener(new View.OnTouchListener() {
public final static int FINGER_RELEASED = 0;
public final static int FINGER_TOUCHED = 1;
public final static int FINGER_DRAGGING = 2;
public final static int FINGER_UNDEFINED = 3;
private int fingerState = FINGER_RELEASED;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
if (fingerState == FINGER_RELEASED) fingerState = FINGER_TOUCHED;
else fingerState = FINGER_UNDEFINED;
break;
case MotionEvent.ACTION_UP:
if(fingerState != FINGER_DRAGGING) {
fingerState = FINGER_RELEASED;
// Your onClick codes
}
else if (fingerState == FINGER_DRAGGING) fingerState = FINGER_RELEASED;
else fingerState = FINGER_UNDEFINED;
break;
case MotionEvent.ACTION_MOVE:
if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING) fingerState = FINGER_DRAGGING;
else fingerState = FINGER_UNDEFINED;
break;
default:
fingerState = FINGER_UNDEFINED;
}
return false;
}
});
同じビューでonClickイベントとonTouchイベントの両方が必要な場合は、 GestureDetector を使用します。
何らかの理由でonMotionEvent()メソッドをオーバーライドし、その場合にtrue/falseを返す必要がある場合は、trueを返す直前にオーバーライドされたonMotionEvent()内でthis.performClick()を呼び出すことにより、OnClickListener()コールバックを手動でトリガーできます。/false。
Falseを返そうとした場合:
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent arg1) {
return false;
}
});
うまくいきませんでした。ScrollViewを使用している場合は、このソリューションを試してください。 ScrollView内にLinearLayoutを追加します。クリック可能をtrueに設定します。 LinearLayoutからsetOnClickListenerとsetOnTouchListenerを呼び出します。
<ScrollView
Android:id="@+id/scrollview"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fillViewport="true"
Android:scrollbarStyle="outsideOverlay">
<LinearLayout
Android:id="@+id/linearlayout"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:clickable="true"
Android:focusable="true"
Android:gravity="center_vertical"
Android:orientation="vertical">
<content... />
</LinearLayout>
</ScrollView>
LinearLayout linearlayout = findViewById(R.id.linearlayout);
linearlayout.setOnClickListener...
linearlayout.setOnTouchListener...