简体   繁体   English

内置ListView的Android CardView-CardView上的onTouchListener不起作用

[英]Android CardView with ListView inside - onTouchListener on CardView not working

I have a cardview with a listview inside. 我有一个cardview里面有一个listview。 I will need the click item in list view too and I want to be able to move the entire cardview using the ontouchlistener too. 我也将需要列表视图中的单击项,并且我也希望能够使用ontouchlistener移动整个cardview。 I have set a onTouchListener on the cardview but it doesn't work. 我已经在cardview上设置了onTouchListener,但是它不起作用。

Code: 码:

Put this in build.gradle: 把它放在build.gradle中:

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

MainActivity: 主要活动:

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;
            }
        });

    }
}

The TOuchedddd never prints. TOuchedddd从不打印。 If I remove the ListView from the cardview, then it starts working. 如果我从cardview中删除ListView,则它开始工作。

So somehow the listView is consuming the touch events instead of the parent cardview first. 因此,以某种方式listView会消耗触摸事件,而不是首先使用父cardview。

XML for MainActivity: 用于MainActivity的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>

I have tried both true and false for the android:clickable, android:focusable and android:focusableInTouchMode. 我已经为android:clickable,android:focusable和android:focusableInTouchMode尝试了true和false。 no luck. 没运气。

In Android, touch events bubble up from child to parents as you would expect. 在Android中,触摸事件会像您期望的那样从孩子到父母冒泡。 However, a parent can choose to intercept all touch events targeted for one of its children and decide to veto dispatch of the event to the child. 但是,父母可以选择拦截针对其孩子之一的所有触摸事件,并决定否决该事件给孩子。 This is exactly what you want, if I understand correctly your touch event should be called whatever happen when you touch your cardview, and then you dispatch the touch event to your child listview if needed. 这正是您想要的,如果我正确理解您的触摸事件,无论您在触摸Cardview时发生什么情况,都应将其称为“触摸事件”,然后在需要时将touch事件调度到子ListView。

To intercept the touch event from the CardView, you need to create a custom view that subclass it and override the onInterceptTouchEvent method: 要从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; 
    } 

} 

Then you use CardViewTouchThief where you would normally use your CardView in your XML layout: 然后,使用CardViewTouchThief,通常在XML布局中使用CardView:

<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>

And in your activity put your own logic to handle whenever you want the touch event to be dispatch to the listview. 并且在您的活动中,只要您希望将触摸事件调度到列表视图,就可以使用自己的逻辑进行处理。

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;
        }
    });

Here is the fixed project source code. 是固定的项目源代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM