I would like to ask a simple but misleading question according to my point of view.
I have a dialog, or better, a custom dialog:
public class MyCustomDialog extends Dialog {
public MyCustomDialog(Context context, int layoutResourceId) {
super(context);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(layoutResourceId);
LayoutParams params = getWindow().getAttributes();
params.width = LayoutParams.MATCH_PARENT;
getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
}
}
This dialog takes a layuoutResourceId (R.layout.some_custom_layout.xml) as argument when it is instantiated. I need to use this dialog to display a custom List of some Master and details data which is dinamically created. In order to do this kind of operation I am using a custom Adapter class , called MasterDetailArrayAdapter:
public class MasterDetailArrayAdapter extends ArrayAdapter<Item> {
private LayoutInflater mdInflater;
public enum EntryType {
DETAIL, MASTER
}
public MasterDetailArrayAdapter(Context context, List<Item> items) {
super(context, 0, items);
mdInflater = LayoutInflater.from(context);
}
@Override
public int getViewTypeCount() {
return EntryType.values().length;
}
@Override
public int getItemViewType(int position) {
return getItem(position).getViewType();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getItem(position).getView(mdInflater, convertView);
}
}
This adapter extends an ArrayAdapter of Item, where Item is an interface I have created:
public interface Item {
public int getViewType();
public View getView(LayoutInflater inflater, View convertView);
}
So The MasterDetailArrayAdapter takes a List as parameter when it is constructed. The Item interface is implemented by a MasterWithValue class (or better by a Master class which MasterWithValue extends):
public class MasterWithValue extends Master {
private String value;
private List<Detail> detailList;
public MasterWithValue(String masterName, String masterValue) {
super(masterName);
this.value = masterValue;
this.detailList = new ArrayList<Detail>();
}
@Override
public int getViewType() {
return super.getViewType();
}
@Override
public View getView(LayoutInflater inflater, View convertView) {
View view;
if (convertView == null) {
view = inflater.inflate(R.layout.statistics_rowlist_master, null);
}
else {
view = convertView;
}
TextView MasterEntryName = (TextView) view.findViewById(R.id.statistics_master_name);
TextView MasterEntryValue = (TextView) view.findViewById(R.id.statistics_master_value);
MasterEntryName.setText(super.name);
MasterEntryValue.setText(this.value);
return view;
}
public String getMasterValue() {
return value;
}
public List<Detail> getDetailList() {
return this.detailList;
}
public void addDetailToMaster(Detail detail) {
this.detailList.add(detail);
}
}
And Detail class:
public class Detail implements Item {
public final String detailName;
public final String detailValue;
public Detail(String detailName, String detailValue) {
this.detailName = detailName;
this.detailValue = detailValue;
}
@Override
public int getViewType() {
return EntryType.DETAIL.ordinal();
}
@Override
public View getView(LayoutInflater inflater, View convertView) {
View view;
if (convertView == null) {
view = inflater.inflate(R.layout.institutional_rowlist_detail, null);
}
else {
view = convertView;
}
TextView detailEntryName = (TextView) view.findViewById(R.id.institutional_detail_name);
TextView detailEntryValue = (TextView) view.findViewById(R.id.institutional_detail_value);
detailEntryName.setText(this.detailName);
detailEntryValue.setText(this.detailValue);
return view;
}
}
Now the code where it's all built:
// instantiating a new CustomDialog class
dialog = new MyCustomDialog(thisContext, R.layout.institutional_info_custom_list);
DetailListView = (ListView) dialog.findViewById(R.id.custom_dialog_list);
final MasterDetailArrayAdapter adapter = new MasterDetailArrayAdapter(ComeHaInvestito.this, MasterAndDetailstatisticsInfoList);
DetailListView.setAdapter(adapter);
thisContext is the context of the activity, MasterAndDetailstatisticsInfoList is a of Item but this is not the point. My result is this:
Everything works perfectly, except if you rotate the screen when the dialog is showed: The dialog closes and then it is NEVER re-showed again. It is so frustrating, sorry for saying that, but it is all day I am trying to figure it out and how can I resolve it.
I understand that when you rotate the screen of the device, the activity is destroyed and recreated, but the dialog is not. I need to keep it on the screen when the device is rotated but I can't use the Manifest solution, thus:
android:configChanges="orientation|keyboardHidden|screenSize
Does not work for me cause I have some other graphical Views that change their position on screen rotate in that way.
So I am looking for another solution. I see that everyone here on SO and in other discussion forums talks about using the Fragments almost everytime you need to retain some data on android device config changes ( this includes screen orientation change ) so I was thinking of doing that, but with the solution I am currentry using I have no idea on how implement a fragment which will retain my custom dialog without messing the code I have already written. So guys I really need some help on this.
Is there a way to integrate a custom dialog class (MyCustomDialog in my case) using Fragments and make it retained on screen orientation change?
Thanks for the attention! Hope for some help!
EDIT: I have made an interface called ActivityToFragmentInteraction. Now with this implementation I can see the Dialog on screen orientation change but the ListView inside of it still disappears. How can I fix it?
public class MyCustomDialogFragmentWithListItem extends DialogFragment {
private List<Item> dialogFragmentItemList;
private Context context;
private ActivityToFragmentInteraction activityToFragmentInteraction;
public interface ActivityToFragmentInteraction {
public List<Item> getListItem();
}
public static MyCustomDialogFragmentWithListItem newInstance(int dialogLayoutResourceId, int dialogListViewResourceId) {
MyCustomDialogFragmentWithListItem dialogFragment = new MyCustomDialogFragmentWithListItem();
Bundle args = new Bundle();
args.putInt("dialog_layout", dialogLayoutResourceId);
args.putInt("dialog_list_view_id", dialogListViewResourceId);
dialogFragment.setArguments(args);
return dialogFragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.context = getActivity();
try {
activityToFragmentInteraction = (ActivityToFragmentInteraction) activity;
}
catch (ClassCastException e) {
e.printStackTrace();
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int dialogLayoutResourceId = getArguments().getInt("dialog_layout");
int dialogListViewResourceId = getArguments().getInt("dialog_list_view_id");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// getting the layout inflater and inflating the view recovered using the dialogLayoutResourceId
// passed before as argument to the factory method.
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(dialogLayoutResourceId, null);
builder.setView(view);
// getting the List<Item> from the activityToFragmentInteraction interface
dialogFragmentItemList = activityToFragmentInteraction.getListItem();
// recovering the ListView of the DialogFragment
ListView listView = (ListView) view.findViewById(dialogListViewResourceId);
// setting the adapter for the ListView of the DialogFragment.
final MasterDetailArrayAdapter adapter = new MasterDetailArrayAdapter(context, dialogFragmentItemList);
listView.setAdapter(adapter);
return builder.create();
}
}