Make the RecyclerView searchable
This commit is contained in:
parent
6275207362
commit
0a5124207d
6 changed files with 148 additions and 20 deletions
|
@ -35,6 +35,8 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
|
@ -48,19 +50,27 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
|
||||
public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.EntryViewHolder>
|
||||
implements ItemTouchHelperAdapter {
|
||||
implements ItemTouchHelperAdapter, Filterable {
|
||||
|
||||
private Context context;
|
||||
private EntryFilter filter;
|
||||
private ArrayList<Entry> entries;
|
||||
private ArrayList<Integer> displayedEntries;
|
||||
public ViewHolderEventCallback viewHolderEventCallback;
|
||||
|
||||
public EntriesCardAdapter(Context context, ArrayList<Entry> entries) {
|
||||
this.context = context;
|
||||
this.entries = entries;
|
||||
|
||||
displayedEntries = defaultIndices();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return displayedEntries.size();
|
||||
}
|
||||
|
||||
public int getFullItemCount() {
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
|
@ -70,11 +80,39 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.
|
|||
|
||||
public void setEntries(ArrayList<Entry> e) {
|
||||
entries = e;
|
||||
|
||||
displayedEntries.clear();
|
||||
displayedEntries = defaultIndices();
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public ArrayList<Integer> defaultIndices() {
|
||||
ArrayList<Integer> newIdx = new ArrayList<>();
|
||||
for (int i = 0; i < entries.size(); i++)
|
||||
newIdx.add(i);
|
||||
|
||||
return newIdx;
|
||||
}
|
||||
|
||||
public int removeIndex(int pos) {
|
||||
int removed = displayedEntries.remove(pos);
|
||||
|
||||
ArrayList<Integer> newIdx = new ArrayList<>();
|
||||
for (int i = 0; i < displayedEntries.size(); i++) {
|
||||
int idx = displayedEntries.get(i);
|
||||
if (idx > removed)
|
||||
idx -= 1;
|
||||
newIdx.add(idx);
|
||||
}
|
||||
displayedEntries = newIdx;
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(EntryViewHolder entryViewHolder, int i) {
|
||||
Entry entry = entries.get(i);
|
||||
Entry entry = entries.get(displayedEntries.get(i));
|
||||
|
||||
entryViewHolder.OTPValue.setText(entry.getCurrentOTP());
|
||||
entryViewHolder.OTPLabel.setText(entry.getLabel());
|
||||
|
@ -104,7 +142,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.
|
|||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
entries.remove(position);
|
||||
entries.remove(removeIndex(position));
|
||||
notifyItemRemoved(position);
|
||||
|
||||
SettingsHelper.store(context, entries);
|
||||
|
@ -121,15 +159,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.
|
|||
|
||||
@Override
|
||||
public boolean onItemMove(int fromPosition, int toPosition) {
|
||||
if (fromPosition < toPosition) {
|
||||
for (int i = fromPosition; i < toPosition; i++) {
|
||||
Collections.swap(entries, i, i + 1);
|
||||
}
|
||||
} else {
|
||||
for (int i = fromPosition; i > toPosition; i--) {
|
||||
Collections.swap(entries, i, i - 1);
|
||||
}
|
||||
}
|
||||
Collections.swap(entries, fromPosition, toPosition);
|
||||
notifyItemMoved(fromPosition, toPosition);
|
||||
|
||||
SettingsHelper.store(context, entries);
|
||||
|
@ -141,7 +171,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.
|
|||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
|
||||
final EditText input = new EditText(context);
|
||||
input.setText(getItem(pos).getLabel());
|
||||
input.setText(entries.get(displayedEntries.get(pos)).getLabel());
|
||||
input.setSingleLine();
|
||||
|
||||
FrameLayout container = new FrameLayout(context);
|
||||
|
@ -156,7 +186,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.
|
|||
.setPositiveButton(R.string.button_save, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
getItem(pos).setLabel(input.getEditableText().toString());
|
||||
entries.get(displayedEntries.get(pos)).setLabel(input.getEditableText().toString());
|
||||
notifyItemChanged(pos);
|
||||
|
||||
SettingsHelper.store(context, entries);
|
||||
|
@ -207,6 +237,43 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntriesCardAdapter.
|
|||
this.viewHolderEventCallback = cb;
|
||||
}
|
||||
|
||||
public EntryFilter getFilter() {
|
||||
if (filter == null)
|
||||
filter = new EntryFilter();
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
public class EntryFilter extends Filter {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
final FilterResults filterResults = new FilterResults();
|
||||
|
||||
ArrayList<Integer> newIdx = new ArrayList<>();
|
||||
if (constraint != null && constraint.length() != 0){
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
if (entries.get(i).getLabel().toLowerCase().contains(constraint.toString().toLowerCase())) {
|
||||
newIdx.add(i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newIdx = defaultIndices();
|
||||
}
|
||||
|
||||
filterResults.count = newIdx.size();
|
||||
filterResults.values = newIdx;
|
||||
|
||||
return filterResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||
displayedEntries = (ArrayList<Integer>) results.values;
|
||||
notifyDataSetChanged();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
public class EntryViewHolder extends RecyclerView.ViewHolder
|
||||
implements ItemTouchHelperViewHolder {
|
||||
|
||||
|
|
|
@ -35,20 +35,30 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
|
|||
|
||||
public static final float ALPHA_FULL = 1.0f;
|
||||
|
||||
private boolean dragEnabled = true;
|
||||
private boolean swipeEnabled = true;
|
||||
private final ItemTouchHelperAdapter mAdapter;
|
||||
|
||||
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
|
||||
mAdapter = adapter;
|
||||
}
|
||||
|
||||
public void setDragEnabled(boolean newDragState) {
|
||||
this.dragEnabled = newDragState;
|
||||
}
|
||||
|
||||
public void setSwipeEnabled(boolean newSwipeState) {
|
||||
this.swipeEnabled = newSwipeState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return true;
|
||||
return dragEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return true;
|
||||
return swipeEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -41,9 +41,11 @@ import android.support.annotation.NonNull;
|
|||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.view.Menu;
|
||||
|
@ -68,6 +70,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
private ArrayList<Entry> entries;
|
||||
private EntriesCardAdapter adapter;
|
||||
private FloatingActionButton fab;
|
||||
private SimpleItemTouchHelperCallback touchHelperCallback;
|
||||
|
||||
private Handler handler;
|
||||
private Runnable handlerTask;
|
||||
|
@ -184,7 +187,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
if (success) {
|
||||
entries = SettingsHelper.load(this);
|
||||
adapter.setEntries(entries);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
Toast.makeText(this, R.string.msg_import_success, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
|
@ -301,8 +303,8 @@ public class MainActivity extends AppCompatActivity {
|
|||
adapter = new EntriesCardAdapter(this, entries);
|
||||
recList.setAdapter(adapter);
|
||||
|
||||
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
|
||||
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
|
||||
touchHelperCallback = new SimpleItemTouchHelperCallback(adapter);
|
||||
ItemTouchHelper touchHelper = new ItemTouchHelper(touchHelperCallback);
|
||||
touchHelper.attachToRecyclerView(recList);
|
||||
|
||||
final float durationScale = fixAnimationScale();
|
||||
|
@ -334,7 +336,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
animation.start();
|
||||
|
||||
boolean change = false;
|
||||
for(int i =0;i < adapter.getItemCount(); i++){
|
||||
for(int i =0;i < adapter.getFullItemCount(); i++){
|
||||
boolean item_changed = adapter.getItem(i).updateOTP();
|
||||
change = change || item_changed;
|
||||
}
|
||||
|
@ -403,6 +405,38 @@ public class MainActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
|
||||
MenuItem searchItem = menu.findItem(R.id.menu_search);
|
||||
SearchView searchView = (SearchView) searchItem.getActionView();
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
adapter.getFilter().filter(newText);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||
fab.setVisibility(View.GONE);
|
||||
touchHelperCallback.setDragEnabled(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||
fab.setVisibility(View.VISIBLE);
|
||||
touchHelperCallback.setDragEnabled(true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
9
app/src/main/res/drawable/ic_search_white.xml
Normal file
9
app/src/main/res/drawable/ic_search_white.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
|
||||
</vector>
|
|
@ -1,6 +1,13 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_search"
|
||||
android:title="@string/title_search"
|
||||
android:icon="@drawable/ic_search_white"
|
||||
app:showAsAction="always|collapseActionView"
|
||||
app:actionViewClass="android.support.v7.widget.SearchView" />
|
||||
|
||||
<item
|
||||
android:id="@+id/submenu_backup"
|
||||
android:title="@string/menu_submenu_backup">
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
<string name="msg_storage_permissions">Storage permissions not granted</string>
|
||||
|
||||
<string name="title_animator_duration">Animator duration scale</string>
|
||||
<string name="title_search">Search</string>
|
||||
|
||||
<string name="pref_animator_warning_displayed">animator_warning_displayed</string>
|
||||
|
||||
|
|
Loading…
Reference in a new issue