대화 상자에서 몰입 형 모드를 유지하려면 어떻게해야합니까?
내 활동에 사용자 지정 대화 상자가 표시 될 때 새로운 몰입 형 모드를 유지하려면 어떻게해야합니까?
대화 상자에서 몰입 형 모드를 유지하기 위해 아래 코드를 사용하고 있지만 해당 솔루션을 사용하면 사용자 지정 대화 상자를 시작할 때 NavBar가 1 초 미만 동안 나타난 다음 사라집니다.
다음 비디오는 문제를 더 잘 설명합니다 (NavBar가 나타날 때 화면 하단 참조). http://youtu.be/epnd5ghey8g
이 동작을 어떻게 피합니까?
암호
내 지원서의 모든 활동의 아버지 :
public abstract class ImmersiveActivity extends Activity {
@SuppressLint("NewApi")
private void disableImmersiveMode() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN
);
}
}
@SuppressLint("NewApi")
private void enableImmersiveMode() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
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_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
);
}
}
/**
* Set the Immersive mode or not according to its state in the settings:
* enabled or not.
*/
protected void updateSystemUiVisibility() {
// Retrieve if the Immersive mode is enabled or not.
boolean enabled = getSharedPreferences(Util.PREF_NAME, 0).getBoolean(
"immersive_mode_enabled", true);
if (enabled) enableImmersiveMode();
else disableImmersiveMode();
}
@Override
public void onResume() {
super.onResume();
updateSystemUiVisibility();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
updateSystemUiVisibility();
}
}
내 모든 사용자 지정 대화 상자는 해당 onCreate(. . .)
메서드 에서이 메서드를 호출합니다 .
/**
* Copy the visibility of the Activity that has started the dialog {@link mActivity}. If the
* activity is in Immersive mode the dialog will be in Immersive mode too and vice versa.
*/
@SuppressLint("NewApi")
private void copySystemUiVisibility() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
mActivity.getWindow().getDecorView().getSystemUiVisibility()
);
}
}
편집-해결책 (Beaver6813 덕분에 자세한 내용은 답변을 참조하십시오) :
내 모든 사용자 지정 대화 상자는 다음과 같은 방식으로 show 메서드를 재정의합니다.
/**
* An hack used to show the dialogs in Immersive Mode (that is with the NavBar hidden). To
* obtain this, the method makes the dialog not focusable before showing it, change the UI
* visibility of the window like the owner activity of the dialog and then (after showing it)
* makes the dialog focusable again.
*/
@Override
public void show() {
// Set the dialog to not focusable.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
copySystemUiVisibility();
// Show the dialog with NavBar hidden.
super.show();
// Set the dialog to focusable again.
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
이 문제에 대한 많은 연구 끝에 Dialog 클래스를 분리하여 찾아내는 문제가 해결되었습니다 . 관리자에 추가하기 전에 UI 가시성을 설정 한 경우에도 대화 창이 창 관리자에 추가되면 탐색 모음이 표시됩니다. Android Immersive 예제 에서는 다음과 같이 주석 처리되었습니다.
// * Uses semi-transparent bars for the nav and status bars
// * This UI flag will *not* be cleared when the user interacts with the UI.
// When the user swipes, the bars will temporarily appear for a few seconds and then
// disappear again.
나는 이것이 우리가 여기에서보고있는 것이라고 믿는다 (새롭고 포커스 가능한 창보기가 관리자에 추가 될 때 사용자 상호 작용이 트리거되고 있음).
이 문제를 어떻게 해결할 수 있습니까? 대화 상자를 만들 때 초점을 맞출 수 없도록 설정하고 (사용자 상호 작용을 트리거하지 않음) 표시된 후 초점을 맞출 수 있도록합니다.
//Here's the magic..
//Set the dialog to not focusable (makes navigation ignore us adding the window)
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
//Show the dialog!
dialog.show();
//Set the dialog to immersive
dialog.getWindow().getDecorView().setSystemUiVisibility(
context.getWindow().getDecorView().getSystemUiVisibility());
//Clear the not focusable flag from the window
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
분명히 이것은 이상적이지는 않지만 Android 버그 인 것 같습니다. Window에 몰입 형 세트가 있는지 확인해야합니다.
내 작업 테스트 코드를 Github로 업데이트했습니다 (해키 지저분 함을 용서하십시오) . Nexus 5 에뮬레이터에서 테스트 해 보았지만 KitKat보다 적은 것으로 폭발 할 수 있지만 개념 증명 전용입니다.
귀하의 정보를 위해 @ Beaver6813의 답변 덕분에 DialogFragment를 사용하여이 작업을 수행 할 수있었습니다.
내 DialogFragment의 onCreateView 메서드에서 다음을 추가했습니다.
getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
getDialog().getWindow().getDecorView().setSystemUiVisibility(getActivity().getWindow().getDecorView().getSystemUiVisibility());
getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
//Clear the not focusable flag from the window
getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
//Update the WindowManager with the new attributes (no nicer way I know of to do this)..
WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
wm.updateViewLayout(getDialog().getWindow().getDecorView(), getDialog().getWindow().getAttributes());
}
});
onCreateDialog () 를 사용하려면 이 클래스를 사용해보십시오. 그것은 나를 위해 꽤 잘 작동합니다 ...
public class ImmersiveDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
.setTitle("Example Dialog")
.setMessage("Some text.")
.create();
// Temporarily set the dialogs window to not focusable to prevent the short
// popup of the navigation bar.
alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
return alertDialog;
}
public void showImmersive(Activity activity) {
// Show the dialog.
show(activity.getFragmentManager(), null);
// It is necessary to call executePendingTransactions() on the FragmentManager
// before hiding the navigation bar, because otherwise getWindow() would raise a
// NullPointerException since the window was not yet created.
getFragmentManager().executePendingTransactions();
// Hide the navigation bar. It is important to do this after show() was called.
// If we would do this in onCreateDialog(), we would get a requestFeature()
// error.
getDialog().getWindow().getDecorView().setSystemUiVisibility(
getActivity().getWindow().getDecorView().getSystemUiVisibility()
);
// Make the dialogs window focusable again.
getDialog().getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
);
}
}
대화 상자를 표시하려면 활동에서 다음을 수행하십시오.
new ImmersiveDialogFragment().showImmersive(this);
여기에 답변을 결합하여 모든 경우에 작동하는 추상 클래스를 만들었습니다.
public abstract class ImmersiveDialogFragment extends DialogFragment {
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
// Make the dialog non-focusable before showing it
dialog.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
@Override
public void show(FragmentManager manager, String tag) {
super.show(manager, tag);
showImmersive(manager);
}
@Override
public int show(FragmentTransaction transaction, String tag) {
int result = super.show(transaction, tag);
showImmersive(getFragmentManager());
return result;
}
private void showImmersive(FragmentManager manager) {
// It is necessary to call executePendingTransactions() on the FragmentManager
// before hiding the navigation bar, because otherwise getWindow() would raise a
// NullPointerException since the window was not yet created.
manager.executePendingTransactions();
// Copy flags from the activity, assuming it's fullscreen.
// It is important to do this after show() was called. If we would do this in onCreateDialog(),
// we would get a requestFeature() error.
getDialog().getWindow().getDecorView().setSystemUiVisibility(
getActivity().getWindow().getDecorView().getSystemUiVisibility()
);
// Make the dialogs window focusable again
getDialog().getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
);
}
}
This also works over ride the onDismiss method of your dialog fragment . And within that method call the method of the activity to which it is attached to again set the full screen flags .
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
Logger.e(TAG, "onDismiss");
Log.e("CallBack", "CallBack");
if (getActivity() != null &&
getActivity() instanceof LiveStreamingActivity) {
((YourActivity) getActivity()).hideSystemUI();
}
}
And in your activity add this method :
public void hideSystemUI() {
// Set the IMMERSIVE flag.
// Set the content to appear under the system bars so that the content
// doesn't resize when the system bars hide and show.
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 // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
Whean you are creating your own DialogFragment you need only override this method.
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
return dialog;
}
I know this is old post, but my answer may help others.
Below is the hacky fix for Immersive effect in Dialogs:
public static void showImmersiveDialog(final Dialog mDialog, final Activity mActivity) {
//Set the dialog to not focusable
mDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
mDialog.getWindow().getDecorView().setSystemUiVisibility(setSystemUiVisibility());
mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
//Clear the not focusable flag from the window
mDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
//Update the WindowManager with the new attributes
WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
wm.updateViewLayout(mDialog.getWindow().getDecorView(), mDialog.getWindow().getAttributes());
}
});
mDialog.getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
mDialog.getWindow().getDecorView().setSystemUiVisibility(setSystemUiVisibility());
}
}
});
}
public static int setSystemUiVisibility() {
return 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;
}
참고URL : https://stackoverflow.com/questions/22794049/how-do-i-maintain-the-immersive-mode-in-dialogs
'Programing' 카테고리의 다른 글
UIView 하위 클래스에 대한 Nib을로드하는 올바른 방법 (0) | 2020.08.21 |
---|---|
vim에서 UI 언어를 어떻게 설정합니까? (0) | 2020.08.21 |
SQL Plus에서 실행되는 SQL 스크립트에서 앰퍼샌드를 무시하려면 어떻게합니까? (0) | 2020.08.21 |
IIS7은 Response.StatusCode를 설정할 때 customErrors를 무시합니까? (0) | 2020.08.21 |
Windows .cmd 파일 또는 배치 파일의 경로에 공백이있는 경로 변수 설정 (0) | 2020.08.21 |