Обратная связь касания с RecyclerView и CardView
Я хотел бы включить сенсорную обратную связь для моей библиотеки с открытым исходным кодом.
Я создал RecyclerView
и CardView
. The CardView
содержит различные области с различными onClick
действия. Теперь я хотел бы вызвать эффект пульсации, если пользователь щелкает в любом месте карты, но я не могу добиться такого поведения.
это мой listitem элемент, Вы также можете найти его на 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 части этого макета. libraryCreator
, libraryDescription
и libraryBottomContainer
.
надеюсь, кто-то понял, что здесь происходит не так.
Спасибо за вашу помощь.
9 ответов
предполагая, что вы используете тему Material / Appcompat и Lollipop, я получил это для работы, сделав CardView иметь следующие атрибуты:
android:focusable="true"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
CardLayout - это просто подкласс ViewGroup, поэтому настройка:
android:background="?android:attr/selectableItemBackground"
следует сделать трюк.
обновление:
(похоже, вы пытаетесь использовать пользовательский цвет пульсации.)
попробуйте использовать Ripple drawable с пользовательским цветом в качестве фона (я не использовал это, поэтому я не могу проверить это поведение.) см.:документация или это вопрос чтобы вы начали.
для меня:
android:background="?android:attr/selectableItemBackground"
сделал он, наконец, работает. см. фон recyclerView / content позади элемента, а также см. эффект пульсации, используемый с recyclerView.
ни один из вышеперечисленных ответов не работал для меня или был слишком сложным.
затем я понял, что мне нужно установить следующие свойства в макете адаптера RECYCLERVIEW.
android:background="?android:attr/selectableItemBackground"
android:focusable="true"
android:clickable="true"
затем я заставил его работать.
теперь я смог решить эту проблему.
проблема в том, что я использую onClickListener в TextViews, и этот прослушиватель щелчка предотвращает уведомление RippleForeground о событии касания. Таким решением является внедрение 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)
android:foreground="?android:attr/selectableItemBackground"
Если вы используете передний план вместо фона, вам не нужно использовать clickable или focusable
в моем случае мне нужно было показать пользовательский фон и эффект пульсации. Таким образом, я достиг этого, применив эти два атрибута к корневому макету моего элемента recycler-view:
android:background="@drawable/custom_bg"
android:foreground="?android:attr/selectableItemBackground"
имел ту же проблему, что и Цзян:
Я должен установить атрибуты в файл макета, который раздувает RecycleView.
Мой Основной Макет: (не добавить свойства здесь!)
<?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"
/>
вы должны добавить следующие строки в макет, который вы используете в разделе 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">