Android: refresh/update fragment from another activity on button clicked - android

I have a Dialog prompt in mainActivity. If user close the Dialog, I need to show red dot to one of the ListView items inside fourthFragment(as per redbox in fourthFragment in image below).
The problem is the red dot only be updated after I close the app and reopened it, because fourthFragment already done created BEFORE user close the Dialog. How can I refresh/update the fourthFragment after Dialog closed so that red dot can be shown immediately?
short description:
mainActivity: on Dialog closed > store showRedDot="1" to local db
fourthFragment: onCreate > read showRedDot from local db, if "1", show red dot. ( problem here, when onCreate, showRedDot is still "0", so I need to update fourthFragment layout after dialog closed.)

Try Interface or Broadcast receivers as above. If else refresh the fragment as
// Reload current fragment
Fragment frg = null;
frg = getSupportFragmentManager().findFragmentByTag("Your_Fragment_TAG");
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();

You have calling a interface to push event dismiss(button click) of dialog.
Like this:
public interface MyDialogListener {
void OnCloseDialog();
}
public class fourthFragment extend Fragment implements MyDialogListener {
public void SomeMethod() {
MyDialog myDialog = new MyDialog(this, this);
myDialog.show();
}
public void OnCloseDialog() {
// Do update your listview in here( maybe call method initialize data for listview)
}
}
public class MyDialog extends Dialog {
MyDialogListener mListener;
public MyDialog (Context context, MyDialogListener listener) {
super(context, R.style.Dialog);
mListener = listener;
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.CloseButton:
// Push event when Dialog close(or anything)
mListener.OnCloseDialog();
dismiss()
break;
default:
//...
}
}
}

Related

DialogFragment doesn't show up in the listener

I know there is one question with same title, but my scenario is a bit complex. In FragmentA, once click the button will start a new activity to show FragmentB, if then click one button in FragmentB, i need to dismiss FragmentB and go back to FragmentA and show DialogFragmentC. What i do is define one listener in FragmentB and implement it in FragmentA.
The sample snippet is as below:
class FragmentA extends Fragment implements FragmentBDelegate {
.......
#Override
public void onButtonClicked() {
DialogFragment popup = new DialogFragmentC();
popup.show(((AppCompatActivity)getContext()).getSupportFragmentManager(), null);
}
......
}
class FragmentB extends Fragment{
......
private void onButtonClicked(View v) {
getActivity().finish();// to dismiss current activity
if(mListener != null) {
mListener.onButtonClicked();
}
}
public interface FragmentBDelegate {
void onButtonClicked();
}
......
}
Why the DialogFragment doesn't show up? If listener cannot implement this requirement, how to implement?
#ADM's comment guide me to one workaround. I define one showWithStateLoss() method with commitAllowingStateLoss() to commit the FragmentTransaction in DialogFragmentC. Then it works.
public void showWithStateLoss(FragmentManager manager, String tag) {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss(); //original it's commit()
}
You should not (maybe you can, but should not) use callback method between different activities.
If this is exactly what you need to do, you need to start 2nd activity for result with startActivityForResult(). Then decide if you want to show dialog based on 2nd activity result. FragmentB will set result rather than trying to call 1st activity's callback.

Sending data between fragments without creating new fragment

So I have a fragment (WifiSetupFragment) that calls a DialogFragment, and that DialogFragment needs to pass a string back to the original fragment. I know to do this you have an interface in the activity that will send data to the original fragment like so, which I am already doing:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.content_frag, WifiSetupFragment.newInstance(password));
transaction.commit();
So the first time I call WifiSetupFragment, I haven't created a DialogFragment yet because I haven't clicked on an item to open the dialog. My question is should I just call
WifiSetupFragment.newInstance(null)
and have a null check for the password string in my fragment? Because I don't have a password unless the DialogFragment is open, and it's not always open. If this made no sense, please tell me and I'll try to explain more clearly. I guess it just seems strange to me to have a parameter for a string that might only be sent to this fragment occasionally since the data isn't constantly being passed in.
You don't need to communicate between these Fragments through the Activity. What you can do instead:
Make your WifiSetupFragment.newInstance() accept no parameters.
Make WifiSetupFragment implement a new interface, let's call it OnPasswordSuppliedListener.
Once you create your DialogFragment instance, attach it to a getChildFragmentManager() instead of getFragmentManager().
Now inside of your DialogFragment subclass you can reference WifiSetupFragment by calling getParentFragment().
Cast getParentFragment() to your interface and voila!
Note: I'm assuming you're using Fragments from the support library. Otherwise please be aware that nested Fragments feature was introduced in the API 17.
Your dialog can define an interface allowing to send input password back to parent fragment / activity:
public class TestDialog extends DialogFragment {
private TextView mPasswordView;
private OnPasswordDefinedCallback mCallback;
public static TestDialog newInstance() {
TestDialog dialog = new TestDialog();
return dialog;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// inflate layout for your dialog (it must include edit text for password)
LayoutInflater inflater = getActivity().getLayoutInflater();
View layout = inflater.inflate(R.layout.dialog_test, null);
// getting ui elements from layout
mPasswordView = (TextView) layout.findViewById(R.id.txt_password);
// building dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(layout);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
try {
mCallback = (OnPasswordDefinedCallback) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException("must implement OnPasswordDefinedCallback");
}
if (mCallback != null) {
// send password back to parent
mCallback.doPasswordDefined(mPasswordView.getText().toString());
}
dismiss();
}
});
return builder.create();
}
public interface OnPasswordDefinedCallback {
void doPasswordDefined(String password);
}
}
Then in WifiSetupFragment you can proceed as follows for opening PasswordDialog:
TestDialog dialog = TestDialog.newInstance();
dialog.setTargetFragment(WifiSetupFragment.this, 1);
dialog.show(getChildFragmentManager(), null);
WifiSetupFragment must of course implement interface OnPasswordDefinedCallback.

How to prevent DialogFragment from being dismissed when activity gets resumed

I have an Activity which shows a DialogFragment when an event occurs in the Activity. When my application is running the user can press home button to make the app run in background. When app is running in background, as soon as the event occurs, the activity should show the DialogFragment, so that when user resumes the app the dialog should be on top of the activity, however I am not getting the results I want. As soon as I resume the app from launcher icon or notification, the dialog does not appear on the activity.
Here is my DialogFragment class:
public static class MyDialog extends DialogFragment {
public static DialogInterface.OnClickListener mListener;
public static String mTitle, mBody;
public static boolean mConfirm;
public static MyDialog getInstance(String body, boolean confirm,
DialogInterface.OnClickListener listener) {
mListener = listener;
mTitle = "MyDialog";
mBody = body;
mConfirm = confirm;
MyDialog fragment = new MyDialog();
return fragment;
}
#Override
public Dialog onCreateDialog(Bundle savedIntanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle(mTitle).setMessage(mBody)
.setPositiveButton("Ok", mListener);
if (mConfirm)
builder.setNegativeButton("Cancel", mListener);
return builder.create();
}
}
The dialog works fine when activity is in foreground.
Here is how I show the dialog:
MyDialog.getInstance("This is dialog body text", true,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
// positive button pressed
}else //negative button pressed
}
}).show(getSupportFragmentManager(), "dialog");
I want a dialog that remains on the activity even if the activity is in background, and as soon as I resume the activity, the dialog should be on top of the activity. How can I achieve this behavior?
You can declare a global boolean to determine if you should show the dialog or not. Then in your activity onResume() method you show the dialog depending on the boolean value.
If the user is finished interacting with the dialog you can set this boolean to false which will cause it not to show again when your activity is in the foreground (onResume).
Try using Fragment's or Activity's showDialog(int) methods and your dialog will be retained automatically.

Android DialogFragment started inside a Fragment

I have a few fragments, and in one of them I have to ask the user to select time, so from the fragment I open up a DialogFragment with TimePicker and Button, so I want when the button is clicked to update the view in the Fragment which opened the dialog, how can I do that?
public interface DialogListener {
public void onDialogEnded(Bundle bundle);
}
in the Parent Fragment listen to this DialogListener.
in the Dialog fragment call the DialogListener with null or any kind of bundle with data this will call the listener in the parent Fragment with what you need.
in the DialogFragment create a setup Listener example :
private DialogListener mListener;
public void setListener(DialogListener listener) { mListener = listner; }
when you call the Dialog call the Listener before.
The easiest way is to replace the fragment calling your context, like this:
public void replaceFrag(){
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, new YourNewFragment());
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
Call this method in your button's onClick() event
this assmumes, that your fragment was programmatically commited into a fragment_container xml tag, which you might need to adapt accordingly.

Interface communication from fragment to activity issue

I've recently tried to use an interface for fragment-activity communication. The idea is that when a button is pressed in a fragment, it retrieves data from an EditText in the same fragment, it then sends the string to the MainActivty - this controls all my fragments - which then starts another fragment and delivers the string to this fragment for use later, however, I'm having trouble initially setting up the first interface which sends the data. Unfortunately nothing happens, and I cannot therefore get to the next fragment which should be displayed. Additionally I have tried using getActivity() but it cannot find the associated method within the fragment, leading me to believe that the fragments somehow aren't directly connected to MainActivity (I've only just grasped basics of Java and a little of Android, just learning.)
I've listed the relevant information below, thanks for the assistance!
Fragment
public class CreateWorkoutFragment extends Fragment implements OnClickListener {
View rootViewCreateWorkoutFragment;
EditText editTextWorkoutName;
// Using an ImageView for custom button
ImageView buttonNext;
String valueCreateWorkoutEditText;
OnDataPass dataPasser;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootViewCreateWorkoutFragment = inflater.inflate(R.layout.fragment_create_workout, container, false);
buttonNext = (ImageView) rootViewCreateWorkoutFragment.findViewById(R.id.button_workout_name_next);
editTextWorkoutName = (EditText) rootViewCreateWorkoutFragment.findViewById(R.id.edit_text_workout_name);
buttonNext.setOnClickListener(this);
return rootViewCreateWorkoutFragment;
}
public interface OnDataPass {
public void onDataPass(String data);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
dataPasser = (OnDataPass) activity;
}
public void passData(String data) {
dataPasser.onDataPass(data);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_workout_name_next:
valueCreateWorkoutEditText = editTextWorkoutName.getText().toString();
passData(valueCreateWorkoutEditText);
break;
}
}
}
Main Activity
public class MainActivity extends FragmentActivity implements OnClickListener, CreateWorkoutFragment.OnDataPass {
ImageView buttonCreate;
Fragment newFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppThemeBlue);
setContentView(R.layout.activity_main);
buttonCreate = (ImageView) findViewById(R.id.create_foreground);
buttonCreate.setOnClickListener(this);
FragmentManager fragManager = getSupportFragmentManager();
FragmentTransaction tranManager = fragManager.beginTransaction();
CreateWorkoutFragment createWorkoutFrag = new CreateWorkoutFragment();
// fragment_change is just the area in XML where fragments switch
tranManager.add(R.id.fragment_change, createWorkoutFrag);
tranManager.commit();
newFragment = null;
}
#Override
public void onDataPass(String data) {
// CreateFragment is not to be confused with CreateWorkoutFragment
// CreateFragment is the fragment I'm trying to start when any strings
// are obtained from CreateWorkoutFragment
newFragment = new CreateFragment();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
// create_foreground is just an ImageView used as a button
// Additionaly, other buttons are used to create other fragments,
// I've cut them out currently as they are not nessesary which is
// why CreateWorkoutFragment is only button and default currently
case R.id.create_foreground:
newFragment = new CreateWorkoutFragment();
break;
default:
newFragment = new CreateWorkoutFragment();
}
FragmentTransaction tranManager = getSupportFragmentManager().beginTransaction();
tranManager.replace(R.id.fragment_change, newFragment);
tranManager.addToBackStack(null);
tranManager.commit();
}
}
Sorry the code isn't exactly tidy, however, it was the most relevant code cut out from a large class. As I said, I have tried other methods yet cannot get any response from MainActivity either way. Thanks in advance!
Just before I posted: Got the app to write logcat messages to me, it manages to pass the data when the button is clicked - at least I think, and is something to do with the fragment not starting! At MainActivity>onDataPass()>new Fragment = new CreateFragment() Any ideas? As mentioned before, other buttons do exist and manage to change the fragment. However, were cutout to reduce amount of code posted.
getActivity() but it cannot find the associated method within the fragment
This is because getActivity() returns an Activity, not a MainActivity which is your custom subclass. You can easily fix this with a cast. For example, in your fragment, you can do this:
OnDataPass main = (OnDataPass) getActivity();
main.onDataPass(message);
Since such a cast is required, the interface seems to get in the way in my opinion. You can just as easily cast directly to MainActivity:
MainActivity main = (MainActivity) getActivity();
main.onDataPass(message);

Categories

Resources