内置ListView的Android CardView-CardView上的onTouchListener不起作用 [英] Android CardView with ListView inside - onTouchListener on CardView not working

查看:56
本文介绍了内置ListView的Android CardView-CardView上的onTouchListener不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个卡片视图,里面有一个列表视图.我也需要列表视图中的单击项,并且我也希望能够使用ontouchlistener移动整个cardview.我已经在cardview上设置了onTouchListener,但是它不起作用.

代码:

将其放入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;
            }
        });

    }
}

TOuchedddd从不打印. 如果我从Cardview中删除了ListView,则它开始工作.

因此,以某种方式listView会消耗触摸事件,而不是首先使用父cardview.

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>

我已经为android:clickable,android:focusable和android:focusableInTouchMode尝试了true和false.没有运气.

解决方案

在Android中,触摸事件会如您所愿地从孩子冒到父母.但是,父母可以选择拦截针对其孩子之一的所有触摸事件,并决定否决该事件给孩子.这正是您想要的,如果我正确理解您的触摸事件,无论您在触摸Cardview时发生什么,都应该将其称为触摸事件",然后在需要时将触摸事件分派给子ListView.

要从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,通常在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>

在您的活动中,只要您希望将touch事件调度到列表视图,就可以使用自己的逻辑来处理.

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

此处是固定的项目源代码. >

I have a cardview with a listview inside. 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. I have set a onTouchListener on the cardview but it doesn't work.

Code:

Put this in 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. If I remove the ListView from the cardview, then it starts working.

So somehow the listView is consuming the touch events instead of the parent cardview first.

XML for MainActivity:

<?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. no luck.

解决方案

In Android, touch events bubble up from child to parents as you would expect. 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.

To intercept the touch event from the CardView, you need to create a custom view that subclass it and override the onInterceptTouchEvent method:

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:

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

这篇关于内置ListView的Android CardView-CardView上的onTouchListener不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆