android - 在 RecyclerView 中分别对 View 进行动画处理

标签 android animation gridview android-recyclerview

我还没有调查这么多,但是我之前没有看到过这样的功能,也没有找到很多关于这个主题的信息,所以我认为最好联系 SO 看看是否有人有之前玩过这个想法,可以提供任何建议。如果没有,我会在找到解决方案后在下面发布解决方案。


期望的结果

目前我有一个填充了内容的GridView。我在 GridView 顶部有一个 FloatingActionButton,当用户点击 FAB 时,我想显示一个新的 View。点击时,我希望每个单独的 GridView 项目旋转并向屏幕边缘移动,从而导致整个 GridView 分开,为新的 View< 腾出空间 从底部滑入。当第二个 View 出现时,RecyclerView 将变得不可滚动,并且会保持这种状态直到用户返回,这样做会导致相反的动画发生,带来 >ViewHolder 回到中心并缩小间隙。


请原谅我试图解决我的问题。 :)

GridView 预动画 enter image description here

动画后的 GridView enter image description here

每个 View 项都应该相互独立地动画,结束动画将模拟一种爆炸 RecyclerView 效果。


目前可能的方法/尝试过

我目前正在阅读有关 RecyclerView 各个元素行为的信息。我也从这个 Android Summit video 得到了一些很好的信息关于 RecyclerView 动画。

现在我认为有几种不同的方法:

  1. 使用两个不同的 LayoutManager 并尝试在它们之间制作动画。

  2. 使用 ItemDecorator 改变每个 ViewHolder 的边距和角度。


任何意见或建议将不胜感激,我会在解决问题时更新上面的列表。

谢谢!

最佳答案

事实证明,能够在 RecyclerView 中为 View 设置动画非常简单!您只需要一个自定义的 RecyclerView.LayoutManager,然后您就可以访问所有可见的 View ,以享受动画乐趣。

这里的主要方法是 getChildCount()getChildAt(int index),这两个方法如下面的 getVisibleViews() 您可以访问 RecyclerView 当前显示的所有 View 。然后,我使用一个简单的 View.animate() 调用将每个 View 动画化到所需的 X 位置和旋转。我相信这也适用于所有其他类型的动画!我现在有了我想要的东西。 :)

这是自定义 LayoutManager,请记住,如果您不扩展预定义的 LayoutManager,例如 GridLayoutManagerLinearLayoutManager,您需要提供更多方法,例如 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;
}
}

关于android - 在 RecyclerView 中分别对 View 进行动画处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38310563/

相关文章:

android - 使用 appium 和 Protractor 在设备浏览器上并行执行

java - 如何加密来自url的视频并将加密的视频保存到设备的SD卡

jquery - 如何让我的应用程序在动画期间不挂起?

java - 为什么我的自定义 GridView 仅显示一列?

css - 当行中的每个单元格具有不同的颜色或 CSS 值时,行可以突出显示吗?

java - Android studio 3.1运行模拟器时无法加载aapt

android - 在 Android Studio 中找不到\gradle-wrapper.properties

javascript - JavaScript 的语法错误

javascript - Three.js 骨骼动画

Android 从 GridView 中的 EditText 获取文本