10

I have an Activity contains ViewPager , first Fragment in this ViewPager contains ListView and when I click on any Item it replaces this Fragment with selected one , I use setCurrentItem(selectedItem,true)//for smooth scroll but ViewPager slides over all Fragments before selected Fragment I want it to slide to selected Fragment only not over all fragments I tried to use PageTransfrom.transformPage like that

@Override
public void transformPage(View page, float position) {
    int currentItem = viewPager.getCurrentItem();
    if (currentItem != selectedItem)
        page.setVisibility(View.GONE);
}

but with no luck

Ma7moud El-Naggar
  • 548
  • 1
  • 6
  • 18

6 Answers6

4

One possible solution is to modify the PagerAdapter to always return the page you want on item #2.

When clicked on any item from the first page, first change the implementation of the method getItem(int position) of the PagerAdapter, (this is easy if your PagerAdapter is implemented in the same class file of your code), to return the page you want when position == 2, and then call setCurrentItem(2, true). This could make a smooth scroll to the selected page, directly. You may also need to change getCount() to limit the count to only 2, otherwise the next page may not be the expected one.

But this method dismisses the other pages. User could only scroll back to the first page and then navigate to another page. If you want keep the natural order of the pages by manual scroll (not by click), you could restore getItem(int position) to your default implementation once the scoll (by click) stops, and reload the stopped current page to the natural order by calling setCurrentItem(position, false)(immediately, not smoothly this time), then user can scroll back and forth manually.

HC Zhang
  • 301
  • 2
  • 5
0

So, if I understand you correctly, you want a smooth scroll to the selected fragment but only from the previous one. Right?

When you pass true to setCurrentItem it does smooth scrolling from the current selected position. This can not be changed. Therefore the solution to your problem is to do a 2-step setup.

First use setCurrentItem (selectedItem-1, false) to set it to the previous item. Once that transition is completed, call setCurrentItem (selectedItem, true).

I have not done that myself, but I foresee a few complications and special cases.

If you put one call to setCurrentItem after another it probably won't work. You may need to listen for the first page change (using OnPageChangeListener) to do the second call to setCurrentItem.

Also there is the out of bounds when the selected item is the first one.

Hope this helps.

shalafi
  • 3,926
  • 2
  • 23
  • 27
0

ViewPager is not the right tool for what you are trying to achieve. If you use ViewPager, add Fragments as pages, and scroll from Page 0 to 3 it will definitely scroll from Page 0 -> Page 1 -> Page 2 -> Page 3. In general, it will go one step at a time where one step corresponds to moving to next page.

What you are looking for is Descendant Navigation.

In your case, You can keep all the fragment implementations as it is. Just host the Fragment containing the ListView in an activity and when the user selects an item in it, add the corresponding Fragment with a slide in transition.

Good luck.

Community
  • 1
  • 1
500865
  • 6,920
  • 7
  • 44
  • 87
0

In general, as many said here already, you shouldn't use ViewPager, as well it absolutely for other purpose.

I think that easiest way is to go with just simple fragment switching, for instance:

yourListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                switch (position) {
                    case 0:
                        getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right)
                                .replace(R.id.content, MyFirstFragment.newInsance()).commit();
                        break;
                    case 1:
                        getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right)
                                .replace(R.id.content, MySecondFragment.newInsance()).commit();
                        /etc.
                }
            }
        });

So you will have full control over it + possibility to set proper animation for each fragment appearance.

Hope you got my idea.

Divers
  • 9,531
  • 7
  • 45
  • 88
0

I solved this problem like this I have One ViewPager (vp1) Contains Two Fragment , Fist one contains ListView of Items , Second Fragments contains another ViewPager (vp2) I slide to selected Item without slide over all previous items like this when user click on Item on Listview

vp2.setCurrentItem(selectedItemIndex,false);
vp1.setCurrentItem(1,true);

first set current item on second viewpager without slide ,and then slide first viewpager , and that's it

Ma7moud El-Naggar
  • 548
  • 1
  • 6
  • 18
0

You have to keep visible not only the selected item but also the one that was selected before this if you want the slide animate from one to the other. After you call setCurrentItem(selectedItem,true), all calls to viewPager.getCurrentItem() inside transformPage returns the same value you set before, it's not that it changes through smooth scroll. I think you can do it this way with transformPage:

int prevSelFrag = 0, currentSelFrag = 0; //member variables

@Override
protected void onCreate(Bundle savedInstanceState) {
    pager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(int pos) {
            prevSelFrag = currentSelFrag;
            currentSelFrag = pos;
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
    pager.setPageTransformer(false, new PageTransformer() {
        @Override
        public void transformPage(View page, float relativePosition) {
            float transDiff = prevSelFrag - currentSelFrag;
            if (transDiff > 1.0f || transDiff < -1.0f) {
                boolean transIsToRight = transDiff < 0.0f;
                if (transIsToRight && relativePosition < -1) {
                    page.setVisibility(View.GONE);
                } else if (relativePosition > 1) { //trans is to left
                    page.setVisibility(View.GONE);
                }else{
                    page.setVisibility(View.VISIBLE);
                }
            }else{
                page.setVisibility(View.VISIBLE);
            }
        }
    });
}

relativePosition is the page position relative to the page set on setCurrentItem, so that the given View page has to go to that position in the animation (but not in real pager state). If for example you are on page 0 and call setCurrentItem(2,true) in transformPage you may receive:

  • current view in page 1 with relativePosition=-2
  • current view in page 0 with relativePosition=-1
  • current view in page 2 with relativePosition=0

Of course these values vary between them to do the transition effect. ViewPager smoothScroll didn't work for me, had to use this solution to fix that -> https://stackoverflow.com/a/14776244/4282954

Community
  • 1
  • 1
Lolme
  • 21
  • 1