use of com.mikepenz.fastadapter.IItem in project FastAdapter by mikepenz.
the class SubItemUtil method getAllItems.
/**
* internal function!
*
* Why countHeaders and subItems => because the subItemsOnly is an internal flag for the recursive call to optimise it!
*/
private static List<IItem> getAllItems(List<IItem> items, boolean countHeaders, boolean subItemsOnly, IPredicate predicate) {
List<IItem> res = new ArrayList<>();
if (items == null || items.size() == 0) {
return res;
}
int temp;
int itemCount = items.size();
IItem item;
List<IItem> subItems;
for (int i = 0; i < itemCount; i++) {
item = items.get(i);
if (item instanceof IExpandable && ((IExpandable) item).getSubItems() != null) {
subItems = ((IExpandable) item).getSubItems();
if (predicate == null) {
if (countHeaders) {
res.add(item);
}
if (subItems != null && subItems.size() > 0) {
res.addAll(subItems);
}
res.addAll(getAllItems(subItems, countHeaders, true, predicate));
} else {
if (countHeaders && predicate.apply(item)) {
res.add(item);
}
temp = subItems != null ? subItems.size() : 0;
for (int j = 0; j < temp; j++) {
if (predicate.apply(subItems.get(j))) {
res.add(subItems.get(j));
}
}
}
} else // sub items will be counted in above if statement!
if (!subItemsOnly && getParent(item) == null) {
if (predicate == null) {
res.add(item);
} else if (predicate.apply(item)) {
res.add(item);
}
}
}
return res;
}
use of com.mikepenz.fastadapter.IItem in project FastAdapter by mikepenz.
the class SubItemUtil method delete.
/**
* deletes all items in identifiersToDelete collection from the adapter respecting if there are sub items or not
* subitems are removed from their parents sublists, main items are directly removed
*
* @param fastAdapter the adapter to remove the items from
* @param identifiersToDelete ids of items to remove
* @param notifyParent if true, headers of removed items will be notified about the change of their child items
* @param deleteEmptyHeaders if true, empty headers will be removed from the adapter
* @return List of items that have been removed from the adapter
*/
public static List<IItem> delete(final FastAdapter fastAdapter, Collection<Long> identifiersToDelete, boolean notifyParent, boolean deleteEmptyHeaders) {
List<IItem> deleted = new ArrayList<>();
if (identifiersToDelete == null || identifiersToDelete.size() == 0) {
return deleted;
}
// we use a LinkedList, because this has performance advantages when modifying the listIterator during iteration!
// Modifying list is O(1)
LinkedList<Long> identifiers = new LinkedList<>(identifiersToDelete);
// we delete item per item from the adapter directly or from the parent
// if keepEmptyHeaders is false, we add empty headers to the selected items set via the iterator, so that they are processed in the loop as well
IItem item, parent;
int pos, parentPos;
boolean expanded;
Long identifier;
ListIterator<Long> it = identifiers.listIterator();
while (it.hasNext()) {
identifier = it.next();
pos = fastAdapter.getPosition(identifier);
item = fastAdapter.getItem(pos);
// search for parent - if we find one, we remove the item from the parent's subitems directly
parent = getParent(item);
if (parent != null) {
parentPos = fastAdapter.getPosition(parent);
boolean success = ((IExpandable) parent).getSubItems().remove(item);
// check if parent is expanded and notify the adapter about the removed item, if necessary (only if parent is visible)
if (parentPos != -1 && ((IExpandable) parent).isExpanded()) {
fastAdapter.notifyAdapterSubItemsChanged(parentPos, ((IExpandable) parent).getSubItems().size() + 1);
}
// if desired, notify the parent about it's changed items (only if parent is visible!)
if (parentPos != -1 && notifyParent) {
expanded = ((IExpandable) parent).isExpanded();
fastAdapter.notifyAdapterItemChanged(parentPos);
// expand the item again if it was expanded before calling notifyAdapterItemChanged
if (expanded) {
fastAdapter.expand(parentPos);
}
}
deleted.add(item);
if (deleteEmptyHeaders && ((IExpandable) parent).getSubItems().size() == 0) {
it.add(parent.getIdentifier());
it.previous();
}
} else if (pos != -1) {
// if we did not find a parent, we remove the item from the adapter
IAdapter adapter = fastAdapter.getAdapter(pos);
boolean success = false;
if (adapter instanceof IItemAdapter) {
success = ((IItemAdapter) adapter).remove(pos) != null;
if (success) {
fastAdapter.notifyAdapterItemRemoved(pos);
}
}
boolean isHeader = item instanceof IExpandable && ((IExpandable) item).getSubItems() != null;
// Log.d("DELETE", "success=" + success + " | deletedId=" + item.getIdentifier() + "(" + (isHeader ? "EMPTY HEADER" : "ITEM WITHOUT HEADER") + ")");
deleted.add(item);
}
}
return deleted;
}
use of com.mikepenz.fastadapter.IItem in project FastAdapter by mikepenz.
the class SubItemUtil method notifyItemsChanged.
/**
* notifies items (incl. sub items if they are currently extended)
*
* @param adapter the adapter
* @param header the expandable header that should be checked (incl. sub items)
* @param identifiers set of identifiers that should be notified
* @param checkSubItems true, if sub items of headers items should be checked recursively
* @param restoreExpandedState true, if expanded headers should stay expanded
*/
public static <Item extends IItem & IExpandable> void notifyItemsChanged(final FastAdapter adapter, Item header, Set<Long> identifiers, boolean checkSubItems, boolean restoreExpandedState) {
int subItems = header.getSubItems().size();
int position = adapter.getPosition(header);
boolean expanded = header.isExpanded();
// 1) check header itself
if (identifiers.contains(header.getIdentifier())) {
adapter.notifyAdapterItemChanged(position);
}
// 2) check sub items, recursively
IItem item;
if (header.isExpanded()) {
for (int i = 0; i < subItems; i++) {
item = (IItem) header.getSubItems().get(i);
if (identifiers.contains(item.getIdentifier())) {
// Log.d("NOTIFY", "Position=" + position + ", i=" + i);
adapter.notifyAdapterItemChanged(position + i + 1);
}
if (checkSubItems && item instanceof IExpandable) {
notifyItemsChanged(adapter, (Item) item, identifiers, true, restoreExpandedState);
}
}
}
if (restoreExpandedState && expanded) {
adapter.expand(position);
}
}
use of com.mikepenz.fastadapter.IItem in project FastAdapter by mikepenz.
the class FastAdapterDiffUtil method set.
public static <A extends ItemAdapter<Item>, Item extends IItem> A set(final A adapter, final List<Item> items, final DiffCallback<Item> callback, final boolean detectMoves) {
if (adapter.isUseIdDistributor()) {
IdDistributor.checkIds(items);
}
//first collapse all items
adapter.getFastAdapter().collapse(false);
//if we have a comparator then sort
if (adapter.getComparator() != null) {
Collections.sort(items, adapter.getComparator());
}
//map the types
adapter.mapPossibleTypes(items);
//remember the old items
final List<Item> oldItems = adapter.getAdapterItems();
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return oldItems.size();
}
@Override
public int getNewListSize() {
return items.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return callback.areItemsTheSame(oldItems.get(oldItemPosition), items.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return callback.areContentsTheSame(oldItems.get(oldItemPosition), items.get(newItemPosition));
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
Object result = callback.getChangePayload(oldItems.get(oldItemPosition), oldItemPosition, items.get(newItemPosition), newItemPosition);
return result == null ? super.getChangePayload(oldItemPosition, newItemPosition) : result;
}
}, detectMoves);
//make sure the new items list is not a reference of the already mItems list
if (items != oldItems) {
//remove all previous items
if (!oldItems.isEmpty()) {
oldItems.clear();
}
//add all new items to the list
oldItems.addAll(items);
}
result.dispatchUpdatesTo(new ListUpdateCallback() {
@Override
public void onInserted(int position, int count) {
adapter.getFastAdapter().notifyAdapterItemRangeInserted(adapter.getFastAdapter().getPreItemCountByOrder(adapter.getOrder()) + position, count);
}
@Override
public void onRemoved(int position, int count) {
adapter.getFastAdapter().notifyAdapterItemRangeRemoved(adapter.getFastAdapter().getPreItemCountByOrder(adapter.getOrder()) + position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
adapter.getFastAdapter().notifyAdapterItemMoved(adapter.getFastAdapter().getPreItemCountByOrder(adapter.getOrder()) + fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count, Object payload) {
adapter.getFastAdapter().notifyAdapterItemRangeChanged(adapter.getFastAdapter().getPreItemCountByOrder(adapter.getOrder()) + position, count, payload);
}
});
return adapter;
}
use of com.mikepenz.fastadapter.IItem in project FastAdapter by mikepenz.
the class StickyHeaderSampleActivity method onCreate.
@Override
protected void onCreate(Bundle savedInstanceState) {
findViewById(android.R.id.content).setSystemUiVisibility(findViewById(android.R.id.content).getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
// Handle Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(R.string.sample_sticky_header);
//style our ui
new MaterializeBuilder().withActivity(this).build();
//create our FastAdapter
fastAdapter = new FastAdapter();
fastAdapter.withSelectable(true);
//create our adapters
final StickyHeaderAdapter stickyHeaderAdapter = new StickyHeaderAdapter();
final HeaderAdapter headerAdapter = new HeaderAdapter();
final ItemAdapter itemAdapter = new ItemAdapter();
//configure our fastAdapter
//as we provide id's for the items we want the hasStableIds enabled to speed up things
fastAdapter.setHasStableIds(true);
//get our recyclerView and do basic setup
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setItemAnimator(new DefaultItemAnimator());
rv.setAdapter(stickyHeaderAdapter.wrap(itemAdapter.wrap(headerAdapter.wrap(fastAdapter))));
//this adds the Sticky Headers within our list
final StickyRecyclerHeadersDecoration decoration = new StickyRecyclerHeadersDecoration(stickyHeaderAdapter);
rv.addItemDecoration(decoration);
//fill with some sample data
headerAdapter.add(new SimpleItem().withName("Header").withIdentifier(1));
List<IItem> items = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
items.add(new SimpleItem().withName("Test " + i).withHeader(headers[i / 5]).withIdentifier(100 + i));
}
itemAdapter.add(items);
//so the headers are aware of changes
stickyHeaderAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
decoration.invalidateHeaders();
}
});
//restore selections (this has to be done after the items were added
fastAdapter.withSavedInstanceState(savedInstanceState);
//set the back arrow in the toolbar
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(false);
}
Aggregations