From 67328724fadc09f19fcf19b2b5827d07f7996efe Mon Sep 17 00:00:00 2001 From: Arshbeer Singh Date: Wed, 11 Nov 2020 01:07:08 -0800 Subject: [PATCH] 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 --- .../card_locker/BaseCursorAdapter.java | 86 ++++++ .../card_locker/CardShortcutConfigure.java | 80 ++--- .../card_locker/LoyaltyCardAnimator.java | 37 +++ .../card_locker/LoyaltyCardCursorAdapter.java | 279 +++++++++++++++--- .../protect/card_locker/MainActivity.java | 258 +++++++++------- app/src/main/res/animator/flip_left_in.xml | 22 ++ app/src/main/res/animator/flip_left_out.xml | 16 + app/src/main/res/animator/flip_right_in.xml | 22 ++ app/src/main/res/animator/flip_right_out.xml | 16 + app/src/main/res/drawable/ic_done.xml | 10 + app/src/main/res/drawable/list_divider.xml | 6 + app/src/main/res/drawable/list_row.xml | 4 + app/src/main/res/layout/content_main.xml | 10 +- .../main/res/layout/loyalty_card_layout.xml | 132 ++++++--- app/src/main/res/values-night/colors.xml | 2 + app/src/main/res/values-v21/styles.xml | 3 +- app/src/main/res/values/colors.xml | 2 + app/src/main/res/values/constants.xml | 2 + app/src/main/res/values/strings.xml | 2 +- .../protect/card_locker/MainActivityTest.java | 48 ++- 20 files changed, 792 insertions(+), 245 deletions(-) create mode 100644 app/src/main/java/protect/card_locker/BaseCursorAdapter.java create mode 100644 app/src/main/java/protect/card_locker/LoyaltyCardAnimator.java create mode 100644 app/src/main/res/animator/flip_left_in.xml create mode 100644 app/src/main/res/animator/flip_left_out.xml create mode 100644 app/src/main/res/animator/flip_right_in.xml create mode 100644 app/src/main/res/animator/flip_right_out.xml create mode 100644 app/src/main/res/drawable/ic_done.xml create mode 100644 app/src/main/res/drawable/list_divider.xml create mode 100644 app/src/main/res/drawable/list_row.xml diff --git a/app/src/main/java/protect/card_locker/BaseCursorAdapter.java b/app/src/main/java/protect/card_locker/BaseCursorAdapter.java new file mode 100644 index 000000000..ee80b7c0c --- /dev/null +++ b/app/src/main/java/protect/card_locker/BaseCursorAdapter.java @@ -0,0 +1,86 @@ +package protect.card_locker; + +import android.database.Cursor; +import androidx.recyclerview.widget.RecyclerView; + +public abstract class BaseCursorAdapter extends RecyclerView.Adapter +{ + 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; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/protect/card_locker/CardShortcutConfigure.java b/app/src/main/java/protect/card_locker/CardShortcutConfigure.java index 0310e51f0..669150996 100644 --- a/app/src/main/java/protect/card_locker/CardShortcutConfigure.java +++ b/app/src/main/java/protect/card_locker/CardShortcutConfigure.java @@ -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 } } diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardAnimator.java b/app/src/main/java/protect/card_locker/LoyaltyCardAnimator.java new file mode 100644 index 000000000..43e6ed6e8 --- /dev/null +++ b/app/src/main/java/protect/card_locker/LoyaltyCardAnimator.java @@ -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(); + } + } + +} diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java b/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java index e828ddfce..869ece904 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java @@ -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 { 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; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/protect/card_locker/MainActivity.java b/app/src/main/java/protect/card_locker/MainActivity.java index 69d86ef42..7f77ccdec 100644 --- a/app/src/main/java/protect/card_locker/MainActivity.java +++ b/app/src/main/java/protect/card_locker/MainActivity.java @@ -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); + } + } } \ No newline at end of file diff --git a/app/src/main/res/animator/flip_left_in.xml b/app/src/main/res/animator/flip_left_in.xml new file mode 100644 index 000000000..79fd3bf85 --- /dev/null +++ b/app/src/main/res/animator/flip_left_in.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/flip_left_out.xml b/app/src/main/res/animator/flip_left_out.xml new file mode 100644 index 000000000..4ff5709ed --- /dev/null +++ b/app/src/main/res/animator/flip_left_out.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/flip_right_in.xml b/app/src/main/res/animator/flip_right_in.xml new file mode 100644 index 000000000..3d252a741 --- /dev/null +++ b/app/src/main/res/animator/flip_right_in.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/flip_right_out.xml b/app/src/main/res/animator/flip_right_out.xml new file mode 100644 index 000000000..bebc16c1e --- /dev/null +++ b/app/src/main/res/animator/flip_right_out.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_done.xml b/app/src/main/res/drawable/ic_done.xml new file mode 100644 index 000000000..a9a5ae203 --- /dev/null +++ b/app/src/main/res/drawable/ic_done.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/list_divider.xml b/app/src/main/res/drawable/list_divider.xml new file mode 100644 index 000000000..5afbb0145 --- /dev/null +++ b/app/src/main/res/drawable/list_divider.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/list_row.xml b/app/src/main/res/drawable/list_row.xml new file mode 100644 index 000000000..62ca0f43c --- /dev/null +++ b/app/src/main/res/drawable/list_row.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml index 46422b10f..0384a349a 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/content_main.xml @@ -27,9 +27,11 @@ android:text="@string/noMatchingGiftCards" android:visibility="gone"/> - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scrollbars="vertical" + android:visibility="gone" /> + diff --git a/app/src/main/res/layout/loyalty_card_layout.xml b/app/src/main/res/layout/loyalty_card_layout.xml index f54b902ea..c0f98980b 100644 --- a/app/src/main/res/layout/loyalty_card_layout.xml +++ b/app/src/main/res/layout/loyalty_card_layout.xml @@ -1,80 +1,118 @@ - - - - - - - + android:layout_marginStart="@dimen/activity_margin" + android:layout_marginLeft="@dimen/activity_margin" + android:layout_toEndOf="@+id/thumbnail_container" + android:layout_toRightOf="@+id/thumbnail_container" + android:layout_weight="1" + android:clickable="true" + android:focusable="true" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="@+id/thumbnail_container" + app:layout_constraintEnd_toStartOf="@+id/star" + app:layout_constraintStart_toEndOf="@+id/thumbnail_container" + app:layout_constraintTop_toTopOf="@+id/thumbnail_container"> - - - - - + android:textSize="@dimen/storeNameTextSize" + android:textStyle="bold" /> + android:lines="1" + android:textSize="@dimen/noteTextSize" /> + android:lines="1" + android:textSize="@dimen/noteTextSize" /> + android:lines="1" + android:textSize="@dimen/noteTextSize" /> + + + + + + + + + + + + + + + + + - + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:layout_marginStart="@dimen/activity_margin" + android:contentDescription="@string/starImage" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:tint="@android:color/black" /> + + \ No newline at end of file diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 745041949..c8dc32230 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -11,6 +11,8 @@ #000000 #ffffff + #88000000 + #070707 #000000 #222222 diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index 775af5f96..0efcd9f3b 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -1,8 +1,9 @@ -> + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 01c87830f..5bc7daeb5 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -10,6 +10,8 @@ #ffffff #000000 + #44000000 + #F8F8F8 #FFFFFF #DDDDDD diff --git a/app/src/main/res/values/constants.xml b/app/src/main/res/values/constants.xml index 45c05623b..60fda819d 100644 --- a/app/src/main/res/values/constants.xml +++ b/app/src/main/res/values/constants.xml @@ -2,4 +2,6 @@ https://github.com/TheLastProject/Catima/releases https://github.com/TheLastProject/Catima + 100 + 50 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f1cdcc58c..65fb75a17 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -77,7 +77,7 @@ Select Barcode Enter the card ID, and either pick its barcode type below, or “This card has no barcode”. - Card ID copied to clipboard + Card ID(s) copied to clipboard Thumbnail for card Favorite star diff --git a/app/src/test/java/protect/card_locker/MainActivityTest.java b/app/src/test/java/protect/card_locker/MainActivityTest.java index b702ea127..641330c58 100644 --- a/app/src/test/java/protect/card_locker/MainActivityTest.java +++ b/app/src/test/java/protect/card_locker/MainActivityTest.java @@ -2,6 +2,10 @@ package protect.card_locker; import android.app.Activity; import android.content.ComponentName; +<<<<<<< HEAD +======= +import android.content.Intent; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Color; @@ -9,14 +13,19 @@ import android.view.Menu; import android.view.View; import android.widget.ListView; import android.widget.TextView; +<<<<<<< HEAD import com.google.android.material.tabs.TabLayout; import com.google.zxing.BarcodeFormat; +======= +import com.google.zxing.BarcodeFormat; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; +<<<<<<< HEAD import org.robolectric.annotation.Config; import org.robolectric.android.controller.ActivityController; import org.robolectric.shadows.ShadowActivity; @@ -28,6 +37,13 @@ import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +======= +import org.robolectric.android.controller.ActivityController; +import org.robolectric.annotation.Config; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) import static org.robolectric.Shadows.shadowOf; @RunWith(RobolectricTestRunner.class) @@ -37,10 +53,9 @@ public class MainActivityTest private SharedPreferences prefs; @Test - public void initiallyNoLoyaltyCards() throws Exception - { + public void initiallyNoLoyaltyCards() { Activity activity = Robolectric.setupActivity(MainActivity.class); - assertTrue(activity != null); + assertNotNull(activity); TextView helpText = activity.findViewById(R.id.helpText); assertEquals(View.VISIBLE, helpText.getVisibility()); @@ -53,12 +68,11 @@ public class MainActivityTest } @Test - public void onCreateShouldInflateLayout() throws Exception - { + public void onCreateShouldInflateLayout() { final MainActivity activity = Robolectric.setupActivity(MainActivity.class); final Menu menu = shadowOf(activity).getOptionsMenu(); - assertTrue(menu != null); + assertNotNull(menu); // The settings, import/export, groups, search and add button should be present assertEquals(menu.size(), 6); @@ -251,7 +265,7 @@ public class MainActivityTest assertEquals(2, list.getCount()); - mainActivity.filter = "store"; + mainActivity.mFilter = "store"; activityController.pause(); activityController.resume(); @@ -262,6 +276,7 @@ public class MainActivityTest assertEquals(2, list.getCount()); +<<<<<<< HEAD // Switch to Group one groupTabs.selectTab(groupTabs.getTabAt(1)); @@ -284,6 +299,9 @@ public class MainActivityTest assertEquals(2, list.getCount()); mainActivity.filter = "first"; +======= + mainActivity.mFilter = "first"; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) activityController.pause(); activityController.resume(); @@ -294,6 +312,7 @@ public class MainActivityTest assertEquals(1, list.getCount()); +<<<<<<< HEAD // Switch to Group one groupTabs.selectTab(groupTabs.getTabAt(1)); @@ -316,6 +335,9 @@ public class MainActivityTest assertEquals(1, list.getCount()); mainActivity.filter = "initial"; +======= + mainActivity.mFilter = "initial"; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) activityController.pause(); activityController.resume(); @@ -326,6 +348,7 @@ public class MainActivityTest assertEquals(1, list.getCount()); +<<<<<<< HEAD // Switch to Group one groupTabs.selectTab(groupTabs.getTabAt(1)); @@ -348,6 +371,9 @@ public class MainActivityTest assertEquals(1, list.getCount()); mainActivity.filter = "second"; +======= + mainActivity.mFilter = "second"; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) activityController.pause(); activityController.resume(); @@ -358,6 +384,7 @@ public class MainActivityTest assertEquals(1, list.getCount()); +<<<<<<< HEAD // Switch to Group one groupTabs.selectTab(groupTabs.getTabAt(1)); @@ -380,6 +407,9 @@ public class MainActivityTest assertEquals(1, list.getCount()); mainActivity.filter = "company"; +======= + mainActivity.mFilter = "company"; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) activityController.pause(); activityController.resume(); @@ -390,6 +420,7 @@ public class MainActivityTest assertEquals(0, list.getCount()); +<<<<<<< HEAD // Switch to Group one groupTabs.selectTab(groupTabs.getTabAt(1)); @@ -412,6 +443,9 @@ public class MainActivityTest assertEquals(0, list.getCount()); mainActivity.filter = ""; +======= + mainActivity.mFilter = ""; +>>>>>>> cdd9472 (WIP Issue #14 (and #65)) activityController.pause(); activityController.resume();