Error adding objects to public arraylist in android application - android

I've extended Application and declared a public ArrayList there that I use to hold data (I know it's not as a Singleton in android should be, but it was the only thing I could make work).
The problem :
When I display my CreateNewObject dialog and press OK I get the following error.
Error:
10-30 10:20:19.069: E/AndroidRuntime(632): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.nuclear.gfr.adapter.PatientAdapter)]
My code:
public class NewPatientDialog extends DialogFragment {
private static final String TAG = "NUKClear";
OnNewPatientlistener listener;
private NewPatientDialog() {
}
public interface OnNewPatientlistener {
public void OnNewPatient(Patient newPatient);
}
public void addPatientAction(Patient patient) {
OnNewPatientlistener activity = (OnNewPatientlistener) getActivity();
activity.OnNewPatient(patient);
}
public static NewPatientDialog newInstance(String title) {
NewPatientDialog frag = new NewPatientDialog();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments().getString("title");
LayoutInflater inflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View newPatient = inflater.inflate(R.layout.new_patient_dialog,
null);
Log.d(TAG, "Creating dialog for new patientinput...");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(title)
.setView(newPatient)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
final EditText name = (EditText) newPatient
.findViewById(R.id.name_edit);
final EditText ssn = (EditText) newPatient
.findViewById(R.id.ssn_edit);
final EditText accnum = (EditText) newPatient
.findViewById(R.id.accnr_edit);
final Patient patient = new Patient(ssn.getText()
.toString(), name.getText().toString(),
new Study(SimpleDateFormat
.getDateInstance().toString(),
accnum.getText().toString()));
addPatientAction(patient);
DatabaseHelper db = new DatabaseHelper(
getActivity());
db.addPatientStudy(patient);
/*DataManager dm = new DataManager(getActivity()
.getBaseContext());
dm.addPatient(patient);*/
/*
* PatientManager pm = new
* PatientManager(getActivity
* ().getBaseContext()); pm.add(patient);
*/
// Interfacecallback
/*
* OnNewPatientlistener activity =
* (OnNewPatientlistener) getActivity();
* activity.OnNewPatient(patient);
*/
}
})
.setNegativeButton(R.string.alert_dialog_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
dismiss();
}
}).create();
}
}
Can anyone explain why this happens and how to circumvent this?

Adding...
runOnUiThread(new Runnable() {
public void run() {
GFRApplication.dPatients.add(newPatient);
}
});
...did the trick.

Related

Sending data from Dialog to Fragment

I am trying to send some data from a DialogFragment to a TextView from a Fragment.
After inserting the data in the available input and pressing SAVE, the app crashes.
I assume there is something wrong with the IncomeDialogListener.
I would appreciate some hints where I did wrong.
This is the Dialog Class
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_incomedialog, null);
builder.setView(view)
.setTitle("Add Income")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
incomeDialogListener.addDetails(Amount, Note, Date);
}
});
enter_income_amount = view.findViewById(R.id.enter_income_amount);
enter_income_note = view.findViewById(R.id.enter_income_note);
enter_income_date = view.findViewById(R.id.enter_income_date);
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
incomeDialogListener = (IncomeDialogListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "Must Implement IncomeDialogListener");
}
}
public interface IncomeDialogListener {
void addDetails(String Amount, String Note, String Date);
}
This is the Fragment to which I want to send the data
public class IncomeFragment extends Fragment implements
IncomeDialog.IncomeDialogListener {
DatabaseHelper myDB;
Button btn_add_income;
TextView display_income;
public IncomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_placeholder2 , container, false);
display_income = (TextView) v.findViewById(R.id.display_income);
btn_add_income = (Button) v.findViewById(R.id.btn_add_income);
myDB = new DatabaseHelper(getActivity());
btn_add_income.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openIncomeDialog();
}
});
return v;
}
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.show(fragmentTransaction, "income dialog" );
}
#Override
public void addDetails(String Amount, String Note, String Date) {
display_income.setText(Amount);
}
}
Here is my solution for you:
IncomeFragment.java
public static final int INCOME_DIALOG_FRAGMENT = 1; // Add this line
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.setTargetFragment(IncomeFragment.this, INCOME_DIALOG_FRAGMENT); // Add this line
incomeDialog.show(fragmentTransaction, "income dialog");
}
IncomeDialog.java
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
IncomeDialogListener listener = (IncomeDialogListener) getTargetFragment();
listener.addDetails(Amount, Note, Date);
}
Update: There is no magic behind, when you open dialog from fragment, you passed itself to dialog by calling setTargetFragment. Then in the dialog you can refer to the fragment that opened it by calling getTargetFragment. Actually there are 2 solutions you can use.
IncomeFragment incomeFragment = (IncomeFragment) getTargetFragment();
incomeFragment.addDetails(Amount, Note, Date);
or
IncomeDialogListener listerner = (IncomeDialogListener) getTargetFragment();
listerner.addDetails(Amount, Note, Date);
I prefer to use the second one because the dialog don't need to know about specific fragment that opened it. This makes the dialog is usable. Imagine a situation, three days later, you would like to open the dialog from another fragment, in that case you don't need to modify the dialog again, just let the another fragment implements IncomeDialogListener. If you use the first one, you must go to the dialog and modify it to make sure it works for the another fragment.

How to create a popup when button is pushed in Android?

How can I create a custom popup class that accepts a simple string message? Im new to Android and help with code will be appreciated.
When a button is pushed in the main layout, the popup must pop up on the screen.
Custom popup class
public class CustomPopup extends PopupWindow {
private String message;
private Double anchorX;
private Double anchorY;
PopupWindow popup;
public CustomPopup(String message) {
super();
this.message = message;
}
public void showPopup(Activity context) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
}
Main Class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText messageTxt = (EditText) findViewById(R.id.messageTxt);
Button generateBtn = (Button) findViewById(R.id.generateBtn);
String message = messageTxt.getText().toString();
final CustomPopup popup = new CustomPopup(message);
generateBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
popup.showPopup();
}
});
}
}
You can change the following code any way you need. This is just an example of how you make and implement a custom DialogFragment.
He is the code I use. I find it quite flexible because you can create several similar dialogs for slightly different tasks. You will need to create a layout file - this gives you a great deal of flexibility on function and style.
My layout file is fragment_ok_cancel_dialog.
To satisfy your requirements just create your own layout file with all the elements in it you need (like your image).
In the Activity that calls the dialog you will need to implement the Listener.
implements OkCancelDialogFragment.OkCancelDialogListener
Another advantage is with my code you can change the title and the message to fit the needs of any Activity.
private void callMyDialog(){
//Customize the title and message as needed
String title = "This is my dialog title";
String mess = "This is my dialog message";
OkCancelDialogFragment dialog = OkCancelDialogFragment.newInstance(title, mess);
dialog.show(getFragmentManager(), "OkCancelDialogFragment2");
}
Now you need to implement the dialog callback in the Activity that calls the DialogFragment.
#Override
public void onFinishOkCancelDialog(boolean submit) {
if(submit){
// Do something positive
}
else{
// Do something negative
}
}
Now the code for the DialogFragment:
public class OkCancelDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
private static final String ARG_MESSAGE = "message";
Context context = null;
private String title;
private String message;
private boolean submitData = false;
private OkCancelDialogListener mListener;
public OkCancelDialogFragment() {
}
public static OkCancelDialogFragment newInstance(String title, String message) {
OkCancelDialogFragment fragment = new OkCancelDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putString(ARG_MESSAGE, message);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
title = getArguments().getString(ARG_TITLE);
message = getArguments().getString(ARG_MESSAGE);
}
}
#Override
public Dialog onCreateDialog(Bundle saveIntsanceState){
context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View rootView = inflater.inflate(R.layout.fragment_ok_cancel_dialog, null, false);
final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);
titleView.setText(title);
messView.setText(message);
builder.setView(rootView)
// .setTitle(title)
.setPositiveButton(R.string.ok_button_dialog_title, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = true;
if(mListener == null) mListener = (OkCancelDialogListener) context;
mListener.onFinishOkCancelDialog(submitData);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = false;
if(mListener == null) mListener = (OkCancelDialogListener) context;
mListener.onFinishOkCancelDialog(submitData);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
if(mListener == null) mListener = (OkCancelDialogListener) context;
}
catch (Exception ex){
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OkCancelDialogListener {
void onFinishOkCancelDialog(boolean submit);
}
}
Please note that .setTitle(title) is valid for API 23 or higher (or maybe API 21 or higher?).
You can create your custom xml layout
and in the OnClickListener of the button you can put this :
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
alertLayout = inflater.inflate(R.layout.YOUR_CUSTOM_POPUP_LAYOUT, null);
final AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setView(alertLayout);
TextView msg= alertLayout.findViewById(R.id.YOUR_TEXTVIEW_ID);
alert.show();
after that you can add another button in your popup and set a listener on it to dismiss the layout after the click.

Calling a method in a Fragment from an AlertDialog

Could you please help with the below:
I am trying to call the method deletePlayer inside the fragment PlayersActivityFragment from the alertdialog NameAlertDialogFragment.
The code is below:
public static class PlayersActivityFragment extends Fragment {
ArrayList<Player> arrayPlayers;
ListView listViewPlayers;
//PlayerAdapter adapter;
public PlayersActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
arrayPlayers = new ArrayList<Player>();
View rootView = inflater.inflate(R.layout.fragment_activity_players, container, false);
Button buttonAddPlayer = (Button) rootView.findViewById(R.id.button_addplayers);
buttonAddPlayer.setOnClickListener(new View.OnClickListener(){
public void onClick(View view) {
arrayPlayers.add(new Player("Player", 0));
Player selectedPlayer = arrayPlayers.get(arrayPlayers.size()-1);
((PlayersActivity)getActivity()).showNameDialogFragment(selectedPlayer);
}
});
listViewPlayers = (ListView) rootView.findViewById(R.id.listView_playername);
return rootView;
}
public void deletePlayer(){
arrayPlayers.remove(arrayPlayers.size()-1);
}
}
void showNameDialogFragment(Player player) {
mDialog = NameAlertDialogFragment.newInstance(player);
mDialog.show(getFragmentManager(),"SCORE DIALOG");
}
// Class that creates the AlertDialog
public static class NameAlertDialogFragment extends DialogFragment {
static Player selectedPlayer;
public static NameAlertDialogFragment newInstance(Player player) {
selectedPlayer = player;
return new NameAlertDialogFragment();
}
// Build AlertDialog using AlertDialog.Builder
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.alertdialog_name, null);
final EditText editTextName = (EditText) view.findViewById(R.id.edittext_name);
return new AlertDialog.Builder(getActivity())
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
.setView(view)
.setMessage("Enter Player's Name:")
//Set up Yes Button
.setPositiveButton("Done", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, int id) {
mName = editTextName.getText().toString().trim();
selectedPlayer.setName(mName);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//PlayersActivityFragment playersActivityFragment = (PlayersActivityFragment) getFragmentManager().findFragmentById(R.id.container);
//playersActivityFragment.deletePlayer();
//((PlayersActivityFragment)getTargetFragment()).deletePlayer();
NameAlertDialogFragment.this.getDialog().cancel();
}
})
.create();
}
}
The two different ways I have tried to call the methods are commented out in the .setNegativeButton onClickListener:
PlayersActivityFragment playersActivityFragment = (PlayersActivityFragment) getFragmentManager().findFragmentById(R.id.container);
playersActivityFragment.deletePlayer();
and
((PlayersActivityFragment)getTargetFragment()).deletePlayer();
Thank you!
First of all, why are all of your classes static? Anyway, here's an answer that should work...
Try using an interface as a callback. For example:
First create an interface.
public interface NameAlertDialogListener {
public void onNegativeClick();
}
Then have PlayersFragment implement NameAlertDialogListener.
public static class PlayersActivityFragment extends Fragment implements NameAlertDialogListener
Next, in the PlayersFragment, create a method called onNegativeClick.
#Override
public void onNegativeClick() {
//delete or whatever you want to do.
}
Create a member variable for the listener:
static Player selectedPlayer;
static NameAlertDialogListener mCallBack;
Next create a method in the dialog fragment called setListener.
public void setListener(NameAlertDialogListener callback) {
try {
mCallBack = callback;
} catch (ClassCastException e){
throw new ClassCastException(callback.toString() + " must implement NameAlertDialogListener" );
}
}
Then, when you create the dialog fragment call the setListener method.
void showNameDialogFragment(Player player) {
mDialog = NameAlertDialogFragment.newInstance(player);
mDialog.setListener(this);
mDialog.show(getFragmentManager(),"SCORE DIALOG");
}
Lastly, in your negative click listener:
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mCallBack.onNegativeClick() ;
NameAlertDialogFragment.this.getDialog().cancel();
}
})
I am not sure if this is the correct way of doing things, but I have come to a working solution.
First I moved ArrayList<Player> arrayPlayers; outside of the PlayersActivityFragment fragment.
Then I moved the method:
public void deletePlayer(){
arrayPlayers.remove(arrayPlayers.size()-1);
}
outside of the PlayersActivityFragment fragment.
I then called the deletePlayer() method inside the alertdialog with the line ((PlayersActivity)getActivity()).deletePlayer();.
Actually, I have a little hack, it's not really good, but it's easy to implement: declare PlayersActivityFragment variable in your DialogFragment. Then change your constructor to:
public static NameAlertDialogFragment newInstance(Player player,PlayersActivityFragment fragment ){
selectedPlayer = player;
NameAlertDialogFragment test = new NameAlertDialogFragment();
test.playerActivityFragment = fragment;
return test;
}
Then you can call playerActivityFragment.deletePlayer() everywhere in your DialogFragment.
P/s: The best way is implement interface, but for lazy coder like me, the method above is better lol!

DialogFragment disappears on screen rotation

This fairly simple dialog dismisses itself after screen rotation despite I setRetainInstance to true. Any ideas whats wrong?
public class StreetDialog extends DialogFragment {
public static StreetDialog newInstance(String[] values) {
StreetDialog f = new StreetDialog();
Bundle args = new Bundle();
args.putStringArray("values", values);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String[] values = getArguments().getStringArray("values");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//build my dialog
return builder.create();
}
#Override
public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
}
If I recall correctly is the normal behaviour. I usually provide a tag to the show method, and when the Activity's onCreate is called again, I look for the tag. If the fragment != null I remove it, before creating and showing the new one. In code, what I usually do is:
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
if (fragment != null) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
new CustomDialogFragment().show(getSupportFragmentManager(), FRAGMENT_TAG );
This is an issue that I believe the best way to solve and using an approach below:
Create a static method to initialize a Dialog, remembering that this is a good practice since we always have the default constructor and the Bundle stores the state of the Fragment.
In onCreateDialog method, initialize the AlertDialog with the data passed in the "constructor method".
In your Activity you can implement an interface (because we can not keep the reference of it, since it may have been destroyed when rotating the device). To open the dialog,
checking that it has been added to FragmentManager otherwise exhibit.
see more here (Link in portuguese - br): http://nglauber.blogspot.com.br/2013_10_01_archive.html
public class SimpleDialog extends DialogFragment implements OnClickListener {
private static final String EXTRA_ID = "id";
private static final String EXTRA_MESSAGE = "message";
private static final String EXTRA_TITLE = "title";
private static final String EXTRA_BUTTONS = "buttons";
private static final String DIALOG_TAG = "SimpleDialog";
private int dialogId;
public static SimpleDialog newDialog(int id,
String title, String message, int[] buttonTexts){
// Using the Bundle to save state
Bundle bundle = new Bundle();
bundle.putInt(EXTRA_ID, id);
bundle.putString(EXTRA_TITLE, title);
bundle.putString(EXTRA_MESSAGE, message);
bundle.putIntArray(EXTRA_BUTTONS, buttonTexts);
SimpleDialog dialog = new SimpleDialog();
dialog.setArguments(bundle);
return dialog;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments() .getString(EXTRA_TITLE);
String message = getArguments().getString(EXTRA_MESSAGE);
int[] buttons = getArguments().getIntArray(EXTRA_BUTTONS);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setTitle(title);
alertDialogBuilder.setMessage(message);
switch (buttons.length) {
case 3:
alertDialogBuilder.setNeutralButton(buttons[2], this);
case 2:
alertDialogBuilder.setNegativeButton(buttons[1], this);
case 1:
alertDialogBuilder.setPositiveButton(buttons[0], this);
}
return alertDialogBuilder.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
// Your Activity must to implements this interface
((FragmentDialogInterface)getActivity()).onClick(dialogId, which);
}
public void openDialog( FragmentManager supportFragmentManager) {
if (supportFragmentManager.findFragmentByTag( DIALOG_TAG) == null){
show(supportFragmentManager, DIALOG_TAG);
}
}
// Interface that was invoked by clicking the button
public interface FragmentDialogInterface {
void onClick(int id, int which);
}
To open the dialog in your activity
public void openSimpleDialog(View v) {
SimpleDialog dialog = SimpleDialog.newDialog(
0, // Id from dialog
"Alert", // title
"Message", // menssage
new int[]{ // texts from buttons
android.R.string.ok,
android.R.string.cancel });
dialog.openDialog(getSupportFragmentManager());
}
#Override
public void onClick(int id, int which) {
Toast.makeText(MainActivity.this,
"Button clicked"+ which, Toast.LENGTH_SHORT)
.show();
}

Show DialogFragment from another DialogFragment

I have a DialogFragment that displays a list of options to the user, one of these options is "Delete" option, when the user presses the delete option I want to show another DialogFragment as a confirmation, unfortunately, the confirmation dialog doesn't show.
here is my code
First Fragment code
public class ContactDialogOption extends SherlockDialogFragment {
public static final String TAG = ContactDialogOption.class.getSimpleName();
public ContactDialogOption() {
super();
// TODO Auto-generated constructor stub
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle(R.string.options);
builder.setItems(new String[] {
getString(R.string.call), getString(R.string.send_message),
getString(R.string.copy), getString(R.string.edit),
getString(R.string.delete)
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(which == 4) //delete
{
FragmentManager mgr = getActivity().getSupportFragmentManager();
FragmentTransaction ft = mgr.beginTransaction();
Fragment old = mgr.findFragmentByTag("SecondFragment");
if (old != null) {
ft.remove(old);
}
ft.addToBackStack(null);
fragment.show(ft, fragmentTag);
}
}
});
return builder.create();
}
}
I got the exact same problem, this situation does not happen when you try to open a DialogFragment from a Fragment.
The only solution I found was to modify the following call:
fragment.show(ft, fragmentTag);
To:
fragment.show(getFragmentManager(), fragmentTag);
The problem with this solution is that we cannot work on the FragmentTransition.
I don't understand why the behavior is different than with the fragments.
I came across the same problem of not being able to show another DialogFragment from within the positive and negative click listeners of the first DialogFragment. My solution was to immediately pop the first fragment, which allows the second DialogFragment to attach and display successfully.
// Call this before adding the second dialog fragment
activity.getSupportFragmentManager().popBackStackImmediate();
Please check this following code. Hope this will help many of you!
public class SubcategoryFragment extends DialogFragment {
public SubcategoryFragment() {
}
public static SubcategoryFragment newInstance(Integer code, String name) {
SubcategoryFragment fragment = new SubcategoryFragment();
mCode = code;
mTitle = name;
return fragment;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
liststring = new ArrayList<>();
getAdapter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_subcategory, container, false);
gridView = (GridView) view.findViewById(R.id.sub_grid);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
closeDialog = (ImageView) getDialog().findViewById(R.id.closeDialog);
title = (TextView) getDialog().findViewById(R.id.dialogTitle);
gridView = (GridView) getDialog().findViewById(R.id.sub_grid);
title.setText(String.format("Choose %s", mTitle));
closeDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getDialog().dismiss();
}
});
}
#Override
public Dialog onCreateDialog(#NonNull Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// request a window without the title
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
// closeDialog = (ImageView) dialog.findViewById(R.id.closeDialog);
return dialog;
}
public void getAdapter() {
gridAdapter = new HomeSubGridViewAdapter(getContext(), R.layout.gridview_custom_layout, liststring);
gridView.setAdapter(gridAdapter);
}
}
This is the method for calling dialog from fragment
fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
SubcategoryFragment postalFragment = SubcategoryFragment.newInstance(Integer.valueOf(item.getId()), item.getName());
postalFragment.show(fragmentManager, "SubcategoryFragment");
Feel Free to ask if you feel any problem is that
You can call a DialogFragment from Another DialogFragment.
NewDialogFragment newDialogFragment= new NewDialogFragment();
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
newDialogFragment.show(transaction, "New_Dialog_Fragment");
Very recently, I had this problem and none of the options above worked for me. I tried using the method below:
DialogFragment fragment = new MyFragment(); //where MyFragment is my fragment I want to show
fragment.setCancelable(true);
fragment.show(getSupportFragmentManager(), "timePicker");
This will ONLY work if you're using this in an activity (i.e to call a dialog fragment from an activity class).
I however fixed this by downcasting my activity instance to an AppCompat activity and using it to call getSupportFragment() as shown below:
DialogFragment timeFragment = new TimePicker();
timeFragment.setCancelable(true);
AppCompatActivity activity = (AppCompatActivity) getActivity();
timeFragment.show(activity.getSupportFragmentManager(), "timePicker");
I hope this helps.. Merry coding!!
This is the code that works for me:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (getArguments() == null) {
throw new InvalidParameterException("The key types dialog needs the protocol id to be in the arguments");
}
if (mCallback == null) {
throw new InvalidParameterException("The key types dialog needs an callback to be set");
}
mProtocolId = getArguments().getInt(ApplicationConstants.FragmentsConstants.PROTOCOL_ID);
final List<KeyTypeEntity> allKeyTypes = BusinessFacade.getInstance(getActivity()).KeyTypeLogic.getAllKeyTypes();
ArrayAdapter<KeyTypeEntity> keyTypeAdapter = new ArrayAdapter<KeyTypeEntity>(getActivity(), android.R.layout.simple_list_item_1, allKeyTypes);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("").setAdapter(keyTypeAdapter, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final KeyTypeEntity keyTypeEntity = allKeyTypes.get(which);
AlertDialog.Builder number = new AlertDialog.Builder(getActivity());
List<String> keyNumbers = new ArrayList<String>();
for (int i = 0; i < 50; i++) {
keyNumbers.add("" + (i + 1));
}
ArrayAdapter<String> kAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, keyNumbers);
number.setTitle("").setAdapter(kAdapter, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
addNewKey(keyTypeEntity, which + 1);
}
});
number.show();
}
}).setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
mCallback.onDialogClosed();
}
});
mDialog = builder.create();
return mDialog;
}
In the first click handler I just create a new dialog and show it. This will close the first dialog, open the second one, and when the user clicks on an item in the list, the second click handler is called.
Hope this helps, and I am not too late :)
You can pass FragmentManage to newInstance() method of First DialogFragment then you can use it to show new dialogfragment
this is my code.
private static FragmentManager fragmentManager;
public static PlayListDialog newInstance(Context context, FragmentManager fragmentManager1) {
playListDialog = new PlayListDialog();
mContext = context;
fragmentManager = fragmentManager1;
return playListDialog;
}
#Override
public void createNewPlaylist() {
NewPlayListDialog newPlayListDialog = NewPlayListDialog.newInstance(mContext);
newPlayListDialog.showDialog(fragmentManager.beginTransaction(),fragmentManager.findFragmentByTag("newdialog"));
}
Use this:
getActivity().getSupportFragmentManager
instead of
getChildFragmentManager().
Hope this helps.
If you want the kotlin version use this:
val newDialogFragment = NewDialogFragment()
val transaction: FragmentTransaction =
requireActivity().supportFragmentManager.beginTransaction()
newDialogFragment.show(transaction, "New_Dialog_Fragment")

Categories

Resources