StackScrollState.java revision 6e3ecebcec1b82fd81f6d78b8deb5c4189b6026e
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.stack;
18
19import android.util.Log;
20import android.view.View;
21import android.view.ViewGroup;
22
23import java.util.HashMap;
24import java.util.Map;
25
26/**
27 * A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
28 * can be applied to a viewGroup.
29 */
30public class StackScrollState {
31
32    private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
33
34    private final ViewGroup mHostView;
35    private Map<View, ViewState> mStateMap;
36    private int mScrollY;
37
38    public int getScrollY() {
39        return mScrollY;
40    }
41
42    public void setScrollY(int scrollY) {
43        this.mScrollY = scrollY;
44    }
45
46    public StackScrollState(ViewGroup hostView) {
47        mHostView = hostView;
48        mStateMap = new HashMap<View, ViewState>();
49    }
50
51    public ViewGroup getHostView() {
52        return mHostView;
53    }
54
55    public void resetViewStates() {
56        int numChildren = mHostView.getChildCount();
57        for (int i = 0; i < numChildren; i++) {
58            View child = mHostView.getChildAt(i);
59            ViewState viewState = mStateMap.get(child);
60            if (viewState == null) {
61                viewState = new ViewState();
62                mStateMap.put(child, viewState);
63            }
64            // initialize with the default values of the view
65            viewState.height = child.getHeight();
66            viewState.alpha = 1.0f;
67        }
68    }
69
70
71    public ViewState getViewStateForView(View requestedView) {
72        return mStateMap.get(requestedView);
73    }
74
75    /**
76     * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
77     * The properties are only applied if they effectively changed.
78     */
79    public void apply() {
80        int numChildren = mHostView.getChildCount();
81        for (int i = 0; i < numChildren; i++) {
82            View child = mHostView.getChildAt(i);
83            ViewState state = mStateMap.get(child);
84            if (state != null) {
85                float alpha = child.getAlpha();
86                float yTranslation = child.getTranslationY();
87                float zTranslation = child.getTranslationZ();
88                int height = child.getHeight();
89                float newAlpha = state.alpha;
90                float newYTranslation = state.yTranslation;
91                float newZTranslation = state.zTranslation;
92                int newHeight = state.height;
93                boolean becomesInvisible = newAlpha == 0.0f;
94                if (alpha != newAlpha) {
95                    // apply layer type
96                    boolean becomesFullyVisible = newAlpha == 1.0f;
97                    boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible;
98                    int layerType = child.getLayerType();
99                    int newLayerType = newLayerTypeIsHardware
100                            ? View.LAYER_TYPE_HARDWARE
101                            : View.LAYER_TYPE_NONE;
102                    if (layerType != newLayerType) {
103                        child.setLayerType(newLayerType, null);
104                    }
105
106                    // apply alpha
107                    if (!becomesInvisible) {
108                        child.setAlpha(newAlpha);
109                    }
110                }
111
112                // apply visibility
113                int oldVisibility = child.getVisibility();
114                int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
115                if (newVisibility != oldVisibility) {
116                    child.setVisibility(newVisibility);
117                }
118
119                // apply yTranslation
120                if (yTranslation != newYTranslation) {
121                    child.setTranslationY(newYTranslation);
122                }
123
124                // apply zTranslation
125                if (zTranslation != newZTranslation) {
126                    child.setTranslationZ(newZTranslation);
127                }
128
129                // apply height
130                if (height != newHeight) {
131                    applyNewHeight(child, newHeight);
132                }
133            } else {
134                Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
135                        "to the hostView");
136            }
137        }
138    }
139
140    private void applyNewHeight(View child, int newHeight) {
141        ViewGroup.LayoutParams lp = child.getLayoutParams();
142        lp.height = newHeight;
143        child.setLayoutParams(lp);
144    }
145
146
147    public static class ViewState {
148
149        // These are flags such that we can create masks for filtering.
150
151        public static final int LOCATION_UNKNOWN = 0x00;
152        public static final int LOCATION_FIRST_CARD = 0x01;
153        public static final int LOCATION_TOP_STACK_HIDDEN = 0x02;
154        public static final int LOCATION_TOP_STACK_PEEKING = 0x04;
155        public static final int LOCATION_MAIN_AREA = 0x08;
156        public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
157        public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
158
159        float alpha;
160        float yTranslation;
161        float zTranslation;
162        int height;
163
164        /**
165         * The location this view is currently rendered at.
166         *
167         * <p>See <code>LOCATION_</code> flags.</p>
168         */
169        int location;
170    }
171}
172