blob: 67a1735606c920e99edf053128dc2a1a2feb2724 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.statusbar.stack;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import java.util.HashMap;
import java.util.Map;
/**
* A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
* can be applied to a viewGroup.
*/
public class StackScrollState {
private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
private final ViewGroup mHostView;
private Map<View, ViewState> mStateMap;
private int mScrollY;
public int getScrollY() {
return mScrollY;
}
public void setScrollY(int scrollY) {
this.mScrollY = scrollY;
}
public StackScrollState(ViewGroup hostView) {
mHostView = hostView;
mStateMap = new HashMap<View, ViewState>();
}
public ViewGroup getHostView() {
return mHostView;
}
public void resetViewStates() {
int numChildren = mHostView.getChildCount();
for (int i = 0; i < numChildren; i++) {
View child = mHostView.getChildAt(i);
ViewState viewState = mStateMap.get(child);
if (viewState == null) {
viewState = new ViewState();
mStateMap.put(child, viewState);
}
// initialize with the default values of the view
viewState.height = child.getHeight();
viewState.alpha = 1.0f;
}
}
public ViewState getViewStateForView(View requestedView) {
return mStateMap.get(requestedView);
}
public void removeViewStateForView(View child) {
mStateMap.remove(child);
}
/**
* Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
* The properties are only applied if they effectively changed.
*/
public void apply() {
int numChildren = mHostView.getChildCount();
for (int i = 0; i < numChildren; i++) {
View child = mHostView.getChildAt(i);
ViewState state = mStateMap.get(child);
if (state != null) {
float alpha = child.getAlpha();
float yTranslation = child.getTranslationY();
float zTranslation = child.getTranslationZ();
int height = child.getHeight();
float newAlpha = state.alpha;
float newYTranslation = state.yTranslation;
float newZTranslation = state.zTranslation;
int newHeight = state.height;
boolean becomesInvisible = newAlpha == 0.0f;
if (alpha != newAlpha) {
// apply layer type
boolean becomesFullyVisible = newAlpha == 1.0f;
boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible;
int layerType = child.getLayerType();
int newLayerType = newLayerTypeIsHardware
? View.LAYER_TYPE_HARDWARE
: View.LAYER_TYPE_NONE;
if (layerType != newLayerType) {
child.setLayerType(newLayerType, null);
}
// apply alpha
if (!becomesInvisible) {
child.setAlpha(newAlpha);
}
}
// apply visibility
int oldVisibility = child.getVisibility();
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
if (newVisibility != oldVisibility) {
child.setVisibility(newVisibility);
}
// apply yTranslation
if (yTranslation != newYTranslation) {
child.setTranslationY(newYTranslation);
}
// apply zTranslation
if (zTranslation != newZTranslation) {
child.setTranslationZ(newZTranslation);
}
// apply height
if (height != newHeight) {
applyNewHeight(child, newHeight);
}
} else {
Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
"to the hostView");
}
}
}
private void applyNewHeight(View child, int newHeight) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
lp.height = newHeight;
child.setLayoutParams(lp);
}
public static class ViewState {
// These are flags such that we can create masks for filtering.
public static final int LOCATION_UNKNOWN = 0x00;
public static final int LOCATION_FIRST_CARD = 0x01;
public static final int LOCATION_TOP_STACK_HIDDEN = 0x02;
public static final int LOCATION_TOP_STACK_PEEKING = 0x04;
public static final int LOCATION_MAIN_AREA = 0x08;
public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
float alpha;
float yTranslation;
float zTranslation;
int height;
/**
* The location this view is currently rendered at.
*
* <p>See <code>LOCATION_</code> flags.</p>
*/
int location;
}
}