我还没有调查过这个问题,但是我还没有看到过这样的功能,或者发现了很多关于这个主题的信息,所以我认为最好接触到SO看看是否有人曾经玩过这个想法,并可以提供任何建议。如果没有,我会在找到解决方案时发布以下解决方案。
目前我有一个GridView
填充了内容。我在FloatingActionButton
之上有一个GridView
,当用户点击FAB时,我想显示一个新的View
。点击后,我希望每个GridView
个项都可以旋转并向屏幕边缘移动,从而导致整个GridView
分离,为新View
从底部滑入腾出空间。当辅助RecyclerView
出现时,View
将变为不可滚动,并且将保持这种状态,直到用户返回为止,这样做会导致相反的动画发生,导致ViewHolder
重新进入中心并缩小差距。
请原谅我试图解决我的问题。 :)
每个视图项应该相互独立动画,结束动画将模拟一种爆炸式RecyclerView
效果。
我目前正在阅读RecyclerView
各个元素的行为。我还从Android Summit video RecyclerView
动画中获得了一些非常好的信息。
现在我认为有几种不同的看法:
使用两个不同的LayoutManager
并尝试在它们之间制作动画。
使用ItemDecorator
更改每个ViewHolder
的边距和角度。
我们将非常感谢任何建议或建议,在我解决问题时,我会更新上面的列表。
谢谢!
答案 0 :(得分:2)
能够在RecyclerView中为视图设置动画效果非常简单!您只需要一个自定义RecyclerView.LayoutManager
,然后您就可以访问所有可以看到动画乐趣的视图。
此处的主要方法是getChildCount()
和getChildAt(int index)
,这两种方法如下所示getVisibleViews()
您可以访问RecyclerView
所有的所有观看次数目前显示。然后,我使用简单的View.animate()
调用将每个视图设置为所需的X位置和旋转。我确信这也适用于所有其他类型的动画!我现在正是我想要的。 :)
这是自定义LayoutManager,请记住,如果您不扩展预定义的LayoutManager
,例如GridLayoutManager
或LinearLayoutManager
,您需要提供更多generateDefaultLayoutParams()
。
public class AnimatingGridLayoutManager extends GridLayoutManager {
private static final int PARTED_ANIMATION_DURATION = 200;
private static final int PARTED_ANIMATION_VARIANCE = 20;
private static final int PARTED_ANIMATION_OFFSET = 25;
private static final int PARTED_ANIMATION_ANGLE = 15;
private boolean itemsParted;
...
public void setItemsParted(boolean itemsParted, Activity context) {
Display display = context.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int screenWidth = size.x;
if (this.itemsParted != itemsParted) {
this.itemsParted = itemsParted;
if (itemsParted) {
partItems(context, screenWidth);
} else {
closeItems(screenWidth);
}
}
}
private void partItems(Context context, int screenWidth) {
List<View> visibleViews = getVisibleViews();
for (int i = 0; i < visibleViews.size(); i++) {
int viewWidth = visibleViews.get(i).getWidth();
int offset = ViewUtils.getPixelsFromDp(getRandomNumberNearInput(PARTED_ANIMATION_OFFSET), context);
int xPos = (-viewWidth) + offset;
int rotation = getRandomNumberNearInput(-PARTED_ANIMATION_ANGLE);
if (viewPositionIsRight(i)) {
// invert values to send view to end of screen instead of start
xPos = screenWidth - offset;
rotation = -rotation;
}
visibleViews.get(i).animate()
.x(xPos)
.rotation(rotation)
.setDuration(PARTED_ANIMATION_DURATION)
.setInterpolator(new FastOutSlowInInterpolator());
}
}
private void closeItems(int screenWidth) {
List<View> visibleViews = getVisibleViews();
for (int i = 0; i < visibleViews.size(); i++) {
int xPos = 0;
if (viewPositionIsRight(i)) {
xPos = screenWidth / 2;
}
visibleViews.get(i).animate()
.x(xPos)
.rotation(0)
.setDuration(PARTED_ANIMATION_DURATION)
.setInterpolator(new FastOutSlowInInterpolator());
}
}
private boolean viewPositionIsRight(int position) {
// if isn't 2 row grid new logic is needed
return position % 2 != 0;
}
private int getRandomNumberNearInput(int input) {
Random random = new Random();
int max = input + PARTED_ANIMATION_VARIANCE;
int min = input - PARTED_ANIMATION_VARIANCE;
return random.nextInt(max - min) + min;
}
private List<View> getVisibleViews() {
List<View> visibleViews = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
visibleViews.add(getChildAt(i));
}
return visibleViews;
}
}