Android CardView с ListView внутри - onTouchListener на CardView не работает

У меня есть карточка со списком внутри. Мне также понадобится элемент щелчка в представлении списка, и я хочу иметь возможность перемещать весь вид карты с помощью онтонучлистена. Я установил onTouchListener в карточке, но он не работает.

Код:

Поместите это в build.gradle:

compile 'com.android.support:cardview-v7:22.0+'

Основная деятельность:

package com.XXXXXXXX.testontouch;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.CardView;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListView mylistview;
    private CardView mycardview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mycardview = (CardView)findViewById(R.id.mycardview);
        mylistview = (ListView) findViewById(R.id.myListView);

        List<String> your_array_list = new ArrayList<String>();
        your_array_list.add("foo");
        your_array_list.add("bar");
        your_array_list.add("foo");
        your_array_list.add("bar");
        your_array_list.add("foo");
        your_array_list.add("bar");
        your_array_list.add("foo");
        your_array_list.add("bar");
        your_array_list.add("foo");
        your_array_list.add("bar");
        your_array_list.add("foo");
        your_array_list.add("bar");
        your_array_list.add("foo");
        your_array_list.add("bar");


        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                your_array_list );

        mylistview.setAdapter(arrayAdapter);
        mycardview.setCardElevation(20);
        mycardview.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                System.out.println("TOuchedddd");
                return true;
            }
        });

    }
}

Toucheddd никогда не печатает. Если я удалю ListView из картотеки, он начнет работать.

Итак, каким-то образом listView сначала потребляет события касания, а не родительскую карточку.

XML для основной активности:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.pranapps.testontouch.MainActivity">



<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:id="@+id/mycardview"
    card_view:cardUseCompatPadding="true">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/myListView"
        android:dividerHeight="0.2dp"
        android:overScrollMode="always"
        android:smoothScrollbar="true"
        android:groupIndicator="@null"
        ></ListView>


</android.support.v7.widget.CardView>

</RelativeLayout>

Я пробовал как true, так и false для android: clickable, android: focusable и android: focusableInTouchMode. неудачно.


person sudoExclaimationExclaimation    schedule 08.05.2016    source источник
comment
Вы хотите щелкнуть элемент в представлении списка?   -  person Milos Lulic    schedule 08.05.2016
comment
Да, мне также понадобится элемент щелчка в представлении списка, и я хочу иметь возможность перемещать весь вид карты с помощью онтонучлистена.   -  person sudoExclaimationExclaimation    schedule 08.05.2016
comment
Вы можете попробовать использовать регистр переключения для «события MotionEvent»: switch(event.getAction()) {case MotionEvent.ACTION_DOWN:.........   -  person Milos Lulic    schedule 08.05.2016
comment
это не работает. System.out появляется даже перед оператором switch и даже не выполняется. Как будто онтоучлистенер даже не запускается в родительском представлении.   -  person sudoExclaimationExclaimation    schedule 08.05.2016


Ответы (1)


В Android сенсорные события всплывают от ребенка к родителям, как и следовало ожидать. Однако родитель может выбрать перехват всех событий касания, предназначенных для одного из его дочерних элементов, и принять решение наложить вето на отправку события дочернему элементу. Это именно то, что вы хотите, если я правильно понимаю, ваше событие касания должно вызываться независимо от того, что происходит, когда вы касаетесь своего представления карты, а затем при необходимости вы отправляете событие касания в свой дочерний список.

Чтобы перехватить событие касания из CardView, вам нужно создать собственное представление, которое является его подклассом, и переопределить метод onInterceptTouchEvent:

package com.pranapps.testontouch;

import android.content.Context;
import android.util.AttributeSet;
import android.support.v7.widget.CardView;
import android.view.MotionEvent;
import android.view.View;

public class CardViewTouchThief extends CardView {

    public CardViewTouchThief(Context context) {
        super(context);
    }
    public CardViewTouchThief(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CardViewTouchThief(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        /* 
        * This method determines whether we want to intercept the motion. 
        * If we return true, onTouchEvent will be called. 
        */ 
        return true; 
    } 

} 

Затем вы используете CardViewTouchThief там, где вы обычно используете CardView в макете XML:

<com.pranapps.testontouch.CardViewTouchThief
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/mycardview"
card_view:cardUseCompatPadding="true">

    <ListView
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:id="@+id/myListView"
    android:dividerHeight="0.2dp"
    android:overScrollMode="always"
    android:smoothScrollbar="true"
    android:groupIndicator="@null"/>

</com.pranapps.testontouch.CardViewTouchThief>

И в вашей деятельности поместите свою собственную логику для обработки всякий раз, когда вы хотите, чтобы событие касания было отправлено в список.

mycardview.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            Log.d("MainActivity", "TOuchedddd");
            if(mylistview!=null){
                //Route all touch event to listview without logic
                mylistview.onTouchEvent(event);
            }
            return true;
        }
    });

Здесь представлен исправленный исходный код проекта.

person Gomino    schedule 12.05.2016
comment
спасибо большое мужик!!!! ТЫ СУПЕР ГЕРОЙ!!!! Это сработало совершенно потрясающе! Надеюсь, остальная часть моего путешествия по Android пройдет хорошо, еще раз спасибо! - person sudoExclaimationExclaimation; 12.05.2016
comment
Я назначу награду через 21 час - person sudoExclaimationExclaimation; 12.05.2016
comment
Рад помочь вам! - person Gomino; 14.05.2016
comment
ваше решение работает, но когда я включаю фактическое перемещение карточного представления и прокрутку списка, оно, похоже, не работает :( не могли бы вы взглянуть на этот новый проект? dropbox.com/sh/8s3v9ydcj6jvpl8/AACZ2VRP2N9R1ec7pxrsAn0ga?dl=0 - person sudoExclaimationExclaimation; 21.05.2016
comment
на самом деле я задал здесь отдельный вопрос, можете ли вы ответить?: stackoverflow.com/questions/37358015/ - person sudoExclaimationExclaimation; 21.05.2016
comment
Спасибо .. Вы сделали мой день!! - person Jay Patel; 22.09.2017