0

I have ViewPager with 3 Fragments. I just want to know is it possible to move elements (ImageView, TextView, e.t.c) in Fragment when user start to scroll the page and go to another page? What the best way to do that? Here below my code that I used before. I used it in my MainActivity. Only after test I understand that I am on the wrong way cause these code will work every time when user scroll. So is it possible to set it in Fragment?

My code that i used before in MainActivity:

@Override
public void transformPage(View page, float position) {
        // transformation here
        int pageWidth = page.getWidth();
        ImageView mImageViewCloud = (ImageView) getView().findViewById(R.id.cloud);
        ImageView mImageButterfly = (ImageView) getView().findViewById(R.id.butterfly);

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            page.setAlpha(0);

        } else if (position <= 1) { // [-1,1]

            if(mImageViewCloud!=null)mImageViewCloud.setTranslationX((float) (-(1 - position) * 0.5 * pageWidth));
            if(mImageButterfly!=null)mImageButterfly.setTranslationX((float) ((1 - position) * 1.5 * pageWidth));
            // The 0.5, 1.5, 1.7 values you see here are what makes the view move in a different speed.
            // The bigger the number, the faster the view will translate.
            // The result float is preceded by a minus because the views travel in the opposite direction of the movement.


        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            page.setAlpha(0);
        }
}

Any help is appreciated. Thanks!

EDIT: AdapterFragment.java

public abstract class AdapterFragment extends Fragment {

    SparseArray<AdapterFragment> registeredFragments = new SparseArray<AdapterFragment>();

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        AdapterFragment fragment = (AdapterFragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public void pass(int farFarAway) {
        for(int i = 0, nSize = registeredFragments.size(); i < nSize; i++)
            registeredFragments.valueAt(i).pass(farFarAway);
    }

    final int pageWidth = ViewPager.getMeasuredWidth(); //after ViewPager drawn, probably its also screen width
    final int scrollRange = (AdapterFragment.getCount()-1)*pageWidth;

    ViewPager.OnPageChangeListener OPCL = new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            float farFarAway=(float)(position*pageWidth+positionOffsetPixels), scrollToFactor = farFarAway/scrollRange;
            AdapterFragment.pass(farFarAway);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    };
}
Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193

2 Answers2

0

have you tried ViewPager.OnPageChangeListener? there is a method in this interface onPageScrolled(int position, float positionOffset, int positionOffsetPixels), last two variables might be useful for your purposes - pass move offset to all Fragments, inside of them move Views

edit:

final int pageWidth=mainViewPager.getMeasuredWidth(); //after ViewPager drawn, probably its also screen width
final int scrollRange = (viewPagerCustomAdapter.getCount()-1)*pageWidth;

OnPageChangeListener onpcl = new OnPageChangeListener() {

                @Override
                public void onPageSelected(int position) {
                }

                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                    float farFarAway=(float)(position*pageWidth+positionOffsetPixels),
                    scrollToFactor = farFarAway/scrollRange;

                    viewPagerCustomAdapter.pass(farFarAway);
                }

                @Override
                public void onPageScrollStateChanged(int state) {
                }
            };

viewPagerCustomAdapter is an adapter dispatching farFarAway - how much distance ViewPager is moved starting left edge of 0 position Fragment. how to dispatch moved value to currently existing Fragments? - check this and create for loop over all registered fragments inside adapter's pass(int farFarAway). inside each Fragment you may calculate proper value for setTranslationX. you may also pass and use scrollToFactor (0.0-1.0) and position, these might be useful. e.g. position might determine if you are on current or next Fragment. note that default ViewPager memory is set to one, so there can't be more than 3 registered Fragments at once (current+both next)

edit 2:

create new class and extend all your Fragments used in your adapter

public abstract class AdapterFragment extends Fragment{
    public abstract pass(int farFarAway);
}

add these lines to your adapter:

SparseArray<AdapterFragment> registeredFragments = new SparseArray<AdapterFragment>();

@Override
public Object instantiateItem(ViewGroup container, int position) {
    AdapterFragment fragment = (AdapterFragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

public void pass(int farFarAway) {
    for(int i = 0, nsize = registeredFragments.size(); i < nsize; i++)
        registeredFragments.valueAt(i).pass(farFarAway);
}

set above OnPageChangeListener for your ViewPager. In this way every Fragment gets current scroll position. so an example of use in one of your Fragments

public void pass(int farFarAway){
    imageView.setTranslationX(farFarAway/10); //sample value 10, farFarAway is too big value for moving any View
}

your ImageView should move when while swiping ViewPager, adjust as you want. This whole post is almost full solution, should be useful...

PS. code not tested, might be some syntax or other bugs

Community
  • 1
  • 1
snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • Hello @snachmsm ! I found that method too before but i dont understand how exactly this method works in my case. How to set positionOffset? Can you show me example. As I said I have 3 pages: 1page(position 0), 2 page(position 1), 3 page(position 2). As example user want to scroll from 1 page to 2 page. – Nurzhan Nogerbek Jan 23 '15 at 13:27
  • check out edit with some sample code and suggestions – snachmsm Jan 23 '15 at 13:54
  • Hello @snachmsm again, I am not sure that I understand your idea. As a matter of fact I have my own ViewPagerAdapter to change Fragments. I will update my post with it. You can check it. Anyway can you show me concrete solution to my task please cause i cant catch your idea! – Nurzhan Nogerbek Jan 23 '15 at 15:11
  • Hello @snachmsm I created new AdapterFragment.class as you said. I edited my post with code of that class. Can you check it? Is it ok? Cause i have some mistakes as: Cannot resolve method instantiateItem, destroyItem, getCount, pass. Another mistake in code is: Non-static method 'getMeasuredWidht()' cannot be refenced from static from a static context... Can you check it? Maybe I'm confused where and how to use concrete method... – Nurzhan Nogerbek Jan 23 '15 at 18:04
  • section in my first edit goes to `Activity` which contains your `ViewPager` and `Adapter`, not into `Adapter` itself. then you are using `mainViewPager.setOnPageChangeListener(onpcl);`. Into your adapter you are copying only this snippet with 'SparseArray'. `AdapterFragment` above is complete, yes, three lines. All your Fragment shoud do smth like this: `public class FirstFragment extends AdapterFragment` (not simply `Fragment`). then all extending Fragment should have implemented `public void pass(int farFarAway)`. My snippets are for multiple classes, you join them in one... – snachmsm Jan 24 '15 at 10:05
0

Try reading about Fragment shared elements. Perhaps this is what you are looking for.

momoja
  • 938
  • 9
  • 23