android - studio - Cómo obtener clics en RecyclerView(NO los niños)
recyclerview android 3 (3)
Intente algo así como concluir su visión de reciclador dentro de un layout relativo o linearlayout o FrameLayout y luego configure el listener de clics en relativelayout / linearlayout / framelayout.
<RelativeLayout
android:id="@+id/myLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Ahora :
RelativeLayout rl = (RelativeLayout) findViewById(R.id.myLayout);
rl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("patricia", view.toString());
}
});
¿Hay alguna manera de configurar un onClickListener
en un RecyclerView
?
Tengo un RecyclerView
con algunos niños y un OnClickListener
en el RecyclerView
padre. Sin embargo, onClick
no se dispara cuando hago clic en esa vista. Consulte el código de muestra a continuación: queremos obtener clics en el elemento principal, NO en los elementos secundarios. En este escenario, no nos importan los clics en los artículos.
He intentado hacer setFocusable(false)
, setClickable(false)
y setOnClickListener(null)
en los niños en vano. En cualquier caso, no creo que los niños estén robando clics del padre, porque cuando hago clic en el área donde no hay hijos, los clics tampoco se registran.
package com.formagrid.hellotest;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.Arrays;
import java.util.List;
public class HelloActivity extends Activity {
private RecyclerView mRecyclerView;
private RecyclerAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new RecyclerAdapter(Arrays.asList("hi", "this", "is", "some", "text"));
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("patricia", view.toString());
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.Holder> {
public class Holder extends RecyclerView.ViewHolder {
protected TextView textView;
public Holder(TextView itemView) {
super(itemView);
this.textView = itemView;
}
}
private List<String> contents;
public RecyclerAdapter(List<String> contents) {
this.contents = contents;
}
@Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
return new Holder(new TextView(parent.getContext()));
}
@Override
public void onBindViewHolder(Holder holder, int position) {
holder.textView.setText(contents.get(position));
}
@Override
public int getItemCount() {
return contents.size();
}
}
}
un evento de clic en RecycleView? intente así:
//set android:descendantFocusability="blocksDescendants" on parent layout
//then setOnClickListener
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
**android:descendantFocusability="blocksDescendants"**
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
¿Hay alguna manera de configurar un
onClickListener
en unRecyclerView
?
No. Es decir, puede configurar OnClickListener
, pero RecyclerView
nunca lo llamará. RecyclerView
intercepta todos los eventos táctiles, pero nunca llama a performClick()
, que es la forma en que View
invoca a su oyente.
Sin embargo, puede simular OnClickListener
con OnTouchListener
y GestureDetector
. Para el oyente GestureDetector
, podemos usar un SimpleOnGestureListener
, implementando solo el método onSingleTapUp()
.
class ClickListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
Toast.makeText(HelloActivity.this, "Clicked", 0).show();
return true;
}
};
Entonces solo necesitamos alimentar el GestureDetector
MotionEvent
desde un OnTouchListener
, y verificar el retorno para decidir si consumimos el evento, para no interferir con el desplazamiento, el arrastre, etc.
final GestureDetector detector = new GestureDetector(HelloActivity.this, new ClickListener());
mRecyclerView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(detector.onTouchEvent(event)) {
return true;
}
return false;
}
}
);
Tenga en cuenta que la solución anterior funciona prácticamente con un RecyclerView
"simple", como el descrito y proporcionado en la pregunta. Si está utilizando un manejo de elementos más complicado, como arrastrar, soltar o deslizar, tendremos que manejar nuestra detección de gestos un poco más adelante en la cadena de eventos táctiles.
Para hacer esto, podemos subclasificar RecyclerView
y realizar la detección en el método dispatchTouchEvent()
. Si se detecta un solo toque, simplemente llamamos a performClick()
, que activará OnClickListener
RecyclerView
.
public class ClickableRecyclerView extends RecyclerView {
private final GestureDetectorCompat detector;
public ClickableRecyclerView(Context context) {
this(context, null);
}
public ClickableRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
detector = new GestureDetectorCompat(context, new ClickListener());
}
private class ClickListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
performClick();
return true;
}
};
@Override
public boolean dispatchTouchEvent(MotionEvent e) {
detector.onTouchEvent(e);
return super.dispatchTouchEvent(e);
}
}
Simplemente use esta subclase en lugar de su RecyclerView
normal, y configure OnClickListener
como lo haría normalmente. Es posible que se necesiten constructores adicionales, dependiendo de cómo esté instanciando esto.