-
Notifications
You must be signed in to change notification settings - Fork 554
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package eu.davidea.flexibleadapter; | ||
|
||
import android.support.v7.widget.RecyclerView; | ||
import android.util.Log; | ||
import android.view.LayoutInflater; | ||
import android.view.View; | ||
import android.view.ViewGroup; | ||
import android.widget.ImageView; | ||
import android.widget.TextView; | ||
|
||
|
||
public class ExampleAdapter extends FlexibleAdapter<ManageLabelsAdapter.ViewHolder, Label> { | ||
|
||
private static final String TAG = ManageLabelsAdapter.class.getSimpleName(); | ||
|
||
public interface OnItemClickListener { | ||
public void onListItemClick(int position); | ||
public boolean onListItemLongClick(int position); | ||
} | ||
|
||
private LayoutInflater mInflater; | ||
|
||
private OnItemClickListener mClickListener; | ||
|
||
public ManageLabelsAdapter(OnItemClickListener listener) { | ||
this.mClickListener = listener; | ||
updateDataSet(); | ||
} | ||
|
||
public void updateDataSet() { | ||
this.mItems = DatabaseService.getInstance().getUserLabelsList(); | ||
} | ||
|
||
public Label getItem(int position) { | ||
return mItems.get(position); | ||
} | ||
|
||
@Override | ||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | ||
Log.d(TAG, "onCreateViewHolder for viewType "+viewType); | ||
if (mInflater == null) { | ||
mInflater = LayoutInflater.from(parent.getContext()); | ||
} | ||
//NOTE: Example for multiple layout. getItemViewType needs to be Overridden | ||
//final int layout = viewType == XXX ? R.layout.item : R.layout.item2; | ||
|
||
View view = mInflater.inflate(R.layout.drawer_list_row, parent, false); | ||
//Eventually set the view's size, margins, paddings and layout parameters | ||
return new ViewHolder(view, mClickListener); | ||
} | ||
|
||
@Override | ||
public void onBindViewHolder(ViewHolder holder, final int position) { | ||
Log.d(TAG, "onBindViewHolder for position "+position); | ||
final Label label = mItems.get(position); | ||
//TODO: Set the proper Icon with tint | ||
holder.mImageView.setImageResource(label.getIconResource()!=null?label.getIconResource():R.drawable.ic_label_grey600_24dp); | ||
holder.mTextView.setText(label.getName()); | ||
holder.mCounterView.setText(String.valueOf(label.getCounter())); | ||
holder.itemView.setActivated(isSelected(position)); | ||
} | ||
|
||
/** | ||
* Provide a reference to the views for each data item. | ||
* Complex data labels may need more than one view per item, and | ||
* you provide access to all the views for a data item in a view holder. | ||
*/ | ||
static final class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, | ||
View.OnLongClickListener { | ||
|
||
ImageView mImageView; | ||
TextView mTextView; | ||
TextView mCounterView; | ||
private OnItemClickListener mClickListener; | ||
|
||
public ViewHolder(View view, OnItemClickListener listener) { | ||
super(view); | ||
mClickListener = listener; | ||
|
||
this.mImageView = (ImageView) view.findViewById(R.id.icon); | ||
this.mTextView = (TextView) view.findViewById(R.id.name); | ||
this.mCounterView = (TextView) view.findViewById(R.id.counter); | ||
|
||
this.itemView.setOnClickListener(this); | ||
this.itemView.setOnLongClickListener(this); | ||
} | ||
|
||
@Override | ||
public void onClick(View view) { | ||
mClickListener.onListItemClick(getAdapterPosition()); | ||
} | ||
|
||
@Override | ||
public boolean onLongClick(View view) { | ||
return mClickListener.onListItemLongClick(getAdapterPosition()); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package eu.davidea.flexibleadapter; | ||
|
||
import java.util.Collections; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
|
||
import android.support.v7.widget.RecyclerView; | ||
import android.util.Log; | ||
import android.view.ViewGroup; | ||
|
||
/** | ||
* This class provides a set of standard methods to handle changes on the data set | ||
* such as adding, removing, moving an item. | ||
* | ||
* Remember to call {@link RecyclerView#scheduleLayoutAnimation()} after adding or | ||
* removing an item from the Adapter when the activity is paused. | ||
* | ||
* <strong>VH</strong> is your implementation of {@link RecyclerView#ViewHolder}. | ||
* <strong>T</strong> is your domain object containing the data. | ||
* | ||
* @author Davide Steduto | ||
*/ | ||
public abstract class FlexibleAdapter<VH extends RecyclerView.ViewHolder, T> extends SelectableAdapter<VH> { | ||
|
||
private static final String TAG = FlexibleAdapter.class.getSimpleName(); | ||
|
||
protected List<T> mItems; | ||
//TODO: Handling the undo functionality | ||
|
||
public FlexibleAdapter() { | ||
|
||
} | ||
|
||
public abstract void updateDataSet(); | ||
|
||
public abstract T getItem(int position); | ||
|
||
@Override | ||
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType); | ||
|
||
@Override | ||
public abstract void onBindViewHolder(VH holder, final int position); | ||
|
||
@Override | ||
public int getItemCount() { | ||
return mItems.size(); | ||
} | ||
|
||
public void addItem(int position, T item) { | ||
mItems.add(position, item); | ||
Log.d(TAG, "addItem notifyItemInserted on position "+position); | ||
notifyItemInserted(position); | ||
} | ||
|
||
private void removeItem(int position) { | ||
Log.d(TAG, "removeItem on position "+position); | ||
mItems.remove(position); | ||
Log.d(TAG, "removeItem notifyItemRemoved on position "+position); | ||
notifyItemRemoved(position); | ||
} | ||
|
||
public void removeItems(List<Integer> selectedPositions) { | ||
Log.d(TAG, "removeItems Sorting positions --------------"); | ||
// Reverse-sort the list | ||
Collections.sort(selectedPositions, new Comparator<Integer>() { | ||
@Override | ||
public int compare(Integer lhs, Integer rhs) { | ||
return rhs - lhs; | ||
} | ||
}); | ||
|
||
// Split the list in ranges | ||
while (!selectedPositions.isEmpty()) { | ||
if (selectedPositions.size() == 1) { | ||
removeItem(selectedPositions.get(0)); | ||
//Align the selection list when removing the item | ||
selectedPositions.remove(0); | ||
} else { | ||
int count = 1; | ||
while (selectedPositions.size() > count && selectedPositions.get(count).equals(selectedPositions.get(count - 1) - 1)) { | ||
++count; | ||
} | ||
|
||
if (count == 1) { | ||
removeItem(selectedPositions.get(0)); | ||
} else { | ||
removeRange(selectedPositions.get(count - 1), count); | ||
} | ||
|
||
for (int i = 0; i < count; ++i) { | ||
selectedPositions.remove(0); | ||
} | ||
} | ||
Log.d(TAG, "removeItems current selection " + getSelectedItems()); | ||
} | ||
} | ||
|
||
private void removeRange(int positionStart, int itemCount) { | ||
Log.d(TAG, "removeRange positionStart="+positionStart+ " itemCount="+itemCount); | ||
for (int i = 0; i < itemCount; ++i) { | ||
mItems.remove(positionStart); | ||
} | ||
Log.d(TAG, "removeRange notifyItemRangeRemoved"); | ||
notifyItemRangeRemoved(positionStart, itemCount); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package eu.davidea.flexibleadapter; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
import android.os.Bundle; | ||
import android.support.v7.widget.RecyclerView; | ||
import android.util.Log; | ||
|
||
/** | ||
* This class provides a set of standard methods to handle the selection on the items of an Adapter. | ||
* | ||
* @author Davide Steduto | ||
*/ | ||
public abstract class SelectableAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { | ||
|
||
private static final String TAG = SelectableAdapter.class.getSimpleName(); | ||
|
||
private ArrayList<Integer> selectedItems; | ||
|
||
public SelectableAdapter() { | ||
selectedItems = new ArrayList<Integer>(); | ||
} | ||
|
||
/** | ||
* Indicates if the item at position position is selected | ||
* @param position Position of the item to check | ||
* @return true if the item is selected, false otherwise | ||
*/ | ||
protected boolean isSelected(int position) { | ||
return selectedItems.contains(Integer.valueOf(position)); | ||
} | ||
|
||
/** | ||
* Toggle the selection status of the item at a given position | ||
* @param position Position of the item to toggle the selection status for | ||
*/ | ||
public void toggleSelection(int position) { | ||
Integer positionTapped = Integer.valueOf(position); | ||
int index = selectedItems.indexOf(positionTapped); | ||
if (index != -1) { | ||
Log.d(TAG, "toggleSelection removing selection on position "+position); | ||
selectedItems.remove(index); | ||
} else { | ||
Log.d(TAG, "toggleSelection adding selection on position "+position); | ||
selectedItems.add(positionTapped); | ||
} | ||
Log.d(TAG, "toggleSelection notifyItemChanged on position "+position); | ||
notifyItemChanged(position); | ||
Log.d(TAG, "toggleSelection current selection "+selectedItems); | ||
} | ||
|
||
/** | ||
* This method remove the selection if at the specified | ||
* position the item was previously selected. | ||
* Note: notifyItemChanged on the position is NOT called! | ||
* This is useful when an item is mainly removed from the | ||
* implementation of the Adapter | ||
* @param position | ||
*/ | ||
protected void removeSelection(int position) { | ||
Log.d(TAG, "removeSelection on position "+position); | ||
int index = selectedItems.indexOf(Integer.valueOf(position)); | ||
if (index != -1) selectedItems.remove(index); | ||
//The notification is made outside this method | ||
//notifyItemChanged(position); | ||
} | ||
|
||
/** | ||
* Add the selection status for all items. | ||
* The selector container is sequentially filled with All items positions. | ||
*/ | ||
public void selectAll() { | ||
Log.d(TAG, "selectAll"); | ||
selectedItems = new ArrayList<Integer>(getItemCount()); | ||
for (int i = 0; i < getItemCount(); i++) { | ||
selectedItems.add(Integer.valueOf(i)); | ||
Log.d(TAG, "selectAll notifyItemChanged on position "+i); | ||
notifyItemChanged(i); | ||
} | ||
//TODO: Not sure about this call notifyDataSetChanged() when ALL items needs to be refreshed. | ||
//notifyDataSetChanged(); | ||
} | ||
|
||
/** | ||
* Clear the selection status for all items. | ||
* If Adapter size match with the size of the selection list, | ||
* then fast clear is performed. | ||
*/ | ||
public void clearSelection() { | ||
if (selectedItems.size() == getItemCount()) { | ||
selectedItems.clear(); | ||
//TODO: Not sure about this call notifyDataSetChanged() when ALL items needs to be refreshed. | ||
Log.d(TAG, "clearSelection notifyDataSetChanged on all position"); | ||
notifyDataSetChanged(); | ||
} else { | ||
Iterator<Integer> iterator = selectedItems.iterator(); | ||
while (iterator.hasNext()) { | ||
//The notification is done only on items that are currently selected. | ||
//Clearing all items on selectedItems, we loose the position to notify. | ||
//TODO: To verify: Clearing all after the notification actually it does any effect because | ||
// the position called rely on the selectionItems that still contains that position | ||
int i = iterator.next(); | ||
iterator.remove(); | ||
Log.d(TAG, "clearSelection notifyItemChanged on position "+i); | ||
notifyItemChanged(i); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Count the selected items | ||
* @return Selected items count | ||
*/ | ||
public int getSelectedItemCount() { | ||
return selectedItems.size(); | ||
} | ||
|
||
/** | ||
* Indicates the list of selected items | ||
* @return List of selected items ids | ||
*/ | ||
public List<Integer> getSelectedItems() { | ||
return selectedItems; | ||
} | ||
|
||
/** | ||
* Save the state of the current selection on the items. | ||
* @param outState | ||
*/ | ||
public void onSaveInstanceState(Bundle outState) { | ||
outState.putIntegerArrayList(TAG, selectedItems); | ||
} | ||
|
||
/** | ||
* Restore the previous state of the selection on the items. | ||
* @param savedInstanceState | ||
*/ | ||
public void onRestoreInstanceState(Bundle savedInstanceState) { | ||
selectedItems = savedInstanceState.getIntegerArrayList(TAG); | ||
} | ||
|
||
} |