I'm using following approach to create bottomsheet dialog, dialog is creating but I want to dismiss on backpress for that all setup I'm using the code below. But not doing able to dismiss dialog.
class MainActivity : BaseClass(), View.OnClickListener {
private lateinit var bottomSheetDialog: BottomSheetDialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bottomSheetDialog=BottomSheetDialog(this)
create.setOnClickListener {
createBottomSheetDialog()
}
}
override fun onBackPressed() {
if (bottomSheetDialog.isShowing){
bottomSheetDialog.dismiss()
}
super.onBackPressed()
}
private fun createBottomSheetDialog(){
bottomSheetDialog.setContentView(R.layout.bottom_sheet_dialog)
bottomSheetDialog.setCancelable(false)
bottomSheetDialog.show()
}
}
I have been tried using this.bottomSheetDialog.dismiss()
but not working I also have try dismissing the dialog without if statement and without using super.onBackPressed() but not working.
you can simply remove this line from your code
bottomSheetDialog.setCancelable(false)
You can get more details about this here. I guess you need to stop dismiss when clicked anywhere outside the fragment so you can add this :-
bottomSheetDialog.setCanceledOnTouchOutside(false)
It will allow you to dismiss onBackPressed but it won't allow you to dismiss if clicked anywhere outside of your bottom sheet.
Also no need to write this in your Main activity :-
override fun onBackPressed() {
if (bottomSheetDialog.isShowing){
bottomSheetDialog.dismiss()
}
super.onBackPressed()
}
Bottom Sheet dialogue will itself dismiss onBackPressed.
Try this:
override fun onBackPressed() {
if (bottomSheetDialog.isShowing){
bottomSheetDialog.dismiss()
} else {
super.onBackPressed()
}
}
Try setting global variable for activity dialog: BottomSheetDialog? = null
Then in the function for displaying dialog give it a value and show it. Then in onCreate (or whenever you want) just use global variable as a reference eg.:
onBackPressed(){
if(dialog != null){
dialog.dismiss()}}
Related
I open a new bottomSheet from a bottomSheet. When service result is successful I call dismiss() and open new fragment. This works most of times but sometimes previous bottomSheet now dismissing. For example when an alertDialog is shown and I close bottom sheet then reopen it and this issue is occurring.
First BottomSheet:
btnSend.click {
viewModel.callServiceFunction()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
observe(viewModel.serviceSuccessLiveData) {
dismiss()
navigator.navigateToSecondSheet(parentFragmentManager)
}
}
navigateToSecondSheet(fm: FragmentManager) {
SecondSheet.show(fm)
}
Second Bottom Sheet:
companion object {
fun show(fm: FragmentManager) {
SecondSheet().show(fm, "TagA")
}
}
So how can I get the first bottom sheet to always be dismissed?
maybe use:
dismissAllowingStateLoss()
Got a class that extends BottomSheetDialogFragment
When I set the dialog to show, the slide from bottom animation occurs and the dialog is shown. Now, If I set the app to background and then bring it back to the foreground, the dialog that was already showing does the same slide in animation.
How can I disable this, that is, if the dialog is already showing, sending the app to background and then foreground does not start the animation?
Showing the dialog like this:
dialog = MyDialogFragment()
dialog?.run {
val args = Bundle()
....
arguments = args
show(this#MyFragment.fragmentManager, tag)
}
Where the dialog class only has this:
class MyDialogFragment : BottomSheetDialogFragment() {
var listener: Listener? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// inflate view
// Given the arguments, sets up the ui
return view
}
interface Listener {
...
}
}
And that's all the code that I have for the dialog.
Combining #nntk and #CKotlin answers made the trick for me. I manage to fix the issue with this code :
override fun onStop() {
super.onStop()
dialog?.window?.setWindowAnimations(-1)
}
Edit:
On Android < P (API 28), it makes the app not responding to touch events. So either you don't use it or you need to surround it with a check:
override fun onStop() {
super.onStop()
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
dialog?.window?.setWindowAnimations(-1)
}
}
overwrite onStop() method in BottomSheetDialogFragment
such as
#Override
public void onStop() {
super.onStop();
getDialog().show(); // important
}
I'm dealing with the same issue. I haven't fully been able to solve this, but I was able to stop the slide up animation from occurring on resume by doing the following:
override fun onResume() {
super.onResume()
// Disable dialog window animations for this instance
dialog?.window?.setWindowAnimations(-1)
}
This doesn't stop the background fade from animating though, so the background shade shows, disappears, and then shows again.
I want to show a progress bar DialogFragment.
It would be shown until either it is cancelled or dismissed.
It can be cancelled if the user either presses back button or touches outside of the dialog, and is dismissed if the user doesn't cancel it before the completion of the task.
So, I want to set listeners for both so I can respond according to the case.
The dialog is being called from a Fragment.
According to this, I can't set listeners, instead I have to override the methods.
My main problem is, I don't know how to do that in kotlin.
I have written some of the code below but it is incomplete. Please correct the code where needed.
I am trying to implement only onCancel for now. Please do tell if onDismiss is needed to be implemented in some different way.
Following the solution here,
this is how I have coded the Fragment:
class MyFragment: Fragment(), DialogInterface.OnCancelListener {
// other code
private fun myFun() {
// show progress dialog
val myDialog = DialogProgress()
myDialog.show(childFragmentManager, "null")
// todo the long task of downloading something
// myDialog.dismiss()
}
override fun onCancel(dialog: DialogInterface?) {
// User canceled the dialog
Toast.makeText(activity, "Process canceled by user!", Toast.LENGTH_SHORT).show()
// todo
}
}
And this is my DialogFragment code:
class DialogProgress: DialogFragment() {
override fun onCancel(dialog: DialogInterface?) {
super.onCancel(dialog)
// need help here
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
super.onCreateDialog(savedInstanceState)
// show progress dialog
val v = activity!!.layoutInflater.inflate(R.layout.dialog_progress, null)
v.findViewById<TextView>(R.id.progress_message).text = "Fetching data"
return activity!!.let {
val builder = AlertDialog.Builder(it, R.style.ThemeOverlay_AppCompat_Dialog)
builder
.setView(progressView)
.create()
}
}
}
For the above code where I need help, I don't know how to convert the following Java code from the link of solution given above into kotlin:
#Override
public void onDismiss(final DialogInterface dialog) {
super.onDismiss(dialog);
Fragment parentFragment = getParentFragment();
if (parentFragment instanceof DialogInterface.OnDismissListener) {
((DialogInterface.OnDismissListener) parentFragment).onDismiss(dialog);
}
}
Note that this is for onDismiss, I want it for onCancel.
The Java code can be simply converted into kotlin code by pasting it into the Android Studio and a pop-up should appear.
This is the conversion of the java code:
override fun onCancel(dialog: DialogInterface?) {
super.onCancel(dialog)
val parentFragment = parentFragment
if (parentFragment is DialogInterface.OnCancelListener) {
(parentFragment as DialogInterface.OnCancelListener).onCancel(dialog)
}
}
My bottomSheet behaves correctly except in this situation. When I return to the activity via 'back button', I want the bottomSheet to collapse and I thought the code below would do the trick, but it doesn't work. What could be the cause ? (I confirmed with debugger that it reaches the statement)
#Override
public void onBackPressed() {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
the same line works fine when it returns via finish():
if (resultCode == Activity.RESULT_OK) {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
If your dialog has setCancelable(true), back button will not trigger the onbackpressed(), you can try this
I have a class call BottomSheetFragmentDialog which is extend from BottomSheetDialogFragment and I have setCanceledOnTouchOutside(false) inside the onCreateDialog Method also overrdie the onCancel()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.setCanceledOnTouchOutside(false)
return dialog
}
override fun onCancel(dialog: DialogInterface) {
super.onCancel(dialog)
Toast.makeText(context, "Break Point Here", Toast.LENGTH_SHORT).show()
}
you can use this code onBackPressed() methode
behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
Simpler solution.
Don't have to override onBackPressed method, just have to remove setCancelable(true) and add bottomSheetDialog.setCanceledOnTouchOutside(false) when you initialise the bottomSheetDialog.
I have a dialog fragment that initializes Google plus views, sometimes those views fail so I'd like to kill the dialog at that point, before it's displayed to the user.
How can I end the dialog creation process? returning null from onCreateDialog which returns a Dialog object crushes the program.
If you'd like to dismiss DialogFragment within onCreateDialog you can do the following:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
setShowsDialog(false);
dismiss();
return null;
}
No need to override onActivityCreated().
Solved it using the onActivityCreated() Fragment callback which is called after OnCreateDialog(). I return a valid Dialog from onCreateDialog() but flag with dismiss that the dialog should be dismissed.
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(dismiss) {
this.dismiss();
}
}
The other answers are a bit outdated and one didn't work for me (wrote there my comments about it), so here's what I think is updated and working:
On the onCreateDialog callback, have your logic of when it succeeds. If failed, return some default dialog (won't be used anyway) while adding to the lifecycle's onStart callback to dismiss the DialogFragment (use dismiss or dismissAllowingStateLoss):
fun Lifecycle.runOnStarted(runnable: () -> Unit) {
addObserver(object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
runnable.invoke()
}
})
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
//create the builder of the dialog, and then check if need to dismiss
if (needToDismiss) {
lifecycle.runOnStarted{
dismissAllowingStateLoss()
}
return builder.create()
}
Alternative, using kotlin coroutines and without using the helper function I've made:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
//create the builder of the dialog, and then check if need to dismiss
if (needToDismiss) {
lifecycleScope.launch {
whenStarted {
dismissAllowingStateLoss()
}
}
return builder.create()
}
Or you can use this helper function that uses kotlin coroutines to make it a bit shorter:
fun LifecycleOwner.runOnStarted(runnable: () -> Unit) {
lifecycleScope.launch {
whenStarted{
runnable.invoke()
}
}
}
The usage would be as short as before:
runOnStarted{
dismissAllowingStateLoss()
}
Note that I use onStart callback instead of onCreate. The reason is that for some cases, onStart works, while onCreate won't.