timusus / RecyclerView-FastScroll

A simple FastScroller for Android's RecyclerView
Other
1.39k stars 182 forks source link

ItemDecoration is drawn over FastScrollPopup #18

Closed Nammari closed 8 years ago

Nammari commented 8 years ago

screenshot_20160221-223754

timusus commented 8 years ago

I'm not able to reproduce this at all. What OS & device are you using? What does your ItemDecoration look like?

ericntd commented 8 years ago

I'm having the same issue.

Android Support library version 23.4.0. Nexus 5 running Lollipop 5.0

timusus commented 8 years ago

Can you provide the details of your item decoration?

timusus commented 8 years ago

@Nammari, I'd be happy to look at your fork & merge it if you could provide the details of your ItemDecoration.. I can't reproduce the issue with my own ItemDecoration, and I'm not convinced that the FastScrollRecyclerView needs changing.

ericntd commented 8 years ago

Hi @timusus my ItemDecorator is as follows:

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;

    public SimpleDividerItemDecoration(Context context) {
        mDivider = context.getResources().getDrawable(R.drawable.line_divider);
    }

    protected boolean isDecorated(View view, RecyclerView parent) {
        return true;
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {

        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            if (isDecorated(child, parent)) {
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

                int top = child.getBottom() + params.bottomMargin;
                int bottom = top + mDivider.getIntrinsicHeight();

                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(c);
            }
        }
    }
}

line_divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <size
        android:width="1dp"
        android:height="1dp" />

    <solid android:color="@color/grey_200" />

</shape>

How I used your view in my fragment:

        mRecyclerView = (FastScrollRecyclerView) rootView.findViewById(R.id.recycler);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));
timusus commented 8 years ago

Edit: This is bad advice. I need to fix this in the RecyclerView-FastScroll library.

You should be drawing your ItemDecoration in onDraw() instead of onDrawOver().

onDraw():

Draw any appropriate decorations into the Canvas supplied to the RecyclerView. Any content drawn by this method will be drawn before the item views are drawn, and will thus appear underneath the views.

onDrawOver():

Draw any appropriate decorations into the Canvas supplied to the RecyclerView. Any content drawn by this method will be drawn after the item views are drawn and will thus appear over the views.

I have tested this and confirmed both the issue and the fix. So, change your ItemDecoration to look like this:

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable divider;

    public SimpleDividerItemDecoration(Context context) {
        divider = context.getResources().getDrawable(R.drawable.line_divider);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);

        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + divider.getIntrinsicHeight();

            divider.setBounds(left, top, right, bottom);
            divider.draw(c);
        }
    }
}
ericntd commented 8 years ago

Hi @timusus , I've made the change according to your suggestion and now the dividers are not showing at all! screen shot 2016-08-16 at 9 37 40 am

timusus commented 8 years ago

Interesting. Are you using a solid background colour for your RecyclerView items? The sample isn't, which might explain why my 'fix' above worked in my testing.

ericntd commented 8 years ago

Sorry, I found the culprit.

So I had white colour as background of my list item. The divider item decorator only works if the background is transparent

timusus commented 8 years ago

@ericn37 yep, so my suggested fix is incorrect - the problem is with the RecyclerView-FastScroll library rather than your ItemDecoration. @Nammari's fix is probably the correct way to approach this.