View translation in sliding a ViewPager

前端 未结 4 1142
猫巷女王i
猫巷女王i 2021-02-13 11:26

I was reading an example on customizing ViewPager\'s sliding page animation that entails translating the page(View) to a certain amount. The example is

相关标签:
4条回答
  • 2021-02-13 11:49

    If you shrink the rectange by scaleFactor,

    Assume Original Height is pageHeight and Width is pageWidth;

    The new shrink Height will be scaleFactor * pageHeight

    shrinkMarginTopBottom = pageHeight - scaleFactor * pageHeight = pageHeight(1 - scaleFactor);
    
    and I assume it will be equally shirnked from bottom and top;
    
    shrinkMarginTop = shrinkMarginTopBottom/2;
    which is equal to below mentioned formula
    float vertMargin = pageHeight * (1 - scaleFactor) / 2;
    

    So post explaning the margin calculations

    float vertMargin = pageHeight * (1 - scaleFactor) / 2;
    float horzMargin = pageWidth * (1 - scaleFactor) / 2;
    if (position < 0) {
        view.setTranslationX(horzMargin - vertMargin / 2);
    } else {
        view.setTranslationX(-horzMargin + vertMargin / 2);
    }
    

    The x translation should have some offset for page positions 0 and 1 to get the animation effect and some distance hence subtracting the margins for both ... The division happens because +ve and -ve x translation adds up to exact margin

    I may be guessing but for me to have a variable x translation and margin which varies with scale factor, vertMargin is used for creating that offset which varies with scale.. if you remove vertMargin code it will still be animating the same but a bit faster but without keeping any margin between two pages.

    0 讨论(0)
  • 2021-02-13 11:51

    GitHub provide a library for animation that you want without any calculations
    You don't need to create your custom ViewPager PageTransformer
    Simply add below library in your app/build.gradle file.

    compile 'com.ToxicBakery.viewpager.transforms:view-pager-transforms:1.2.32@aar'
    

    MainActivity.java

    public class MainActivity extends Activity {
    
        private static final String KEY_SELECTED_PAGE = "KEY_SELECTED_PAGE";
        private static final String KEY_SELECTED_CLASS = "KEY_SELECTED_CLASS";
    
        private int mSelectedItem;
        private ViewPager mPager;
        private PageAdapter mAdapter;
    
        @SuppressWarnings("deprecation")
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            int selectedPage = 0;
            if (savedInstanceState != null) {
                mSelectedItem = savedInstanceState.getInt(KEY_SELECTED_CLASS);
                selectedPage = savedInstanceState.getInt(KEY_SELECTED_PAGE);
            }
    
    
            setContentView(R.layout.activity_main);
    
            mAdapter = new PageAdapter(getFragmentManager());
    
            mPager = (ViewPager) findViewById(R.id.container);
            mPager.setAdapter(mAdapter);
            try {
                mPager.setPageTransformer(true, new TransformerItem(ZoomOutSlideTransformer.class).clazz.newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            mPager.setCurrentItem(selectedPage);
    
        }
    
    
        public static class PlaceholderFragment extends Fragment {
    
            private static final String EXTRA_POSITION = "EXTRA_POSITION";
            private static final int[] COLORS = new int[] { 0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444 };
    
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                final int position = getArguments().getInt(EXTRA_POSITION);
                final TextView textViewPosition = (TextView) inflater.inflate(R.layout.fragment_main, container, false);
                textViewPosition.setText(Integer.toString(position));
                textViewPosition.setBackgroundColor(COLORS[position - 1]);
    
                return textViewPosition;
            }
    
        }
    
        private static final class PageAdapter extends FragmentStatePagerAdapter {
    
            public PageAdapter(FragmentManager fragmentManager) {
                super(fragmentManager);
            }
    
            @Override
            public Fragment getItem(int position) {
                final Bundle bundle = new Bundle();
                bundle.putInt(PlaceholderFragment.EXTRA_POSITION, position + 1);
    
                final PlaceholderFragment fragment = new PlaceholderFragment();
                fragment.setArguments(bundle);
    
                return fragment;
            }
    
            @Override
            public int getCount() {
                return 5;
            }
    
        }
    
        private static final class TransformerItem {
    
            final String title;
            final Class<? extends PageTransformer> clazz;
    
            public TransformerItem(Class<? extends PageTransformer> clazz) {
                this.clazz = clazz;
                title = clazz.getSimpleName();
            }
    
            @Override
            public String toString() {
                return title;
            }
    
        }
    
    }
    

    activity_main.xml

    <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="MainActivity" />
    

    fragment_main.xml

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:text="@string/app_name"
    android:textColor="@android:color/white"
    android:textSize="72sp"
    tools:context="MainActivity$PlaceholderFragment" />
    

    I hope this may help you.:-)

    0 讨论(0)
  • 2021-02-13 11:54

    There is one thing you are missing here, the PageTransformer is applied to the views AFTER they have been positioned.

    So, with or without a PageTransformer attached to the PageView - when you scroll between pages - you simply doing a scroll (like in a LiseView) with SNAP capabilities.

    The PageTransformer only adds effects on top of that.

    So the purpose of,

    float vertMargin = pageHeight * (1 - scaleFactor) / 2;
    float horzMargin = pageWidth * (1 - scaleFactor) / 2;
    if (position < 0) {
        view.setTranslationX(horzMargin - vertMargin / 2);
    } else {
        view.setTranslationX(-horzMargin + vertMargin / 2);
    }
    

    is NOT to move the pages - but to compensate the page shrinking.

    Without it, the page will have some ugly side effects. TRY IT, remove the lines :) - The views will go right/left but the positioning will be off.

    So, the translation X does not move the page, but, in this case, simply manages the pages spacing to improve the animation feel - the above is the Math for it. What it does is to reduce the space between the pages based on the screen height/width. First it negates the space (horzMargin) then it adds a little spacing (- vertMargin / 2)

    And that is why your calculation is not good (w*x) - You are trying to move the page - But it is already moving.

    0 讨论(0)
  • 2021-02-13 12:12

    As I re-read your question and this answer, I'm not sure I've really addressed your question. I think it may be of some help though so I'm posting it.

    According to this, position=0 means this page is front & center (& for this example, full screen). We only care about a page with position in the -1 to +1 range, otherwise it is too far out of view to care about. You can see this in the 1st & last conditions where alpha is set to 0, making the view fully transparent.

    I am unable to understand the statement,

    view.setTranslationX(horzMargin - vertMargin / 2);

    As I looked at it, I didn't see much value in this section of code as well. Since the margins are calculated based on the scaleFactor, & that is limited to 0.85 - 1.0, it doesn't make a lot of difference in the appearance of the transition. I'm sure that someone with a much better eye for design than me would disagree. However, I removed this portion of code as an experiment.

            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }
    

    While I could see small differences depending on setting translationX if I looked closely, I'd never notice with casual use. More of a difference can be seen by setting MIN_SCALE to 0.5 (or smaller).

    what would be wrong with my calculation?

    Probably nothing as long as you limited it to a small result like the current code does. Keep in mind though that the ViewPager class is the primary controller of the animation rather than setTranslationX().

    0 讨论(0)
提交回复
热议问题