在滑动ViewPager时查看翻译

我正在阅读一个关于自定义ViewPager的滑动页面animation的示例,该animation需要将页面( View )翻译成一定量。 这个例子来自文档 。 具体来说,它是一个名为ZoomOutPageTransformer的实现,可以通过setPageTransformer()ViewPager上设置,以自定义页面的滑动方式(在其中包含缩放animation)。

这是最终结果应该是这样的:

在此处输入图像描述

现在,他们描述了他们将如何做到这一点:

transformPage()实现中,您可以创建自定义幻灯片animation,方法是根据屏幕上页面的位置确定需要转换哪些页面,这是从transformPage()方法的position参数获得的。

position参数指示给定页面相对于屏幕中心的位置。 它是一个动态属性,随着用户滚动页面而变化。 当页面填满屏幕时,其position值为0.当页面刚刚从屏幕右侧绘制时,其position值为1.如果用户在第1页和第2页之间滚动,则第1页的position为-0.5和第二页的position为0.5。 根据屏幕上页面的position ,您可以通过使用setAlpha()setTranslationX()setScaleY()等方法设置页面属性来创建自定义幻灯片animation。

这是他们提供的PageTransformer的实现:

 public class ZoomOutPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 1) { // [-1,1] // Modify the default slide transition to shrink the page as well float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); 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); } // Scale the page down (between MIN_SCALE and 1) view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); // Fade the page relative to its size. view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } } 

问题:

我无法理解这句话,

 view.setTranslationX(horzMargin - vertMargin / 2); 

我的理解是position参数的值1.0等于覆盖屏幕宽度,即w。 因此,如果页面的中心移动了x个position单位,那么以像素/ dp表示的平移将是w * x。 但他们正在使用一些保证金计算来计算翻译金额。

任何人都可以解释他们如何进行这种计算以及我的计算会出现什么问题?

这里有一件事你没有,PageTransformer会在它们定位应用于视图。

因此,无论是否将PageTransformer附加到PageView – 当您在页面之间滚动时 – 您只需使用SNAPfunction进行滚动(如在LiseView中)。

PageTransformer仅在其上添加效果。

所以目的,

 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); } 

不是为了移动页面 - 而是为了补偿页面缩小。

没有它,页面将有一些丑陋的副作用。 尝试,删除行:) - 视图将向右/向左,但定位将关闭。

因此,翻译X不会移动页面,但是,在这种情况下,只需管理页面间距以改善animation效果 - 上面就是数学。 它的作用是根据屏幕高度/宽度减少页面之间的空间。 首先它否定了空间(horzMargin)然后它增加了一点间距( - vertMargin / 2)

这就是为什么你的计算不好(w * x) - 你试图移动页面 - 但它已经在移动。

GitHub提供了一个你想要的animation库 ,无需任何计算
您无需创建自定义ViewPager PageTransformer
只需在app/build.gradle文件中添加以下库。

 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 clazz; public TransformerItem(Class clazz) { this.clazz = clazz; title = clazz.getSimpleName(); } @Override public String toString() { return title; } } } 

activity_main.xml中

  

fragment_main.xml

  

我希望这可以帮到你。:-)

当我重新阅读你的问题和答案时,我不确定我是否已经真正解决了你的问题。 我认为它可能会有一些帮助,所以我发布它。

根据这个 ,position = 0表示该页面是前面和中心(对于这个例子,全屏)。 我们只关心位置在-1到+1范围内的页面,否则它太远了以至于无法关注。 您可以在alpha设置为0的第一个和最后一个条件中看到这一点,使视图完全透明。

我无法理解这句话,

view.setTranslationX(horzMargin - vertMargin / 2);

在我看的时候,我在这部分代码中也没有看到太多价值。 由于边距是基于scaleFactor计算的,并且限制为0.85 – 1.0,因此它不会在转换的外观上产生很大的差异。 我敢肯定,那些对我的设计有着比我更好的人会不同意。 但是,我删除了这部分代码作为实验。

  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); } 

虽然如果我仔细观察,我可以看到根据设置translationX的小差异,我从来没有注意到随便使用。 将MIN_SCALE设置为0.5(或更小)可以看出更多的差异。

我的计算会出现什么问题?

可能没什么,只要你将它限制为像当前代码那样的小结果。 请记住,ViewPager类是animation的主要控制器而不是setTranslationX()

如果你通过scaleFactor缩小rectange,

假设原始高度为pageHeight,宽度为pageWidth;

新的缩小高度将是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; 

所以在解释保证金计算后

 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); } 

x平移应该对页面位置0和1有一些偏移以获得animation效果和一些距离因此减去两者的边距...因为+ ve和-ve x平移加起来精确边缘

我可能猜测但是对于我来说,variablesx平移和余量随着比例因子而变化,vertMargin用于创建随着比例变化的偏移量。如果删除vertMargin代码,它仍然会animation相同但速度更快但没有在两页之间保留任何余地。