使用动画更改gridview中的列数(项目到项目)

时间:2017-03-07 05:17:03

标签: android animation gridview scroll

我想用Gridview在android中创建一个动画。动画将在我将列数从2更改为4时。

我使用以下行来更改列数:

If (true)
    gridView.setNumColumns(2);
Else 
    gridView.setNumColumns(4);

我想要实现这样的动画:

https://www.youtube.com/watch?v=1NkuChdWA_I

1 个答案:

答案 0 :(得分:0)

我也需要它然后我创建了以下类:

/**
* Created by Butzke on 19/05/2017.
*/

public class GridViewAnimated extends GridView {
    private int animationDuration = 300, nextColumns;
    private boolean animating = false, waitingScroll, shouldWait = true;
    private GridViewAnimationListener animationListener;
    public GridViewAnimated(Context context) {
        super(context);
        init();
    }
    public GridViewAnimated(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public GridViewAnimated(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    @TargetApi(21)
    public GridViewAnimated(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }
    @Override
    public int computeVerticalScrollOffset() {
        return super.computeVerticalScrollOffset();
    }
    private void init() {
        this.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
    }
    public void setAnimating(boolean animating) {
        this.animating = animating;
    }
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        if (waitingScroll) {
            super.onScrollChanged(l, t, oldl, oldt);
            if (computeVerticalScrollOffset() == 0) {
                setEnabled(true);
                waitingScroll = false;
                setAnimating(false);
                setNumColumns(nextColumns);
            }
        } else if (!animating) {
            super.onScrollChanged(l, t, oldl, oldt);
        }
    }
    public int getAnimationDuration() {
        return animationDuration;
    }
    public void setAnimationDuration(int animationDuration) {
        this.animationDuration = animationDuration;
    }
    public interface GridViewAnimationListener {
        void onAnimationStart(Animator animator);
        void onAnimationEnd(Animator animator);
        void onAnimationCancel(Animator animator);
        void onAnimationRepeat(Animator animator);
    }
    public GridViewAnimationListener getAnimationListener() {
        return animationListener;
    }
    public void setAnimationListener(GridViewAnimationListener animationListener) {this.animationListener = animationListener;}
    public void removeAt(int... positions) {
        ArrayList<MyInteger> ints = new ArrayList<>();
        for (Integer pos : positions) {
            ints.add(new MyInteger(pos));
        }
        Collections.sort(ints);
        int lowest = 99999, highest = 0;
        for (MyInteger pos : ints) {
            lowest = lowest < pos.getValue() ? lowest : pos.getValue();
            highest = highest > pos.getValue() ? highest : pos.getValue();
        }

        if (lowest >= 0 && highest <= getChildCount()) {
            ViewsVO originalViews = getOriginalViews();
            for (MyInteger pos : ints) {
                getAdapter().removeAt(pos.getValue());
            }
            getAdapter().notifyDataSetChanged();
            animateChildViews(originalViews);
        }
    }
    @Override
    public void setAdapter(ListAdapter adapter) {
        if (adapter instanceof GridViewAnimatedAdapter) {
            super.setAdapter(adapter);
        } else {
            Log.e("GridViewAnimated", "Adapter needs to be instance of GridViewAnimatedAdapter");
            Toast.makeText(getContext(), "Adapter needs to be instance of GridViewAnimatedAdapter", Toast.LENGTH_SHORT).show();
        }
    }
    @Override
    public GridViewAnimatedAdapter getAdapter() {
        return (GridViewAnimatedAdapter) super.getAdapter();
    }
    @Override
    public void setNumColumns(int numColumns) {
        if (getAdapter() == null || !getAdapter().hasStableIds() || getChildCount() == 0) {
            super.setNumColumns(numColumns);
            setAnimating(false);
            return;
        } else if (animating) {
            return;
        }
        setAnimating(true);
        if (computeVerticalScrollOffset() > 0) {
            waitingScroll = true;
            setEnabled(false);
            smoothScrollToPosition(0);
            nextColumns = numColumns;
            return;
        }
        ViewsVO originalViews = getOriginalViews();
        super.setNumColumns(numColumns);
        getAdapter().notifyDataSetChanged();
        animateChildViews(originalViews);
    }
    private ViewsVO getOriginalViews() {
        ViewsVO originalViews = new ViewsVO();
        for (int i = 0; i < getChildCount(); i++) {
            originalViews.addView(getChildAt(i));
        }
        return originalViews;
    }
    private void animateChildViews(final ViewsVO originalViews) {
        final GridViewAnimated gridView = this;
        getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                gridView.getViewTreeObserver().removeOnPreDrawListener(this);
                ViewsVO newViews = new ViewsVO();
                if (Build.VERSION.SDK_INT >= 21) {
                    for (int i = 0, z = getChildCount() - 1; z >= 0; z--, i++) {
                        gridView.getChildAt(z).setTranslationZ(i);
                    }
                }
                boolean hasFirst = false;
                View firstView = null, lastView = null;
                float firstHeight = 0, lastHeight = 0;
                ViewsVO newViewsFirstTime = new ViewsVO();
                for (int i = 0; i < getChildCount(); i++) {
                    View view = getChildAt(i);
                    ViewVO nView = newViews.addView(view);
                    ViewVO oView = originalViews.getView(view.getId());
                    if (oView != null) {
                        view.setScaleX(getScaleX(oView, nView));
                        view.setScaleY(getScaleY(oView, nView));
                        view.setTranslationX(getTranslateX(oView, nView));
                        view.setTranslationY(getTranslateY(oView, nView));
                        if (!hasFirst) {
                            firstView = view;
                            firstHeight = oView.getHeight();
                            hasFirst = true;
                        }
                        lastView = view;
                        lastHeight = oView.getHeight();
                        animateView(view);
                    } else {
                        newViewsFirstTime.addView(nView);
                    }
                }
                for (int i = 0; i < newViewsFirstTime.size(); i++) {
                    try {
                        View view = newViewsFirstTime.getViews().get(i).getView();
                        view.getId();
                        view.setScaleX(view.getId() > firstView.getId() ? firstView.getScaleX() : lastView.getScaleX());
                        view.setScaleY(view.getId() > firstView.getId() ? firstView.getScaleY() : lastView.getScaleX());
                        view.setTranslationX(view.getId() > firstView.getId() ? firstView.getTranslationX() : lastView.getTranslationX());
                        view.setTranslationY(view.getId() > firstView.getId() ? 0 - firstHeight : lastView.getTranslationY() + lastHeight);
                        animateView(view);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                return false;
            }
        });
    }
    private void animateView(final View view) {
        ViewPropertyAnimator animator = view.animate().setDuration(animationDuration).translationX(0).translationY(0).scaleX(1).scaleY(1).setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {animationListener.onAnimationStart(animator);}
            @Override
            public void onAnimationEnd(Animator animator) {
                setAnimating(false);
                animationListener.onAnimationEnd(animator);
                ViewGroup.LayoutParams params = view.getLayoutParams();
                params.width = ViewGroup.LayoutParams.MATCH_PARENT;
                params.height = ViewGroup.LayoutParams.MATCH_PARENT;
                view.setLayoutParams(params);
            }
            @Override
            public void onAnimationCancel(Animator animator) {animationListener.onAnimationCancel(animator);}
            @Override
            public void onAnimationRepeat(Animator animator) {animationListener.onAnimationRepeat(animator);}
        });
        if (Build.VERSION.SDK_INT >= 21) {
            animator.translationZ(0);
        }
    }
    private float getTranslateX(ViewVO ov, ViewVO nv) {return ov.getPosX() - nv.getPosX() - ((ov.getWidth() < nv.getWidth() ? nv.getWidth() - ov.getWidth() : ov.getWidth() - nv.getWidth()) * (ov.getWidth() < nv.getWidth() ? 0.5f : -0.5f));}
    private float getTranslateY(ViewVO ov, ViewVO nv) {return ov.getPosY() - nv.getPosY() - ((ov.getHeight() < nv.getHeight() ? nv.getHeight() - ov.getHeight() : ov.getHeight() - nv.getHeight()) * (ov.getHeight() < nv.getHeight() ? 0.5f : -0.5f));}
    private float getScaleY(ViewVO ov, ViewVO nv) {
        return ov.getHeight() / nv.getHeight();
    }
    private float getScaleX(ViewVO ov, ViewVO nv) {
        return ov.getWidth() / nv.getWidth();
    }
    private class ViewsVO {
        private ArrayList<ViewVO> views;
        private int size() {
            return views.size();
        }
        private ViewsVO() {
            views = new ArrayList<>();
        }
        private ViewVO addView(View view) {
            ViewVO v = new ViewVO(view);
            addView(v);
            return v;
        }
        private void addView(ViewVO view) {
            views.add(view);
        }
        private ViewVO getView(long id) {
            for (ViewVO view : views) {
                if (view.getId() == id) {
                    return view;
                }
            }
            return null;
        }
        private ArrayList<ViewVO> getViews() {
            return views;
        }
    }
    private class ViewVO {
        private View view;
        private int id;
        private float posY;
        private float posX;
        private float width;
        private float height;
        private ViewVO(View view) {
            this.view = view;
            id = view.getId();
            posX = view.getLeft();
            posY = view.getTop();
            width = view.getWidth();
            height = view.getHeight();
        }
        public int getId() {
            return id;
        }
        public View getView() {
            return view;
        }
        private float getWidth() {
            return width;
        }
        private float getHeight() {
            return height;
        }
        private float getPosY() {
            return posY;
        }
        private float getPosX() {
            return posX;
        }
    }
    public static class GridViewAnimatedAdapter extends ArrayAdapter {
        private List objects;
        public GridViewAnimatedAdapter(Context context, int resource, List objects) {
            super(context, resource, objects);
            this.objects = objects;
        }
        public void removeAt(int pos) {objects.remove(pos);}
        @Override
        public boolean hasStableIds() {
            return true;
        }
        public View dealViewToAnimation(View view) {
            ViewGroup.LayoutParams params = view.getLayoutParams();
            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
            params.height = ViewGroup.LayoutParams.MATCH_PARENT;
            view.setLayoutParams(params);
            return view;
        }
    }
    private class MyInteger implements Comparable<MyInteger> {
        private int value;
        public MyInteger(int value) {
            this.value = value;
        }
        public int getValue() {
            return value;
        }
        public void setValue(int value) {
            this.value = value;
        }
        @Override
        public int compareTo(MyInteger another) {return value > another.getValue() ? -1 : (value == another.getValue() ? 0 : 1);}}
}

使用它非常简单, GridView的适配器需要扩展GridViewAnimatedAdapter和: getView():要为每个视图设置一个ID并在方法getView的末尾,需要完成使用方法dealViewToAnimation(View view)Ex:

@Override
public View getView(int position, View view, ViewGroup parent) {
    ...
    view.setId(images.getId());
    ...
    return dealViewToAnimation(view);
}

您还可以将侦听器设置为动画状态:

gridView.setAnimationListener(new GridViewAnimated.GridViewAnimationListener() {
    @Override
    public void onAnimationStart(Animator animator) {
        mListMenu.setVisible(false);
    }
    @Override
    public void onAnimationEnd(Animator animator) {
        mListMenu.setVisible(true);
        gridView.setAnimating(false);
    }
    @Override
    public void onAnimationCancel(Animator animator) {}

    @Override
    public void onAnimationRepeat(Animator animator) {
    }
});

使用此GridView,您可以设置列号的更改动画并动画删除它...

动画更改列号:

gridView.setNumColumns(5);

动画删除itens:

gridView.removeAt(2, 7, 4);
gridView.removeAt(2);

当多个,无关紧要的顺序时,方法将检查顺序并从最高到最低删除,考虑到最高id(添加到视图中的图像)是第一个视图... < / p>

但是尽管它没有GridViewAnimated中的缩放比例动画,但最好使用RecyclerView,GridLayoutManager和DefaultItemAnimator,因为它会更改列数并且不会滚动...

GridLayoutmanager gridLayoutManager = new GridLayoutManager(context, 2);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());

然后当你需要更改列时:

gridLayoutManager.requestSimpleAnimationsInNextLayout();        
gridLayoutManager.setSpanCount(newNumberOfColumns);