Как потреблять детское представление касания в родительском представлении touchlistener?
В моем приложении я хочу получить событие касания всего дочернего вида в своем родительском представлении onTouchListener
, но я не смог получить это.
Пример:
В моем представлении активности у меня есть один макет кадра, в котором есть несколько кнопок и edittexts. Поэтому всякий раз, когда я нажимаю кнопки или редактирую текст, я хочу получить это событие касания в кадре onTouchListeners
.
Вот мой код..
Активность:
private FrameLayout rootView;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
rootView = (FrameLayout) findViewById(R.id.rootview);
rootView.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
Log.e("Touch Event: ", " X: " + event.getX() + " Y: " + event.getY());
return false;
}
});
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:id="@+id/rootview">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical"
android:layout_gravity="center"
android:padding="10dip">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="4dp"
android:text="Login"
android:textColor="@android:color/black"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Username"
android:textColor="@android:color/black"
android:textSize="14dp"
android:textStyle="bold" />
<EditText
android:id="@+id/edttextusername"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:imeOptions="flagNoExtractUi"
android:singleLine="true" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Password"
android:textColor="@android:color/black"
android:textSize="14dp"
android:textStyle="bold" />
<EditText
android:id="@+id/edttextpassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:imeOptions="flagNoExtractUi"
android:password="true" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
android:padding="10dp" >
<Button
android:id="@+id/btnlogin"
android:layout_width="0dip"
android:layout_height="40dip"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:enabled="false"
android:text="Login"
android:padding="5dip"
android:textColor="@android:color/black"
android:textStyle="bold"
/>
<Button
android:id="@+id/btncall"
android:layout_width="0dip"
android:layout_height="40dip"
android:layout_marginLeft="5dp"
android:layout_weight="1"
android:padding="5dip"
android:text="Cancel"
android:textColor="@android:color/black"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
Проблема: Поэтому, когда я прикасаюсь к кнопкам или edittext, я не могу получить касание co-ordition в макете макета onTouchListener (он не вызывается).
Примечание. Я не хочу добавлять отдельный onTouchListener для всех дочерних элементов.
Спасибо заранее.
Ответы
Ответ 1
Это можно сделать, переопределив dispatchTouchEvent
в макете.
public class MyFrameLayout extends FrameLayout {
@Override
public boolean dispatchTouchEvent(MotionEvent e) {
// do what you need to with the event, and then...
return super.dispatchTouchEvent(e);
}
}
Затем используйте этот макет вместо обычного FrameLayout:
<com.example.android.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:id="@+id/rootview">
...
Вы также можете пропустить супервызов полностью, если вам нужно предотвратить получение дочерних просмотров событием, но я думаю, что это было бы редко. Если вам нужно воссоздать некоторые, но не все, функции по умолчанию, есть много, чтобы переписать:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/view/ViewGroup.java#ViewGroup.dispatchTouchEvent%28android.view.MotionEvent%29
Ответ 2
Я пробовал аналогичный дизайн с (только один приемник onTouch в корневой FrameLayout), и он сработал. Я получаю все точки, при условии, что onTouch возвращает true вместо false. В противном случае, я просто получу первый пункт. Я не мог узнать причину этой проблемы "возвращения", так как я ожидаю противоположного поведения.
Однако, исходя из моего опыта, если вы установите любое дочернее представление clickable, то его родительский onTouch не будет работать. Если у вас есть другое решение, и если вы поделитесь, это будет здорово.
Ответ 3
2 решения:
-
Используйте onInterceptTouchEvent в ViewGroup, как показано здесь
-
Избегайте, чтобы макет обрабатывал события касания и имел представление, которое представляет собой дочерний вид макета, который охватывает весь его размер, для обработки событий касания.
Это не так эффективно, как расширение классов, но это намного проще и не требует создания новых файлов/классов.
Пример:
Просто добавьте события касания к представлению и обработайте их, а не любые другие представления.
Ответ 4
Это может быть достигнуто с помощью "onInterceptTouchEvent". Пожалуйста, попробуйте это, он может работать
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
onTouchEvent(ev);
return false;
}