i'm building a simple recyclerview with custom layout (Text view and switch) and a custom adapter.
My problem is i can't handle the click event for the switch (Which make it toggle its state), i have built a touch listener for the RecyclerView
and it fires every time i click on the Switch
.
After a lot of trials the switch touch listener fires also, but i want to disable the event of touch for the recyclerView if the switch is clicked.
Here is my Layout code :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="60.0dip"
android:layout_weight="1.0"
android:orientation="horizontal"
android:paddingLeft="16dp">
<TextView
android:id="@+id/category_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="false"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:text="Category Name"
android:textAppearance="?android:textAppearanceLarge" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/category_switch"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:checked="true"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:paddingRight="16dp" />
</RelativeLayout>
this is my adapter code :
public CategoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View row = layoutInflater.inflate(R.layout.single_row_category, parent, false);
CategoryViewHolder holder = new CategoryViewHolder(row);
return holder;
}
public void onBindViewHolder(CategoryViewHolder holder, final int position) {
AlarmCategory thisCat = categories.get(position);
holder.catName.setText(thisCat.getCategoryName());
holder.catStatus.setChecked(thisCat.isOn());
holder.catStatus.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.d("fpp", view.getClass().getName() + " is clicked");
return true;
}
});
}
public class CategoryViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {
public TextView catName;
public SwitchCompat catStatus;
public CategoryViewHolder(View itemView) {
super(itemView);
itemView.setOnCreateContextMenuListener(this);
catName = (TextView) itemView.findViewById(R.id.category_name);
catStatus = (SwitchCompat) itemView.findViewById(R.id.category_switch);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
menu.add(0, 1001, 0, "Edit");//groupId, itemId, order, title
menu.add(0, 1002, 1, "Delete");
}
}
And here's my recyclerView touch handler :
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
Log.d("fpp", child.getClass().getName() + " is clicked");
return false;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
and in the onCreate
Method i call it through :
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, recyclerView, new ClickListener() {
@Override
public void onClick(View view, int position) {
Intent i = new Intent(CategoriesList.this, AlarmList.class);
i.putExtra("catID", categories.get(position).getCategoryID());
startActivity(i);
}
@Override
public void onLongClick(View view, int position) {
catPos = position;
}
}));
Any help please, I already tried a lot of solutions but nothing worked for sorry.
Thanks in advance.
One way is to update your holder to handle any view clicks internally, e.g.
public class CategoryViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener, View.OnClickListener, CompoundButton.OnSetCheckedListener {
public CategoryViewHolder(View itemView) {
super(itemView);
itemView.setOnCreateContextMenuListener(this);
itemView.setOnClickListener(this);
catName = (TextView) itemView.findViewById(R.id.category_name);
catStatus = (SwitchCompat) itemView.findViewById(R.id.category_switch);
catStatus.setOnCheckChangedListener(this);
}
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// deal with catStatus change
}
public void onClick(View view) {
// deal with itemView click
}
}