question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Expand item isn't working well

See original GitHub issue

Hi, i’m trying to make some expandable recycler view with this libs.

I looked over wiki, demo app and issues to make these functionality, finally i can almost reach about it.

But at this point, i face a 2 little problem.

  1. For making item expanded, i have to click twice. if i click the item as first action, it isn’t expand. only making just some animation, but get back to orgin status.
  2. After then, i clicking secondly, expand function works well. But also, in this section, i have a tiny problem. Smooth scrolling isn’t consistent according to item. some item scrolling proper size, but others scrolling only deficient size.

I’ll attach some of my code, please give me some useful advice T-T

[A. expand (parent) item ]

public class StockTemp
        implements IFlexible<StockTemp.HeaderViewHolder>,
        IExpandable<StockTemp.HeaderViewHolder, PollTemp>,
        IHeader<StockTemp.HeaderViewHolder>, IFilterable {

    private static final int TYPE_STOCK = 0;
    private static final int TYPE_STOCK_FAVOR = 1;
    private static final int TYPE_STOCK_FAVOR_BENEFIT = 2;
    private static final int TYPE_STOCK_ALL = 3;

    private boolean mExpand = false;
    private boolean mEnable = false;

    private int type;
    private StockInfo stockInfo;
    private List<PollTemp> pollTemps;

    public StockTemp(int type) {
        super();
        this.type = type;
        setHidden(false);
        setExpanded(false);
        setEnabled(false);
        setSelectable(false);
    }

    public StockTemp(int type, StockInfo stockInfo) {
        super();
        setExpanded(true);
        setEnabled(true);
        setSelectable(false);

        this.stockInfo = stockInfo;
        this.type = type;
    }


    @Override
    public int hashCode() {
        if (type == TYPE_STOCK) {
            return stockInfo.hashCode();
        } else {
            return -1;
        }
    }

    @Override
    public boolean equals(Object inObject) {
        if (type == TYPE_STOCK && inObject instanceof StockTemp) {
            StockTemp inItem = (StockTemp) inObject;
            return this.stockInfo.equals(inItem.stockInfo);
        }
        return false;
    }

    @Override
    public List<PollTemp> getSubItems() {
        if(type == TYPE_STOCK) {
            return pollTemps;
        }
        else
            return null;
    }

    public void addPoll(PollTemp poll) {
        if(type == TYPE_STOCK) {
            if (pollTemps == null)
                pollTemps = new ArrayList<>();
            pollTemps.add(poll);
        }
    }

    @Override
    public int getLayoutRes() {
        if (type == TYPE_STOCK) {
            return R.layout.custom_stock_list_close;
        } else if (type == TYPE_STOCK_FAVOR || type == TYPE_STOCK_ALL) {
            return R.layout.custom_stock_list_title;
        } else {
            return R.layout.custom_stock_list_benefit;
        }
    }

    @Override
    public HeaderViewHolder createViewHolder(FlexibleAdapter adapter, LayoutInflater inflater, ViewGroup parent) {
        return new HeaderViewHolder((inflater.inflate(getLayoutRes(), parent, false)), adapter, type);
    }

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

            if (type == TYPE_STOCK) {
           ...
            } else if (type == TYPE_STOCK_FAVOR) {
              ...
            } else
              ...
        }
    }

    public StockInfo getStockInfo() {
        return stockInfo;
    }

    public static class HeaderViewHolder extends ExpandableViewHolder {

        private StockPriceTwoLine stockPriceTwoLine;
        private TextView customStockName;

        public HeaderViewHolder(View view, FlexibleAdapter adapter, int type) {
            super(view, adapter, true);
            if (type == TYPE_STOCK) {
                stockPriceTwoLine = (StockPriceTwoLine) view.findViewById(R.id.custom_list_stock_price);
                customStockName = (TextView) view.findViewById(R.id.custom_list_stock_name);
            } else if (type == TYPE_STOCK_FAVOR || type == TYPE_STOCK_ALL) {
                customStockName = (TextView) view.findViewById(R.id.custom_stock_list_title);
            } else {
                customStockName = (TextView) view.findViewById(R.id.custom_stock_list_benefit);
            }
        }


        @Override
        protected boolean isViewExpandableOnClick() {
            return true;
        }

        @Override
        protected void expandView(int position) {
            super.expandView(position);
            if (mAdapter.isExpanded(position)) mAdapter.notifyItemChanged(position, true);
        }

        @Override
        protected void collapseView(int position) {
            super.collapseView(position);
            if (!mAdapter.isExpanded(position)) mAdapter.notifyItemChanged(position, true);
        }

        @Override
        public void scrollAnimators(@NonNull List<Animator> animators, int position, boolean isForward) {
            super.scrollAnimators(animators, position, isForward);
            AnimatorHelper.slideInFromBottomAnimator(animators, itemView, mAdapter.getRecyclerView());
        }
    }

    @Override
    public boolean isExpanded() {
        return mExpand;
    }

    @Override
    public void setExpanded(boolean expanded) {
        mExpand = expanded;
    }

    @Override
    public int getExpansionLevel() {
        return 0;
    }

    @Override
    public boolean isEnabled() {
        return mEnable;
    }

    @Override
    public void setEnabled(boolean enabled) {
        mEnable = enabled;
    }

    @Override
    public boolean isHidden() {
        return false;
    }

    @Override
    public void setHidden(boolean hidden) {}

    @Override
    public boolean isSelectable() {
        return false;
    }

    @Override
    public void setSelectable(boolean selectable) {

    }

    @Override
    public boolean isDraggable() {  return false; }

    @Override
    public void setDraggable(boolean draggable) {    }

    @Override
    public boolean isSwipeable() { return false;   }

    @Override
    public void setSwipeable(boolean swipeable) {}
}

[ B. child Item ]

public class PollTemp
        implements IFlexible<PollTemp.SubViewHolder>, ISectionable<PollTemp.SubViewHolder, IHeader>{

    IHeader header;

    private StockInfo stockInfo;
    private PollData pollData;

    public PollTemp(StockInfo stockInfo, PollData pollData, FragmentActivity activity) {
        this.stockInfo = stockInfo;
        this.pollData = pollData;
    }

    @Override
    public IHeader getHeader() {
        return header;
    }

    @Override
    public void setHeader(IHeader header) {
        this.header = header;
    }

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

    @Override
    public SubViewHolder createViewHolder(FlexibleAdapter adapter, LayoutInflater inflater, ViewGroup parent) {
        return new SubViewHolder(inflater.inflate(getLayoutRes(), parent, false), adapter);
    }

    @Override
    public void bindViewHolder(FlexibleAdapter adapter, SubViewHolder holder, int position, List payloads) {
        Context context = holder.itemView.getContext();
        FavorPollFragment.newInstance(pollData);
    }

    public PollData getPollData() {
        return pollData;
    }

    public StockInfo getStockInfo() {
        return stockInfo;
    }

    public static class SubViewHolder extends FlexibleViewHolder {

        private FavorStockPollAdapter pollAdapter;
        private ViewPager pollPager;
        private TabLayout pollTabs;

        public SubViewHolder(View view, FlexibleAdapter adapter) {
            super(view, adapter);
             ...}
    }

    @Override
    public boolean isEnabled() {  return false;    }

    @Override
    public void setEnabled(boolean enabled) {    }

    @Override
    public boolean isHidden() {  return false;    }

    @Override
    public void setHidden(boolean hidden) {    }

    @Override
    public boolean isSelectable() {        return false;    }

    @Override
    public void setSelectable(boolean selectable) {    }

    @Override
    public boolean isDraggable() {        return false;}

    @Override
    public void setDraggable(boolean draggable) {    }

    @Override
    public boolean isSwipeable() {     return false;    }

    @Override
    public void setSwipeable(boolean swipeable) {}
}

[C. In Calling Fragment]

...
        List<IFlexible> stockList = new ArrayList<>();
        getList();
        stockListView = (RecyclerView) favorView.findViewById(R.id.favor_stock_list);
        stockListView.setHasFixedSize(true);
        stockListView.setLayoutManager(createNewLinearLayoutManager());

       adapter =  new FlexibleAdapter(stockList, getActivity());
       stockListView.setAdapter(adapter);
       adapter.setNotifyMoveOfFilteredItems(false)//
                    .setNotifyChangeOfUnfilteredItems(true)/
                    .setAutoScrollOnExpand(true);

    public void getList() {
        List<StockTemp> allList = new ArrayList<>();
        allStockList.add(new StockTemp(0, new StockInfo("kq", "KOSDAQ", "1", 668.50, 688.80, 0)));
        allStockList.add(new StockTemp(0, new StockInfo("ks", "KOSPI", "0", 2054.23, 2048.58, 0)));

        for (int i = 0; i < allStockList.size(); i++) {
            PollTemp tmp = new PollTemp(allStockList.get(i).getStockInfo(), getPollData(4), getActivity());
            tmp.setHeader(allStockList.get(i));
            allStockList.get(i).addPoll(tmp);
            stockList.add(allStockList.get(i));
        }
}

If this makes bothering you, sorry to do that…

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
davideascommented, Oct 6, 2016

@shin2jhoon, let’s go in order.

  1. The flag doesn’t match with the initialized flag. You definitely need to read the Wiki page Item Interfaces and their abstract implementation + Headers-and-Sections#initialization (use case 2). You will discover that you simply need to add only the expandable items not the sub items to the Adapter list, The Adapter will read the flags to initially expand those expaded=true at startup. Also, your initialization is quite complicated in getList(), I don’t understand which is the main list. Make it simpler.
  2. Very important thing: the flags are used and modified internally by the Adapter, the IFlexible & IExplandable (etc…) interfaces expose the methods for the Adapter, but the flags must be real fields in the item. I think it’s obvious that, if you want to use the interfaces, instead of the Abstract classes, you must support all the flags as they are done in the prepared Abstract classes: your new item must be in charge to hold those flags. More specifically you can’t use isHidden() {return hardcoded boolean} or setHidden() {empty}. So your code must be reviewed a bit. Just a note for the future: I will deprecate the flags for dragging and swiping in the item. The ViewHolder will be responsible for those flags.
  3. Smooth scroll is done mainly to auto scroll after an expansion, to show as most sub items as possible if the expansions occurs at the bottom edge of the screen. This works quite well, can you explain better the behavior you have?
  4. Now, if the 3 sub items become visible (parent at 0 index is expanded) all the indexes of all next items in main list are modified by 3, because the main list is an ArrayList. It’s obvious that, the position of the next parent change to 4. Indeed, when I developed the expansion I don’t recalculate the positions, I get it by reference, it is always the correct one. But equals method in the item must return the unique value, be sure to have implemented well.
  5. If the child is not visible then it is not present in the Adapter main list, so getRelativePosition() returns ‘-1’, correct! It’s also written in the javaDoc. If it is visible, then you have ‘0’ as result. But you already know the relative position! you asked for the element at 0 index: get(0)!!! The method getRelativePosition() should be used in another context/use case. If you already have the sublist with getSublist() then you know all the items and their relative positions even if they are not visible/present in the Adapter.
0reactions
davideascommented, Oct 10, 2016

@shin2jhoon,

Point 1) I really don’t have any idea.

Point 2) OrphanHeader is when header loose it’s children, (strange name, I will deprecate this functionality, since it makes confusion). But with Expandables, I’m sure that if you remove it, it will collapse automatically and then deleted. If you delete all children the OprhanHeaders = true will delete also the parent.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Problem with topmost expand command on page
I have several instances of the [expand] command on the same page. All work fine, except for the one nearest the top of...
Read more >
cannot expand single item · Issue #50 · dtolnay/cargo-expand
I have an issue expanding a single item. I get the error "cannot expand single item (single::item) without rustfmt" it does give the...
Read more >
jquery expand/collapse not working right - Stack Overflow
So i'm building expand/collapse style menu where I have two items (two titles). When I click one of the titles, the item and...
Read more >
combo box: property: auto expand = yes ; doesn't seem to work
I open the form, experiment, and whaddya know: numberCombo works just fine, including auto expand. text combo works correctly except auto expand doesn't...
Read more >
Basic Troubleshooting When TextExpander Isn't Working
If TextExpander is not working, try these basic troubleshooting steps based on how ... menu bar item and ensure that the second item...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found