diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java b/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java index 18cf407..f245a33 100644 --- a/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java +++ b/app/src/main/java/com/majinnaibu/monstercards/ui/library/LibraryFragment.java @@ -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); - } - } } diff --git a/app/src/main/java/com/majinnaibu/monstercards/ui/shared/SwipeToDeleteCallback.java b/app/src/main/java/com/majinnaibu/monstercards/ui/shared/SwipeToDeleteCallback.java new file mode 100644 index 0000000..46830c2 --- /dev/null +++ b/app/src/main/java/com/majinnaibu/monstercards/ui/shared/SwipeToDeleteCallback.java @@ -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); + } +} diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index b91e898..ba0ed7c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -4,4 +4,14 @@ #661A10 #995500 + + + #FF3B30 + #FF9500 + #FFCC00 + #4CD964 + #5AC8FA + #007AFF + #5855D6 + #FF2D55 \ No newline at end of file