WIP Issue #14 (and #65)

Add Ability to Select Multiple Cards
Highlight Card on Long Press/Click
Replace ListView with RecyclerView for Extra Features and Functionality
Add Card Long Press Animations
Replace CursorAdapter with a combination of RecyclerViewAdapter and Cursor Adapter
This commit is contained in:
Arshbeer Singh
2020-11-11 01:07:08 -08:00
committed by Sylvia van Os
parent 55373e82a5
commit 67328724fa
20 changed files with 792 additions and 245 deletions

View File

@@ -0,0 +1,86 @@
package protect.card_locker;
import android.database.Cursor;
import androidx.recyclerview.widget.RecyclerView;
public abstract class BaseCursorAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V>
{
private Cursor mCursor;
private boolean mDataValid;
private int mRowIDColumn;
public BaseCursorAdapter(Cursor inputCursor)
{
setHasStableIds(true);
swapCursor(inputCursor);
}
public abstract void onBindViewHolder(V inputHolder, Cursor inputCursor);
@Override
public void onBindViewHolder(V inputHolder, int inputPosition)
{
if (!mDataValid)
{
throw new IllegalStateException("Cannot bind view holder when cursor is in invalid state.");
}
if (!mCursor.moveToPosition(inputPosition))
{
throw new IllegalStateException("Could not move cursor to position " + inputPosition + " when trying to bind view holder");
}
onBindViewHolder(inputHolder, mCursor);
}
@Override
public int getItemCount()
{
if (mDataValid)
{
return mCursor.getCount();
}
else
{
return 0;
}
}
@Override
public long getItemId(int inputPosition)
{
if (!mDataValid)
{
throw new IllegalStateException("Cannot lookup item id when cursor is in invalid state.");
}
if (!mCursor.moveToPosition(inputPosition))
{
throw new IllegalStateException("Could not move cursor to position " + inputPosition + " when trying to get an item id");
}
return mCursor.getLong(mRowIDColumn);
}
public void swapCursor(Cursor inputCursor)
{
if (inputCursor == mCursor)
{
return;
}
if (inputCursor != null)
{
mCursor = inputCursor;
mDataValid = true;
notifyDataSetChanged();
}
else
{
notifyItemRangeRemoved(0, getItemCount());
mCursor = null;
mRowIDColumn = -1;
mDataValid = false;
}
}
}

View File

@@ -10,24 +10,24 @@ import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
/**
* The configuration screen for creating a shortcut.
*/
public class CardShortcutConfigure extends AppCompatActivity
public class CardShortcutConfigure extends AppCompatActivity implements LoyaltyCardCursorAdapter.MessageAdapterListener
{
static final String TAG = "Catima";
final DBHelper mDb = new DBHelper(this);
@Override
public void onCreate(Bundle bundle)
{
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// Set the result to CANCELED. This will cause nothing to happen if the
@@ -45,53 +45,59 @@ public class CardShortcutConfigure extends AppCompatActivity
final DBHelper db = new DBHelper(this);
// If there are no cards, bail
if(db.getLoyaltyCardCount() == 0)
{
if (db.getLoyaltyCardCount() == 0) {
Toast.makeText(this, R.string.noCardsMessage, Toast.LENGTH_LONG).show();
finish();
}
final ListView cardList = findViewById(R.id.list);
final RecyclerView cardList = findViewById(R.id.list);
cardList.setVisibility(View.VISIBLE);
Cursor cardCursor = db.getLoyaltyCardCursor();
final LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(this, cardCursor);
final LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(this, cardCursor, this);
cardList.setAdapter(adapter);
}
cardList.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Cursor selected = (Cursor) parent.getItemAtPosition(position);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
private void onClickAction(int position) {
Cursor selected = mDb.getLoyaltyCardCursor();
selected.moveToPosition(position);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
Log.d(TAG, "Creating shortcut for card " + loyaltyCard.store + "," + loyaltyCard.id);
Log.d(TAG, "Creating shortcut for card " + loyaltyCard.store + "," + loyaltyCard.id);
Intent shortcutIntent = new Intent(CardShortcutConfigure.this, LoyaltyCardViewActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCard.id);
bundle.putBoolean("view", true);
shortcutIntent.putExtras(bundle);
Intent shortcutIntent = new Intent(CardShortcutConfigure.this, LoyaltyCardViewActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN);
// Prevent instances of the view activity from piling up; if one exists let this
// one replace it.
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle bundle = new Bundle();
bundle.putInt("id", loyaltyCard.id);
bundle.putBoolean("view", true);
shortcutIntent.putExtras(bundle);
Bitmap icon = Utils.generateIcon(CardShortcutConfigure.this, loyaltyCard.store, loyaltyCard.headerColor, true).getLetterTile();
Parcelable icon = Intent.ShortcutIconResource.fromContext(CardShortcutConfigure.this, R.mipmap.ic_launcher);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, loyaltyCard.store);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
setResult(RESULT_OK, intent);
ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(CardShortcutConfigure.this, String.valueOf(loyaltyCard.id))
.setIntent(shortcutIntent)
.setIcon(IconCompat.createWithAdaptiveBitmap(icon))
.setShortLabel(loyaltyCard.store)
.build();
finish();
}
Intent intent = ShortcutManagerCompat.createShortcutResultIntent(CardShortcutConfigure.this, shortcutInfo);
setResult(RESULT_OK, intent);
@Override
public void onIconClicked(int inputPosition) {
onClickAction(inputPosition);
}
finish();
}
});
@Override
public void onMessageRowClicked(int inputPosition) {
onClickAction(inputPosition);
}
@Override
public void onRowLongClicked(int inputPosition) {
// do nothing
}
}

View File

@@ -0,0 +1,37 @@
package protect.card_locker;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.content.Context;
import android.view.View;
public class LoyaltyCardAnimator {
private static AnimatorSet selectedViewIn, defaultViewOut, selectedViewOut, defaultViewIn;
public static void flipView(Context inputContext, final View inputSelectedView, final View inputDefaultView, boolean inputItemSelected) {
selectedViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_in);
defaultViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_out);
selectedViewOut = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_left_out);
defaultViewIn = (AnimatorSet) AnimatorInflater.loadAnimator(inputContext, R.animator.flip_right_in);
final AnimatorSet showFrontAnim = new AnimatorSet();
final AnimatorSet showBackAnim = new AnimatorSet();
selectedViewIn.setTarget(inputSelectedView);
defaultViewOut.setTarget(inputDefaultView);
showFrontAnim.playTogether(selectedViewIn, defaultViewOut);
selectedViewOut.setTarget(inputSelectedView);
defaultViewIn.setTarget(inputDefaultView);
showBackAnim.playTogether(defaultViewIn, selectedViewOut);
if (inputItemSelected) {
showFrontAnim.start();
} else {
showBackAnim.start();
}
}
}

View File

@@ -2,98 +2,283 @@ package protect.card_locker;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.SparseBooleanArray;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Date;
import androidx.cardview.widget.CardView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import protect.card_locker.preferences.Settings;
class LoyaltyCardCursorAdapter extends CursorAdapter
public class LoyaltyCardCursorAdapter extends BaseCursorAdapter<LoyaltyCardCursorAdapter.LoyaltyCardListItemViewHolder>
{
Settings settings;
public LoyaltyCardCursorAdapter(Context context, Cursor cursor)
private static int mCurrentSelectedIndex = -1;
Settings mSettings;
boolean mDarkModeEnabled;
private Context mContext;
private MessageAdapterListener mListener;
private SparseBooleanArray mSelectedItems;
private SparseBooleanArray mAnimationItemsIndex;
private boolean mReverseAllAnimations = false;
public LoyaltyCardCursorAdapter(Context inputContext, Cursor inputCursor, MessageAdapterListener inputListener)
{
super(context, cursor, 0);
settings = new Settings(context);
super(inputCursor);
settings = new Settings(inputContext);
this.mContext = inputContext;
this.mListener = inputListener;
mSelectedItems = new SparseBooleanArray();
mAnimationItemsIndex = new SparseBooleanArray();
mSettings = new Settings(inputContext);
mDarkModeEnabled = MainActivity.isDarkModeEnabled(inputContext);
}
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
public LoyaltyCardListItemViewHolder onCreateViewHolder(ViewGroup inputParent, int inputViewType)
{
return LayoutInflater.from(context).inflate(R.layout.loyalty_card_layout, parent, false);
View itemView = LayoutInflater.from(inputParent.getContext()).inflate(R.layout.loyalty_card_layout, inputParent, false);
return new LoyaltyCardListItemViewHolder(itemView);
}
// The bindView method is used to bind all data to a given view
// such as setting the text on a TextView.
@Override
public void bindView(View view, Context context, Cursor cursor)
{
// Find fields to populate in inflated template
ImageView thumbnail = view.findViewById(R.id.thumbnail);
TextView storeField = view.findViewById(R.id.store);
TextView noteField = view.findViewById(R.id.note);
TextView balanceField = view.findViewById(R.id.balance);
TextView expiryField = view.findViewById(R.id.expiry);
ImageView star = view.findViewById(R.id.star);
public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor inputCursor) {
if (mDarkModeEnabled) {
inputHolder.mStarIcon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
}
// Extract properties from cursor
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(cursor);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor);
// Populate fields with extracted properties
storeField.setText(loyaltyCard.store);
storeField.setTextSize(settings.getFontSizeMax(settings.getMediumFont()));
if(!loyaltyCard.note.isEmpty())
{
noteField.setVisibility(View.VISIBLE);
noteField.setText(loyaltyCard.note);
noteField.setTextSize(settings.getFontSizeMax(settings.getSmallFont()));
inputHolder.mStoreField.setText(loyaltyCard.store);
inputHolder.mStoreField.setTextSize(mSettings.getMediumFont());
if(!loyaltyCard.note.isEmpty()) {
inputHolder.mNoteField.setVisibility(View.VISIBLE);
inputHolder.mNoteField.setText(loyaltyCard.note);
inputHolder.mNoteField.setTextSize(mSettings.getSmallFont());
}
else
{
noteField.setVisibility(View.GONE);
inputHolder.mNoteField.setVisibility(View.GONE);
}
if(!loyaltyCard.balance.equals(new BigDecimal("0"))) {
balanceField.setVisibility(View.VISIBLE);
balanceField.setText(context.getString(R.string.balanceSentence, Utils.formatBalance(context, loyaltyCard.balance, loyaltyCard.balanceType)));
balanceField.setTextSize(settings.getFontSizeMax(settings.getSmallFont()));
inputHolder.mBalanceField.setVisibility(View.VISIBLE);
inputHolder.mBalanceField.setText(mContext.getString(R.string.balanceSentence, Utils.formatBalance(mContext, loyaltyCard.balance, loyaltyCard.balanceType)));
inputHolder.mBalanceField.setTextSize(settings.getFontSizeMax(settings.getSmallFont()));
}
else
{
balanceField.setVisibility(View.GONE);
inputHolder.mBalanceField.setVisibility(View.GONE);
}
if(loyaltyCard.expiry != null)
{
expiryField.setVisibility(View.VISIBLE);
inputHolder.mExpiryField.setVisibility(View.VISIBLE);
int expiryString = R.string.expiryStateSentence;
if(Utils.hasExpired(loyaltyCard.expiry)) {
expiryString = R.string.expiryStateSentenceExpired;
expiryField.setTextColor(context.getResources().getColor(R.color.alert));
inputHolder.mExpiryField.setTextColor(mContext.getResources().getColor(R.color.alert));
}
expiryField.setText(context.getString(expiryString, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry)));
expiryField.setTextSize(settings.getFontSizeMax(settings.getSmallFont()));
inputHolder.mExpiryField.setText(mContext.getString(expiryString, DateFormat.getDateInstance(DateFormat.LONG).format(loyaltyCard.expiry)));
inputHolder.mExpiryField.setTextSize(settings.getFontSizeMax(settings.getSmallFont()));
}
else
{
expiryField.setVisibility(View.GONE);
inputHolder.mExpiryField.setVisibility(View.GONE);
}
if (loyaltyCard.starStatus!=0) star.setVisibility(View.VISIBLE);
else star.setVisibility(View.GONE);
inputHolder.mStarIcon.setVisibility(((loyaltyCard.starStatus!=0)) ? View.VISIBLE : View.GONE);
inputHolder.mCardIcon.setImageBitmap(Utils.generateIcon(mContext, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
inputHolder.itemView.setActivated(mSelectedItems.get(inputCursor.getPosition(), false));
applyIconAnimation(inputHolder, inputCursor.getPosition());
applyClickEvents(inputHolder, inputCursor.getPosition());
thumbnail.setImageBitmap(Utils.generateIcon(context, loyaltyCard.store, loyaltyCard.headerColor).getLetterTile());
}
}
private void applyClickEvents(LoyaltyCardListItemViewHolder inputHolder, final int inputPosition)
{
inputHolder.mThumbnailContainer.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View inputView)
{
mListener.onIconClicked(inputPosition);
}
});
inputHolder.mRow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View inputView)
{
mListener.onMessageRowClicked(inputPosition);
}
});
inputHolder.mInformationContainer.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View inputView)
{
mListener.onMessageRowClicked(inputPosition);
}
});
inputHolder.mRow.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(inputPosition);
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
});
inputHolder.mInformationContainer.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(inputPosition);
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
});
}
private void applyIconAnimation(LoyaltyCardListItemViewHolder inputHolder, int inputPosition)
{
if (mSelectedItems.get(inputPosition, false))
{
inputHolder.mThumbnailFrontContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailBackContainer);
inputHolder.mThumbnailBackContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailBackContainer.setAlpha(1);
if (mCurrentSelectedIndex == inputPosition)
{
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, true);
resetCurrentIndex();
}
}
else
{
inputHolder.mThumbnailBackContainer.setVisibility(View.GONE);
resetIconYAxis(inputHolder.mThumbnailFrontContainer);
inputHolder.mThumbnailFrontContainer.setVisibility(View.VISIBLE);
inputHolder.mThumbnailFrontContainer.setAlpha(1);
if ((mReverseAllAnimations && mAnimationItemsIndex.get(inputPosition, false)) || mCurrentSelectedIndex == inputPosition)
{
LoyaltyCardAnimator.flipView(mContext, inputHolder.mThumbnailBackContainer, inputHolder.mThumbnailFrontContainer, false);
resetCurrentIndex();
}
}
}
private void resetIconYAxis(View inputView)
{
if (inputView.getRotationY() != 0)
{
inputView.setRotationY(0);
}
}
public void resetAnimationIndex()
{
mReverseAllAnimations = false;
mAnimationItemsIndex.clear();
}
public void toggleSelection(int inputPosition)
{
mCurrentSelectedIndex = inputPosition;
if (mSelectedItems.get(inputPosition, false))
{
mSelectedItems.delete(inputPosition);
mAnimationItemsIndex.delete(inputPosition);
}
else
{
mSelectedItems.put(inputPosition, true);
mAnimationItemsIndex.put(inputPosition, true);
}
notifyItemChanged(inputPosition);
}
public void clearSelections()
{
mReverseAllAnimations = true;
mSelectedItems.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount()
{
return mSelectedItems.size();
}
private void resetCurrentIndex()
{
mCurrentSelectedIndex = -1;
}
public interface MessageAdapterListener
{
void onIconClicked(int inputPosition);
void onMessageRowClicked(int inputPosition);
void onRowLongClicked(int inputPosition);
}
public class LoyaltyCardListItemViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener
{
public TextView mStoreField, mNoteField, mBalanceField, mExpiryField;
public LinearLayout mInformationContainer;
public ImageView mCardIcon, mStarIcon;
public CardView mThumbnailContainer;
public ConstraintLayout mRow;
public RelativeLayout mThumbnailFrontContainer, mThumbnailBackContainer;
public LoyaltyCardListItemViewHolder(View inputView)
{
super(inputView);
mThumbnailContainer = (CardView) inputView.findViewById(R.id.thumbnail_container);
mRow = (ConstraintLayout) inputView.findViewById(R.id.row);
mThumbnailFrontContainer = (RelativeLayout) inputView.findViewById(R.id.thumbnail_front);
mThumbnailBackContainer = (RelativeLayout) inputView.findViewById(R.id.thumbnail_back);
mInformationContainer= (LinearLayout) inputView.findViewById(R.id.information_container);
mStoreField = (TextView) inputView.findViewById(R.id.store);
mNoteField = (TextView) inputView.findViewById(R.id.note);
mBalanceField = (TextView) inputView.findViewById(R.id.balanceField);
mExpiryField = (TextView) inputView.findViewById(R.id.expiryField);
mCardIcon = (ImageView) inputView.findViewById(R.id.thumbnail);
mStarIcon = (ImageView) inputView.findViewById(R.id.star);
inputView.setOnLongClickListener(this);
}
@Override
public boolean onLongClick(View inputView)
{
mListener.onRowLongClicked(getAdapterPosition());
inputView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
}
}

View File

@@ -24,65 +24,73 @@ import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import java.util.List;
import protect.card_locker.preferences.SettingsActivity;
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener
public class MainActivity extends AppCompatActivity implements LoyaltyCardCursorAdapter.MessageAdapterListener, GestureDetector.OnGestureListener
{
private static final String TAG = "Catima";
LoyaltyCard card;
private ActionMode currentActionMode;
private Menu menu;
private GestureDetector gestureDetector;
protected String filter = "";
private final DBHelper mDB = new DBHelper(this);
private LoyaltyCardCursorAdapter mAdapter;
private LoyaltyCard mCard;
private ActionMode mCurrentActionMode;
private Menu mMenu;
private GestureDetector mGestureDetector;
protected String mFilter = "";
protected int selectedTab = 0;
private RecyclerView mCardList;
private ActionMode.Callback currentActionModeCallback = new ActionMode.Callback()
private ActionMode.Callback mCurrentActionModeCallback = new ActionMode.Callback()
{
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
public boolean onCreateActionMode(ActionMode inputMode, Menu inputMenu)
{
mode.getMenuInflater().inflate(R.menu.card_longclick_menu, menu);
mode.setTitle(getString(R.string.card_selected) + card.store);
inputMode.getMenuInflater().inflate(R.menu.card_longclick_menu, inputMenu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu)
public boolean onPrepareActionMode(ActionMode inputMode, Menu inputMenu)
{
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
public boolean onActionItemClicked(ActionMode inputMode, MenuItem inputItem)
{
if (item.getItemId() == R.id.action_copy_to_clipboard)
if (inputItem.getItemId() == R.id.action_copy_to_clipboard)
{
mode.finish();
inputMode.finish();
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(card.store, card.cardId);
ClipData clip = ClipData.newPlainText(mCard.store, mCard.cardId);
clipboard.setPrimaryClip(clip);
Toast.makeText(MainActivity.this, R.string.copy_to_clipboard_toast, Toast.LENGTH_LONG).show();
return true;
}
else if (item.getItemId() == R.id.action_share)
else if (inputItem.getItemId() == R.id.action_share)
{
mode.finish();
inputMode.finish();
final ImportURIHelper importURIHelper = new ImportURIHelper(MainActivity.this);
importURIHelper.startShareIntent(card);
importURIHelper.startShareIntent(mCard);
return true;
}
else if(item.getItemId() == R.id.action_edit)
else if(inputItem.getItemId() == R.id.action_edit)
{
mode.finish();
inputMode.finish();
Intent intent = new Intent(getApplicationContext(), LoyaltyCardEditActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("id", card.id);
bundle.putInt("id", mCard.id);
bundle.putBoolean("update", true);
intent.putExtras(bundle);
startActivity(intent);
@@ -93,28 +101,37 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
}
@Override
public void onDestroyActionMode(ActionMode mode)
public void onDestroyActionMode(ActionMode inputMode)
{
currentActionMode= null;
mAdapter.clearSelections();
mCurrentActionMode = null;
mCardList.post(new Runnable()
{
@Override
public void run()
{
mAdapter.resetAnimationIndex();
}
});
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
protected void onCreate(Bundle inputSavedInstanceState)
{
super.onCreate(savedInstanceState);
super.onCreate(inputSavedInstanceState);
setContentView(R.layout.main_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
updateLoyaltyCardList(filter, null);
updateLoyaltyCardList(mFilter, null);
TabLayout groupsTabLayout = findViewById(R.id.groups);
groupsTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
selectedTab = tab.getPosition();
updateLoyaltyCardList(filter, tab.getTag());
updateLoyaltyCardList(mFilter, tab.getTag());
// Store active tab in Shared Preference to restore next app launch
SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences(
@@ -136,12 +153,12 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
}
});
gestureDetector = new GestureDetector(this, this);
mGestureDetector = new GestureDetector(this, this);
View.OnTouchListener gestureTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event){
return gestureDetector.onTouchEvent(event);
return mGestureDetector.onTouchEvent(event);
}
};
@@ -183,26 +200,6 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
.show();
}
*/
ListView listView = findViewById(R.id.list);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
if (currentActionMode != null)
{
return false;
}
ListView listView = findViewById(R.id.list);
Cursor cardCursor = (Cursor) listView.getItemAtPosition(position);
card = LoyaltyCard.toLoyaltyCard(cardCursor);
currentActionMode = startSupportActionMode(currentActionModeCallback);
return true;
}
});
}
@Override
@@ -210,13 +207,19 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
{
super.onResume();
if (menu != null)
if(mCurrentActionMode != null)
{
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
mAdapter.clearSelections();
mCurrentActionMode.finish();
}
if (mMenu != null)
{
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified())
{
filter = searchView.getQuery().toString();
mFilter = searchView.getQuery().toString();
}
}
@@ -242,7 +245,7 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
assert tab != null;
group = tab.getTag();
}
updateLoyaltyCardList(filter, group);
updateLoyaltyCardList(mFilter, group);
// End of active tab logic
FloatingActionButton addButton = findViewById(R.id.fabAdd);
@@ -263,14 +266,12 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
if (requestCode == Utils.MAIN_REQUEST) {
// We're coming back from another view so clear the search
// We only do this now to prevent a flash of all entries right after picking one
filter = "";
if (menu != null)
mFilter = "";
if (mMenu != null)
{
MenuItem searchItem = menu.findItem(R.id.action_search);
MenuItem searchItem = mMenu.findItem(R.id.action_search);
searchItem.collapseActionView();
}
// In case the theme changed
recreate();
return;
@@ -291,13 +292,13 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
@Override
public void onBackPressed()
{
if (menu == null)
if (mMenu == null)
{
super.onBackPressed();
return;
}
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
SearchView searchView = (SearchView) mMenu.findItem(R.id.action_search).getActionView();
if (!searchView.isIconified())
{
@@ -321,21 +322,28 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
group = (Group) tag;
}
final ListView cardList = findViewById(R.id.list);
mCardList = findViewById(R.id.list);
RecyclerView.LayoutManager mLayoutManager= new LinearLayoutManager(getApplicationContext());
mCardList.setLayoutManager(mLayoutManager);
mCardList.setItemAnimator(new DefaultItemAnimator());
DividerItemDecoration itemDecorator= new DividerItemDecoration(this, LinearLayoutManager.VERTICAL);
itemDecorator.setDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.list_divider));
mCardList.addItemDecoration(itemDecorator);
final TextView helpText = findViewById(R.id.helpText);
final TextView noMatchingCardsText = findViewById(R.id.noMatchingCardsText);
final DBHelper db = new DBHelper(this);
Cursor cardCursor = db.getLoyaltyCardCursor(filterText, group);
Cursor cardCursor = mDB.getLoyaltyCardCursor(filterText, group);
if(db.getLoyaltyCardCount() > 0)
if(mDB.getLoyaltyCardCount() > 0)
{
// We want the cardList to be visible regardless of the filtered match count
// to ensure that the noMatchingCardsText doesn't end up being shown below
// the keyboard
cardList.setVisibility(View.VISIBLE);
mCardList.setVisibility(View.VISIBLE);
helpText.setVisibility(View.GONE);
if(cardCursor.getCount() > 0)
if(mDB.getLoyaltyCardCount(filterText) > 0)
{
noMatchingCardsText.setVisibility(View.GONE);
}
@@ -346,35 +354,15 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
}
else
{
cardList.setVisibility(View.GONE);
mCardList.setVisibility(View.GONE);
helpText.setVisibility(View.VISIBLE);
noMatchingCardsText.setVisibility(View.GONE);
}
final LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(this, cardCursor);
cardList.setAdapter(adapter);
mAdapter = new LoyaltyCardCursorAdapter(this, cardCursor, this);
mCardList.setAdapter(mAdapter);
registerForContextMenu(cardList);
cardList.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Cursor selected = (Cursor) parent.getItemAtPosition(position);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
Intent i = new Intent(view.getContext(), LoyaltyCardViewActivity.class);
i.setAction("");
final Bundle b = new Bundle();
b.putInt("id", loyaltyCard.id);
i.putExtras(b);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard, i);
startActivityForResult(i, Utils.MAIN_REQUEST);
}
});
registerForContextMenu(mCardList);
}
public void updateTabGroups(TabLayout groupsTabLayout)
@@ -415,16 +403,16 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
public boolean onCreateOptionsMenu(Menu inputMenu)
{
this.menu = menu;
this.mMenu = inputMenu;
getMenuInflater().inflate(R.menu.main_menu, menu);
getMenuInflater().inflate(R.menu.main_menu, inputMenu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null)
{
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
SearchView searchView = (SearchView) inputMenu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(false);
@@ -449,13 +437,13 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
@Override
public boolean onQueryTextChange(String newText)
{
filter = newText;
mFilter = newText;
TabLayout groupsTabLayout = findViewById(R.id.groups);
TabLayout.Tab currentTab = groupsTabLayout.getTabAt(groupsTabLayout.getSelectedTabPosition());
updateLoyaltyCardList(
newText,
mFilter,
currentTab != null ? currentTab.getTag() : null
);
@@ -463,13 +451,13 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
}
});
}
return super.onCreateOptionsMenu(menu);
return super.onCreateOptionsMenu(inputMenu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
public boolean onOptionsItemSelected(MenuItem inputItem)
{
int id = item.getItemId();
int id = inputItem.getItemId();
if (id == R.id.action_manage_groups)
{
@@ -505,7 +493,7 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
return true;
}
return super.onOptionsItemSelected(item);
return super.onOptionsItemSelected(inputItem);
}
protected static boolean isDarkModeEnabled(Context inputContext)
@@ -584,4 +572,72 @@ public class MainActivity extends AppCompatActivity implements GestureDetector.O
return false;
}
@Override
public void onRowLongClicked(int inputPosition)
{
enableActionMode(inputPosition);
}
private void enableActionMode(int inputPosition)
{
if (mCurrentActionMode == null)
{
mCurrentActionMode = startSupportActionMode(mCurrentActionModeCallback);
}
toggleSelection(inputPosition);
}
private void toggleSelection(int inputPosition)
{
mAdapter.toggleSelection(inputPosition);
int count = mAdapter.getSelectedItemCount();
if (count == 0)
{
mCurrentActionMode.finish();
} else
{
mCurrentActionMode.setTitle("Selected: " + count + " Cards");
mCurrentActionMode.invalidate();
}
}
@Override
public void onIconClicked(int inputPosition)
{
if (mCurrentActionMode == null)
{
mCurrentActionMode = startSupportActionMode(mCurrentActionModeCallback);
}
toggleSelection(inputPosition);
}
@Override
public void onMessageRowClicked(int inputPosition)
{
if (mAdapter.getSelectedItemCount() > 0)
{
enableActionMode(inputPosition);
}
else
{
Cursor selected = (Cursor) mDB.getLoyaltyCardCursor();
selected.moveToPosition(inputPosition);
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
Intent i = new Intent(this, LoyaltyCardViewActivity.class);
i.setAction("");
final Bundle b = new Bundle();
b.putInt("id", loyaltyCard.id);
i.putExtras(b);
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard, i);
startActivityForResult(i, Utils.MAIN_REQUEST);
}
}
}