Merge pull request #99 from wongma7/master

Multi-select (for password deletion)
This commit is contained in:
Mohamed Zenadi 2015-07-04 16:05:38 +02:00
commit 97c5c5da95
4 changed files with 98 additions and 17 deletions

View file

@ -1,10 +1,11 @@
package com.zeapo.pwdstore.utils; package com.zeapo.pwdstore.utils;
import android.graphics.Color; import android.graphics.Color;
import android.support.v7.widget.PopupMenu; import android.support.v7.view.ActionMode;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -15,11 +16,15 @@ import com.zeapo.pwdstore.PasswordStore;
import com.zeapo.pwdstore.R; import com.zeapo.pwdstore.R;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set;
import java.util.TreeSet;
public class PasswordRecyclerAdapter extends RecyclerView.Adapter<PasswordRecyclerAdapter.ViewHolder> { public class PasswordRecyclerAdapter extends RecyclerView.Adapter<PasswordRecyclerAdapter.ViewHolder> {
private final PasswordStore activity; private final PasswordStore activity;
private final ArrayList<PasswordItem> values; private final ArrayList<PasswordItem> values;
private final PasswordFragment.OnFragmentInteractionListener listener; private final PasswordFragment.OnFragmentInteractionListener listener;
private final Set<Integer> selectedItems;
private ActionMode mActionMode;
// Provide a reference to the views for each data item // Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and // Complex data items may need more than one view per item, and
@ -44,6 +49,7 @@ public class PasswordRecyclerAdapter extends RecyclerView.Adapter<PasswordRecycl
this.values = values; this.values = values;
this.activity = activity; this.activity = activity;
this.listener = listener; this.listener = listener;
selectedItems = new TreeSet<>();
} }
// Create new views (invoked by the layout manager) // Create new views (invoked by the layout manager)
@ -89,33 +95,75 @@ public class PasswordRecyclerAdapter extends RecyclerView.Adapter<PasswordRecycl
holder.view.setOnClickListener(new View.OnClickListener() { holder.view.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
listener.onFragmentInteraction(pass); if (mActionMode != null) {
toggleSelection(holder.position);
if (selectedItems.isEmpty()) {
mActionMode.finish();
}
} else {
listener.onFragmentInteraction(pass);
}
} }
}); });
holder.view.setOnLongClickListener(new View.OnLongClickListener() { holder.view.setOnLongClickListener(new View.OnLongClickListener() {
@Override @Override
public boolean onLongClick(View v) { public boolean onLongClick(View v) {
PopupMenu p = new PopupMenu(activity, v); if (mActionMode != null) {
p.getMenuInflater().inflate( return false;
R.menu.context_pass, p.getMenu()); }
p.show(); toggleSelection(holder.position);
p.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { // Start the CAB using the ActionMode.Callback
@Override mActionMode = activity.startSupportActionMode(mActionModeCallback);
public boolean onMenuItemClick(MenuItem menuItem) { return true;
if (menuItem.getItemId() == R.id.menu_delete_password) {
activity.deletePassword(PasswordRecyclerAdapter.this, holder.position);
}
return false;
}
});
return false;
} }
}); });
holder.view.setSelected(selectedItems.contains(position));
} }
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
mode.getMenuInflater().inflate(R.menu.context_pass, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete_password:
for (int position : selectedItems) {
activity.deletePassword(PasswordRecyclerAdapter.this, position);
}
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
@Override
public void onDestroyActionMode(ActionMode mode) {
selectedItems.clear();
mActionMode = null;
notifyDataSetChanged();
}
};
// Return the size of your dataset (invoked by the layout manager) // Return the size of your dataset (invoked by the layout manager)
@Override @Override
public int getItemCount() { public int getItemCount() {
@ -146,4 +194,11 @@ public class PasswordRecyclerAdapter extends RecyclerView.Adapter<PasswordRecycl
this.notifyItemRemoved(position); this.notifyItemRemoved(position);
} }
public void toggleSelection(int position) {
if (!selectedItems.remove(position)) {
selectedItems.add(position);
}
notifyItemChanged(position);
}
} }

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/selected_rectangle" />
<item android:drawable="@drawable/rectangle" />
</selector>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle"
android:dither="true">
<corners android:radius="2dp"/>
<solid android:color="@color/blue_grey_200" />
</shape>
</item>
<item android:bottom="2dp" android:left="1dp" android:right="1dp">
<shape android:shape="rectangle" android:dither="true">
<corners android:radius="2dp" />
<solid android:color="@color/blue_grey_100" />
<padding android:bottom="2dp" android:left="1dp"/>
</shape>
</item>
</layer-list>

View file

@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/rectangle" android:background="@drawable/password_row_background"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:layout_gravity="start|center_vertical"> android:layout_gravity="start|center_vertical">