KKO
KKO

Reputation: 1933

ViewPager animation fade in/out instead of slide

I got the FragmentBasics example from here. Is there a way make the ViewPager animation simply fade in and out when I swipe instead of sliding left and right? I've been trying some stuff with PageTransformer, but no success, I can still see it sliding. So I guess I need to somehow force its position to stay put, while sliding my finger only affects the alpha.

public class SecondActivity extends Activity {

SectionsPagerAdapter mSectionsPagerAdapter;

ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setPageTransformer(false, new FadePageTransformer());
    mViewPager.setAdapter(mSectionsPagerAdapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.second, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a PlaceholderFragment (defined as a static inner class below).
        return PlaceholderFragment.newInstance(position + 1);
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return getString(R.string.title_section2).toUpperCase(l);
        case 2:
            return getString(R.string.title_section3).toUpperCase(l);
        }
        return null;
    }
}

public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    /**
     * Returns a new instance of this fragment for the given section number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_second, container, false);
        TextView textView = (TextView) rootView.findViewById(R.id.section_label);
        textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
        return rootView;
    }
}

public class FadePageTransformer implements ViewPager.PageTransformer {
        public void transformPage(View view, float position) {

            if (position < -1 || position > 1) {
                view.setAlpha(0);
            }
            else if (position <= 0 || position <= 1) {
                // Calculate alpha. Position is decimal in [-1,0] or [0,1]
                float alpha = (position <= 0) ? position + 1 : 1 - position;
                view.setAlpha(alpha);
            }
            else if (position == 0) {
                view.setAlpha(1);
            }
        }
    }

Upvotes: 45

Views: 47338

Answers (6)

Riyaz Uddin
Riyaz Uddin

Reputation: 1

In my case, I was using @umberto_sidoti solution but I was facing issue with inconsistency of the alpha with page switching, sometimes the pager would show blank white page(when setting alpha less than 1F) more longer. This was becaue the transformPage function was being called multiple time for every page from current to the destination page. I solved this by adding extra check to distinguish the destination page inside tranformPage.

override fun transformPage(page: View, position: Float) {
    if(position <= -1.0F || position >= 1.0F) {
        page.translationX = page.width * position;
    } else if( position == 0.0F ) {
        page.translationX = page.width * position;
    } else {
        // position is between -1.0F & 0.0F OR 0.0F & 1.0F
        page.translationX = page.width * -position;
    }
    if(position!=0.0f) return
    page.setAlpha(0.25f)
    page.visibility = View.VISIBLE

    // Start Animation for a short period of time
    page.animate().alpha(1f).setDuration(800);
}

Upvotes: 0

umberto_sidoti
umberto_sidoti

Reputation: 559

Based on a @murena's answer, this should work better for the fade in/out transform. At the end of animation the position is restored to default value.

public void transformPage(View view, float position) {
    if(position <= -1.0F || position >= 1.0F) {
        view.setTranslationX(view.getWidth() * position);
        view.setAlpha(0.0F);
    } else if( position == 0.0F ) {
        view.setTranslationX(view.getWidth() * position);
        view.setAlpha(1.0F);
    } else { 
        // position is between -1.0F & 0.0F OR 0.0F & 1.0F
        view.setTranslationX(view.getWidth() * -position);
        view.setAlpha(1.0F - Math.abs(position));
    }
}
  

Upvotes: 54

Jo&#227;o Dinis
Jo&#227;o Dinis

Reputation: 141

Fade according to Google: https://developer.android.com/training/animation/reveal-or-hide-view

viewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
    @Override
    public void transformPage(@NonNull View page, float position) {
        page.setAlpha(0f);
        page.setVisibility(View.VISIBLE);

        // Start Animation for a short period of time
        page.animate()
            .alpha(1f)
            .setDuration(page.getResources().getInteger(android.R.integer.config_shortAnimTime));
    }
});

Upvotes: 14

murena
murena

Reputation: 1156

This should work better for the fade in/out transform:

public void transformPage(View view, float position) {
    view.setTranslationX(view.getWidth() * -position);
       
    if(position <= -1.0F || position >= 1.0F) {
        view.setAlpha(0.0F);
    } else if( position == 0.0F ) {
        view.setAlpha(1.0F);
    } else { 
        // position is between -1.0F & 0.0F OR 0.0F & 1.0F
        view.setAlpha(1.0F - Math.abs(position));
    }
}

Upvotes: 84

Pablo S. Campos
Pablo S. Campos

Reputation: 131

I found @murena's answer super helpful. However, I ran into a problem when I tried to add an OnClickListener to each tab. I needed each page to open a different URL link. I modified the code to hide the views that are out of sight and added a little extra effect to slide the view at .5 the speed:

public void transformPage(View view, float position) {

    if (position <= -1.0F || position >= 1.0F) {        // [-Infinity,-1) OR (1,+Infinity]
        view.setAlpha(0.0F);
        view.setVisibility(View.GONE);
    } else if( position == 0.0F ) {     // [0]
        view.setAlpha(1.0F);
        view.setVisibility(View.VISIBLE);
    } else {

        // Position is between [-1,1]
        view.setAlpha(1.0F - Math.abs(position));
        view.setTranslationX(-position * (view.getWidth() / 2));
        view.setVisibility(View.VISIBLE);
    }
}

Upvotes: 3

stephan
stephan

Reputation: 527

A simple fading transformer could be implemented like this:

private static class FadePageTransformer implements ViewPager.PageTransformer {
    public void transformPage(View view, float position) {
        view.setAlpha(1 - Math.abs(position));
        if (position < 0) {
            view.setScrollX((int)((float)(view.getWidth()) * position));
        } else if (position > 0) {
            view.setScrollX(-(int) ((float) (view.getWidth()) * -position));
        } else {
            view.setScrollX(0);
        }
    }
}

Maybe not exactly what your looking for, but a good starting point.

Upvotes: 7

Related Questions