AlertDialog displays the content and buttons perfectly until the contents grow to the point that scrolling is required to display it all. At that point the buttons disappear, even though the list shows in its entirety.
I see that in years gone by this question was asked (this one is essentially identical to mine (DialogFragment buttons pushed off screen API 24 and above), but the answers all seemed hit or miss, haphazard even: setting layout_weight, switching from setMessage() to setTitle(), and finally switching away from AlertDialog to Dialog.
None of these are working form me, and avoiding AlertDialog is NOT an appealing option because I am using the setMultiChoiceItems() method that seems (incredibly to me, perhaps given my extremely limited knowledge) available only to AlertDialog.
Thus in desperation and frustration I appeal directly to the collective brains of stackoverflow.
This is a pared down version of my DialogFragment:
public class SurfaceDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = requireActivity().getLayoutInflater();
builder.setView(inflater.inflate(R.layout.surface_dialog, null))
.setTitle(mMessage)
.setMultiChoiceItems(mSurfaceList, mCheckedSurfaces, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
mCheckedSurfacesPositions.add(which);
} else {
mCheckedSurfacesPositions.remove(mCheckedSurfacesPositions.indexOf(which));
}
}
});
// builder.setCancelable(false);
builder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ProcessDialogSelections(mCheckedSurfacesPositions);
dismiss();
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
listener.onSurfaceDialogSelectedSent(mUnitSurfaces);
dismiss();
}
});
return builder.create();
}
That not working, I then coded my own buttons and displayed them:
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = requireActivity().getLayoutInflater();
View dialogView = inflater.inflate(R.layout.surface_dialog, null);
builder.setView(dialogView)
.setTitle(mMessage)
.setMultiChoiceItems(mSurfaceList, mCheckedSurfaces, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
mCheckedSurfacesPositions.add(which);
} else {
mCheckedSurfacesPositions.remove(mCheckedSurfacesPositions.indexOf(which));
}
}
});
Button positiveButton = dialogView.findViewById(R.id.positive_button);
Button negativeButton = dialogView.findViewById(R.id.negative_button);
positiveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProcessDialogSelections(mCheckedSurfacesPositions);
dismiss();
}
});
negativeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onSurfaceDialogSelectedSent(mUnitSurfaces);
dismiss();
}
});
return builder.create();
}
and here is my revised XML file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
android:orientation="vertical">
</ScrollView>
<Button
android:id="#+id/positive_button"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:layout_width="wrap_content"
android:text="Done"
app:layout_constraintBaseline_toBaselineOf="#+id/negative_button"
app:layout_constraintEnd_toStartOf="#+id/negative_button"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/negative_button"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:layout_width="wrap_content"
android:text="Cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/positive_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
And with THAT not working, I then followed the advice of Vikas Singh (AlertDialog Buttons not visible when using Custom layout). This is what the new code looks like (essentially creating the layout in Java rather than XML.
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// New code from Vikas Singh
LinearLayout rootLayout = new LinearLayout(getActivity());
rootLayout.setOrientation(LinearLayout.VERTICAL);
ScrollView scrollView = new ScrollView(getActivity());
LinearLayout layout = new LinearLayout(getActivity());
layout.setOrientation(LinearLayout.VERTICAL);
scrollView.addView(layout);
rootLayout.addView(scrollView);
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton("Go", null);
builder.setView(rootLayout);
builder//.setView(dialogView)
//.setTitle(mMessage)
.setMultiChoiceItems(mSurfaceList, mCheckedSurfaces, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
mCheckedSurfacesPositions.add(which);
} else {
mCheckedSurfacesPositions.remove(mCheckedSurfacesPositions.indexOf(which));
}
}
});
return builder.create();
}
Still no buttons when I have to scroll.
Why not and what can I do about it?
Here is the solution:
public class SurfaceDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//LayoutInflater inflater = requireActivity().getLayoutInflater();
builder
//.setView(inflater.inflate(R.layout.surface_dialog, null)) didn't work
// nor did setView with android.R.layout.select_dialog_multichoice
// nor android.R.layout.simple_list_item_multiple_choice work
.setTitle(mMessage)
.setMultiChoiceItems(mSurfaceList, mCheckedSurfaces, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
mCheckedSurfacesPositions.add(which);
} else {
mCheckedSurfacesPositions.remove(mCheckedSurfacesPositions.indexOf(which));
}
}
});
// builder.setCancelable(false);
builder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ProcessDialogSelections(mCheckedSurfacesPositions);
dismiss();
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
listener.onSurfaceDialogSelectedSent(mUnitSurfaces);
dismiss();
}
});
return builder.create();
}
The multiChoiceItems DialogFragment now works like a charm!
All I had to do was simply comment out the above lines.
As a result, there is no layout explicitly inflated, no view set.
But it works nonetheless.
Now I would love it if someone could explain to me
the details of why this works,
why the other did not, and
in light of the earlier failure, how could a custom layout be implemented to achieve this result of not losing the action buttons when the view scrolled
Related
I'm trying to getText() from EditText view in an AlertDialog.
In the main activity in the method onCreate() I set the button listener.
public class MainActivity2 extends AppCompatActivity {
private ActivityMain2Binding mainActivity2;
private ArrayAdapter adapter;
private ArrayList<simpleArrayAdapterElement> data;
private final static String KEY_TITLE = "title";
private final static String KEY_DESCRIPTION = "description";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity2 = ActivityMain2Binding.inflate(getLayoutInflater());
View view = mainActivity2.getRoot();
setContentView(view);
arrayAdapter();
mainActivity2.buttonIddItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showCustomDialog();
}
});
// setupListViewSimple();
}
Then I call the showCustomDialog() in onClick.
private void showCustomDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(R.layout.custom_dialog);
builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
EditText alertDialogText = (EditText) findViewById(R.id.setText1);
System.out.println(alertDialogText.getText());
System.out.println(alertDialogText.getText().toString()); // just in case
}
});
builder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
EditText alertDialogText = (EditText) findViewById(R.id.setText1); // return none
Here is my layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<EditText
android:id="#+id/setText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints"
android:layout_marginTop="16dp"
android:hint="Type your name here:"
android:text="Some"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
*I also use binding in my activity.
What I'm doing wrong?
You are referring to MainActivity2 itself. you need to refer to its view by using LayoutInflater. You can check example answer here: https://stackoverflow.com/a/36793463/9346054
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
View dialogView = inflater.inflate(R.layout.custom_dialog, null);
builder.setView(dialogView);
builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
EditText alertDialogText = dialogView.findViewById(R.id.setText1);
System.out.println(alertDialogText.getText());
System.out.println(alertDialogText.getText().toString()); // just in case
}
});
builder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
I have an alertDialog that is read by multiple fragments or activities, on one instance the alert dialog is going to show a listView with 2 editText options plus the standard positive and negative button presses, I want to position the listView after the editTexts and I'm stuck.
Everything displays properly but positioning is where I'm stuck.
Dialog class
public class addTaskDialog extends DialogFragment {
String mString;
taskDialogListener listener;
ArrayList<String> tradeTitles;
/*
* Class interface from jobRoomDetails, interfaces are called from the parent activity class
*/
public interface taskDialogListener {
void onDialogPositiveClick(DialogFragment dialog);
void onDialogNegativeClick(DialogFragment dialog);
void onDialogListSelect();
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try{
listener = (taskDialogListener) context;
} catch(ClassCastException e) {
throw new ClassCastException(getActivity().toString() + "must implement taskDialogListener");
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
AlertDialog alert = builder.create();
mString = getArguments().getString("title");
tradeTitles = getArguments().getStringArrayList("tradeTitleArray");
builder.setTitle(mString);
//Inflate the layout dialog_add_task.xml
LayoutInflater inflater = requireActivity().getLayoutInflater();
//Pattern matcher for literal strings from different addTaskDialog calls
Pattern p = Pattern.compile("Add new task +");
Matcher m = p.matcher(mString);
Pattern q = Pattern.compile("Add Task +");
Matcher n = q.matcher(mString);
/*
*Test for new task and add trade names, this means that the calling window is jobRoomDetails and this is a new task
* and it will be assigned to a trade upon creation
*/
if(m.find()){
Log.d("Line: 56","Test for trade name" + tradeTitles.toString());
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.select_dialog_singlechoice, tradeTitles);
//ListView list = (ListView) alert.findViewById(R.id.tradeItems);
builder.setView(inflater.inflate(R.layout.dialog_add_task, null))
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Save the new task to task hashmap
listener.onDialogPositiveClick(addTaskDialog.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Cancel operation and return
listener.onDialogNegativeClick(addTaskDialog.this);
}
})
.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
}
});
} else if (n.find()){
builder.setView(inflater.inflate(R.layout.dialog_add_task, null))
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Save the new task to task hashmap
listener.onDialogPositiveClick(addTaskDialog.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Cancel operation and return
listener.onDialogNegativeClick(addTaskDialog.this);
}
});
} else {
builder.setView(inflater.inflate(R.layout.dialog_add_task, null))
.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Save the new task to task hashmap
listener.onDialogPositiveClick(addTaskDialog.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Cancel operation and return
listener.onDialogNegativeClick(addTaskDialog.this);
}
});
}
return builder.create();
}
}
dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<TextView
style="#style/textBox"
android:layout_margin="20dp"
android:layout_marginTop="5dp"
android:text="#string/add_task_ex"/>
<EditText
android:id="#+id/taskNameEditText"
style="#style/editTextBox"
android:hint="#string/add_task_name"
android:inputType="text"/>
<EditText
android:id="#+id/taskCost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="0"
android:textSize="25sp"
android:inputType="numberDecimal"/>
<FrameLayout
android:id="#+id/tradeListItems"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="#+id/tradeItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
At one point I tried to add it via a listView but to no success, I think the return type on the onCreateDialog might be hindering things but I'm not sure, I think the return type is necessary because I'm bringing through arguments but I could be wrong. As always help is appreciated.
Simple answer is create your own Alert dialog, you can simply make a fragment that looks and acts similar to an alert dialog but with far more functionality.
I created a custom AlertDialog and I want to save the values that the user has set. However I can't access them because Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference.
I am in HomeFragment, I created the AlertDialog and set the layout. I did it like this :
public class HomeFragment extends Fragment implements CustomDialog.CustomDialogListener {
private HomeViewModel homeViewModel;
private View root;
public View onCreateView(#NonNull final LayoutInflater inflater,
final ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
root = inflater.inflate(R.layout.fragment_home, container, false);
final TextView textView = root.findViewById(R.id.text_home);
homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
Button btn_add_apero = (Button) root.findViewById(R.id.btn_add_apero);
btn_add_apero.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(root.getContext());
builder.setTitle("Super un nouvel apéro !");
final EditText name_apero = (EditText)root.findViewById(R.id.edit_apero);
final EditText date_apero = (EditText)root.findViewById(R.id.edit_date);
builder.setView(inflater.inflate(R.layout.layout_dialog, null))
// Add action buttons
.setPositiveButton(R.string.text_add, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
LaperoDatabase db = Room.databaseBuilder(root.getContext(),
LaperoDatabase.class, "lapero_db").allowMainThreadQueries().build();
AperoDao dbApero = db.getAperoDao();
Apero new_apero = new Apero(name_apero.getText().toString(), date_apero.getText().toString());
dbApero.insert(new_apero);
}
})
.setNegativeButton(R.string.text_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
builder.show();
}
});
return root;
}
In my layout_dialog.xml I set the 2 EditText :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<EditText
android:id="#+id/edit_apero"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/edit_apero" />
<EditText
android:id="#+id/edit_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/edit_apero"
android:layout_alignParentStart="true"
android:hint="#string/edit_date"
android:layout_alignParentLeft="true" />
</RelativeLayout>
How can I manage to get the value that are in those 2 fields ?
First thing i noticed is that you're using root to find your dialog views, but root points to your fragment layout. root = inflater.inflate(R.layout.fragment_home, container, false);
First inflate your dialog layout before referencing its resource id.
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View inflater = getLayoutInflater().inflate(R.layout.layout_dialog, null);
builder.setView(inflater);
Then change root to inflater so you reference the view from your dialog layout
final EditText name_apero = (EditText)inflater.findViewById(R.id.edit_apero);
final EditText date_apero = (EditText)inflater.findViewById(R.id.edit_date);
Full code
Button btn_add_apero = (Button) root.findViewById(R.id.btn_add_apero);
btn_add_apero.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
View inflater = getLayoutInflater().inflate(R.layout.layout_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(inflater);
builder.setTitle("Super un nouvel apéro !");
final EditText name_apero = (EditText)inflater.findViewById(R.id.edit_apero);
final EditText date_apero = (EditText)inflater.findViewById(R.id.edit_date);
// Add action buttons
builder.setPositiveButton(R.string.text_add, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
LaperoDatabase db = Room.databaseBuilder(root.getContext(),
LaperoDatabase.class, "lapero_db").allowMainThreadQueries().build();
AperoDao dbApero = db.getAperoDao();
Apero new_apero = new Apero(name_apero.getText().toString(), date_apero.getText().toString());
dbApero.insert(new_apero);
}
})
builder.setNegativeButton(R.string.text_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
builder.show();
}
});
I am trying to pass Information from my AlertDialog to the parent Fragment it is on. But as soon as you klick the positive button, the app will crash.
I dont really know what todo anymore already read many Posts and articles but could not find the Problem.
Would be great if you could help me out.(Im a beginner)
Here is the Error I get with the first Problem in Code and the second commented.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test, PID: 20682
java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.test.SchulfachDialog$SchulfachDialogListener.applyTexts(java.lang.String)' on a null object reference
at com.example.test.SchulfachDialog$1.onClick(SchulfachDialog.java:39)
at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
here is my code for the alert Dialog:
builder.setView(view)
.setTitle("Add new subject")
.setMessage("Message")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String name = editTextName.getText().toString();
listener.applyTexts(name); // Problem 1: when positiv Button is pushed this line causes a crash
}
});
editTextName = view.findViewById(R.id.edit_name);
return builder.create();
}
this is the applyTexts which I override in the fragments Code:
public interface SchulfachDialogListener{
void applyTexts(String name);
}
}
#Override public void applyTexts(String name) {
test = name;
}
}
I also have this block in which the 2 commented lines cause a crash when clicking on the button which starts the alert Dialog:
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (SchulfachDialogListener) context;
} catch (ClassCastException e) {
// throw new ClassCastException(context.toString()+
// "must implement SchulfachDialogListener");
}
}
Solution: To pass data from an alert dialog to a parent fragment, the easier way is let the dialog extends DialogFragment. Then using setTargetFragment and setTargetFragment to send data between them.
Because you do not post parent fragment code, so I assume here is xml and java code of your parent fragment.
MainFragment.java
public class MainFragment extends Fragment implements SchulfachDialogListener{
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
Button btnShowAlertDialog = view.findViewById(R.id.button_show_alert_dialog);
btnShowAlertDialog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SchulfachDialog dialog = new SchulfachDialog();
dialog.setTargetFragment(MainFragment.this, 0);
dialog.show(requireActivity().getSupportFragmentManager(), null);
}
});
return view;
}
#Override
public void applyTexts(String text) {
Toast.makeText(requireActivity(), text, Toast.LENGTH_SHORT).show();
}
}
fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Show Alert Dialog"
android:id="#+id/button_show_alert_dialog"/>
</LinearLayout>
Let the alert dialog extends DialogFragment.
public class SchulfachDialog extends DialogFragment {
private EditText editTextName;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
View view = LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_schulfach, null);
builder.setView(view)
.setTitle("Add new subject")
.setMessage("Message")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String name = editTextName.getText().toString();
SchulfachDialogListener listener = (SchulfachDialogListener) getTargetFragment();
listener.applyTexts(name);
}
});
editTextName = view.findViewById(R.id.edit_name);
return builder.create();
}
}
I am working on a coding exercise,which is about AlertDialog. In the Dialog, I hope the image or view can be placed on the top of the dialog,like a header,but it goes to the bottom.
The XML code:
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/star"/>
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:text=" choose your sex"
android:gravity="center_vertical"/>
Activity code:
private void showSingleDialog() {
LayoutInflater factory = LayoutInflater.from(this);
final View view = factory.inflate(R.layout.activity_solo, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(view);
final String[] sex = {
"male",
"felmale",
"unknow",
"guess"
};
builder.setSingleChoiceItems(sex, 0, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(MainActivity.this, "your choice is:" + sex[i], Toast.LENGTH_LONG).show();
dialog.dismiss();
}
});
builder.show();
}
I tried to place the builder.setView(view) in different place, it still go to the bottom.
Is there any hints for me? Thanks a lot
p.s Sorry for my poor English, I attached the image hereMy Result
I hope the little Star and "choose your sex" go on the top
Alternatively you can achieve the same view with drawable and title methods:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String[] array = {"male","felmale","unknow","guess"};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setIcon(R.drawable.ic_star);
builder.setTitle("Choose your sex")
.setSingleChoiceItems(array, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
sex = array[i];
//handle on click
}
});
return builder.create();
}
I achieved the same view like this: