Groupie: Allow show/hiding a group

Created on 16 Mar 2017  Â·  9Comments  Â·  Source: lisawray/groupie

Hi,
thanks for that awesome library! I struggle a bit to find the best way to hide/show entire groups.
A have a view that shows two different sets of items depending on the view state. So I created two groups and want to show/hide them. Any suggestions?

enhancement

Most helpful comment

I am considering allowing any Group (that would also mean any individidual Item) to be either shown or hidden. If a Group is hidden, all its children would be hidden too.

What would you prefer to see?

Group.setVisible(boolean visible)

or

Group.hide() / Group.show()

?

All 9 comments

In my opinion, the best way is to create a custom group. I've done this in the past with the ToggleGroup code below (name suggestions welcome). I planned on submitting it as a groupie enhancement at some point but haven't had time clean up the code or write tests for it (there may be bugs). The basic idea is that you can add multiple children to this group and then easily select which child is visible by calling toggleGroup.setVisible(int visibleIndex)

import com.genius.groupie.Group;
import com.genius.groupie.NestedGroup;

import java.util.ArrayList;
import java.util.List;


public class ToggleGroup extends NestedGroup {
    private int visibleIndex = 0;
    private final List<Group> children = new ArrayList<>();

    public ToggleGroup(final Group firstGroup) {
        super.add(firstGroup);
        children.add(firstGroup);
        notifyItemRangeInserted(0, firstGroup.getItemCount());
    }

    @Override
    public void add(final Group group) {
        super.add(group);
        children.add(group);
    }

    @Override
    public Group getGroup(final int position) {
        if (position != 0) {
            return null;
        }
        return children.get(visibleIndex);
    }

    @Override
    public int getPosition(final Group group) {
        if (children.contains(group)) {
            return 0;
        }
        return -1;
    }

    @Override
    public int getGroupCount() {
        return 1;
    }

    public int getVisibleIndex() {
        return visibleIndex;
    }

    public void setVisible(final int visibleIndex) {
        if (this.visibleIndex == visibleIndex) {
            return;
        }

        int oldSize = getItemCount();
        this.visibleIndex = visibleIndex;
        int newSize = getItemCount();

        if (oldSize == newSize) {
            notifyItemRangeChanged(0, newSize);
        } else {
            notifyItemRangeRemoved(0, oldSize);
            notifyItemRangeInserted(0, newSize);
        }
    }

    private boolean dispatchChildChanges(final Group group) {
        return visibleIndex == children.indexOf(group);
    }

    @Override
    public void onChanged(Group group) {
        if (dispatchChildChanges(group)) {
            super.onChanged(group);
        }
    }

    @Override
    public void onItemInserted(Group group, int position) {
        if (dispatchChildChanges(group)) {
            super.onItemInserted(group, position);
        }
    }

    @Override
    public void onItemChanged(Group group, int position) {
        if (dispatchChildChanges(group)) {
            super.onItemChanged(group, position);
        }
    }

    @Override
    public void onItemChanged(Group group, int position, Object payload) {
        if (dispatchChildChanges(group)) {
            super.onItemChanged(group, position, payload);
        }
    }

    @Override
    public void onItemRemoved(Group group, int position) {
        if (dispatchChildChanges(group)) {
            super.onItemRemoved(group, position);
        }
    }

    @Override
    public void onItemRangeChanged(Group group, int positionStart, int itemCount) {
        if (dispatchChildChanges(group)) {
            super.onItemRangeChanged(group, positionStart, itemCount);
        }
    }

    @Override
    public void onItemRangeInserted(Group group, int positionStart, int itemCount) {
        if (dispatchChildChanges(group)) {
            super.onItemRangeInserted(group, positionStart, itemCount);
        }
    }

    @Override
    public void onItemRangeRemoved(Group group, int positionStart, int itemCount) {
        if (dispatchChildChanges(group)) {
            super.onItemRangeRemoved(group, positionStart, itemCount);
        }
    }

    @Override
    public void onItemMoved(Group group, int fromPosition, int toPosition) {
        if (dispatchChildChanges(group)) {
            super.onItemMoved(group, fromPosition, toPosition);
        }
    }
}

There are several ways you could approach this, depending on your requirements and how you like to think about it!

  • @oldergod ExpandableGroup is a little different than what OP is asking for. It shows or hides the items in a single group but it is also intended to have a "parent" Group which is always visible. Of course, that could be a group of 0 items. So you could easily make something like
public class DisappearingGroup extends ExpandableGroup {
    public DisappearingGroup() {
        super(new EmptyGroup());
    }

    public void toggleVisibility() {
        onToggleExpanded();
    }
}

It reads a little strange to me, but it is certainly easy.

  • @kjpublic01 's code above is more complex but would also satisfy your requirement.

  • You could also make a SwitchingGroup which extends Section, has references to your groups A and B, and simply adds one group and removes the other when you call switch().

  • If it's top level, you could just remove one group and add the other at the adapter level, honestly.

If there's a lot of interest in hiding / showing individual groups, I'm down to consider it more deeply and add something specifically for this purpose to the library. It might make sense to have ExpandableGroup be simpler and itself simply contain a ToggleGroup or DisappearingGroup (names welcome)!

+1 for hiding / showing individual groups. I've encountered several situations in which this would come in handy in our app - for example showing a dismissable card at some index in a list. Sure, you could just add / remove the card item manually, but you'd have to calculate the index which quickly becomes a pain if you have other dismissable cards.

I am considering allowing any Group (that would also mean any individidual Item) to be either shown or hidden. If a Group is hidden, all its children would be hidden too.

What would you prefer to see?

Group.setVisible(boolean visible)

or

Group.hide() / Group.show()

?

btw @chip2n — in the case of dismissable cards, simply hold a reference to the card item. When it is dismissed, call GroupAdapter.remove(cardItem). References are the best way to interact with Groupie. If you're messing with indices, something is wrong!

This would be a great addition. Especially for items. I've run into several cases where I end up putting a single item in a group similar to the ToggleGroup I mentioned above.

Think I would prefer Group.setVisible(boolean visible). The hide() / show() seem like it would turn into isVisible ? group.show() : group.hide().

@lisawray Agreed - in one of my apps I have "reserved spots" in which a card should be shown in some situations. Instead of using indices, you could use an empty "placeholder" group in which you add/remove the card as needed. But calling remove on the GroupAdapter itself wouldn't work in that case, since the card would lose it's position in the list when I add it later (unless you know the index).

Anyways, I agree with @kjpublic01 - it seems that Group.setVisible(boolean visible) would avoid a small amount of boilerplate code (especially with a reactive architecture).

@chip2n—I get what you're saying now; yep I've used a Group to wrap individual items as a placeholder, but toggling visibility does seem like a missing feature in that case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mattinger picture mattinger  Â·  3Comments

Nimrodda picture Nimrodda  Â·  3Comments

amervelic picture amervelic  Â·  3Comments

forntoh picture forntoh  Â·  3Comments

jordond picture jordond  Â·  6Comments