Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView overlay another layout when scroll

Actually I don't know how it properly called - overlay, parallax or slideUP, whatever, I have an Activity called "cafe details" which presents a Container(LinearLayout) with header information (name, min price, delivery time min e.t.c) and other container (ViewPager) which contains a ExpandableListView with something information (menus&dishes) and all I want to do is slide up my Viewpager when scrolls listview to scpecific Y position to cover(or overlay) header information.

MyPic

A similar effect (but with parallax that I don't need to use) looks like this

Similar effect

I can detect when user scrolling listview down or up but how I can move container with ViewPager to overlay other container? Please give me ideas, regards.

UPD I have tried a huge number of ways how to implement it and all of them unfortunately are not suitable. So now I have come to next variant - add scroll listener to ListView, calculate scrollY position of view and then based on that move the viewpager on y axis by calling setTranslationY(); Here is some code

1) ViewPager's fragment

    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView absListView, int i) {

        }

        @Override
        public void onScroll(AbsListView absListView, int i, int i1, int i2) {
            if (getActivity() != null) {
                ((MainActivity) getActivity()).resizePagerContainer(absListView);
            }
        }
    });

2) MainActivity

//object fields

int previousPos; 
private float minTranslation;
private float minHeight;

<--------somewhere in onCreate

minTranslation = - (llVendorDescHeaders.getMeasuredHeight()+llVendorDescNote.getMeasuredHeight());
//llVendorDescHeaders is linearLayout with headers that should be hidden
//lVendorDescNote is a textView on green background;

minHeight = llVendorDescriptionPagerContainer.getMeasuredHeight();
//llVendorDescriptionPagerContainer is a container which contains ViewPager
--------->

public void resizePagerContainer(AbsListView absListView){

    final int scrollY = getScrollY(absListView);
    if (scrollY != previousPos) {
        final float translationY = Math.max(-scrollY, minTranslation);

        llVendorDescriptionPagerContainer.setTranslationY(translationY);

        previousPos = scrollY;
    }
}

private int getScrollY(AbsListView view) {
    View child = view.getChildAt(0);
    if (child == null) {
        return 0;
    }

    int firstVisiblePosition = view.getFirstVisiblePosition();
    int top = child.getTop();

    return -top + firstVisiblePosition * child.getHeight() ;
}

This simple solution unfortunately has a problem - it is blinking and twitching (I don't know how to call it right) when scrolls slowly. So instead setTranslationY() I've used an objectAnimator:

public void resizePagerContainer(AbsListView absListView){
    .............

    ObjectAnimator moveAnim = ObjectAnimator.ofFloat(llVendorDescriptionPagerContainer, "translationY", translationY);
    moveAnim.start();
   ..............
}

I don't like this solution because 1) anyway it does resize viewpager with delay, not instantly 2) I don't think that is good idea to create many ObjectAnimator's objects every time when I scroll my listView. Need your help and fresh ideas. Regards.

like image 481
whizzzkey Avatar asked May 22 '15 12:05

whizzzkey


2 Answers

I'm assuming that you are scrolling the top header (the ImageView is a child of the header) based on the scrollY of the ListView/ScrollView, as shown below:

float translationY = Math.max(-scrollY, mMinHeaderTranslation);
mHeader.setTranslationY(translationY);
mTopImage.setTranslationY(-translationY / 3); // For parallax effect

If you want to stick the header/image to a certain dimension and continue the scrolling without moving it anymore, then you can change the value of mMinHeaderTranslation to achieve that effect.

//change this value to increase the dimension of header stuck on the top
int tabHeight = getResources().getDimensionPixelSize(R.dimen.tab_height); 

mHeaderHeight = getResources().getDimensionPixelSize(R.dimen.header_height);
mMinHeaderTranslation = -mHeaderHeight + tabHeight;

The code snippets above are in reference to my demo but I think it's still general enough for you.

If you're interested you can check out my demo https://github.com/boxme/ParallaxHeaderViewPager

like image 50
boxme Avatar answered Oct 17 '22 05:10

boxme


Have you tried CoordinatorLayout from this new android's design support library? It looks like it's what you need. Check this video from 3:40 or this blog post.

like image 33
Gintas_ Avatar answered Oct 17 '22 04:10

Gintas_