我的应用程序大部分时间都需要全屏显示。我知道如果显示警报或显示其他窗口,则在活动窗口的顶部,会暂时删除全屏。不幸的是,当为EditText或其他东西显示软键盘时,当用户使用完键盘时,不会恢复全屏沉浸式模式。
知道如何实现这一目标吗?
答案 0 :(得分:13)
从this sample app by Google获取,您需要在活动结束时将其附加到最后一个结束括号之前:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
// When the window loses focus (e.g. the action overflow is shown),
// cancel any pending hide action. When the window gains focus,
// hide the system UI.
if (hasFocus) {
delayedHide(300);
} else {
mHideHandler.removeMessages(0);
}
}
private void hideSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LOW_PROFILE |
View.SYSTEM_UI_FLAG_IMMERSIVE
);
}
private void showSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
}
private final Handler mHideHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
hideSystemUI();
}
};
private void delayedHide(int delayMillis) {
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, delayMillis);
}
你应该做得好。 :)
答案 1 :(得分:2)
我建议将AppCompatActivity扩展到一个新类(ImmersiveAppCompatActivity)。通过这样做,您使用此类创建的任何活动都将内置处理沉浸式模式。
如果在软键盘出现后尝试过快地设置沉浸式模式,它将无法隐藏。
另请注意,通过切换到静态处理程序来改进处理程序 - 如果用户在隐藏GUI之前离开活动,这将防止泄漏。
public abstract class ImmersiveAppCompatActivity extends AppCompatActivity {
private HideHandler mHideHandler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create a handler to set immersive mode on a delay
mHideHandler = new HideHandler(this);
}
@Override
protected void onResume() {
super.onResume();
setToImmersiveMode();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
mHideHandler.removeMessages(0);
mHideHandler.sendEmptyMessageDelayed(0, 300);
}
else mHideHandler.removeMessages(0);
}
private void setToImmersiveMode() {
// set to immersive
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
private static class HideHandler extends Handler {
private final WeakReference<ImmersiveAppCompatActivity> mActivity;
HideHandler(ImmersiveAppCompatActivity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
ImmersiveAppCompatActivity activity = mActivity.get();
if(activity != null) activity.setToImmersiveMode();
}
}
}
这是Kotlin版本:
abstract class ImmersiveAppCompatActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
setToImmersiveMode()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
val runnable = Runnable { setToImmersiveMode() }
val handler = Handler(Looper.getMainLooper())
handler.postDelayed(runnable, 300)
}
private fun setToImmersiveMode() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
}
现在,使用此类创建您的活动:
public class SettingsActivity extends ImmersiveAppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}
}
我已经在Android 5.1和7.0中对此进行了测试,以便在没有操作栏的全屏应用中工作。
此外,如果您在EditText中使用键盘,请注意imeOptions。在横向模式下,您可以获得奇怪的全屏编辑行为。可以通过设置类EditorInfo中包含的imeOptions标志来禁用它:
<EditText
android:layout_width="@dimen/pin_width"
android:layout_height="wrap_content"
android:inputType="numberPassword"
android:imeOptions="flagNoExtractUi"
android:ems="10"
android:id="@+id/editTextPIN"
android:textSize="@dimen/pin_large_text_size"/>
https://developer.android.com/reference/android/view/inputmethod/EditorInfo.html
答案 2 :(得分:1)
这是正常行为。但你可以分两步修复它:
1.找出键盘隐藏的时间
2.设置沉浸式全屏模式(再次)
第1步有点棘手。你可以在这里查看我的答案:
https://stackoverflow.com/a/27567074/2525452
第2步很简单:
public static void setImmersiveMode( Activity activity )
{
// Get the Activity's content View
ViewGroup content = (ViewGroup) activity.findViewById( android.R.id.content );
//
// Set the immersive mode flags at the content View
content.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
);
}
答案 3 :(得分:1)
我将此代码放在布局更改的onCreate()观察器上
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int screenHeight = getWindow().getDecorView().getRootView().getHeight();
int keyboardHeight = screenHeight - rect.bottom;
if (keyboardHeight > screenHeight * 0.15) {
setToImmersiveMode();
}
}
});
private void setToImmersiveMode() {
// set to immersive
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
答案 4 :(得分:0)
在启用软输入并键入时,保持沉浸式模式不变。您需要在活动窗口中设置标志。不装饰视图。
YourActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
要删除它,只需
YourActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
还可以根据需要在装饰视图上保留系统UI可见性设置。