翻译 ViewPager 滚动条上的浮动操作按钮
Translate Floating Action Button on ViewPager scroll
我有一个包含 3 个选项卡的屏幕,下面是一个包含 3 个片段的 ViewPager 和一个位于右下角的浮动操作按钮。
当第一个选项卡是当前选项卡时,我想在右下角显示 FAB。当第二个选项卡是当前选项卡时,我想在底部中心显示 FAB。当第 3 个选项卡是当前选项卡时,我想隐藏 FAB。
从右下角到中下角或相反的平移动画应该在视图分页器滚动时发生,即基于滚动量。
下面是我试过的。
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
ViewCompat.animate(mFAB)
.translationX(-translate)
.withLayer()
.setDuration(0)
.setInterpolator(new LinearInterpolator())
.start();
}
@Override
public void onPageSelected(int position) {
mTabLayout.getTabAt(position).select();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
这是最好的方法吗?如果是,翻译变量的值应该是多少?
请帮我实现这个。
您可以查看 Android Lollipop Call 应用程序作为参考。显示拨号器的 FAB 以类似的方式进行动画处理。对于第一个选项卡,它位于右下角,然后对于中间选项卡,它位于中心。这正是我想要的。
最简单的方法是这样的:
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
final int width = mViewPager.getWidth();
if (position == 0) { // represents transition from page 0 to page 1 (horizontal shift)
int translationX = (int) ((-(width - mFab.getWidth()) / 2f) * positionOffset);
mFab.setTranslationX(translationX);
mFab.setTranslationY(0);
} else if (position == 1) { // represents transition from page 1 to page 2 (vertical shift)
int translationY = (int) (mFab.getHeight() * positionOffset);
mFab.setTranslationY(translationY);
mFab.setTranslationX(-(width - mFab.getWidth()) / 2f);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
请记住,width
参数应该表示屏幕的宽度(我假设 ViewPager
填充了屏幕的宽度(所以我分配了 width = mViewPager.getWidth()
)。
您也没有明确说明您希望以何种方式隐藏您的 FAB
。所以我只是垂直翻译它。您还可以使用 setScaleX(...)
和 setScaleY(...)
.
编辑:
应使用以下方法计算已更改参数的(步长)值(我们称之为 - 以供将来参考 - formula 1
):
// formula 1
value = targetValue - ((targetValue - initialValue) * (1.0f - offset));
其中 offset
表示变化的参数(在范围 [0f; 1f]
内)。所以在你的情况下 offset
是 onPageScrolled
方法的 positionOffset
参数。
让我们分析第 0 页和第 1 页之间的过渡(您的情况;position==0
):
- 您想水平移动
FAB
,因此您将修改 translationX
参数。
FAB
锚定在右下角(例如 layout_gravity="bottom|right"
)
FAB
的初始位置是不滚动第 0 页动画的正确位置。因此 translationX
的 initialValue
动画是 0
initialValue = 0;
- 您想将
FAB
移到屏幕中央。给定屏幕宽度作为变量 width
,您可以计算 FAB
向屏幕中心移动的正确 targetValue
。它等于屏幕宽度的一半减去 FAB
宽度的一半。由于您是从右角开始的,因此该值为负数 (``)
targetValue = -(width - mFab.getWidth()) / 2f;
- 由于
initialValue
参数为0
,可以将formula 1
简化为(将引用为formula 2
):
// formula 2
value = targetValue * offset;
- 采用计算的
targetValue
你最终得到这个(formula 2
计算的 targetValue
和 positionOffset
而不是 offset
):
value = (-(width - mFab.getWidth()) / 2f) * positionOffset;
这正是我用来将 FAB
从初始位置 (bottom|right
) 移动到屏幕中心(水平)的方法。
在计算第 1 页和第 2 页之间过渡中 translationY
的所需步长值时,我经历了类似的过程。
您需要做的是对以后的任何步骤做同样的事情。考虑动画参数的 initialValue
和 targetValue
,将计算值插入 formula 1
并查看它是否按预期工作。
我有一个包含 3 个选项卡的屏幕,下面是一个包含 3 个片段的 ViewPager 和一个位于右下角的浮动操作按钮。
当第一个选项卡是当前选项卡时,我想在右下角显示 FAB。当第二个选项卡是当前选项卡时,我想在底部中心显示 FAB。当第 3 个选项卡是当前选项卡时,我想隐藏 FAB。
从右下角到中下角或相反的平移动画应该在视图分页器滚动时发生,即基于滚动量。
下面是我试过的。
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
ViewCompat.animate(mFAB)
.translationX(-translate)
.withLayer()
.setDuration(0)
.setInterpolator(new LinearInterpolator())
.start();
}
@Override
public void onPageSelected(int position) {
mTabLayout.getTabAt(position).select();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
这是最好的方法吗?如果是,翻译变量的值应该是多少?
请帮我实现这个。
您可以查看 Android Lollipop Call 应用程序作为参考。显示拨号器的 FAB 以类似的方式进行动画处理。对于第一个选项卡,它位于右下角,然后对于中间选项卡,它位于中心。这正是我想要的。
最简单的方法是这样的:
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
final int width = mViewPager.getWidth();
if (position == 0) { // represents transition from page 0 to page 1 (horizontal shift)
int translationX = (int) ((-(width - mFab.getWidth()) / 2f) * positionOffset);
mFab.setTranslationX(translationX);
mFab.setTranslationY(0);
} else if (position == 1) { // represents transition from page 1 to page 2 (vertical shift)
int translationY = (int) (mFab.getHeight() * positionOffset);
mFab.setTranslationY(translationY);
mFab.setTranslationX(-(width - mFab.getWidth()) / 2f);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
请记住,width
参数应该表示屏幕的宽度(我假设 ViewPager
填充了屏幕的宽度(所以我分配了 width = mViewPager.getWidth()
)。
您也没有明确说明您希望以何种方式隐藏您的 FAB
。所以我只是垂直翻译它。您还可以使用 setScaleX(...)
和 setScaleY(...)
.
编辑:
应使用以下方法计算已更改参数的(步长)值(我们称之为 - 以供将来参考 - formula 1
):
// formula 1
value = targetValue - ((targetValue - initialValue) * (1.0f - offset));
其中 offset
表示变化的参数(在范围 [0f; 1f]
内)。所以在你的情况下 offset
是 onPageScrolled
方法的 positionOffset
参数。
让我们分析第 0 页和第 1 页之间的过渡(您的情况;position==0
):
- 您想水平移动
FAB
,因此您将修改translationX
参数。 FAB
锚定在右下角(例如layout_gravity="bottom|right"
)FAB
的初始位置是不滚动第 0 页动画的正确位置。因此translationX
的initialValue
动画是0
initialValue = 0;
- 您想将
FAB
移到屏幕中央。给定屏幕宽度作为变量width
,您可以计算FAB
向屏幕中心移动的正确targetValue
。它等于屏幕宽度的一半减去FAB
宽度的一半。由于您是从右角开始的,因此该值为负数 (``)
targetValue = -(width - mFab.getWidth()) / 2f;
- 由于
initialValue
参数为0
,可以将formula 1
简化为(将引用为formula 2
):
// formula 2
value = targetValue * offset;
- 采用计算的
targetValue
你最终得到这个(formula 2
计算的targetValue
和positionOffset
而不是offset
):
value = (-(width - mFab.getWidth()) / 2f) * positionOffset;
这正是我用来将 FAB
从初始位置 (bottom|right
) 移动到屏幕中心(水平)的方法。
在计算第 1 页和第 2 页之间过渡中 translationY
的所需步长值时,我经历了类似的过程。
您需要做的是对以后的任何步骤做同样的事情。考虑动画参数的 initialValue
和 targetValue
,将计算值插入 formula 1
并查看它是否按预期工作。