NavigationBarView.java revision e3646dd8d96fb9756c8a7a4757ad5277e3801aed
1/*
2 * Copyright (C) 2008 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.phone;
18
19import android.animation.Animator;
20import android.animation.AnimatorSet;
21import android.animation.AnimatorListenerAdapter;
22import android.animation.ObjectAnimator;
23import android.content.Context;
24import android.content.res.Resources;
25import android.os.ServiceManager;
26import android.util.AttributeSet;
27import android.util.Slog;
28import android.view.animation.AccelerateInterpolator;
29import android.view.Display;
30import android.view.KeyEvent;
31import android.view.MotionEvent;
32import android.view.View;
33import android.view.ViewGroup;
34import android.view.Surface;
35import android.view.WindowManager;
36import android.widget.LinearLayout;
37import android.content.res.Configuration;
38
39import com.android.internal.statusbar.IStatusBarService;
40
41import com.android.systemui.R;
42
43public class NavigationBarView extends LinearLayout {
44    final static boolean DEBUG = false;
45    final static String TAG = "NavigationBarView";
46
47    final static boolean DEBUG_DEADZONE = false;
48
49    final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
50
51    final static boolean ANIMATE_HIDE_TRANSITION = false; // turned off because it introduces unsightly delay when videos goes to full screen
52
53    protected IStatusBarService mBarService;
54    final Display mDisplay;
55    View mCurrentView = null;
56    View[] mRotatedViews = new View[4];
57    AnimatorSet mLastAnimator = null;
58
59    int mBarSize;
60    boolean mVertical;
61
62    boolean mHidden, mLowProfile;
63    boolean mEnabled = true;
64
65    public View getRecentsButton() {
66        return mCurrentView.findViewById(R.id.recent_apps);
67    }
68
69    public View getMenuButton() {
70        return mCurrentView.findViewById(R.id.menu);
71    }
72
73    public View getBackButton() {
74        return mCurrentView.findViewById(R.id.back);
75    }
76
77    public View getHomeButton() {
78        return mCurrentView.findViewById(R.id.home);
79    }
80
81    public NavigationBarView(Context context, AttributeSet attrs) {
82        super(context, attrs);
83
84        mHidden = false;
85
86        mDisplay = ((WindowManager)context.getSystemService(
87                Context.WINDOW_SERVICE)).getDefaultDisplay();
88        mBarService = IStatusBarService.Stub.asInterface(
89                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
90
91        final Resources res = mContext.getResources();
92        mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
93        mVertical = false;
94    }
95
96    public void setEnabled(final boolean enable) {
97        mEnabled = enable;
98        mCurrentView.setVisibility(enable ? View.VISIBLE : View.INVISIBLE);
99    }
100
101    View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
102        @Override
103        public boolean onTouch(View v, MotionEvent ev) {
104            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
105                // even though setting the systemUI visibility below will turn these views
106                // on, we need them to come up faster so that they can catch this motion
107                // event
108                setLowProfile(false, false);
109
110                try {
111                    mBarService.setSystemUiVisibility(0);
112                } catch (android.os.RemoteException ex) {
113                }
114            }
115            return false;
116        }
117    };
118
119    public void setLowProfile(final boolean lightsOut) {
120        setLowProfile(lightsOut, true);
121    }
122
123    public void setLowProfile(final boolean lightsOut, final boolean animate) {
124        if (lightsOut == mLowProfile) return;
125
126        mLowProfile = lightsOut;
127
128        if (DEBUG) Slog.d(TAG, "setting lights " + (lightsOut?"out":"on"));
129
130        final View navButtons = mCurrentView.findViewById(R.id.nav_buttons);
131        final View lowLights = mCurrentView.findViewById(R.id.lights_out);
132
133        if (!animate) {
134            lowLights.setVisibility(View.GONE);
135            navButtons.setAlpha(1f);
136        } else {
137            navButtons.animate()
138                .alpha(lightsOut ? 0f : 1f)
139                .setDuration(lightsOut ? 600 : 200)
140                .start();
141
142            lowLights.setOnTouchListener(mLightsOutListener);
143            lowLights.setAlpha(0f);
144            lowLights.setVisibility(View.VISIBLE);
145            lowLights.animate()
146                .alpha(lightsOut ? 1f : 0f)
147                .setStartDelay(lightsOut ? 500 : 0)
148                .setDuration(lightsOut ? 1000 : 300)
149                .setInterpolator(new AccelerateInterpolator(2.0f))
150                .setListener(lightsOut ? null : new AnimatorListenerAdapter() {
151                    @Override
152                    public void onAnimationEnd(Animator _a) {
153                        lowLights.setVisibility(View.GONE);
154                    }
155                })
156                .start();
157        }
158    }
159
160    public void setHidden(final boolean hide) {
161        if (hide == mHidden) return;
162
163        mHidden = hide;
164        Slog.d(TAG,
165            (hide ? "HIDING" : "SHOWING") + " navigation bar");
166
167        // bring up the lights no matter what
168        setLowProfile(false);
169
170        if (!ANIMATE_HIDE_TRANSITION) {
171            setVisibility(hide ? View.GONE : View.VISIBLE);
172            return;
173        }
174
175        float oldAlpha = mCurrentView.getAlpha();
176        if (DEBUG) {
177            Slog.d(TAG, "animating alpha: " + oldAlpha + " -> "
178                + (!hide ? 1f : 0f));
179        }
180
181        if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
182
183        if (!hide) {
184            setVisibility(View.VISIBLE);
185        }
186
187        // play us off, animatorset
188        mLastAnimator = new AnimatorSet();
189        mLastAnimator.playTogether(
190                ObjectAnimator.ofFloat(mCurrentView, "alpha", hide ? 0f : 1f),
191                ObjectAnimator.ofFloat(mCurrentView,
192                                       mVertical ? "translationX" : "translationY",
193                                       hide ? mBarSize : 0)
194        );
195        mLastAnimator.setDuration(!hide ? 250 : 1000);
196        mLastAnimator.addListener(new AnimatorListenerAdapter() {
197            @Override
198            public void onAnimationEnd(Animator _a) {
199                mLastAnimator = null;
200                if (hide) {
201                    setVisibility(View.GONE);
202                }
203            }
204        });
205        mLastAnimator.start();
206    }
207
208    public void onFinishInflate() {
209        mRotatedViews[Surface.ROTATION_0] =
210        mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
211
212        mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
213
214        mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
215                                                ? findViewById(R.id.rot90)
216                                                : findViewById(R.id.rot270);
217
218        for (View v : mRotatedViews) {
219            // this helps avoid drawing artifacts with glowing navigation keys
220            ViewGroup group = (ViewGroup) v.findViewById(R.id.nav_buttons);
221            group.setMotionEventSplittingEnabled(false);
222        }
223        mCurrentView = mRotatedViews[Surface.ROTATION_0];
224    }
225
226    @Override
227    public boolean onTouchEvent(MotionEvent ev) {
228        try {
229            mBarService.setSystemUiVisibility(0);
230        } catch (android.os.RemoteException ex) {
231        }
232        return false; // pass it on
233    }
234
235    public void reorient() {
236        final int rot = mDisplay.getRotation();
237        for (int i=0; i<4; i++) {
238            mRotatedViews[i].setVisibility(View.GONE);
239        }
240        mCurrentView = mRotatedViews[rot];
241        mCurrentView.setVisibility(View.VISIBLE);
242        mVertical = (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270);
243
244        if (DEBUG_DEADZONE) {
245            mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
246        }
247
248        if (DEBUG) {
249            Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
250        }
251    }
252}
253