Makes the swipe to delete callback more generic.
This commit is contained in:
		| @@ -1,19 +1,11 @@ | ||||
| package com.majinnaibu.monstercards.ui.library; | ||||
|  | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.Paint; | ||||
| import android.graphics.PorterDuff; | ||||
| import android.graphics.PorterDuffXfermode; | ||||
| import android.graphics.drawable.ColorDrawable; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.os.Bundle; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.core.content.ContextCompat; | ||||
| import androidx.navigation.NavDirections; | ||||
| import androidx.navigation.Navigation; | ||||
| import androidx.recyclerview.widget.ItemTouchHelper; | ||||
| @@ -27,6 +19,7 @@ import com.majinnaibu.monstercards.data.MonsterRepository; | ||||
| import com.majinnaibu.monstercards.models.Monster; | ||||
| import com.majinnaibu.monstercards.ui.MCFragment; | ||||
| import com.majinnaibu.monstercards.ui.MonsterListRecyclerViewAdapter; | ||||
| import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | ||||
| import com.majinnaibu.monstercards.utils.Logger; | ||||
|  | ||||
| import java.util.UUID; | ||||
| @@ -41,30 +34,10 @@ public class LibraryFragment extends MCFragment { | ||||
|         View root = inflater.inflate(R.layout.fragment_library, container, false); | ||||
|  | ||||
|         FloatingActionButton fab = root.findViewById(R.id.fab); | ||||
|         fab.setOnClickListener(view -> { | ||||
|             Monster monster = new Monster(); | ||||
|             monster.name = "Unnamed Monster"; | ||||
|             MonsterRepository repository = this.getMonsterRepository(); | ||||
|             repository.addMonster(monster) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(() -> { | ||||
|                         Snackbar.make( | ||||
|                                 getView(), | ||||
|                                 String.format("%s created", monster.name), | ||||
|                                 Snackbar.LENGTH_LONG) | ||||
|                                 .setAction("Action", (_view) -> { | ||||
|                                     navigateToMonsterDetail(monster.id); | ||||
|                                 }) | ||||
|                                 .show(); | ||||
|                     }, throwable -> { | ||||
|                         Logger.logError("Error creating monster", throwable); | ||||
|                         Snackbar.make(getView(), "Failed to create monster", Snackbar.LENGTH_LONG) | ||||
|                                 .setAction("Action", null).show(); | ||||
|                     }); | ||||
|         }); | ||||
|         assert fab != null; | ||||
|         setupAddMonsterButton(fab); | ||||
|  | ||||
|         RecyclerView recyclerView = root.findViewById(R.id.monster_list); | ||||
|         final RecyclerView recyclerView = root.findViewById(R.id.monster_list); | ||||
|         assert recyclerView != null; | ||||
|         setupRecyclerView(recyclerView); | ||||
|  | ||||
| @@ -89,69 +62,40 @@ public class LibraryFragment extends MCFragment { | ||||
|                 mTwoPane); | ||||
|         recyclerView.setAdapter(adapter); | ||||
|         recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); | ||||
|         ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteMonsterCallback(adapter)); | ||||
|         ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(getContext(), (position) -> { | ||||
|             adapter.deleteItem(position); | ||||
|         })); | ||||
|         itemTouchHelper.attachToRecyclerView(recyclerView); | ||||
|     } | ||||
|  | ||||
|     private void setupAddMonsterButton(@NonNull FloatingActionButton fab) { | ||||
|         fab.setOnClickListener(view -> { | ||||
|             Monster monster = new Monster(); | ||||
|             monster.name = "Unnamed Monster"; | ||||
|             MonsterRepository repository = this.getMonsterRepository(); | ||||
|             repository.addMonster(monster) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(() -> { | ||||
|                         Snackbar.make( | ||||
|                                 getView(), | ||||
|                                 String.format("%s created", monster.name), | ||||
|                                 Snackbar.LENGTH_LONG) | ||||
|                                 .setAction("Action", (_view) -> { | ||||
|                                     navigateToMonsterDetail(monster.id); | ||||
|                                 }) | ||||
|                                 .show(); | ||||
|                     }, throwable -> { | ||||
|                         Logger.logError("Error creating monster", throwable); | ||||
|                         Snackbar.make(getView(), "Failed to create monster", Snackbar.LENGTH_LONG) | ||||
|                                 .setAction("Action", null).show(); | ||||
|                     }); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     protected void navigateToMonsterDetail(UUID monsterId) { | ||||
|         NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString()); | ||||
|         Navigation.findNavController(getView()).navigate(action); | ||||
|     } | ||||
|  | ||||
|     public static class SwipeToDeleteMonsterCallback extends ItemTouchHelper.SimpleCallback { | ||||
|         private final MonsterListRecyclerViewAdapter mAdapter; | ||||
|         private final Drawable icon; | ||||
|         private final ColorDrawable background; | ||||
|         private final Paint clearPaint; | ||||
|  | ||||
|         public SwipeToDeleteMonsterCallback(MonsterListRecyclerViewAdapter adapter) { | ||||
|             super(0, ItemTouchHelper.LEFT); | ||||
|             mAdapter = adapter; | ||||
|             icon = ContextCompat.getDrawable(mAdapter.getContext(), R.drawable.ic_delete_white_36); | ||||
|             background = new ColorDrawable(Color.RED); | ||||
|             clearPaint = new Paint(); | ||||
|             clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { | ||||
|             int position = viewHolder.getAdapterPosition(); | ||||
|             mAdapter.deleteItem(position); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { | ||||
|             View itemView = viewHolder.itemView; | ||||
|             int itemHeight = itemView.getBottom() - itemView.getTop(); | ||||
|             boolean isCancelled = dX == 0 && !isCurrentlyActive; | ||||
|  | ||||
|             if (isCancelled) { | ||||
|                 c.drawRect(itemView.getRight() + dX, itemView.getTop(), itemView.getRight(), itemView.getBottom(), clearPaint); | ||||
|                 return; | ||||
|             } | ||||
|             // Draw the red delete background | ||||
|             background.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); | ||||
|             background.draw(c); | ||||
|  | ||||
|             // Calculate position of delete icon | ||||
|             int iconHeight = icon.getIntrinsicHeight(); | ||||
|             int iconWidth = icon.getIntrinsicWidth(); | ||||
|             int iconTop = itemView.getTop() + (itemHeight - iconHeight) / 2; | ||||
|             int iconMargin = (itemHeight - iconHeight) / 2; | ||||
|             int iconLeft = itemView.getRight() - iconMargin - iconWidth; | ||||
|             int iconRight = itemView.getRight() - iconMargin; | ||||
|             int iconBottom = iconTop + iconHeight; | ||||
|  | ||||
|             // Draw the icon | ||||
|             icon.setBounds(iconLeft, iconTop, iconRight, iconBottom); | ||||
|             icon.draw(c); | ||||
|  | ||||
|             super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,87 @@ | ||||
| package com.majinnaibu.monstercards.ui.shared; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.graphics.Canvas; | ||||
| import android.graphics.Paint; | ||||
| import android.graphics.PorterDuff; | ||||
| import android.graphics.PorterDuffXfermode; | ||||
| import android.graphics.drawable.ColorDrawable; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.view.View; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.core.content.ContextCompat; | ||||
| import androidx.recyclerview.widget.ItemTouchHelper; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
|  | ||||
| import com.majinnaibu.monstercards.R; | ||||
|  | ||||
| public class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback { | ||||
|  | ||||
|     public interface OnDeleteCallback { | ||||
|         void onDelete(int position); | ||||
|     } | ||||
|  | ||||
|     private final Drawable icon; | ||||
|     private final ColorDrawable background; | ||||
|     private final Paint clearPaint; | ||||
|     private final OnDeleteCallback mOnDelete; | ||||
|     private final Context mContext; | ||||
|  | ||||
|     public SwipeToDeleteCallback(Context context, OnDeleteCallback onDelete) { | ||||
|         super(0, ItemTouchHelper.LEFT); | ||||
|         mOnDelete = onDelete; | ||||
|         mContext = context; | ||||
|         icon = ContextCompat.getDrawable(mContext, R.drawable.ic_delete_white_36); | ||||
|         background = new ColorDrawable(context.getResources().getColor(R.color.red)); | ||||
|         clearPaint = new Paint(); | ||||
|         clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean onMove( | ||||
|             @NonNull RecyclerView recyclerView, | ||||
|             @NonNull RecyclerView.ViewHolder viewHolder, | ||||
|             @NonNull RecyclerView.ViewHolder target | ||||
|     ) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { | ||||
|         if (mOnDelete != null) { | ||||
|             int position = viewHolder.getAdapterPosition(); | ||||
|             mOnDelete.onDelete(position); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { | ||||
|         View itemView = viewHolder.itemView; | ||||
|         int itemHeight = itemView.getBottom() - itemView.getTop(); | ||||
|         boolean isCancelled = dX == 0 && !isCurrentlyActive; | ||||
|  | ||||
|         if (isCancelled) { | ||||
|             c.drawRect(itemView.getRight() + dX, itemView.getTop(), itemView.getRight(), itemView.getBottom(), clearPaint); | ||||
|             return; | ||||
|         } | ||||
|         // Draw the red delete background | ||||
|         background.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); | ||||
|         background.draw(c); | ||||
|  | ||||
|         // Calculate position of delete icon | ||||
|         int iconHeight = icon.getIntrinsicHeight(); | ||||
|         int iconWidth = icon.getIntrinsicWidth(); | ||||
|         int iconTop = itemView.getTop() + (itemHeight - iconHeight) / 2; | ||||
|         int iconMargin = (itemHeight - iconHeight) / 2; | ||||
|         int iconLeft = itemView.getRight() - iconMargin - iconWidth; | ||||
|         int iconRight = itemView.getRight() - iconMargin; | ||||
|         int iconBottom = iconTop + iconHeight; | ||||
|  | ||||
|         // Draw the icon | ||||
|         icon.setBounds(iconLeft, iconTop, iconRight, iconBottom); | ||||
|         icon.draw(c); | ||||
|  | ||||
|         super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user