Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AbstractSectionableItem items not showing header when adding items at runtime #462

Closed
orrinLife360 opened this issue Oct 3, 2017 · 8 comments

Comments

@orrinLife360
Copy link

Wanted to start out by saying thanks for providing this awesome library! I have loved it so far.

I am however having some trouble trying to show a list with headers in my application. All of my views are dynamically added at runtime and are not set in the adapters constructor. I have created an item that extends AbstractSectionableItem and a header that abstracts AbstractHeaderItem. I am trying to add these items using addItem(position,item) and am not sure if the only way to make these work is with addItemToSection() functions. However even with calling that the headers will not show unless I add them with addSection(). I am not sure if this is intended functionality however I was under the assumption that you are not supposed to have to handle the section headers manually and they work based on the list of items. Here is what I have currently:

Header view -

public class ProfileListHeader extends AbstractHeaderItem {

    public ProfileListHeader() {
        setHidden(false);
        setEnabled(false);
        setSelectable(false);
    }

    @Override
    public boolean equals(Object o) {
        return o instanceof ProfileListHeader;
    }

    @Override
    public int getLayoutRes() {
        return R.layout.profile_list_header;
    }

    @Override
    public RecyclerView.ViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
        return new ProfileListHeaderHolder(view, adapter);
    }

    @Override
    public void bindViewHolder(FlexibleAdapter adapter, RecyclerView.ViewHolder holder, int position, List payloads) {

    }

    /**
     * The ViewHolder used by this item.
     * Extending from FlexibleViewHolder is recommended especially when you will use
     * more advanced features.
     */
    public class ProfileListHeaderHolder extends FlexibleViewHolder {

        ProfileListHeaderHolder(View view, FlexibleAdapter adapter) {
            super(view, adapter, true);
            ButterKnife.bind(this, view);
        }
    }
}

Sectionable -

public class ProfileListCell extends AbstractSectionableItem<ProfileListCell.ProfileViewHolder, ProfileListHeader> {

    @Getter
    private final String id;
    private final String name;

    public ProfileListCell(@NonNull ProfileListHeader header, @NonNull String id, @NonNull String name) {
        super(header);
        setEnabled(true);
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object inObject) {
        if (inObject instanceof ProfileListCell) {
            ProfileListCell inItem = (ProfileListCell) inObject;
            return this.id.equals(inItem.getId());
        }
        return false;
    }

    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }

    @Override
    public int getLayoutRes() {
        return R.layout.profile_view_holder;
    }

    @Override
    public ProfileViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
        return new ProfileViewHolder(view, adapter);
    }

    @Override
    public void bindViewHolder(FlexibleAdapter adapter, ProfileViewHolder holder, int position, List payloads) {
        // todo subscribe observable
        holder.setName(name);
    }

    @Override
    public void unbindViewHolder(FlexibleAdapter adapter, ProfileViewHolder holder, int position) {
        // todo unsubscribe observable
    }

    /**
     * The ViewHolder used by this item.
     * Extending from FlexibleViewHolder is recommended especially when you will use
     * more advanced features.
     */
    public class ProfileViewHolder extends FlexibleViewHolder {

        @BindView(R2.id.name)
        TextView name;

        ProfileViewHolder(View view, FlexibleAdapter adapter) {
            super(view, adapter);
            ButterKnife.bind(this, view);
        }

        public void setName(String name) {
            this.name.setText(name);
        }
    }

}

My simple adapter setup -

adapter = new FlexibleAdapter<>(null);
        recyclerView.setAdapter(adapter);
        adapter.setDisplayHeadersAtStartUp(true);

Simple adding item -

    @Override
    public void addListItem(int position, BaseSectionView listItem) {
        Assert.assertNotNull(adapter);
        final ISectionable sectionable = (ISectionable) listItem.getView();
        adapter.addItem(position, sectionable);
    }

I am assuming I am doing something wrong however it was not clear in the documentation how its supposed to be done and the sample app does all its adding of headers with one list at initialization. I was able to get it to work by adding the section using addSection() however then also the headers seem to be calculated into the list so and when dealing with click listeners I have I get the global position even when using getCardinalPositionOf() I notice that the mScrollableHeaders size is 0. I dont know if this means I have to manage my own position including headers or if there is another way for flexible adapter to manage it.

Thanks again for the library and the help!

@davideas
Copy link
Owner

davideas commented Oct 4, 2017

@orrinLife360, thank you very much! I appreciate.

This implementation is wrong, the equals must identify uniquely an object, and this doesn't:

@Override
public boolean equals(Object o) {
    return o instanceof ProfileListHeader;
}

addSection adds a new header only, while addItemToSection is only for items with a header.

Then, ScrollableHeaders is another feature you can read about more in the Wiki and in the javaDoc, thing that you should always do it, so the cardinal position is relative to main items only (list without scrollable footers and headers).

@orrinLife360
Copy link
Author

orrinLife360 commented Oct 5, 2017

Okay I will try this. Thanks!

So if I add a ISectionable using addItem it will not add a header?

Also just to confirm if headers are added they are counted as part of the list items? Is there any way to get position of items discarding the headers?

@davideas
Copy link
Owner

davideas commented Oct 5, 2017

@orrinLife360, also addItem will display a header if not already visible, but the position should be calculated before. With addItemToSection, you can pass a custom Comparator. Also you have calculatePositionFor.

To count specific items you have getItemCountOfTypes.

@orrinLife360
Copy link
Author

orrinLife360 commented Oct 6, 2017

Thanks, I understand the adding sections now and modified my implementation to work to fit into that using addItemToSection.

I am still not sure if flexible adapter provides a way to find out the position of an item in the list without including headers. I can make that logic myself if needed but wanted to leverage flexible adapter if possible.

@davideas
Copy link
Owner

davideas commented Oct 6, 2017

@orrinLife360, can you please elaborate better the way a position is retrieved without including headers?

@orrinLife360
Copy link
Author

Sure. Say I have a list that looks like this:

HEADER_0 (0)
ITEM_0 (1)
ITEM_1 (2)
HEADER_1 (3)
ITEM_2 (4)
HEADER_2 (5)
ITEM_3 (6)

I would like a way to get the position of item 3 without including the headers 0, 3, & 5. So I would like ITEM_3 to return position 3 not the index in the global list 6.

Right now I am just getting all the headers and finding how many are in between the start of the list and the item to get it to get that count but if flexible adapter could handle that logic too.

@davideas
Copy link
Owner

davideas commented Oct 8, 2017

@orrinLife360, ah ok, I understood and we can add it. Just that, getCardinalPositionOf is already dedicated for position excluding the scrollable headers and footers. So, for the position of this kind it, we should count only the items of the same type, but I don't find a name for it: getXXXPositionOf(item).
Regarding the routine, I don't see another quick elaboration than that.

@orrinLife360
Copy link
Author

Okay awesome. Thanks for all the help. I have what i need working for now.

@davideas davideas added this to the 5.0.0-rc3 milestone Oct 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants