Estoy tratando de implementar un dedo para desestimar la acción en un RecyclerView pero cuando me puse un OnClickListener en cualquier Vista en un ViewHolder anula todos los OnTouch eventos en esa vista.

Puedo abandonar OnClickListener y manejar todos los clics en la TouchListener pero si tengo varios botones en un niño de la RecycleView de que será una gran cantidad de código y este no tiene el aspecto de una manera correcta.

En mi RecyleView estoy de poner el dedo para despedir a los oyentes (similar a este):

    setOnTouchListener(touchListener);
    setOnScrollListener(touchListener.makeScrollListener());

Funciona en el ListView, pero en el RecycleView el OnClickListener bloques OnTouchListner eventos.

Ejemplo de la disposición de ViewHolder vista.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="72dp"
android:descendantFocusability="blocksDescendants">

<ImageView
    android:id="@+id/keep_icon"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:layout_centerInParent="true"
    android:src="@drawable/ic_received" />

Inflar en la RecyclerView.Adaptador:

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = mInflater.inflate(R.layout.push_card_view_compat, viewGroup, false);
    return new ViewHolder(v, onClickListener, onKeepListener);
}

La ViewHolder:

public ViewHolder(final View itemView,
                  final OnViewHolderClickListener onClickListener,
                  final OnKeepListener onKeepListener) {
    super(itemView);
    keepButton = (ImageView) itemView.findViewById(R.id.keep_icon);

    itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        onItemClickListener.onClick(getPosition(), itemView);
    }
    });
    keepButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        onKeepListener.onClick(getPosition(), itemView);
    }
    });
}
  • publica tu código, a continuación,
  • ¿por qué un montón de código?
  • He añadido el código.
  • trate de añadir a su xml outter ViewGroup para la fila elementos: android:descendantFocusability="blocksDescendants"
  • No trabajo.
  • ¿agregar esto a su elemento padre de su vista de titular?
  • Sí, también he intentado «afterDescendants», pero tampoco funcionó.
  • publica tu xml por favor
  • Añadido xml y más código.
  • han utilizado RecyclerView.OnItemTouchListener ?
  • Se parece a un RecyclerView.OnItemTouchListener es el camino a seguir, un OnClickListener no bloquear sus eventos. Pero funciona de forma diferente que OnTouchListener y necesita un poco de implementación diferente para los golpes.
  • funciona como un ViewGroup toque eventos: usted tiene onInterceptTouchEvent y OnTouchEvent
  • Encontraste el solition? Si sí, por favor compartirlo.

InformationsquelleAutor Ivan Fork | 2014-10-29

1 Comentario

  1. 22

    He conseguido que mediante la asignación de OnClickListener para los botones en la ViewHolder, y la creación de una interfaz para los eventos de toque.

    El proyecto de ejemplo está en GitHub: https://github.com/brnunes/SwipeableRecyclerView.

    En mi caso, cada elemento es un CardView con dos botones, y la quiero para detectar los eventos de toque en la CardView y la Buttons. El CardView diseño se parece a esto:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.CardView 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="match_parent"
        android:layout_margin="5dp"
        android:clickable="true"
        android:foreground="?android:attr/selectableItemBackground"
        android:orientation="vertical"
        card_view:cardCornerRadius="5dp">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                android:id="@+id/card_view_title"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:gravity="center"
                android:textColor="@android:color/black"
                android:textSize="24sp" />
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_below="@id/card_view_title"
                android:layout_centerHorizontal="true"
                android:gravity="center">
    
                <Button
                    android:id="@+id/card_view_button1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Button1" />
    
                <Button
                    android:id="@+id/card_view_button2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Button2" />
            </LinearLayout>
        </RelativeLayout>
    
    </android.support.v7.widget.CardView>

    A continuación, en la Activity, me declara una interfaz para recibir el toque eventos:

    public interface OnItemTouchListener {
        public void onCardViewTap(View view, int position);
        public void onButton1Click(View view, int position);
        public void onButton2Click(View view, int position);
    }

    Y en el ViewHolder puedo asignar OnClickListeners a los objetos que quiero escuchar, y llame a mi costumbre de escucha:

    public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.ViewHolder> {
    private List<String> cards;
    private OnItemTouchListener onItemTouchListener;
    public CardViewAdapter(List<String> cards, OnItemTouchListener onItemTouchListener) {
    this.cards = cards;
    this.onItemTouchListener = onItemTouchListener;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view_layout, viewGroup, false);
    return new ViewHolder(v);
    }
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
    viewHolder.title.setText(cards.get(i));
    }
    @Override
    public int getItemCount() {
    return cards == null ? 0 : cards.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder {
    private TextView title;
    private Button button1;
    private Button button2;
    public ViewHolder(View itemView) {
    super(itemView);
    title = (TextView) itemView.findViewById(R.id.card_view_title);
    button1 = (Button) itemView.findViewById(R.id.card_view_button1);
    button2 = (Button) itemView.findViewById(R.id.card_view_button2);
    button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    onItemTouchListener.onButton1Click(v, getPosition());
    }
    });
    button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    onItemTouchListener.onButton2Click(v, getPosition());
    }
    });
    itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    onItemTouchListener.onCardViewTap(v, getPosition());
    }
    });
    }
    }
    }

    Finalmente, crear la costumbre OnItemTouchListener y se pasa a la CardViewAdapter constructor:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mItems = new ArrayList<>(30);
    for (int i = 0; i < 30; i++) {
    mItems.add(String.format("Card number %2d", i));
    }
    OnItemTouchListener itemTouchListener = new OnItemTouchListener() {
    @Override
    public void onCardViewTap(View view, int position) {
    Toast.makeText(MainActivity.this, "Tapped " + mItems.get(position), Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onButton1Click(View view, int position) {
    Toast.makeText(MainActivity.this, "Clicked Button1 in " + mItems.get(position), Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onButton2Click(View view, int position) {
    Toast.makeText(MainActivity.this, "Clicked Button2 in " + mItems.get(position), Toast.LENGTH_SHORT).show();
    }
    };
    mAdapter = new CardViewAdapter(mItems, itemTouchListener);
    mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    mRecyclerView.setAdapter(mAdapter);
    //... Assign the swipe listener
    }
    • Me gustaría poder hasta votar un millón de veces! Mi desplazamiento es todavía un poco escalonada, debido a la carga de imágenes… algún consejo sobre que sería genial. :\
    • La solución es cargar la imagen a la memoria de forma asincrónica en un AsyncTask, y luego mostrarlo en el ImageView. Consulte este artículo developer.android.com/training/improving-layouts/…. Este post también habla sobre async carga. En el ejemplo de las imágenes que se descargan de internet, pero es aún más simple si se carga a nivel local: android-developers.blogspot.com/2010/07/…
    • gracias por este.

Dejar respuesta

Please enter your comment!
Please enter your name here