EditText inside AlertDialog always null

2019-01-28 17:56发布

问题:

I've search over the threads but so far I have not found what I'm looking for. I created a custom Alert Dialog that show up and I can do almost anything with it. It custom dialog is made of 3 TextViews and 3 EditText but whenever I need to get the EditText I get a null component.

From my xml file

 <TextView android:layout_alignParentTop="true" 
    android:id="@+id/txtAccName" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Name"
    android:textSize="23dp"
    >

</TextView>
<EditText android:id="@+id/txtEditName" 
    android:layout_below="@+id/txtAccName" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="" 
    android:maxLength="20"
    >

I'm trying to get the EditText field with:

    EditText txtAccName = (EditText) findViewById(R.id.txtEditName);
    Log.d("#############################", "txtAccName="+txtAccName.getText().toString());

But when doing this, the first line works well, the second home causes a crash and the control is null. This is the Overwrite method that I use to create the custom AlertDialog that I need.

    @Override
protected Dialog onCreateDialog(int id) {
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View layout = inflater.inflate(R.layout.accountdialog, (ViewGroup) findViewById(R.id.accDialog));

    AlertDialog.Builder builder = new AlertDialog.Builder(this);

    builder.setNegativeButton(android.R.string.cancel,new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {

        }
        });
    builder.setPositiveButton(android.R.string.ok,
            new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                EditText txtAccName = (EditText) findViewById(R.id.txtEditName);
                //EditText txtAccCur = (EditText) findViewById(R.id.txtEditCur);
                //EditText txtAccCountry = (EditText) findViewById(R.id.txtEditCountry);
                //DBConn db = new DBConn(Accounts.this.getApplicationContext(), "msaverdb", null, 0);
                Log.d("#############################", "CALLING db.insertAccount");
                Log.d("#############################", "txtAccName="+txtAccName.getText().toString());
                //db.insertAccount(txtAccName.getText().toString(), txtAccCountry.getText().toString(), 
                //      txtAccCur.getText().toString());
                Accounts.this.removeDialog(ACC_DIALOG);
            }
            });
    builder.setNegativeButton(android.R.string.cancel,
            new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                Accounts.this.removeDialog(ACC_DIALOG);
            }
            });
    builder.setView(layout);
    AlertDialog ad = builder.create();
    return ad;
}

Any help is most appreciated.

回答1:

Take note of how all of your method calls are being resolved within your anonymous inner classes.

findViewById is a method that exists on views and on your activity. The version of this method on your activity searches for a view within the activity window's view hierarchy. The version on views searches that view instance and all attached children.

Your call on the problematic line of code:

EditText txtAccName = (EditText) findViewById(R.id.txtEditName);

is resolving to Activity#findViewById. But your dialog's layout is not attached to your activity window, it's attached to the dialog. You can find the correct view reference in several ways but the simplest in your case is probably to search from the root of the layout that you inflated:

EditText txtAccName = (EditText) layout.findViewById(R.id.txtEditName);


回答2:

When you use findViewById you implicitly refer to the current activity. The part you have to change is

EditText txtAccName = (EditText) ad.findViewById(R.id.txtEditName);

instead of

EditText txtAccName = (EditText) findViewById(R.id.txtEditName);

when you attempt to resolve it. You'll also have to change the scope of the AlertDialog object ad to class-wide and make sure that it's not null, before you search for views in it. That's pretty much it.



回答3:

The explanation by adamp is great. But that method didn't work for me. The simplest way for me is like this:

builder.setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   Dialog dialogView = (Dialog) dialog;
                   EditText et;
                   et = (EditText) dialogView.findViewById(R.id.addressinput);

Hope this helps somebody.