ParallaxScroll icon indicating copy to clipboard operation
ParallaxScroll copied to clipboard

Dividers

Open mypplication opened this issue 10 years ago • 11 comments

Hello, I have a problem with ParallaxListView when i use it with a single header. In my header, i have a dark background. I have also dividers enabled in my listview. When i scroll, i see the header's background hover the dividers..

do you know this problem ? (tested on Kitkat/ICS/gingerbread)

thank you

mypplication avatar Apr 22 '14 13:04 mypplication

I guess its make sense since the dividers are draw separately from the views - that get offset to make the parallax effect. I think that the best thing will be to override the way the dividers work in the ParrallaxListView but for now you can use your dividers as part of your views and it will work fine - you can make a vertical linear layout that contains your list view item with addition of a separator view.

nirhart avatar Apr 24 '14 04:04 nirhart

Yes, that's exactly what I did. I just was pointing the problem for your knowledge :)

mypplication avatar Apr 24 '14 08:04 mypplication

Hi @mypplication , Could you provide an example of the fix? I'd like to remove the dividers showing the background

edit: adding android:divider="@null" to the ParallaxListView fixed it

        <com.nirhart.parallaxscroll.views.ParallaxListView xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/list_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:parallax_factor="1.9"
            tools:context=".MainActivity"
            android:divider="@null"
        />

erickhun avatar Apr 27 '14 03:04 erickhun

No it did't work. Whenever parallax background is drawing with the list, they just mix up.

imoblife avatar May 28 '14 12:05 imoblife

If you want definitively remove divider in your listview, set android:divider="@null" and android:dividerHeight="0dp"

mypplication avatar May 28 '14 12:05 mypplication

thank you

imoblife avatar Jun 14 '14 03:06 imoblife

@nirhart I've found a pretty horrendous solution since it requires API 18, but at least it might be helpful for yourself to figure out a better way. So the problem is with the headerview drawing over the divider/adapter views. Ideally the headerview can be clipped by the offset so that it doesn't draw over the adapter views (this happens if you add any transparency to the adapter views, you can see an odd effect with the parallax). API 18 added a way to clip views but only clips itself and not its children.

I tried a quick solution below just to prove it could work:

view.setTranslationY(offset);
if (android.os.Build.VERSION.SDK_INT >= 18) { //obv this could be optimised
    Rect clipRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom() + (int) offset);
    view.setClipBounds(clipRect);
    if(view instanceof ViewGroup) { //here we would have to act recursively to get all children views and set the clipping on every child and child's child (ughh)
        ((ViewGroup) view).getChildAt(0).setClipBounds(clipRect);
    }
}

The actual code to clip the view isn't big (when thinking of compatibility). see: http://stackoverflow.com/questions/18724976/can-setclipbounds-be-called-on-a-view-before-it-has-been-drawn#answer-19927060

But it would be very inconvenient if every view within the headerview had to extend a custom view

LukeDeighton avatar Jul 24 '14 16:07 LukeDeighton

@nirhart I had another attempt tonight to find an easier solution and here it is.

public class ClippingRelativeLayout extends RelativeLayout {

    private int offset;

    public ClippingRelativeLayout(Context context) {
        super(context);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.clipRect(new Rect(getLeft(), getTop(), getRight(), getBottom() + offset));
        super.dispatchDraw(canvas);
    }

    public void setClipY(int offset) {
        this.offset = offset;
        invalidate();
    }
}

by doing the clipRect() in dispatchDraw all the children are clipped and therefore don't need the recursive approach above. It is also fully compatible (although I haven't tested on older versions of android). Then in ParallaxView:

@SuppressLint("NewApi")
    public void setOffset(float offset) {
        ClippingRelativeLayout view = this.view.get();
        if (view != null) {
            if (isAPI11) {
                view.setTranslationY(offset);
            } else {
                translatePreICS(view, offset);
            }
            view.setClipY((int) offset);
        }
}

And then

public void addParallaxedHeaderView(View v) {
        ClippingRelativeLayout clippingLayout = new ClippingRelativeLayout(v.getContext());
        clippingLayout.addView(v);

        super.addHeaderView(clippingLayout);
        helper.addParallaxedHeaderView(clippingLayout);
    }

Note - It would need testing/tweaking for adding multiple HeaderViews.

Edit: It also needs sorting for parallax factors other than 1.9

LukeDeighton avatar Jul 24 '14 21:07 LukeDeighton

@LukeDeighton Thank you very much for your contribution, I'll take a look at it once I'll have some spare time

nirhart avatar Jul 25 '14 03:07 nirhart

@nirhart Any update regarding the issue? Thanks.

a-marwane avatar Oct 29 '14 11:10 a-marwane

@LukeDeighton awesome!

mawenge avatar May 24 '16 08:05 mawenge