Let’s start with the renderings

Source github.com/woshiwzy/Ca…

Implementation principle:

Inherit LinearLayout 2. Rewrite onLayout, onMeasure method 3. Use ValueAnimator to implement animation 4. In the animation callback requestLayout implementation animation effect

Ideas:

1. Record the initial position, current position, and moving target position of each CardView object using the Bounds object

2. When clicking, calculate the corresponding view and the movement target position of the view that may produce associated movement, move from the current position to the target position, and then implement ValueAnimator animation with these two positions as animation parameters, and trigger onLayout in the animation callback to achieve the effect of animation.

Override the adView method to make sure that the newly added one is here and that all child views have an initial bounds position

   @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        super.addView(child, params);
        Bounds bounds = getBunds(getChildCount());
    }
Copy the code

Make sure the measurement property width of each child View fills the parent component


    boolean mesured = false;
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mesured == true) {// Only need to measure once
            return;
        }
        mesured = true;
        int childCount = getChildCount();
        int rootWidth = getWidth();
        int rootHeight = getHeight();
        if (childCount > 0) {
            View child0 = getChildAt(0);
            int modeWidth = MeasureSpec.getMode(child0.getMeasuredWidth());
            int sizeWidth = MeasureSpec.getSize(child0.getMeasuredWidth());

            int modeHeight = MeasureSpec.getMode(child0.getMeasuredHeight());
            int sizeHeight = MeasureSpec.getSize(child0.getMeasuredHeight());

            if (childCount > 0) {
                for (int i = 0; i < childCount; i++) {
                    View childView = getChildAt(i);
                    childView.measure(MeasureSpec.makeMeasureSpec(sizeWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(sizeHeight, MeasureSpec.EXACTLY));
                    int top = (int) (i * (sizeHeight * carEvPercnet)); getBunds(i).setTop(top); getBunds(i).setCurrentTop(top); getBunds(i).setLastCurrentTop(top); getBunds(i).setHeight(sizeHeight); }}}}Copy the code

Overwriting the onLayout method is the key, it is the main purpose of the animation trigger, the layout parameters are not written dead, but calculated (ValueAnimator calculated)

@Override
    protected void onLayout(boolean changed, int sl, int st, int sr, int sb) {
        int childCount = getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                View view = getChildAt(i);
                int mWidth = view.getMeasuredWidth();
                int mw = MeasureSpec.getSize(mWidth);
                int l = 0, r = l + mw; view.layout(l, getBunds(i).getCurrentTop(), r, getBunds(i).getCurrentTop() + getBunds(i).getHeight()); }}}Copy the code

The source code

Making: github.com/woshiwzy/Ca…