Browse Source

Recyclerview selection experiment

main
M66B 6 years ago
parent
commit
6b8222f3c5
8 changed files with 221 additions and 3 deletions
  1. BIN
      .idea/caches/build_file_checksums.ser
  2. +1
    -0
      app/build.gradle
  3. +19
    -2
      app/src/main/java/eu/faircode/email/AdapterMessage.java
  4. +61
    -1
      app/src/main/java/eu/faircode/email/FragmentMessages.java
  5. +38
    -0
      app/src/main/java/eu/faircode/email/MyActionModeController.java
  6. +30
    -0
      app/src/main/java/eu/faircode/email/MyItemDetail.java
  7. +37
    -0
      app/src/main/java/eu/faircode/email/MyItemKeyProvider.java
  8. +35
    -0
      app/src/main/java/eu/faircode/email/MyItemLookup.java

BIN
.idea/caches/build_file_checksums.ser View File


+ 1
- 0
app/build.gradle View File

@ -79,6 +79,7 @@ dependencies {
implementation "androidx.appcompat:appcompat:$androidx_version"
implementation "androidx.recyclerview:recyclerview:$androidx_version"
implementation "androidx.recyclerview:recyclerview-selection:$androidx_version"
implementation "com.google.android.material:material:$androidx_version"
implementation "androidx.browser:browser:$androidx_version"
implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version"


+ 19
- 2
app/src/main/java/eu/faircode/email/AdapterMessage.java View File

@ -24,6 +24,7 @@ import android.content.Intent;
import android.graphics.Typeface;
import android.preference.PreferenceManager;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -41,6 +42,8 @@ import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.selection.SelectionTracker;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
@ -48,6 +51,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
private Context context;
private LifecycleOwner owner;
private ViewType viewType;
private SelectionTracker selectionTracker;
private boolean debug;
private DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.LONG);
@ -84,12 +88,12 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
private void wire() {
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
//itemView.setOnLongClickListener(this);
}
private void unwire() {
itemView.setOnClickListener(null);
itemView.setOnLongClickListener(null);
//itemView.setOnLongClickListener(null);
}
private void clear() {
@ -107,6 +111,8 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
private void bindTo(final TupleMessageEx message) {
pbLoading.setVisibility(View.GONE);
itemView.setActivated(selectionTracker.isSelected(message.id));
if (EntityFolder.DRAFTS.equals(message.folderType) ||
EntityFolder.OUTBOX.equals(message.folderType) ||
EntityFolder.SENT.equals(message.folderType)) {
@ -209,6 +215,16 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
return true;
}
public ItemDetailsLookup.ItemDetails getItemDetails() {
Log.i(Helper.TAG, "getItemDetails");
return new MyItemDetail(getAdapterPosition(), getItem(getAdapterPosition()).id);
}
}
public void setSelectionTracker(SelectionTracker selectionTracker) {
Log.i(Helper.TAG, "setSelectionTracker");
this.selectionTracker = selectionTracker;
}
AdapterMessage(Context context, LifecycleOwner owner, ViewType viewType) {
@ -243,6 +259,7 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.unwire();
Log.i(Helper.TAG, "onBindViewHolder");
TupleMessageEx message = getItem(position);
if (message == null)


+ 61
- 1
app/src/main/java/eu/faircode/email/FragmentMessages.java View File

@ -28,6 +28,7 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
@ -46,6 +47,10 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList;
import androidx.recyclerview.selection.OnDragInitiatedListener;
import androidx.recyclerview.selection.SelectionPredicates;
import androidx.recyclerview.selection.SelectionTracker;
import androidx.recyclerview.selection.StorageStrategy;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -58,6 +63,7 @@ public class FragmentMessages extends FragmentEx {
private long primary = -1;
private AdapterMessage adapter;
private SelectionTracker selectionTracker;
private static final int PAGE_SIZE = 50;
@ -118,7 +124,14 @@ public class FragmentMessages extends FragmentEx {
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (selectionTracker != null)
selectionTracker.onSaveInstanceState(outState);
}
@Override
public void onActivityCreated(@Nullable final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Get arguments
@ -191,6 +204,53 @@ public class FragmentMessages extends FragmentEx {
Log.i(Helper.TAG, "Submit messages=" + messages.size());
adapter.submitList(messages);
selectionTracker = new SelectionTracker.Builder<>(
"messages-selection",
rvMessage,
new MyItemKeyProvider(messages),
new MyItemLookup(rvMessage),
StorageStrategy.createLongStorage())
.withSelectionPredicate(SelectionPredicates.<Long>createSelectAnything())
.withOnDragInitiatedListener(new OnDragInitiatedListener() {
@Override
public boolean onDragInitiated(@NonNull MotionEvent e) {
Log.i(Helper.TAG, "onDragInitiated");
return true;
}
}).build();
adapter.setSelectionTracker(selectionTracker);
selectionTracker.addObserver(new SelectionTracker.SelectionObserver() {
@Override
public void onItemStateChanged(@NonNull Object key, boolean selected) {
Log.i(Helper.TAG, "onItemStateChanged");
super.onItemStateChanged(key, selected);
}
@Override
public void onSelectionRefresh() {
Log.i(Helper.TAG, "onSelectionRefresh");
super.onSelectionRefresh();
}
@Override
public void onSelectionChanged() {
Log.i(Helper.TAG, "onSelectionChanged");
super.onSelectionChanged();
}
@Override
public void onSelectionRestored() {
Log.i(Helper.TAG, "onSelectionRestored");
super.onSelectionRestored();
}
});
if (savedInstanceState != null)
selectionTracker.onRestoreInstanceState(savedInstanceState);
pbWait.setVisibility(View.GONE);
grpReady.setVisibility(View.VISIBLE);


+ 38
- 0
app/src/main/java/eu/faircode/email/MyActionModeController.java View File

@ -0,0 +1,38 @@
package eu.faircode.email;
import android.content.Context;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.view.ActionMode;
import androidx.recyclerview.selection.SelectionTracker;
public class MyActionModeController implements ActionMode.Callback {
private final Context context;
private final SelectionTracker selectionTracker;
public MyActionModeController(Context context, SelectionTracker selectionTracker) {
this.context = context;
this.selectionTracker = selectionTracker;
}
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return false;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode actionMode) {
selectionTracker.clearSelection();
}
}

+ 30
- 0
app/src/main/java/eu/faircode/email/MyItemDetail.java View File

@ -0,0 +1,30 @@
package eu.faircode.email;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.recyclerview.selection.ItemDetailsLookup;
public class MyItemDetail extends ItemDetailsLookup.ItemDetails<Long> {
private final int adapterPosition;
private final Long selectionKey;
public MyItemDetail(int adapterPosition, Long selectionKey) {
Log.i(Helper.TAG, "MyItemDetail");
this.adapterPosition = adapterPosition;
this.selectionKey = selectionKey;
}
@Override
public int getPosition() {
Log.i(Helper.TAG, "MyItemDetail.getPosition=" + adapterPosition);
return adapterPosition;
}
@Nullable
@Override
public Long getSelectionKey() {
Log.i(Helper.TAG, "MyItemDetail.getSelectionKey=" + selectionKey);
return selectionKey;
}
}

+ 37
- 0
app/src/main/java/eu/faircode/email/MyItemKeyProvider.java View File

@ -0,0 +1,37 @@
package eu.faircode.email;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.paging.PagedList;
import androidx.recyclerview.selection.ItemKeyProvider;
import androidx.recyclerview.widget.RecyclerView;
public class MyItemKeyProvider extends ItemKeyProvider<Long> {
private final PagedList<TupleMessageEx> messages;
public MyItemKeyProvider(PagedList<TupleMessageEx> messages) {
super(ItemKeyProvider.SCOPE_MAPPED);
this.messages = messages;
Log.i(Helper.TAG, "MyItemKeyProvider");
}
@Nullable
@Override
public Long getKey(int position) {
Log.i(Helper.TAG, "MyItemKeyProvider.getKey pos=" + position + " key=" + messages.get(position).id);
return messages.get(position).id;
}
@Override
public int getPosition(@NonNull Long key) {
Log.i(Helper.TAG, "MyItemKeyProvider.getPosition key=" + key);
int pos = RecyclerView.NO_POSITION;
for (int i = 0; i < messages.size(); i++)
if (messages.get(i).id.equals(key))
pos = i;
Log.i(Helper.TAG, "MyItemKeyProvider.getPosition key=" + key + " pos=" + pos);
return pos;
}
}

+ 35
- 0
app/src/main/java/eu/faircode/email/MyItemLookup.java View File

@ -0,0 +1,35 @@
package eu.faircode.email;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.widget.RecyclerView;
public class MyItemLookup extends ItemDetailsLookup<Long> {
private final RecyclerView recyclerView;
public MyItemLookup(RecyclerView recyclerView) {
Log.i(Helper.TAG, "MyItemLookup");
this.recyclerView = recyclerView;
}
@Nullable
@Override
public ItemDetails<Long> getItemDetails(@NonNull MotionEvent e) {
Log.i(Helper.TAG, "MyItemLookup.getItemDetails");
View view = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (view != null) {
RecyclerView.ViewHolder viewHolder = recyclerView.getChildViewHolder(view);
if (viewHolder instanceof AdapterMessage.ViewHolder) {
return ((AdapterMessage.ViewHolder) viewHolder).getItemDetails();
}
}
return null;
}
}

Loading…
Cancel
Save