lmw
2023-04-03 16ea883d3c03fd8b910f9282aa1bc08378d40d54
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package com.beloo.widget.chipslayoutmanager.layouter;
 
 
import androidx.annotation.CallSuper;
import androidx.recyclerview.widget.RecyclerView;
 
public class MeasureSupporter extends RecyclerView.AdapterDataObserver implements IMeasureSupporter {
 
    private RecyclerView.LayoutManager lm;
    private boolean isAfterRemoving;
 
    private int measuredWidth;
    private int measuredHeight;
 
    private boolean isRegistered;
 
    /**
     * width of RecyclerView before removing item
     */
    private Integer beforeRemovingWidth = null;
 
    /**
     * width which we receive after {@link RecyclerView.LayoutManager#onLayoutChildren} method finished.
     * Contains correct width after auto-measuring
     */
    private int autoMeasureWidth = 0;
 
    /**
     * height of RecyclerView before removing item
     */
    private Integer beforeRemovingHeight = null;
 
    /**
     * height which we receive after {@link RecyclerView.LayoutManager#onLayoutChildren} method finished.
     * Contains correct height after auto-measuring
     */
    private int autoMeasureHeight = 0;
 
    public MeasureSupporter(RecyclerView.LayoutManager lm) {
        this.lm = lm;
    }
 
    @Override
    public void onSizeChanged() {
        autoMeasureWidth = lm.getWidth();
        autoMeasureHeight = lm.getHeight();
    }
 
    boolean isAfterRemoving() {
        return isAfterRemoving;
    }
 
    @Override
    public int getMeasuredWidth() {
        return measuredWidth;
    }
 
    private void setMeasuredWidth(int measuredWidth) {
        this.measuredWidth = measuredWidth;
    }
 
    @Override
    public int getMeasuredHeight() {
        return measuredHeight;
    }
 
    @Override
    public boolean isRegistered() {
        return isRegistered;
    }
 
    @Override
    public void setRegistered(boolean isRegistered) {
        this.isRegistered = isRegistered;
    }
 
    private void setMeasuredHeight(int measuredHeight) {
        this.measuredHeight = measuredHeight;
    }
 
    @Override
    @CallSuper
    public void measure(int autoWidth, int autoHeight) {
        if (isAfterRemoving()) {
            setMeasuredWidth(Math.max(autoWidth, beforeRemovingWidth));
            setMeasuredHeight(Math.max(autoHeight, beforeRemovingHeight));
        } else {
            setMeasuredWidth(autoWidth);
            setMeasuredHeight(autoHeight);
        }
    }
 
    @Override
    public void onItemsRemoved(final RecyclerView recyclerView){
        //subscribe to next animations tick
        lm.postOnAnimation(new Runnable() {
 
            private void onFinished() {
                //when removing animation finished return auto-measuring back
                isAfterRemoving = false;
                // and process measure again
                lm.requestLayout();
            }
 
            @Override
            public void run() {
                if (recyclerView.getItemAnimator() != null) {
                    //listen removing animation
                    recyclerView.getItemAnimator().isRunning(new RecyclerView.ItemAnimator.ItemAnimatorFinishedListener() {
                        @Override
                        public void onAnimationsFinished() {
                            onFinished();
                        }
                    });
                } else {
                    onFinished();
                }
            }
        });
    }
 
    @Override
    @CallSuper
    public void onItemRangeRemoved(int positionStart, int itemCount) {
        super.onItemRangeRemoved(positionStart, itemCount);
        /** we detected removing event, so should process measuring manually
         * @see <a href="http://stackoverflow.com/questions/40242011/custom-recyclerviews-layoutmanager-automeasuring-after-animation-finished-on-i">Stack Overflow issue</a>
         */
        isAfterRemoving = true;
 
        beforeRemovingWidth = autoMeasureWidth;
        beforeRemovingHeight = autoMeasureHeight;
    }
}