Android BottomSheetDialogFragment that does not take whole width - android

How do I make BottomSheetDialogFragment that does not cover entire width of the screen (something like "Share via" sheet in Chrome on tablets)?

As a developer suggested in the issue linked by #UfoXp, the problem is BottomSheetDialog.onCreate() setting the window to MATCH_PARENT both ways:
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dialog = super.onCreateDialog(savedInstanceState);
if ((isTablet(getContext()) || isLandscape(getContext()))) {
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogINterface) {
dialog.getWindow().setLayout(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
});
}
return dialog;
}
private boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
private boolean isLandscape(Context context) {
return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}

Just use getWindow().setLayout() after showing the Dialog
dialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT);

Looks like this is not possible right now:
https://code.google.com/p/android/issues/detail?id=204670

Related

Android studio Expand Bottom Sheet on button click Inside its Fragment

I have a Bottom Sheet and I want to add a button in which the bottom sheet dialog expands on click
enter image description here
Is it doable to put onclicklistener inside bottom sheet fragment onCreateView and change the state of the dialog?
heres my Bottom Sheet Fragment
public class RepliesToComment extends BottomSheetDialogFragment {
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
Window window = dialog.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
dialog.getBehavior().setState(BottomSheetBehavior.STATE_COLLAPSED); <--change to STATE_EXPANDED on click-->
return dialog;
}
ImageButton expandBtn;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_replies_to_comment, container, false);
{...}
expandBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
----
}
});
}
I manage to make it work heres my solution
dialog to global then made a boolean identifier to switch the state of the dialog
boolean identifier = true;
BottomSheetDialog dialog;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
Window window = dialog.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
return dialog;
}
public void expand(){
if (!identifier){
dialog.getBehavior().setState(BottomSheetBehavior.STATE_COLLAPSED);
}else {
dialog.getBehavior().setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
then made the button into toggle button to change the value of the identifier
//expand
expandBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
identifier = b;
expand();
}
});

PopupWindow cannot display Unity3D views in Android, but Dialog does?

Here is some brief codes of my project, in which I'd like to display a Unity3D model to do something.
public class MainActivity extends FragmentActivity{
protected UnityPlayer mUnityPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
getWindow().setFormat(PixelFormat.RGBX_8888);
mUnityPlayer = new UnityPlayer(this);
...
mTestImageButton = ***;
mTestImageButton.setOnClickListener(mTestImageButtonClickListener);
}
private ImageButton mTestImageButton;
private View.OnClickListener mTestImageButtonClickListener = new
View.OnClickListener() {
#Override
public void onClick(View v) {
showUnity3D_dialog(v);
//showUnity3D_popupwindow(v);
}
};
private void showUnity3D_dialog(View v) {
Dialog dialog = new Dialog(v.getContext(), R.style.move_dialog);
dialog.setContentView(mUnityPlayer);
Window window = dialog.getWindow();
window.setWindowAnimations(R.style.move_dialog);
WindowManager.LayoutParams lp = window.getAttributes();
window.setGravity(Gravity.RIGHT | Gravity.BOTTOM);
lp.width = 1179;
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
window.setAttributes(lp);
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
dialog.setCanceledOnTouchOutside(true);
dialog.show();
mUnityPlayer.resume();
}
private void showUnity3D_popupwindow(View v) {
PopupWindow pop = new PopupWindow(mUnityPlayer, 1000, 800);
pop.setBackgroundDrawable(new BitmapDrawable());
pop.setFocusable(true);
pop.setOutsideTouchable(false);
pop.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
}
});
pop.showAtLocation(v, Gravity.BOTTOM, 0, 0);
mUnityPlayer.resume();
}
}
As codes above, I tried to display a Unity3D-model in a PopupWindow, but the result makes me a bit confused, since there is nothing on screen when I called showUnity3D_popupwindow(v).
But when I called showUnity3D_dialog(v), the model by Unity3D shows.
I really can't understand what caused such scenario, and how can I display my model in a PopupWindow in android? Or, is it an impossible task?
I have my project under Android 4.3 & Unity 5.4.0.
Thanks a lot.
Looks like you are currently using the PopupWindow(View contentView, int width, int height) overload function. I've seen instances where functions that take View, Context or Activity does not work in Unity and you have to try other overloads.
You've tried the one takes View, now try the Context overload:
PopupWindow(Context context)
then set the width and height later on with the setWidth and setHeight function. You can get the current Context with UnityPlayer.currentActivity.getApplicationContext().
private void showUnity3D_popupwindow(View v)
{
Context mContext = UnityPlayer.currentActivity.getApplicationContext();
PopupWindow pop = new PopupWindow(mContext);
pop.setWidth(1000);
pop.setHeight(800);
pop.setBackgroundDrawable(new BitmapDrawable());
pop.setFocusable(true);
pop.setOutsideTouchable(false);
pop.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
}
});
pop.showAtLocation(v, Gravity.BOTTOM, 0, 0);
mUnityPlayer.resume();
}

BottomSheetDialog remains hidden after dismiss by dragging down

I am pretty curious about the behavior of the BottomSheetDialog when it is dismissed : when the user draggs it down to hide it, it will remain hidden, even if bottomSheetDialog#show() is called after. This only happens when it is dragged down, not when the user touches outside or when bottomSheetDialog#dismiss() is called programatically.
It is really annoying because I have a pretty big bottomSheetDialog with a recyclerview inside, and I have to create a new one every time I want to show the bottomSheetDialog.
So instead of just doing this :
if(bottomSheetDialog != null){
bottomSheetDialog.show();
else{
createNewBottomSheetDialog();
}
I have to create one every time.
Am I missing something or is it the normal behavior ? (Btw I use appcompat-v7:23.2.1)
So I finally managed to solve this problem by looking directly into the BottomSheetDialog implementation, and I discovered it was nothing but a simple Dialog wrapped into a regular BottomSheet.
The problem was in the BottomSheetCallBack :
#Override
public void onStateChanged(#NonNull View bottomSheet,
#BottomSheetBehavior.State int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
The problem occurs when the state HIDDEN is reached which happens when the dialog is dismissed by being dragged down. After that the dialog stays hidden even if bottomSheetDialog.show() is called. The most simple fix I found was to remove this state and replace it by the COLLAPSED state.
I create a classCustomBottomSheetDialog, copied the entire BottomSheetDialog class and added a single line to fix the problem :
#Override
public void onStateChanged(#NonNull View bottomSheet,
#BottomSheetBehavior.State int newState) {
if (newState == CustomBottomSheetBehavior.STATE_HIDDEN) {
dismiss();
bottomSheetBehavior.setState(CustomBottomSheetBehavior.STATE_COLLAPSED);
}
}
Here is the final code:
public class CustomBottomSheetDialog extends AppCompatDialog {
public CustomBottomSheetDialog (#NonNull Context context) {
this(context, 0);
}
public CustomBottomSheetDialog (#NonNull Context context, #StyleRes int theme) {
super(context, getThemeResId(context, theme));
// We hide the title bar for any style configuration. Otherwise, there will be a gap
// above the bottom sheet when it is expanded.
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
}
protected CustomBottomSheetDialog (#NonNull Context context, boolean cancelable,
OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
}
#Override
public void setContentView(#LayoutRes int layoutResId) {
super.setContentView(wrapInBottomSheet(layoutResId, null, null));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setLayout(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
#Override
public void setContentView(View view) {
super.setContentView(wrapInBottomSheet(0, view, null));
}
#Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
super.setContentView(wrapInBottomSheet(0, view, params));
}
private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(),
R.layout.design_bottom_sheet_dialog, null);
if (layoutResId != 0 && view == null) {
view = getLayoutInflater().inflate(layoutResId, coordinator, false);
}
FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback);
if (params == null) {
bottomSheet.addView(view);
} else {
bottomSheet.addView(view, params);
}
// We treat the CoordinatorLayout as outside the dialog though it is technically inside
if (shouldWindowCloseOnTouchOutside()) {
coordinator.findViewById(R.id.touch_outside).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
if (isShowing()) {
cancel();
}
}
});
}
return coordinator;
}
private boolean shouldWindowCloseOnTouchOutside() {
if (Build.VERSION.SDK_INT < 11) {
return true;
}
TypedValue value = new TypedValue();
//noinspection SimplifiableIfStatement
if (getContext().getTheme()
.resolveAttribute(android.R.attr.windowCloseOnTouchOutside, value, true)) {
return value.data != 0;
}
return false;
}
private static int getThemeResId(Context context, int themeId) {
if (themeId == 0) {
// If the provided theme is 0, then retrieve the dialogTheme from our theme
TypedValue outValue = new TypedValue();
if (context.getTheme().resolveAttribute(
R.attr.bottomSheetDialogTheme, outValue, true)) {
themeId = outValue.resourceId;
} else {
// bottomSheetDialogTheme is not provided; we default to our light theme
themeId = R.style.Theme_Design_Light_BottomSheetDialog;
}
}
return themeId;
}
private BottomSheetBehavior.BottomSheetCallback mBottomSheetCallback
= new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet,
#BottomSheetBehavior.State int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
bottomSheetBehavior.setState(CustomBottomSheetBehavior.STATE_COLLAPSED);
}
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
};
}
Update: The problem has been resolved at some version of the support library. I don't really know the exact version that fixes it but in 27.0.2 it is fixed.
Note: The URL does no longer refer to the issue described due to some modification on the URL schema by Google.
A workaround better than copying the whole class just to add a single line
// Fix BottomSheetDialog not showing after getting hidden when the user drags it down
myBottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
FrameLayout bottomSheet = (FrameLayout) bottomSheetDialog
.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
see: https://code.google.com/p/android/issues/detail?id=202396#c7
I have sample demo I hope that is useful.
public class BottomListMenu extends BottomSheetDialog {
private List<MenuDTO> menuList;
private OnMenuItemTapped menuTapListener;
public BottomListMenu(#NonNull Context context, List<MenuDTO> menuList, OnMenuItemTapped menuTapListener) {
super(context);
this.menuList = menuList;
this.menuTapListener = menuTapListener;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_menu_list);
RecyclerView rcvList = (RecyclerView) findViewById(R.id.rcv_menu_list);
rcvList.setLayoutManager(new LinearLayoutManager(getContext()));
BottomSheetMenuListAdapter adapter = new BottomSheetMenuListAdapter(getContext(), this, menuList, menuTapListener);
rcvList.setAdapter(adapter);
}
}
--- Use ---
BottomListMenu menu = new BottomListMenu(MainActivity.this, MenuUtils.getListMenu(MainActivity.this), new OnMenuItemTapped() {
#Override
public void onClickMenuItem(MenuDTO menu) {
if (menu.getMenuTitle().equals(getString(R.string.menu_edit))) {
Toast.makeText(MainActivity.this, "Edit Clicked", Toast.LENGTH_SHORT).show();
} else if (menu.getMenuTitle().equals(getString(R.string.menu_delete))) {
Toast.makeText(MainActivity.this, "Delete Clicked", Toast.LENGTH_SHORT).show();
} else if (menu.getMenuTitle().equals(getString(R.string.menu_attach))) {
Toast.makeText(MainActivity.this, "Attach Clicked", Toast.LENGTH_SHORT).show();
}
}
});
menu.show();
-- Full Sample Code Available Here --
https://github.com/bita147/BottomSheetDialog

Android full screen dialog fragment like calendar app

I am trying to achieve a full-screen dialog like the below image. I am able to show a full screen dialog but when the dialog is shown the status bar color changes to black and does not keep the primary-dark color.
Heres my dialog fragment
public class IconsDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.fragment_icons_dialog, container, false);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final RelativeLayout root = new RelativeLayout(getActivity());
root.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
// creating the fullscreen dialog
final Dialog dialog = new Dialog(getActivity());
dialog.setContentView(root);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.YELLOW));
dialog.getWindow().setWindowAnimations(R.style.DialogAnimation);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
return dialog;
}
}
To get DialogFragment on full screen
Override onStart of your DialogFragment like this:
#Override
public void onStart()
{
super.onStart();
Dialog dialog = getDialog();
if (dialog != null)
{
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width, height);
}
}
In order to setStatusBarColor you need to set the flag: FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
public void setStatusBarColorIfPossible(int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(color);
}
}
One way is to change back your status bar color as theme programmatically whenever you open the dialog.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Your theme color);
}

Back pressed events with system alert window

I need to dismiss system alert window on back pressed and home button event.I have tried with onKeyEvent but in vain. As we can't capture the back pressed event in a service, how to achieve this?
Since it's a service that hosting an overlay window, It's a bit tricky solution but it is possible.
You should handle these 2 cases separately (overriding home button press, and back button press).
1. Overriding home button press:
Create this HomeWatcher class which contains a BroadcastReceiver that will notify when home button was pressed. Register this receiver only when your window comes up.
Android: associate a method to home button of smartphone
Inside your service onCreate method use this:
HomeWatcher mHomeWatcher = new HomeWatcher(this);
mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
#Override
public void onHomePressed() {
yourWindow.hide() //means: windowManager.removeView(view);
}
#Override
public void onHomeLongPressed() {
}
});
mHomeWatcher.startWatch();
2. Overriding back button press:
The idea is creating an empty layout as a data member of your window class,
and attach your view to it (even if its an inflated XML layout).
For example, this is gonna be your window class:
public class MyWindow
{
private WindowManager windowManager;
private WindowManager.LayoutParams params;
private View view;
// Add this empty layout:
private MyLayout myLayout;
public MyWindow()
{
windowManager = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.your_original_window_layout, null);
// Add your original view to the new empty layout:
myLayout = new MyLayout(this);
myLayout.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
// And show this layout instead of your original view:
public void show()
{
windowManager.addView(myLayout, params);
}
public void hide()
{
windowManager.removeView(myLayout);
}
}
And now create the MyLayout class to override the back button press:
public class MyLayout extends LinearLayout
{
private MyWindow myWindow;
public MyLayout(MyWindow myWindow)
{
super(myWindow.context);
this.myWindow = myWindow;
}
#Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0)
{
getKeyDispatcherState().startTracking(event, this);
return true;
}
else if (event.getAction() == KeyEvent.ACTION_UP)
{
getKeyDispatcherState().handleUpEvent(event);
if (event.isTracking() && !event.isCanceled())
{
// dismiss your window:
myWindow.hide();
return true;
}
}
}
return super.dispatchKeyEvent(event);
}
}
I know it's a bit complicated as I said since it's a system alert window hosted by a service, BUT it's working. I have the same issue as well and it has been solved exactly like that.
Good luck.
use below method to handle back button pressed.
public void onBackPressed()
{
super.onBackPressed();
}
You need to overwrite the onBackPressed method.
#Override
public void onBackPressed() {
super.onBackPressed(); // remove this if u want to handle this event
}
Use the code below
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exitByBackKey();
//moveTaskToBack(false);
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void exitByBackKey() {
AlertDialog alertbox = new AlertDialog.Builder(this)
.setMessage("Do you want to exit application?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
// do something when the button is clicked
public void onClick(DialogInterface arg0, int arg1) {
finish();
//close();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
// do something when the button is clicked
public void onClick(DialogInterface arg0, int arg1) {
}
})
.show();
}
#Override
public void onBackPressed()
{
super.onBackPressed();
}
Declare this on your activity. super.OnBackPressed automatically calls back method in android. it will surely cancel your dialog.
in addition, your dialog must look like this.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder1.setMessage("TEST DIALOG.\n");
builder1.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
Toast.makeText(MainActivity.this, "This Is test Dialog", Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert11 = builder1.create();
alert11.show();
or you can set Negative button..
Hope this helps!
Define a custom layout and override dispatchKeyEvent, for example:
public class CustomSystemAlertWindow extends FrameLayout {
public static final String TAG = "CustomSystemAlertWindow";
private WeakReference<Context> mContext;
public CustomSystemAlertWindow(Context context) {
super(context);
mContext = new WeakReference<Context>(context);
// Set a background color to identify the view on the screen
this.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Log.d(TAG, "back button pressed");
if (mContext != null && mContext.get() != null) {
WindowManager wm = (WindowManager) mContext.get().getSystemService(Context.WINDOW_SERVICE);
wm.removeView(this);
}
return true;
}
return super.dispatchKeyEvent(event);
}
}
Then add the view with this code:
CustomSystemAlertWindow customSystemAlertWindow = new CustomSystemAlertWindow(context);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.addView(customSystemAlertWindow, params);
When you press the back button the view will dismiss.
Show the Alert window through the Activity so you can detect it.
Implement the code to detect easily Back Button or Home Button pressed.
public class alertPopup extends Activity {
Context context;
final AlertDialog alertDialog;
String TAG = "your Activity Name"
boolean homePressed = false; // to detect the Homebutton pressed
#Override
public void onCreate(Bundle savedInstanceState) {
AlertDialog.Builder builder = newAlertDialog.Builder(YourActivity.this, R.style.AppCompatAlertDialogStyle);
builder.setTitle("AlertDialog Title");
..........
....... // Build ur AlertDialog
alertDialog= builder.create();
alertDialog.show();
//to detect Alert Dialog cancel when user touches outside the Dialog prompt
alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
Log.v(TAG,"Alert Dialog cancelled when user touches outside the Dialog prompt")
}
});
}
#Override
public void onBackPressed()
{
Log.v(TAG,"Back Button Pressed");
super.onBackPressed();
alertDialog.dismiss(); //dismiss the alertDialog
alertPopup.this.finish(); // Destroy the current activity
homePressed = false;
}
#Override
public void onResume() {
super.onResume();
homePressed = true; // default: other wise onBackPressed will set it to false
}
#Override
public void onPause() {
super.onPause();
if(homePressed) {
alertDialog.dismiss(); //dismiss the alertDialog
alertPopup.this.finish(); // Destroy the current activity
Log.v(TAG, "Home Button Pressed"); }
}
public void onDestroy(){
super.onDestroy();
}
}
Note:
Add this Permission in Android Manifest to show the alert Window .
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Happy Coding :)
I understand that you are using the <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> permission for showing a floating view.
Using a floating view you can intercept the back button press, but the home button press cannot be intercepted (android won't let you primarily because of security reasons).
To intercept the back button press you need to add a wrapper when you inflate your floating view.
Your wrapper should look like this:
// Wrapper for intercepting System/Hardware key events
ViewGroup wrapper = new FrameLayout(this) {
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
hideAddNotesFloatingView();
return true;
}
return super.dispatchKeyEvent(event);
}
};
Then you add it to your floating view as a root:
mAddNoteFloatingView = mInflater.inflate(R.layout.floating_add_note, wrapper);
My complete code looks like this:
private void addFloatingView() {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_PHONE,
0,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.CENTER | Gravity.LEFT;
params.x = 0;
params.y = 0;
// Wrapper for intercepting System/Hardware key events
FrameLayout wrapper = new FrameLayout(this) {
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
// Add your code for handling the back button press
return true; // Return true means that the event was handled
}
return super.dispatchKeyEvent(event);
}
};
mAddNoteFloatingView = mInflater.inflate(R.layout.floating_view, wrapper);
mWindowManager.addView(mAddNoteFloatingView, params);
}
It's simple. Follow these steps:
Create a view like Relative Layout, Linear Layout or Frame Layout Dynamically. 2. Override the dispatchKeyEvent while creating the view.
Add your original view into this dynamically created view with addView() method.
Add the dynamically created view to your Window Manager or Alert Dialog whichever you want.
In addition to #Eliran Kuta's solution, this is more simple answer for Back button.
val view = getAlertView()
val windowParam = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, // whatever
WindowManager.LayoutParams.WRAP_CONTENT, // whatever
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // use WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY before Oreo
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, // whatever
PixelFormat.TRANSLUCENT // whatever
)
view.isFocusableInTouchMode = true
view.setOnKeyListener { view, keyCode, event ->
when (keyCode) {
KeyEvent.KEYCODE_BACK -> {
// do your work here
true
}
else -> false
}
}
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.addView(view, windowParam)

Categories

Resources