How to show a Fragment in a Dialog? - android

I have created a fragment with some text and an image:
public class ContentFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_content, container, false);
return view;
}
}
Is there any way to get it to show in a dialog?
For example:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Showing a fragment in a dialog");
// Load fragment as dialog content somehow
AlertDialog alert = builder.create();
alert.show();

Every dialog has setView method which you can create programmatically or inflate, see this example
You should also consider to use a DialogFragment

AlertDialog is not supposed to host a fragment.
A workaround you can use is to replace dialog UI, which can be achieved by:
dialog.setContentView(R.layout.fragment_content)
This will just change the dialog view, if you want to bind events or data to the controls inside your fragment, you need to do it after setContentView

Related

Changing DialogFragment Layouts while dialog is open

I have an Android Activity, from which I want to show a Dialog. It would probably be a custom DialogFragment. Now when the user clicks on specific buttons I want the layout's inside the dialog to change with the data from the previous DialogFragment and so that it would have an ability to also go back to previous Layout.
I dont think there is an easy way to change views inside of the same DialogFragment so what would be the best way to do this?
I have tried doing it in method onViewCreated and when a button is clicked, but nothing happens.
In my activity I call the fragment like this at the moment:
FragmentManager fm = getSupportFragmentManager();
NewDialog newDialog = NewDialog.newInstace(userId, loc, currentId);
newDialog.setNewClickListener(new NewDialog.OnNewClickListener() {
#Override
public void onCancelClicked() {
finishAdd();
}
#Override
public void onAcceptClicked() {
...
}
});
newDialog.show(fm, "new_frag");
And the fragment:
public class NewDeliveryPointDialog extends DialogFragment {
private LayoutInflater inflater;
private ViewGroup container;
public NewDialog(){
}
public static NewDialog newInstace(){
...
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
this.inflater = inflater;
this.container = container;
return inflater.inflate(R.layout.dialog_layout_1, container);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
saveButton.setOnClickListener(v -> {
View.inflate(getContext(), R.layout.dialog_layout_2, container);
view.invalidate();
view.refreshDrawableState();
}
});
}
}
A DialogFragment is not made to have navigation to other fragments within the same dialog.
You basically have these options:
On your button click you close the Dialog and open another Dialog. But this seems odd. If there is so much happening, probably dialogs are not the best shot.
Instead of DialogFragments have another fragment container overlaying the original one (basically what a Dialog fragment does for you). Within the second container you can easily navigate to other fragments and set it to gone when the user finished interaction.
If there are just a few Views in the Dialog, you could consider setting the old ones to gone and the new ones to visible
I think your code didn't work, because container is null. Method onCreateView gives you #Nullable ViewGroup container, which is null for DialogFragment (but non null for Fragment). So when you call View.inflate(getContext(), R.layout.dialog_layout_2, container), it just creates a view in memory and doesn't attach it to container, cause it is null. See LayoutInflater.inflate, cause View.inflate is just a convenience wrapper for this function.
I dont think there is an easy way to change views inside of the same DialogFragment so what would be the best way to do this?
Instead of changing dialog root you can just manipulate child views inside dialog root layout (add, remove them, or change visibility).
Also my advice is to use recommended way to create dialog with custom layout (onCreateDialog + setView), but if you don't want to do that, you can refer view you've created in onCreateView as dialog root.
You can try creating a dialog fragment with an empty shell layout in which you would replace your two different fragments with ChildFragmentManager and regular fragment transactions
passing data between them can be done using the activity's view model since they both live in the same activity.
So add the ShellDialogFragment using the activity's FragmentManager and in the shell fragment class change between NewDialog & NewDeliveryPointDialog on your button click listener with ChildFragmentManager

How to add a Done(Check) button on top right in a Dialog Fragment?

I've been struggling to add a Done(Check) button like Google Calender(right one) on the top right of the dialog fragment.
Currently, I'm displaying a title and a map inside the Dialog Fragment. Is there a way to customise the dialog fragment like that?
Thanks!
You can set the style to STYLE_NO_FRAME and create a custom dialog layout. Then you'd be free to add any views you want, including buttons in a title area.
You should create your custom dialog fragment, this is an example how to do that:
public class EditNameDialog extends DialogFragment {
private EditText mEditText;
public EditNameDialog() {
// Empty constructor required for DialogFragment
}
public static EditNameDialog newInstance(String title) {
EditNameDialog frag = new EditNameDialog();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container);
mEditText = (EditText) view.findViewById(R.id.txt_your_name);
String title = getArguments().getString("title", "Enter Name");
getDialog().setTitle(title);
// Show soft keyboard automatically
mEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
return view;
}
}
you can change the fragment_edit_name.xml and put your buttons, title, map...
PS: i copy this code from this tutorial

DialogFragment setCancelable property not working

I am working in an android application and am using a DialogFragment to show a dialog and I want to make that DialogFragment not cancelable. I have made the dialog cancelable property to false, but still its not affecting.
Please look into my code and suggest me a solution.
public class DialogTest extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return super.onCreateDialog(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_test, container, true);
getDialog().requestWindowFeature(STYLE_NO_TITLE);
getDialog().setCancelable(false);
return view;
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_test, container, true);
getDialog().requestWindowFeature(STYLE_NO_TITLE);
getDialog().setCancelable(false);
return view;
}
instead of getDialog().setCancelable(false); you have to use directly setCancelable(false);
so the updated answer will be like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_test, container, true);
getDialog().requestWindowFeature(STYLE_NO_TITLE);
setCancelable(false);
return view;
}
Use the following Snippet
void showDialog() {
DialogFragment newFragment = MyAlertDialogFragment.newInstance(
R.string..alert_dialog_two_buttons_title);
newFragment.setCancelable(false);
newFragment.show(getFragmentManager(), "dialog");
}
and if you want to disable the out side touch around dialog use the following line of code
DialogFragment.getDialog().setCanceledOnTouchOutside(true);
In case you use alert builder (and probably in every case you wrap dialog inside a DialogFragment) to help build your dialog, please don't use getDialog().setCancelable(false) or Dialog.setCancelable(false) because it's not going to work.
Use setCancelable(false) as shown in code below as it's mentioned in oficial android documentation:
public void setCancelable (boolean cancelable)
Added in API level 11
Control whether the shown Dialog is cancelable. Use this instead of directly calling Dialog.setCancelable(boolean), because DialogFragment needs to change its behavior based on this."
ref:http://developer.android.com/reference/android/app/DialogFragment.html#setCancelable(boolean)
public class MyDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_layout, null, false);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle("in case you want use a title").setView(view);
AlertDialog alert = builder.create();
// alert.setCancelable(false); <-- dont' use that instead use bellow approach
setCancelable(false); <- press back button not cancel dialog, this one works fine
alert.setCanceledOnTouchOutside(false); <- to cancel outside touch
return alert;
}
Simple Solution in DialogFragment
Used
dialog.setCanceledOnTouchOutside(false)
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
AlertDialog.Builder(activity!!).apply {
isCancelable = false
setMessage("Your message")
// your other adjustments
return this.create()
}
}
worked for me.
The main thing is to use isCancelable = false over setCancellable(false)
within override fun onCreateDialog().
/**
* Control whether the shown Dialog is cancelable. Use this instead of
* directly calling {#link Dialog#setCancelable(boolean)
* Dialog.setCancelable(boolean)}, because DialogFragment needs to change
* its behavior based on this.
*
* #param cancelable If true, the dialog is cancelable. The default
* is true.
*/
DialogFragment.setCancelable(boolean cancelable) {
mCancelable = cancelable;
if (mDialog != null) mDialog.setCancelable(cancelable);
}

Android DialogFragment: How to preserve view in multiple show() invocation?

I have a dialog fragment using a custom layout with a quite complex View hierarchy. The code for the dialog fragment is more or less similar to the following.
public class CardDetailDialog extends DialogFragment {
public CardDetailDialog() {
setRetainInstance(true);
setStyle(STYLE_NORMAL, android.R.style.Theme_Light);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.card_detail_dialog, container, false);
/* Modify some view objects ... */
return view;
}
}
Whenever I invoked the show() method for this dialog fragment, I noticed that onCreateView is always called and layout inflation process is repeated. In my app, user might want to show the dialog multiple times during a session and I thought this is inefficient. Is there any way to keep the view / dialog instance across multiple show() invocation? Is it possible to do this using DialogFragment, or do I have to deal directly with Dialog class?
Using a boolean flag seems to do the trick (See the KEY CHANGEs). I override onCreateDialog, but employing the same strategy in onCreateView should work as well (keep a reference to your view you create)
I'm still getting some issues related to Orientation changes, but it may be related to a different issue
public class LogFragment extends DialogFragment{
private boolean isCreated; //KEY CHANGE
private Dialog mDialog; //KEY CHANGE -- to hold onto dialog instance across show()s
public LogFragment() {
setRetainInstance(true); // This keeps the fields across activity lifecycle
isCreated = false; // KEY CHANGE - we create the dialog/view the 1st time
}
#Override
public Dialog onCreateDialog(Bundle inState) {
if (isCreated) return mDialog; // KEY CHANGE - don't recreate, just send it back
View v = View.inflate(getActivity(),R.layout.log_layout,null);
mDialog = new AlertDialog.Builder(getActivity())
...
.create();
isCreated = true; // KEY CHANGE Set the FLAG
return mDialog;
}

Is it possible to add a ViewPager into a DialogFragment?

my code:
public class CustomDialogFragment extends SherlockDialogFragment {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.p_product_gallery, container, false);
ImageView tttiv=(ImageView)v.findViewById(R.id.test_image);
tttiv.setImageResource(R.drawable.baozi);
return v;
}
/** The system calls this only when creating the layout in a dialog. */
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// The only reason you might override this method when using onCreateView() is
// to modify any dialog characteristics. For example, the dialog includes a
// title by default, but your custom layout might not need it. So here you can
// remove the dialog title, but you must call the superclass to get the Dialog.
mDialog = super.onCreateDialog(savedInstanceState);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.getWindow().setBackgroundDrawable((new ColorDrawable(0x0f000000)));
mPager = (ViewPager) mDialog.findViewById(R.id.aa_pager);
mPager.setAdapter(mAdapter);
mAdapter = new ProductGalleryAdapter(getSupportFragmentManager());
return mDialog;
}
}
The "mPager" always is null.
Can any one provide an example?
tkx!
Unless you are using Android 4.2 (and Android Support Library rev 11), fragments are not supported in fragments...
Fragments within Fragments

Categories

Resources