I've tried to use RecyclerView in my android project, and everything works fine instead of the swipe touch handling. What I would like to approach is a custom view (mainly some buttons), under the list items. See the screenshot below: swipeable item background expectation
I already find the way how to perform the animation, but I can't click on the button on the background view. I guess the problem is that my touchlistener still wants to perform the swipe effect instead of click event, because the "swipeable area" is still the complete width of the view (foreground and background). Is there any known workaround or best practice to handle click events under the main item? Or can I make only the foreground swipeable?
Here are my code snippets.
Touch Listener:
public class TrainingListOnSwipeAndDragListener extends ItemTouchHelper.SimpleCallback {
private final MainActivity Activity;
private TrainingRoutineListAdapter Adapter;
public TrainingListOnSwipeAndDragListener(MainActivity activity, TrainingRoutineListAdapter adapter, int dragDirs, int swipeDirs) {
super(dragDirs, swipeDirs);
this.Activity = activity;
this.Adapter = adapter;
}
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return Adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public void onChildDraw(Canvas c, final RecyclerView recyclerView, final RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
View itemView = ((RoutineViewHolder) viewHolder).Foreground;
itemView.setTranslationX(dX / 2);
}else{
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
}
Item Layout xml:
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llTrainingExerciseLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:clickable="true"
android:focusable="true">
<RelativeLayout
android:id="@+id/background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/bg_extra_dark"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:visibility="visible">
<ImageView
android:id="@+id/deleteTrSet"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:padding="5dp"
android:src="@drawable/trash_neon_48"
android:clickable="true"/>
<ImageView
android:id="@+id/editTrSet"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignTop="@+id/deleteTrSet"
android:layout_toLeftOf="@+id/deleteTrSet"
android:layout_toStartOf="@+id/deleteTrSet"
android:padding="10dp"
android:src="@drawable/edit_neon_50"
android:clickable="true"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/foreground"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/calendar_background_statelist"
android:paddingBottom="8dp"
android:paddingTop="8dp"
android:visibility="visible">
<ImageView
android:id="@+id/imgTrainingActivityImage"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:background="@drawable/navdrawer_list_item_icon_backgroud"
android:padding="5dp"
android:src="@drawable/bear_footprint_50" />
<TextView
android:id="@+id/tvTrainingActivityTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/imgTrainingActivityImage"
android:layout_toEndOf="@+id/imgTrainingActivityImage"
android:layout_toRightOf="@+id/imgTrainingActivityImage"
android:text="Fekvőtámasz"
android:textColor="@color/text_white"
android:textSize="14sp" />
<TextView
android:id="@+id/tvTrainingActivitySetandReps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/tvTrainingActivityTitle"
android:layout_alignStart="@+id/tvTrainingActivityTitle"
android:layout_below="@+id/tvTrainingActivityTitle"
android:layout_gravity="center_horizontal"
android:layout_margin="2dp"
android:text="2 x 12"
android:textColor="@color/text_white"
android:textSize="@dimen/abc_text_size_medium_material" />
</RelativeLayout>
</RelativeLayout>
Adapter:
public class TrainingRoutineListAdapter extends RecyclerView.Adapter<RoutineViewHolder> implements CalendarClickCallback{
private MainActivity Activity;
private CustomFragmentFactory fragmentFactory;
private List<TrainingSet> mData;
public void setmData(List<TrainingSet> mData) {
this.mData = mData;
}
public TrainingRoutineListAdapter(MainActivity activity, List<TrainingSet> mData) {
this.Activity = activity;
this.fragmentFactory = CustomFragmentFactory.getCustomFragmentFactory();
this.mData = mData;
}
@Override
public RoutineViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View itemView = LayoutInflater.from(Activity).inflate(R.layout.trainingroutine_listitem_layout,parent,false);
return new RoutineViewHolder(itemView);
}
@Override
public void onBindViewHolder(RoutineViewHolder holder, final int position) {
holder.ExerciseName.setText(mData.get(position).getmExercise().getmName());
holder.Icon.setImageBitmap(Convert_Utils.decodeBase64(mData.get(position).getmExercise().getmIcon().getmBase64String()));
String reps ="";
String weight = "";
String time = "";
if ( mData.get(position).getmReps() != 0){
reps = mData.get(position).getmReps() + " Ism";
}
if ( mData.get(position).getmWeight() != 0){
weight = " ("+mData.get(position).getmWeight() + " kg)";
}
if ( mData.get(position).getmTime() != 0){
time = new SimpleDateFormat("mm:ss.SS").format(new Date(mData.get(position).getmTime()));
}
holder.SetsRepsTime.setText(reps + weight + time);
holder.EditSetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onEditRowClicked(position);
}
});
holder.DeleteSetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDeleteRowClicked(position);
}
});
}
@Override
public int getItemCount() {
return mData.size();
}
public void addItem(TrainingSet set) {
mData.add(set);
notifyItemInserted(mData.size());
}
public void removeItem(int position) {
mData.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mData.size());
}
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mData, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mData, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemClick(View view, int position) {
Bundle data = new Bundle();
data.putParcelable("Exercise", mData.get(position).getmExercise());
data.putBoolean("IsNewExercise", true);
data.putBoolean("AppBarRestore", false);
fragmentFactory.changeContentFragment(Activity, "Fragment_3_Details", data, FragmentTransaction.TRANSIT_FRAGMENT_OPEN, true);
}
@Override
public void onItemLongClick(View view, int position) {
//Toast.makeText(Activity, "Long clicked (" + position + ")", Toast.LENGTH_SHORT).show();
}
public void onEditRowClicked(int position) {
Toast.makeText(Activity, "Edit button clicked (" + position + ")", Toast.LENGTH_SHORT).show();
}
public void onDeleteRowClicked(int position) {
Toast.makeText(Activity, "Delete button clicked (" + position + ")", Toast.LENGTH_SHORT).show();
}
}
As I'm a beginner in Android, any comments and hints are welcome.
Thank you in advance,