I've seen other posts but can't make heads nor tails of the following error.
Trying to have a dialog pop up on Recycler View item. I do have a similar dialog that works. I must use a different dialog because of different options in the second instance.
public class EditItemDialog extends AppCompatDialogFragment{
private EditText projectAmountEditText;
private EditDialogListener listener;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View v = inflater.inflate(R.layout.activity_inventory_item, null);
builder.setView(v)
.setTitle("Edit Amount")
.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) {
int amountChanged = Integer.parseInt(projectAmountEditText.getText().toString());
listener.editAmount(amountChanged);
}
});
projectAmountEditText = v.findViewById(R.id.amount_edit_text_item_activity);
if(projectAmountEditText == null){
//TODO
}
builder.show();
return builder.create();
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
listener = (EditDialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() +
"must implement EditDialogLister");
}
}
public interface EditDialogListener{
void editAmount(int amountChanged);
}
}
Here is the logcat
Process: com.x.x, PID: 8485
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:5235)
at android.view.ViewGroup.addView(ViewGroup.java:5064)
at android.view.ViewGroup.addView(ViewGroup.java:5036)
I had to add a onDestroy override on the dialog to free the View.
Related
I have created a custom dialog showing a grid of items. When another option is clicked, it will also open another custom dialog with an editText field. The problem I am facing is getting a null object error for the textfield. I found an answer here but when I applied it, the result is still the same.
Basically, the app is crashing when retrieving the textfield value in the custom dialog that opens from another custom dialog. Here is what I have so far:
onCreate()
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button donate = findViewById(R.id.button);
donate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showDonateDialog();
}
});
}
showDonateDialog()
//Donate dialog with grid options
private void showDonateDialog() {
// Prepare grid view
GridView gridView = new GridView(this);
String[] donateAmount = getResources().getStringArray(R.array.donationAmount);
List<String> donateList = new ArrayList<String>();
Collections.addAll(donateList, donateAmount);
gridView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, donateList));
gridView.setNumColumns(3);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), "Thank you for your donation!", Toast.LENGTH_SHORT).show();
}
});
// Set grid view to alertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(gridView);
builder.setTitle("Donate");
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setNeutralButton("Other amount", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
showCustomDonate();
}
});
builder.setCancelable(false);
builder.show();
}
showCustomDonate()
//Donate dialog for custom amount
private void showCustomDonate() {
AlertDialog.Builder builderCustom = new AlertDialog.Builder(this);
Context context = builderCustom.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.custom_donate_amount, null, false);
final EditText donateAmount = findViewById(R.id.editAmount);
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) {
dialog.cancel();
} else {
String amount = donateAmount.getText().toString(); //Error null object reference here
Toast.makeText(getApplicationContext(), "Thank you for donating " + amount, Toast.LENGTH_LONG).show();
}
}
};
builderCustom.setView(view)
.setTitle("Custom Donation")
.setCancelable(false)
.setPositiveButton("OK", listener)
.setNegativeButton("CANCEL", listener)
.show();
}
Log
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.customdialog, PID: 12011
java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
at com.example.customdialog.MainActivity$5.onClick(MainActivity.java:94)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
i hope it is work for you
showCustomDonate()
//Donate dialog for custom amount
private void showCustomDonate() {
AlertDialog.Builder builderCustom = new AlertDialog.Builder(this);
Context context = builderCustom.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.custom_donate_amount, null, false);
final EditText donateAmount = findViewById(R.id.editAmount);
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) {
dialog.cancel();
} else {
String amount = donateAmount.getText().toString(); //Error null object reference here
Toast.makeText(getApplicationContext(), "Thank you for donating " + amount, Toast.LENGTH_LONG).show();
}
}
};
builderCustom.setView(view)
.setTitle("Custom Donation")
.setCancelable(false)
.setPositiveButton("OK", listener)
.setNegativeButton("CANCEL", listener)
.show();
}
Change on this line
final EditText donateAmount = view.findViewById(R.id.editAmount);
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 have made a custom alertdialog that has 2 Edittexts in it. I want to pass information to it from an existing database when clicking something.
this is the Custom alert dialog's class
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.add_job_dialouge, null);
builder.setView(view).setTitle("Add Job")
.setPositiveButton("add", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if(isDouble(wageValue.getText().toString())){
String nameOjob = jobName.getText().toString();
Double valueOwage = Double.parseDouble(wageValue.getText().toString());
listener.applyTexts(nameOjob, valueOwage);
builder.create();
}else{
wageValue.setError("Wrong Format Error");
}
}
})
.setNeutralButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
jobName = view.findViewById(R.id.job_name_ETD);
wageValue = view.findViewById(R.id.wage_ETD);
//I want to pass information to these
//jobName.setText();
//wageValue.setText();
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener =(ExampleDialogueListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement Example Dialogue Listener");
}
}
public interface ExampleDialogueListener{
void applyTexts(String jobname, Double wage);
}
boolean isDouble(String str) {
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}
I want to pass info to the edittext through parameters, so that there's info on the edit text when I create the alertdialog
It looks like you're extending a DialogFragment.
You can pass data in the same as you would a regular Fragment.
Bundle args = new Bundle();
args.putString("arg_key","something");
f.setArguments(args);
Where f is the instance of your DialogFragment.
Inside your DialogFragment you can call getArguments() to get your bundle.
I build an AlertDialog box with
public class ConstantDialogFragment extends DialogFragment {
private AlertDialog.Builder builder;
private AlertDialog alertDialog;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final int[] constantProtocol = {0};
builder = new AlertDialog.Builder(getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
builder.setTitle(getResources().getString(R.string.some_message))
.setMultiChoiceItems(R.array.some_choice, null,
new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
// some method
}
})
.setPositiveButton(getResources().getString(R.string.ok_dialog), new DialogInterface.OnClickListener() {
class LoadConfigTask {
private ProgressDialog dialog;
private Activity activity;
public LoadConfigTask(Activity activity) {
this.activity = activity;
dialog = new ProgressDialog(activity, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
}
public void execute() {
try {
// some method
} catch (Exception e) {
// some method
}
}
}
#Override
public void onClick(DialogInterface dialog, int id) {
// some method
}
})
.setNegativeButton(getResources().getString(R.string.cancel_dialog), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// some thing
}
});
builder.create();
alertDialog = builder.show();
return alertDialog;
}
public AlertDialog getAlertDialog(){
return alertDialog;
}
Then I tried this espresso implementation:
onView(withText("my first choice")).
perform(click());
and I get
NoMatchingViewException: No views in hierarchy found matching: with text: is my string"
How can I fix that ?
Fetching in the Android source code, I found useful methods. So to get control on the items of the AlertDialog, I had to do that
ListView listView = alertDialog.getListView();
View child = listView.getChildAt(0);
child.performClick();
Whenever I debug the application it crashes when I click the button that pops up the dialog.
What should I do to make that dialog work?
public class Actionbar_BtnHandler extends Activity {
Context context;
public Actionbar_BtnHandler (Context context)
{
this.context=context;
}
public void btn_handler (Button btn_mic,Button btn_post)
{
btn_mic.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context,"MICROPHONE",Toast.LENGTH_LONG).show();
}
});
btn_post.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// Get the layout inflater
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton("Post", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
builder.create();
}
});
}
}
Thanks in advance...
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
is inaccurate... The cast seems to fail
Try :
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// Get the layout inflater
LayoutInflater inflater = Actionbar_BtnHandler.this.getLayoutInflater();
Try this write your AlertDialog code using Handler..
btn_post.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Handler handler = new Handler();
handler.post(MessagealertDisplay);
}
});
}
Runnable MessagealertDisplay = new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// Get the layout inflater
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton("Post", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
builder.create();
}
};
i used
Actionbar_BtnHandler btns = new Actionbar_BtnHandle(Class.this);
btns.btn_handler(btn_post, btn_mic);
instead of
Actionbar_BtnHandler btns = new Actionbar_BtnHandler(getApplicationContext);
btns.btn_handler(btn_post, btn_mic);
and it worked