web-dev-qa-db-ja.com

RecyclerViewとCardViewによるタッチフィードバック

オープンソースライブラリのタッチフィードバックを有効にしたいと思います。

RecyclerViewCardViewを作成しました。 CardViewには、異なるonClickアクションを持つ異なる領域が含まれています。ユーザーがカードの任意の場所をクリックすると、リップル効果がトリガーされますが、この動作を実現することはできません。

これは私のリストアイテムです。GitHubでも見つけることができます。 https://github.com/mikepenz/AboutLibraries/blob/master/library/src/main/res/layout/listitem_opensource.xml

<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:clickable="true"
    Android:background="@drawable/button_rect_normal"/>

<LinearLayout
    Android:padding="6dp"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="vertical">

    <LinearLayout
        Android:gravity="center_vertical"
        Android:paddingLeft="8dp"
        Android:paddingRight="8dp"
        Android:orientation="horizontal"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <TextView
            Android:id="@+id/libraryName"
            Android:textColor="@color/title_openSource"
            Android:textSize="@dimen/textSizeLarge_openSource"
            Android:textStyle="normal"
            Android:layout_width="0dp"
            Android:layout_weight="5"
            Android:layout_height="wrap_content"
            Android:ellipsize="end"
            Android:maxLines="1"/>

        <TextView
            Android:id="@+id/libraryCreator"
            Android:textColor="@color/text_openSource"
            Android:textStyle="normal"
            Android:layout_width="0dp"
            Android:layout_weight="2"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="2dp"
            Android:gravity="right"
            Android:maxLines="2"
            Android:textSize="@dimen/textSizeSmall_openSource"/>
    </LinearLayout>

    <View
        Android:layout_width="match_parent"
        Android:layout_height="1px"
        Android:layout_marginTop="4dp"
        Android:background="@color/dividerLight_openSource"/>

    <TextView
        Android:id="@+id/libraryDescription"
        Android:textSize="@dimen/textSizeSmall_openSource"
        Android:textStyle="normal"
        Android:textColor="@color/text_openSource"
        Android:padding="8dp"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:maxLines="20">
    </TextView>

    <View
        Android:id="@+id/libraryBottomDivider"
        Android:layout_width="match_parent"
        Android:layout_height="1px"
        Android:layout_marginTop="4dp"
        Android:background="@color/dividerLight_openSource"/>

    <LinearLayout
        Android:id="@+id/libraryBottomContainer"
        Android:gravity="center_vertical"
        Android:paddingLeft="8dp"
        Android:paddingTop="4dp"
        Android:paddingRight="8dp"
        Android:orientation="horizontal"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <TextView
            Android:id="@+id/libraryVersion"
            Android:textColor="@color/text_openSource"
            Android:textStyle="normal"
            Android:layout_width="0dp"
            Android:layout_weight="1"
            Android:layout_height="wrap_content"
            Android:gravity="left"
            Android:maxLines="1"
            Android:textSize="@dimen/textSizeSmall_openSource"/>

        <TextView
            Android:id="@+id/libraryLicense"
            Android:textColor="@color/text_openSource"
            Android:textStyle="normal"
            Android:layout_width="0dp"
            Android:layout_weight="1"
            Android:layout_height="wrap_content"
            Android:gravity="right"
            Android:maxLines="1"
            Android:textSize="@dimen/textSizeSmall_openSource"/>
    </LinearLayout>
</LinearLayout>

また、onClickは、このレイアウトの3つの部分に設定されています。 libraryCreatorlibraryDescription、およびlibraryBottomContainer

ここで何が間違っているのか、誰かがアイデアを得たと思います。

ご協力いただきありがとうございます。

67
mikepenz

これで問題を解決できました。

問題は、TextViewsでonClickListenerを使用し、このクリックリスナーがRippleForegroundがタッチイベントについて通知されないようにすることです。そのため、解決策は、これらのTextViewにTouchListenerを実装し、タッチイベントを渡すことです。

クラスは本当にシンプルで、どこでも使用できます。

package com.mikepenz.aboutlibraries.util;

import Android.support.v7.widget.CardView;
import Android.view.MotionEvent;
import Android.view.View;

/**
 * Created by mikepenz on 16.04.15.
 */
public class RippleForegroundListener implements View.OnTouchListener {
    CardView cardView;

    public RippleForegroundListener setCardView(CardView cardView) {
        this.cardView = cardView;
        return this;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // Convert to card view coordinates. Assumes the Host view is
        // a direct child and the card view is not scrollable.
        float x = event.getX() + v.getLeft();
        float y = event.getY() + v.getTop();

        if (Android.os.Build.VERSION.SDK_INT >= 21) {
            // Simulate motion on the card view.
            cardView.drawableHotspotChanged(x, y);
        }

        // Simulate pressed state on the card view.
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                cardView.setPressed(true);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                cardView.setPressed(false);
                break;
        }

        // Pass all events through to the Host view.
        return false;
    }
}

これをTouchListenerとして追加することで使用できます。

RippleForegroundListener rippleForegroundListener = new RippleForegroundListener();
older.libraryCreator.setOnTouchListener(rippleForegroundListener);

このリスナーは、タッチイベントをCardViewに渡すだけで、正しいリップル効果をトリガーします。 (任意のビューを取得するようにこれを変更することもできます。CardViewに限定されるべきではありません)

10
mikepenz

Material/AppcompatテーマとLollipopを使用していると仮定すると、CardViewに次の属性を持たせることでこれが機能するようになりました。

Android:focusable="true"
Android:clickable="true"
Android:foreground="?android:attr/selectableItemBackground"
120
Gak2

CardLayoutはViewGroupのサブクラスなので、設定は次のとおりです。

Android:background="?android:attr/selectableItemBackground"

トリックを行う必要があります。

UPDATE:

(カスタムリップル色を使用しようとしているように見えます。)

背景としてカスタムカラーのリップルドローアブルを使用してみてください(これを使用していません。したがって、この動作を確認できません。)参照: documentation またはthis question あなたが始めました。

52
Avinash R

私のために:

Android:background="?android:attr/selectableItemBackground"

ようやく機能しました。 recyclerViewの背景/アイテムの背後にあるコンテンツを参照し、recyclerViewで使用される波及効果も参照してください。

22
cV2

上記の答えはどれも私にとってはうまくいかず、あまりにも複雑でした。

その後、RECYCLERVIEW ADAPTERレイアウトで次のプロパティを設定する必要があることに気付きました。

Android:background="?android:attr/selectableItemBackground"
Android:focusable="true"
Android:clickable="true"

それから私はそれを動作させました。

14
Jjang
Android:foreground="?android:attr/selectableItemBackground"

バックグラウンドの代わりにフォアグラウンドを使用する場合、クリック可能またはフォーカス可能を使用する必要はありません

9
sativa

私の場合、カスタムの背景と波及効果も表示する必要がありました。したがって、これを実現する方法は、リサイクラービューアイテムのルートレイアウトに次の2つの属性を適用することです。

Android:background="@drawable/custom_bg"
Android:foreground="?android:attr/selectableItemBackground"
5
Safeer

江と同じ問題がありました:

RecycleViewを膨らませるレイアウトファイルに属性を設定する必要があります。

私のメインレイアウト:(Do n'tここにプロパティを追加してください!)

<?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.support.v7.widget.RecyclerView
    Android:id="@+id/recycler_view"
    Android:scrollbars="vertical"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content" />

</RelativeLayout>

私のRecycleViewAdapter:

            View v = inflater.inflate(R.layout.list_center_item, parent, false);

私のlist_center_item.xml(ここにプロパティを追加してください!

<?xml version="1.0" encoding="utf-8"?>


<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@Android:id/text1"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:gravity="center"


Android:background="?android:attr/selectableItemBackground"
Android:clickable="true"
Android:focusable="true"
/>
4
basti12354

CardViewの下で使用しているレイアウトに次の行を追加する必要があります

Android:clickable="true"
Android:focusable="true"
Android:background="@drawable/my_ripple"

<Android.support.v7.widget.CardView Android:layout_height="wrap_content"
Android:layout_width="match_parent"
xmlns:Android="http://schemas.Android.com/apk/res/Android">

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:clickable="true"
Android:focusable="true"
Android:background="@drawable/my_ripple">
0
priyankvex

私の場合、実際の馬鹿げた問題は次のとおりです...

技術的には、私の場合、誰もがここで提案しているようなことではありません。本当の問題は、LayoutViewRelativeView、またはTextViewのどこでもAndroid:clickable = "true"を使用してはならないことです。

CardViewにのみ存在する必要があります。その後、チャームのように動作します

Android:focusable="true"は本当に必要ではありません。

CardViewに以下を追加するだけです

Android:clickable="true" Android:foreground="?android:attr/selectableItemBackground"


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:card_view="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content">

    <Android.support.v7.widget.CardView
        Android:id="@+id/card_view"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_gravity="center"
        Android:layout_margin="@dimen/card_margin"
        Android:foreground="?android:attr/selectableItemBackground"
        Android:clickable="true"
        Android:elevation="3dp"
        card_view:cardCornerRadius="@dimen/card_corner_radius">

        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent">

            <ImageView
                Android:id="@+id/card_template_item_image"
                Android:layout_width="match_parent"
                Android:layout_height="@dimen/card_size_height"
                Android:scaleType="fitXY" />

            <TextView
                Android:id="@+id/card_template_item_title"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_below="@id/card_template_item_image"
                Android:paddingLeft="@dimen/card_title_padding"
                Android:paddingRight="@dimen/card_title_padding"
                Android:paddingTop="@dimen/card_title_padding"
                Android:textSize="@dimen/card_title_size"
                Android:text="@string/place_holder_item_name"/>

            <TextView
                Android:id="@+id/card_template_item_sub_title"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_below="@id/card_template_item_title"
                Android:paddingBottom="@dimen/card_sub_title_padding"
                Android:paddingLeft="@dimen/card_sub_title_padding"
                Android:paddingRight="@dimen/card_sub_title_padding"
                Android:textSize="@dimen/card_sub_title_size"
                Android:text="@string/place_holder_item_category"/>

        </RelativeLayout>

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

</LinearLayout>
0
Kirk