1 /*
2 * Copyright (C) 2012 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 package com.example.android.advancedimmersivemode;
17 
18 import android.os.Bundle;
19 import android.support.v4.app.Fragment;
20 import android.view.LayoutInflater;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.Button;
24 import android.widget.CheckBox;
25 
26 import com.example.android.common.logger.Log;
27 
28 /**
29  * Demonstrates how to update the app's UI by toggling immersive mode.
30  * Checkboxes are also made available for toggling other UI flags which can
31  * alter the behavior of immersive mode.
32  */
33 public class AdvancedImmersiveModeFragment extends Fragment {
34 
35     public static final String TAG = "AdvancedImmersiveModeFragment";
36     public CheckBox mHideNavCheckbox;
37     public CheckBox mHideStatusBarCheckBox;
38     public CheckBox mImmersiveModeCheckBox;
39     public CheckBox mImmersiveModeStickyCheckBox;
40     public CheckBox mLowProfileCheckBox;
41 
42 
43     @Override
onCreate(Bundle savedInstanceState)44     public void onCreate(Bundle savedInstanceState) {
45         super.onCreate(savedInstanceState);
46         setHasOptionsMenu(true);
47     }
48 
49     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state)50     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
51         final View flagsView = inflater.inflate(R.layout.fragment_flags, container, false);
52         mLowProfileCheckBox = (CheckBox) flagsView.findViewById(R.id.flag_enable_lowprof);
53         mHideNavCheckbox = (CheckBox) flagsView.findViewById(R.id.flag_hide_navbar);
54         mHideStatusBarCheckBox = (CheckBox) flagsView.findViewById(R.id.flag_hide_statbar);
55         mImmersiveModeCheckBox = (CheckBox) flagsView.findViewById(R.id.flag_enable_immersive);
56         mImmersiveModeStickyCheckBox =
57                 (CheckBox) flagsView.findViewById(R.id.flag_enable_immersive_sticky);
58 
59         Button toggleFlagsButton = (Button) flagsView.findViewById(R.id.btn_changeFlags);
60         toggleFlagsButton.setOnClickListener(new View.OnClickListener() {
61             @Override
62             public void onClick(View view) {
63                 toggleUiFlags();
64             }
65         });
66 
67         Button presetsImmersiveModeButton = (Button) flagsView.findViewById(R.id.btn_immersive);
68         presetsImmersiveModeButton.setOnClickListener(new View.OnClickListener() {
69             @Override
70             public void onClick(View view) {
71 
72                 // BEGIN_INCLUDE(immersive_presets)
73                 // For immersive mode, the FULLSCREEN, HIDE_HAVIGATION and IMMERSIVE
74                 // flags should be set (you can use IMMERSIVE_STICKY instead of IMMERSIVE
75                 // as appropriate for your app).  The LOW_PROFILE flag should be cleared.
76 
77                 // Immersive mode is primarily for situations where the user will be
78                 // interacting with the screen, like games or reading books.
79                 int uiOptions = flagsView.getSystemUiVisibility();
80                 uiOptions &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
81                 uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
82                 uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
83                 uiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE;
84                 uiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
85                 flagsView.setSystemUiVisibility(uiOptions);
86                 // END_INCLUDE(immersive_presets)
87 
88                 dumpFlagStateToLog(uiOptions);
89 
90                 // The below code just updates the checkboxes to reflect which flags have been set.
91                 mLowProfileCheckBox.setChecked(false);
92                 mHideNavCheckbox.setChecked(true);
93                 mHideStatusBarCheckBox.setChecked(true);
94                 mImmersiveModeCheckBox.setChecked(true);
95                 mImmersiveModeStickyCheckBox.setChecked(false);
96             }
97         });
98 
99 
100         Button presetsLeanbackModeButton = (Button) flagsView.findViewById(R.id.btn_leanback);
101         presetsLeanbackModeButton.setOnClickListener(new View.OnClickListener() {
102             @Override
103             public void onClick(View view) {
104                 // BEGIN_INCLUDE(leanback_presets)
105                 // For leanback mode, only the HIDE_NAVE and HIDE_STATUSBAR flags
106                 // should be checked.  In this case IMMERSIVE should *not* be set,
107                 // since this mode is left as soon as the user touches the screen.
108                 int uiOptions = flagsView.getSystemUiVisibility();
109                 uiOptions &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
110                 uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
111                 uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
112                 uiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE;
113                 uiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
114                 flagsView.setSystemUiVisibility(uiOptions);
115                 // END_INCLUDE(leanback_presets)
116 
117                 dumpFlagStateToLog(uiOptions);
118 
119                 // The below code just updates the checkboxes to reflect which flags have been set.
120                 mLowProfileCheckBox.setChecked(false);
121                 mHideNavCheckbox.setChecked(true);
122                 mHideStatusBarCheckBox.setChecked(true);
123                 mImmersiveModeCheckBox.setChecked(false);
124                 mImmersiveModeStickyCheckBox.setChecked(false);
125             }
126         });
127 
128         // Setting these flags makes the content appear under the navigation
129         // bars, so that showing/hiding the nav bars doesn't resize the content
130         // window, which can be jarring.
131         int uiOptions = flagsView.getSystemUiVisibility();
132         uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
133         uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
134         uiOptions |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
135         flagsView.setSystemUiVisibility(uiOptions);
136 
137         return flagsView;
138     }
139 
140     /**
141      * Helper method to dump flag state to the log.
142      * @param uiFlags Set of UI flags to inspect
143      */
dumpFlagStateToLog(int uiFlags)144     public void dumpFlagStateToLog(int uiFlags) {
145         if ((uiFlags & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
146             Log.i(TAG, "SYSTEM_UI_FLAG_LOW_PROFILE is set");
147         } else {
148             Log.i(TAG, "SYSTEM_UI_FLAG_LOW_PROFILE is unset");
149         }
150 
151         if ((uiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
152             Log.i(TAG, "SYSTEM_UI_FLAG_FULLSCREEN is set");
153         } else {
154             Log.i(TAG, "SYSTEM_UI_FLAG_FULLSCREEN is unset");
155         }
156 
157         if ((uiFlags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
158             Log.i(TAG, "SYSTEM_UI_FLAG_HIDE_NAVIGATION is set");
159         } else {
160             Log.i(TAG, "SYSTEM_UI_FLAG_HIDE_NAVIGATION is unset");
161         }
162 
163         if ((uiFlags & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0) {
164             Log.i(TAG, "SYSTEM_UI_FLAG_IMMERSIVE is set");
165         } else {
166             Log.i(TAG, "SYSTEM_UI_FLAG_IMMERSIVE is unset");
167         }
168 
169         if ((uiFlags & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0) {
170             Log.i(TAG, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY is set");
171         } else {
172             Log.i(TAG, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY is unset");
173         }
174     }
175 
176     /**
177      * Detects and toggles immersive mode (also known as "hidey bar" mode).
178      */
toggleUiFlags()179     public void toggleUiFlags() {
180 
181         // BEGIN_INCLUDE (get_current_ui_flags)
182         // The "Decor View" is the parent view of the Activity.  It's also conveniently the easiest
183         // one to find from within a fragment, since there's a handy helper method to pull it, and
184         // we don't have to bother with picking a view somewhere deeper in the hierarchy and calling
185         // "findViewById" on it.
186         View decorView = getActivity().getWindow().getDecorView();
187         int uiOptions = decorView.getSystemUiVisibility();
188         int newUiOptions = uiOptions;
189         // END_INCLUDE (get_current_ui_flags)
190 
191         // BEGIN_INCLUDE (toggle_lowprofile_mode)
192         // Low profile mode doesn't resize the screen at all, but it covers the nav & status bar
193         // icons with black so they're less distracting.  Unlike "full screen" and "hide nav bar,"
194         // this mode doesn't interact with immersive mode at all, but it's instructive when running
195         // this sample to observe the differences in behavior.
196         if (mLowProfileCheckBox.isChecked()) {
197             newUiOptions |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
198         } else {
199             newUiOptions &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
200         }
201         // END_INCLUDE (toggle_lowprofile_mode)
202 
203         // BEGIN_INCLUDE (toggle_fullscreen_mode)
204         // When enabled, this flag hides non-critical UI, such as the status bar,
205         // which usually shows notification icons, battery life, etc
206         // on phone-sized devices.  The bar reappears when the user swipes it down.  When immersive
207         // mode is also enabled, the app-drawable area expands, and when the status bar is swiped
208         // down, it appears semi-transparently and slides in over the app, instead of pushing it
209         // down.
210         if (mHideStatusBarCheckBox.isChecked()) {
211             newUiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
212         } else {
213             newUiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
214         }
215         // END_INCLUDE (toggle_fullscreen_mode)
216 
217         // BEGIN_INCLUDE (toggle_hidenav_mode)
218         // When enabled, this flag hides the black nav bar along the bottom,
219         // where the home/back buttons are.  The nav bar normally instantly reappears
220         // when the user touches the screen.  When immersive mode is also enabled, the nav bar
221         // stays hidden until the user swipes it back.
222         if (mHideNavCheckbox.isChecked()) {
223             newUiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
224         } else {
225             newUiOptions &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
226         }
227         // END_INCLUDE (toggle_hidenav_mode)
228 
229         // BEGIN_INCLUDE (toggle_immersive_mode)
230         // Immersive mode doesn't do anything without at least one of the previous flags
231         // enabled.  When enabled, it allows the user to swipe the status and/or nav bars
232         // off-screen.  When the user swipes the bars back onto the screen, the flags are cleared
233         // and immersive mode is automatically disabled.
234         if (mImmersiveModeCheckBox.isChecked()) {
235             newUiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE;
236         } else {
237             newUiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE;
238         }
239         // END_INCLUDE (toggle_immersive_mode)
240 
241         // BEGIN_INCLUDE (toggle_immersive_mode_sticky)
242         // There's actually two forms of immersive mode, normal and "sticky".  Sticky immersive mode
243         // is different in 2 key ways:
244         //
245         // * Uses semi-transparent bars for the nav and status bars
246         // * This UI flag will *not* be cleared when the user interacts with the UI.
247         //   When the user swipes, the bars will temporarily appear for a few seconds and then
248         //   disappear again.
249         if (mImmersiveModeStickyCheckBox.isChecked()) {
250             newUiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
251         } else {
252             newUiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
253         }
254         // END_INCLUDE (toggle_immersive_mode_sticky)
255 
256         // BEGIN_INCLUDE (set_ui_flags)
257         //Set the new UI flags.
258         decorView.setSystemUiVisibility(newUiOptions);
259         // END_INCLUDE (set_ui_flags)
260 
261         dumpFlagStateToLog(uiOptions);
262     }
263 }
264