Makes the swipe to delete callback more generic.
This commit is contained in:
@@ -1,19 +1,11 @@
|
|||||||
package com.majinnaibu.monstercards.ui.library;
|
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.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.navigation.NavDirections;
|
import androidx.navigation.NavDirections;
|
||||||
import androidx.navigation.Navigation;
|
import androidx.navigation.Navigation;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
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.models.Monster;
|
||||||
import com.majinnaibu.monstercards.ui.MCFragment;
|
import com.majinnaibu.monstercards.ui.MCFragment;
|
||||||
import com.majinnaibu.monstercards.ui.MonsterListRecyclerViewAdapter;
|
import com.majinnaibu.monstercards.ui.MonsterListRecyclerViewAdapter;
|
||||||
|
import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
|
||||||
import com.majinnaibu.monstercards.utils.Logger;
|
import com.majinnaibu.monstercards.utils.Logger;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -41,30 +34,10 @@ public class LibraryFragment extends MCFragment {
|
|||||||
View root = inflater.inflate(R.layout.fragment_library, container, false);
|
View root = inflater.inflate(R.layout.fragment_library, container, false);
|
||||||
|
|
||||||
FloatingActionButton fab = root.findViewById(R.id.fab);
|
FloatingActionButton fab = root.findViewById(R.id.fab);
|
||||||
fab.setOnClickListener(view -> {
|
assert fab != null;
|
||||||
Monster monster = new Monster();
|
setupAddMonsterButton(fab);
|
||||||
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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
RecyclerView recyclerView = root.findViewById(R.id.monster_list);
|
final RecyclerView recyclerView = root.findViewById(R.id.monster_list);
|
||||||
assert recyclerView != null;
|
assert recyclerView != null;
|
||||||
setupRecyclerView(recyclerView);
|
setupRecyclerView(recyclerView);
|
||||||
|
|
||||||
@@ -89,69 +62,40 @@ public class LibraryFragment extends MCFragment {
|
|||||||
mTwoPane);
|
mTwoPane);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
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);
|
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) {
|
protected void navigateToMonsterDetail(UUID monsterId) {
|
||||||
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString());
|
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString());
|
||||||
Navigation.findNavController(getView()).navigate(action);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,4 +4,14 @@
|
|||||||
<color name="colorPrimaryDark">#661A10</color>
|
<color name="colorPrimaryDark">#661A10</color>
|
||||||
<!-- <color name="colorAccent">#188B9B</color>-->
|
<!-- <color name="colorAccent">#188B9B</color>-->
|
||||||
<color name="colorAccent">#995500</color>
|
<color name="colorAccent">#995500</color>
|
||||||
|
|
||||||
|
<!-- fruit system colors -->
|
||||||
|
<color name="red">#FF3B30</color>
|
||||||
|
<color name="orange">#FF9500</color>
|
||||||
|
<color name="yellow">#FFCC00</color>
|
||||||
|
<color name="green">#4CD964</color>
|
||||||
|
<color name="tealBlue">#5AC8FA</color>
|
||||||
|
<color name="blue">#007AFF</color>
|
||||||
|
<color name="purple">#5855D6</color>
|
||||||
|
<color name="pink">#FF2D55</color>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user