1816aa142023c75cf427401c21831193998bdf233Alan Viverette/*
2816aa142023c75cf427401c21831193998bdf233Alan Viverette * Copyright (C) 2015 The Android Open Source Project
3816aa142023c75cf427401c21831193998bdf233Alan Viverette *
4816aa142023c75cf427401c21831193998bdf233Alan Viverette * Licensed under the Apache License, Version 2.0 (the "License");
5816aa142023c75cf427401c21831193998bdf233Alan Viverette * you may not use this file except in compliance with the License.
6816aa142023c75cf427401c21831193998bdf233Alan Viverette * You may obtain a copy of the License at
7816aa142023c75cf427401c21831193998bdf233Alan Viverette *
8816aa142023c75cf427401c21831193998bdf233Alan Viverette *      http://www.apache.org/licenses/LICENSE-2.0
9816aa142023c75cf427401c21831193998bdf233Alan Viverette *
10816aa142023c75cf427401c21831193998bdf233Alan Viverette * Unless required by applicable law or agreed to in writing, software
11816aa142023c75cf427401c21831193998bdf233Alan Viverette * distributed under the License is distributed on an "AS IS" BASIS,
12816aa142023c75cf427401c21831193998bdf233Alan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13816aa142023c75cf427401c21831193998bdf233Alan Viverette * See the License for the specific language governing permissions and
14816aa142023c75cf427401c21831193998bdf233Alan Viverette * limitations under the License.
15816aa142023c75cf427401c21831193998bdf233Alan Viverette */
16816aa142023c75cf427401c21831193998bdf233Alan Viverette
17816aa142023c75cf427401c21831193998bdf233Alan Viverettepackage com.android.internal.widget;
18816aa142023c75cf427401c21831193998bdf233Alan Viverette
19816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.content.Context;
20816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.graphics.drawable.Drawable;
21816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.util.AttributeSet;
22816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.view.View;
23816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.widget.ViewAnimator;
24816aa142023c75cf427401c21831193998bdf233Alan Viverette
25816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport java.util.ArrayList;
26816aa142023c75cf427401c21831193998bdf233Alan Viverette
27816aa142023c75cf427401c21831193998bdf233Alan Viverette/**
28816aa142023c75cf427401c21831193998bdf233Alan Viverette * ViewAnimator with a more reasonable handling of MATCH_PARENT.
29816aa142023c75cf427401c21831193998bdf233Alan Viverette */
30816aa142023c75cf427401c21831193998bdf233Alan Viverettepublic class DialogViewAnimator extends ViewAnimator {
31816aa142023c75cf427401c21831193998bdf233Alan Viverette    private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
32816aa142023c75cf427401c21831193998bdf233Alan Viverette
33816aa142023c75cf427401c21831193998bdf233Alan Viverette    public DialogViewAnimator(Context context) {
34816aa142023c75cf427401c21831193998bdf233Alan Viverette        super(context);
35816aa142023c75cf427401c21831193998bdf233Alan Viverette    }
36816aa142023c75cf427401c21831193998bdf233Alan Viverette
37816aa142023c75cf427401c21831193998bdf233Alan Viverette    public DialogViewAnimator(Context context, AttributeSet attrs) {
38816aa142023c75cf427401c21831193998bdf233Alan Viverette        super(context, attrs);
39816aa142023c75cf427401c21831193998bdf233Alan Viverette    }
40816aa142023c75cf427401c21831193998bdf233Alan Viverette
41816aa142023c75cf427401c21831193998bdf233Alan Viverette    @Override
42816aa142023c75cf427401c21831193998bdf233Alan Viverette    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
43816aa142023c75cf427401c21831193998bdf233Alan Viverette        final boolean measureMatchParentChildren =
44816aa142023c75cf427401c21831193998bdf233Alan Viverette                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
45816aa142023c75cf427401c21831193998bdf233Alan Viverette                        MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
46816aa142023c75cf427401c21831193998bdf233Alan Viverette
47816aa142023c75cf427401c21831193998bdf233Alan Viverette        int maxHeight = 0;
48816aa142023c75cf427401c21831193998bdf233Alan Viverette        int maxWidth = 0;
49816aa142023c75cf427401c21831193998bdf233Alan Viverette        int childState = 0;
50816aa142023c75cf427401c21831193998bdf233Alan Viverette
51816aa142023c75cf427401c21831193998bdf233Alan Viverette        // First measure all children and record maximum dimensions where the
52816aa142023c75cf427401c21831193998bdf233Alan Viverette        // spec isn't MATCH_PARENT.
53816aa142023c75cf427401c21831193998bdf233Alan Viverette        final int count = getChildCount();
54816aa142023c75cf427401c21831193998bdf233Alan Viverette        for (int i = 0; i < count; i++) {
55816aa142023c75cf427401c21831193998bdf233Alan Viverette            final View child = getChildAt(i);
56816aa142023c75cf427401c21831193998bdf233Alan Viverette            if (getMeasureAllChildren() || child.getVisibility() != GONE) {
57816aa142023c75cf427401c21831193998bdf233Alan Viverette                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
58816aa142023c75cf427401c21831193998bdf233Alan Viverette                final boolean matchWidth = lp.width == LayoutParams.MATCH_PARENT;
59816aa142023c75cf427401c21831193998bdf233Alan Viverette                final boolean matchHeight = lp.height == LayoutParams.MATCH_PARENT;
60816aa142023c75cf427401c21831193998bdf233Alan Viverette                if (measureMatchParentChildren && (matchWidth || matchHeight)) {
61816aa142023c75cf427401c21831193998bdf233Alan Viverette                    mMatchParentChildren.add(child);
62816aa142023c75cf427401c21831193998bdf233Alan Viverette                }
63816aa142023c75cf427401c21831193998bdf233Alan Viverette
64816aa142023c75cf427401c21831193998bdf233Alan Viverette                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
65816aa142023c75cf427401c21831193998bdf233Alan Viverette
66816aa142023c75cf427401c21831193998bdf233Alan Viverette                // Measured dimensions only count against the maximum
67816aa142023c75cf427401c21831193998bdf233Alan Viverette                // dimensions if they're not MATCH_PARENT.
68816aa142023c75cf427401c21831193998bdf233Alan Viverette                int state = 0;
69816aa142023c75cf427401c21831193998bdf233Alan Viverette
70816aa142023c75cf427401c21831193998bdf233Alan Viverette                if (measureMatchParentChildren && !matchWidth) {
71816aa142023c75cf427401c21831193998bdf233Alan Viverette                    maxWidth = Math.max(maxWidth, child.getMeasuredWidth()
72816aa142023c75cf427401c21831193998bdf233Alan Viverette                            + lp.leftMargin + lp.rightMargin);
73816aa142023c75cf427401c21831193998bdf233Alan Viverette                    state |= child.getMeasuredWidthAndState() & MEASURED_STATE_MASK;
74816aa142023c75cf427401c21831193998bdf233Alan Viverette                }
75816aa142023c75cf427401c21831193998bdf233Alan Viverette
76816aa142023c75cf427401c21831193998bdf233Alan Viverette                if (measureMatchParentChildren && !matchHeight) {
77816aa142023c75cf427401c21831193998bdf233Alan Viverette                    maxHeight = Math.max(maxHeight, child.getMeasuredHeight()
78816aa142023c75cf427401c21831193998bdf233Alan Viverette                            + lp.topMargin + lp.bottomMargin);
79816aa142023c75cf427401c21831193998bdf233Alan Viverette                    state |= (child.getMeasuredHeightAndState() >> MEASURED_HEIGHT_STATE_SHIFT)
80816aa142023c75cf427401c21831193998bdf233Alan Viverette                            & (MEASURED_STATE_MASK >> MEASURED_HEIGHT_STATE_SHIFT);
81816aa142023c75cf427401c21831193998bdf233Alan Viverette                }
82816aa142023c75cf427401c21831193998bdf233Alan Viverette
83816aa142023c75cf427401c21831193998bdf233Alan Viverette                childState = combineMeasuredStates(childState, state);
84816aa142023c75cf427401c21831193998bdf233Alan Viverette            }
85816aa142023c75cf427401c21831193998bdf233Alan Viverette        }
86816aa142023c75cf427401c21831193998bdf233Alan Viverette
87816aa142023c75cf427401c21831193998bdf233Alan Viverette        // Account for padding too.
88816aa142023c75cf427401c21831193998bdf233Alan Viverette        maxWidth += getPaddingLeft() + getPaddingRight();
89816aa142023c75cf427401c21831193998bdf233Alan Viverette        maxHeight += getPaddingTop() + getPaddingBottom();
90816aa142023c75cf427401c21831193998bdf233Alan Viverette
91816aa142023c75cf427401c21831193998bdf233Alan Viverette        // Check against our minimum height and width.
92816aa142023c75cf427401c21831193998bdf233Alan Viverette        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
93816aa142023c75cf427401c21831193998bdf233Alan Viverette        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
94816aa142023c75cf427401c21831193998bdf233Alan Viverette
95816aa142023c75cf427401c21831193998bdf233Alan Viverette        // Check against our foreground's minimum height and width.
96816aa142023c75cf427401c21831193998bdf233Alan Viverette        final Drawable drawable = getForeground();
97816aa142023c75cf427401c21831193998bdf233Alan Viverette        if (drawable != null) {
98816aa142023c75cf427401c21831193998bdf233Alan Viverette            maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
99816aa142023c75cf427401c21831193998bdf233Alan Viverette            maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
100816aa142023c75cf427401c21831193998bdf233Alan Viverette        }
101816aa142023c75cf427401c21831193998bdf233Alan Viverette
102816aa142023c75cf427401c21831193998bdf233Alan Viverette        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
103816aa142023c75cf427401c21831193998bdf233Alan Viverette                resolveSizeAndState(maxHeight, heightMeasureSpec,
104816aa142023c75cf427401c21831193998bdf233Alan Viverette                        childState << MEASURED_HEIGHT_STATE_SHIFT));
105816aa142023c75cf427401c21831193998bdf233Alan Viverette
106816aa142023c75cf427401c21831193998bdf233Alan Viverette        // Measure remaining MATCH_PARENT children again using real dimensions.
107816aa142023c75cf427401c21831193998bdf233Alan Viverette        final int matchCount = mMatchParentChildren.size();
108816aa142023c75cf427401c21831193998bdf233Alan Viverette        for (int i = 0; i < matchCount; i++) {
109816aa142023c75cf427401c21831193998bdf233Alan Viverette            final View child = mMatchParentChildren.get(i);
110816aa142023c75cf427401c21831193998bdf233Alan Viverette            final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
111816aa142023c75cf427401c21831193998bdf233Alan Viverette
112816aa142023c75cf427401c21831193998bdf233Alan Viverette            final int childWidthMeasureSpec;
113816aa142023c75cf427401c21831193998bdf233Alan Viverette            if (lp.width == LayoutParams.MATCH_PARENT) {
114816aa142023c75cf427401c21831193998bdf233Alan Viverette                childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
115816aa142023c75cf427401c21831193998bdf233Alan Viverette                        getMeasuredWidth() - getPaddingLeft() - getPaddingRight()
116816aa142023c75cf427401c21831193998bdf233Alan Viverette                                - lp.leftMargin - lp.rightMargin,
117816aa142023c75cf427401c21831193998bdf233Alan Viverette                        MeasureSpec.EXACTLY);
118816aa142023c75cf427401c21831193998bdf233Alan Viverette            } else {
119816aa142023c75cf427401c21831193998bdf233Alan Viverette                childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
120816aa142023c75cf427401c21831193998bdf233Alan Viverette                        getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin,
121816aa142023c75cf427401c21831193998bdf233Alan Viverette                        lp.width);
122816aa142023c75cf427401c21831193998bdf233Alan Viverette            }
123816aa142023c75cf427401c21831193998bdf233Alan Viverette
124816aa142023c75cf427401c21831193998bdf233Alan Viverette            final int childHeightMeasureSpec;
125816aa142023c75cf427401c21831193998bdf233Alan Viverette            if (lp.height == LayoutParams.MATCH_PARENT) {
126816aa142023c75cf427401c21831193998bdf233Alan Viverette                childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
127816aa142023c75cf427401c21831193998bdf233Alan Viverette                        getMeasuredHeight() - getPaddingTop() - getPaddingBottom()
128816aa142023c75cf427401c21831193998bdf233Alan Viverette                                - lp.topMargin - lp.bottomMargin,
129816aa142023c75cf427401c21831193998bdf233Alan Viverette                        MeasureSpec.EXACTLY);
130816aa142023c75cf427401c21831193998bdf233Alan Viverette            } else {
131816aa142023c75cf427401c21831193998bdf233Alan Viverette                childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
132816aa142023c75cf427401c21831193998bdf233Alan Viverette                        getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin,
133816aa142023c75cf427401c21831193998bdf233Alan Viverette                        lp.height);
134816aa142023c75cf427401c21831193998bdf233Alan Viverette            }
135816aa142023c75cf427401c21831193998bdf233Alan Viverette
136816aa142023c75cf427401c21831193998bdf233Alan Viverette            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
137816aa142023c75cf427401c21831193998bdf233Alan Viverette        }
138816aa142023c75cf427401c21831193998bdf233Alan Viverette
139816aa142023c75cf427401c21831193998bdf233Alan Viverette        mMatchParentChildren.clear();
140816aa142023c75cf427401c21831193998bdf233Alan Viverette    }
141816aa142023c75cf427401c21831193998bdf233Alan Viverette}
142