Looking for best way to implement modal dialog in onPause - android

I have fragment with EditTexts that user can change.
As well I have back button on Toolbar (and physical back button too)
When the user hits back, I check if the data was changed and if it was - I need to open dialog and ask the user "Do you want to save changes?". Get the click and act accordingly (positive or negative answer).
The best place to save the data (maybe I wrong) is in onPause of this fragment.
The problem is with the dialog - it is not modal and while it's showing the question and waits for user reaction - the fragment under it disappears and previous come back from stack.
I need to "pause the onPause" with the dialog until the user make his choice. What the easy (or most correct) way to do it?
#Override
public void onPause() {
if (!(text.getText().toString().equals(user.getName())))
{
new MaterialDialog.Builder(getActivity())
.title("Save changes?")
.content("You changed you personal details, save changes?")
.cancelable(false)
.positiveText("Save")
.negativeText("Discard")
.onPositive(new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
save();
}})
.show();
}
super.onPause();
}
If I want to do it before onPause - I'll need to catch the Toolbar's back button and physical back button - seems too much work for this. Looking for elegant way.
Thank you

onPause is called when the activity moves into the background (not being shown on the screen anymore).
To show a dialog before the app goes off screen, you can override the "onBackPressed" function in an activity.
#Override
public void onBackPressed() {
performBackPressed();
}
public void performBackPressed(){
//show your dialog here
//call finish(); when done to close app
}
You can call the performBackPressed() method whenever the Toolbar's back button is pressed too.
If you're trying to show a popup from a fragment when back is pressed, then you still have to override that method in the activity, then notifiy the fragment whenever back is pressed.
In my app I have a container in the activity that holds all my fragments. I use this code to get the currently active fragment:
YourFragmentClass curFrag = (YourFragmentClass) fragmentManager.findFragmentById(R.id.fragment_container);
then I have a method in the fragment called onBackPressed() and I just call that on the fragment I just got.

Related

Unable to finish activity when click back button

I used below code to close activity after back button pressed.
#Override
public void onBackPressed()
{
super.onBackPressed();
finish();
}
after 5 time pressed it worked
how to solve it ?
remove super.onBackPressed(); to avoid handling the back button by the class parents
If you want to finish when back press. don't need to Override.
#Override
public void onBackPressed()
{
// do something
}
this will do nothing when you press back button.
onBackPressed() usually needed when you want make custom ask to close dialog when back press.

clean RecyclerView after tap to button Back

I have RecyclerView that is filled with a list of items received from the server response.
First, the user enters a log / password and selects a specific content, such as: 1 content.
After login the user go to the activity with has RecyclerView, where there are fields of content 1.
When user click on the Back button he goes back to the main activity of registration and selects the already content 2. After clicking the Login button, again goes to RecyclerView, but for some reason it has fields from the content 1 and fields content 2 Add to end of list.
I use this methods :
#Override
public void onBackPressed() {
super.onBackPressed();
recyclerView.removeAllViewsInLayout();
recyclerView.removeAllViews();
unswerFromMain.clear();
recyclerAdapter.updateAdapter(unswerFromMain);
}
This is in Adapter :
public void updateAdapter (ArrayList<Unswer> updateUnswer){
getUnswer.clear();
getUnswer.addAll(updateUnswer);
notifyDataSetChanged();
}
All this method didn`t work.
I believe this is because you are calling onBackPressed() before you do anything else. This means those other lines never run. Try swapping it around:
#Override
public void onBackPressed() {
recyclerView.removeAllViewsInLayout();
recyclerView.removeAllViews();
unswerFromMain.clear();
recyclerAdapter.updateAdapter(unswerFromMain);
super.onBackPressed();
}
Set an empty array into your adapter and notify
adapter.setItems(new ArrayList<MyPOJO>);
adapter.notifyDataSetChanged();
EDIT
You should call super.onBackpressed for the last. Like this
#Override
public void onBackPressed() {
recyclerView.removeAllViewsInLayout();
recyclerView.removeAllViews();
unswerFromMain.clear();
recyclerAdapter.updateAdapter(unswerFromMain);
super.onBackPressed();
}
I found a bug.
The problem was not to clean the adapter, it was not cleansed ArrayList which was from the main activity. This ArrayList contains a field content 1 and when I was at activity with RecyclerView and pressed the Back button that returns to the main activity already filled ArrayList data content 1. Then I chose the content 2 and the data on it just added to the end of the ArrayList.
I completely removed all methods onBackPressed (), except super.onBackPressed (); and everything was working fine. Thank you all !
I'm tried with above answer are not work for me.
So I have handle RecyclerView with hide and show.
recyclerview.setVisiblity(View.GONE);
recyclerview.setVisiblity(View.VISIBLE);
and my logic is,
first initialize one int value globally like, int clicked = 0;
BackPress event use that below code:
public void onBackPressed(){
if(recycler_view!=null){
if(clicked==0){
recycler_view.setVisibility(View.GONE);
clicked =1;
}else{
finishAffinity();
}
}else {
finishAffinity();
}
}
When you show(recyclerview.setVisiblity(View.VISIBLE);) recyclerview in activity that time set Clicked =0
So, easy way to show and hide recyclerview as well as backpress also handled.

DialogFragment dismiss() does not pop backstack

I have a simple DialogFragment that calls dismiss when exits, according to the documentation:
public void dismiss()
Dismiss the fragment and its dialog. If the fragment was added to the
back stack, all back stack state up to and including this entry will
be popped. Otherwise, a new transaction will be committed to remove
the fragment.
however, I found that the fragment is still on the backstack after calling dismiss() so I have to click back button to clear it. Does anyone know why ?
here's my code:
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.test_layout);
class MyDialogFragment extends DialogFragment implements OnClickListener{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.hello_world, container, false);
Button b = (Button)v.findViewById(R.id.btn);
b.setOnClickListener(this);
return v;
}
#Override
public void onClick(View v) {
dismiss();
}
}
getFragmentManager().beginTransaction().add(android.R.id.content, new MyDialogFragment(), "test").addToBackStack("b").commit();
}
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
I also found out that if I don't override onBackPressed(), the back button simple doesn't work, no matter how many fragments I add to the activity, the back button always exits the activity right away.
I can confirm what #Luksprog said in his comment: the dialog must be started through show(FragmentTransaction, String).
Note after looking the source: make sure to call addToBackStack(String) on the supplied transaction or else it still won't work.
That it's a wrong way to create a DialogFragment.
Never ever use the FragmentManager to show a DialogFragment. To be shown there are a method called show(FragmentTransacion, String).
In java:
MyDialogFragment mDialogFragment = new MyDialogFragment();
mDialogFragment.show(getFragmentManager(), "MyDialogFragment");
For another hand, to dismiss the dialog just do this:
mDialogFragment.dismiss()
Another think that I would like to highlight is that the MyDialogFragment class is defined inner onCreate method :'(
Please, define the class outside the method or in another file if you want :)
Good Look!
dismiss()
findNavController().navigate(FirstBottomSheetDialogDirections.actionFirstSheetToSecondSheet())
This code is always the wrong thing to do: dismiss() is an asynchronous operation that doesn't actually dismiss anything immediately. That is unlike the navigate() which does immediately update the NavController's state, stacking the new dialog destination on top of the previous one.
This means that when the asynchronous dismiss actually happens, it correctly removes the dialog and, because it is a navigation stack, removes everything on top of it - including your second dialog. However, due to a bug in the DialogFragmentNavigator, we don't actually dismiss that second dialog, which is why it appears to work, despite everything actually already being internally out of sync (thus causing the later crash).
The correct way to pop a destination and navigate to a new destination as an atomic, immediate operation is to use popUpTo and popUpToInclusive. Therefore you can fix the sample app by removing the call to dismiss() and updating the action to pop the first dialog as part of the navigate call:
<action
android:id="#+id/action_firstSheet_to_secondSheet"
app:destination="#id/secondSheet"
app:popUpTo="#id/firstSheet"
app:popUpToInclusive="true"/>
This correctly pops the first dialog off the back stack and then navigates to the new dialog destination.
please refer this link : https://issuetracker.google.com/issues/191073055

BackButton in the Fragment cannot be disabled

I have a mainActivity with viewPager and three tabs, each tab has its respective fragment. i want when this mainActivity is launched and the backButton is pressed, nothing to happen.
to achieve this, i override onBackPressed() inside the mainActivity the one has viewPager with tabs, but when the mainActivity ia launched one of the tabs, which represents Fragment, by default appears, and when i press the backButton, i go back, which means the Backbuton is not disabled.
that is it, in the mainActivity, i have:
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
Log.w(TAG, "#onBackPressed().");
}
and he backbutton is not disabled in the Fragment, each time i press it, the logCat displays the message in the onBackPressed and i go back, and i do not want this, i want while i am in the Fragment "any one of the tabs", the backButton should has no effect.
please let me know how to achieve this?
Try not calling
super.onBackPressed();
Although the log will still print because the method will be called, this will stop Android performing it's logic and going back.
If you want the fragment tabs to do nothing, but the viewpager to handle it, do something like this
#Override
public void onBackPressed() {
if (getCurrentTab == 0) {
super.onBackPressed();
} else {
//This will stop the fragment tabs from doing anything when back is pressed
}
}
If you need avoid the back button, comment the super call //super.onBackPressed();

How can I re use my alert DialogFragment for a result?

I recently created a standard list DialogFragment to build an AlertDialog in my Activity as can be seen as the answer here:
What is the best way to recreate an AlertDialog when the screen is rotated?
Now I would like to re-use this fragment for 3 different "Pop Up" selection lists in my activity. For each of the three buttons I need to identify the calling button to determine what action to take when the item from the list is selected.
What is the best way to achieve this?
Currently I am thinking that I need to pass the calling button ID to the DialogFragment and then pass it back to the activity with the result when the dialog completes. Is there a better way to achieve this goal?
I think probably the easiest way to achieve what you're going for is to just have three different listeners inside of your DialogFragment, and then have setters for each. Then when you build the alert dialog as a fragment, you can define what the onClick method for each listener will do in the calling method. So something like this:
protected DialogInterface.OnClickListener mListener1;
protected DialogInterface.OnClickListener mListener2;
protected DialogInterface.OnClickListener mListener3;
public void setListener1(final YourDialogFragment.OnClickListener passedListener) {
mListener1 = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
listener.onClick(getActivity(), dialog, which);
}
};
}
Then inside of the code that calls the DialogFragment, call something like:
// Building the Dialog Fragment here
YourDialogFragment.setListener1(new YourDialogFragment.OnClickListener() {
#Override
public void onClick(FragmentActivity activity, DialogInterface dialog, int which) {
// Whatever you want to happen when you click goes here
}
});
Ideally you make some sort of helper to just take parameters so you're not explicitly calling the set methods from an activity, but that's the gist of it.
I would recommend you to show the dialog fragment from another fragment where you can implement the onClick listeners and use setTargetFragment() to tell the dialog fragment that who it is working with..
dialogFragment.setTargetFragment(this, 0);
and use getTargetFragment() to get the parent fragment from DialogFragment.
here is some code snippets from sample programs..
// Retrieve the progress bar from the target's view hierarchy.
mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById(
R.id.progress_horizontal);
And also you can use setRetainInstance(true) in onCreate() method to tell the framework to try to keep this fragment around during a configuration changes
See this answer to get more idea, hope this helps..

Categories

Resources