it-roy-ru.com

Как реализовать пользовательское представление AlertDialog

В Android-документах по AlertDialog , он дает следующую инструкцию и пример для настройки пользовательского представления в AlertDialog:

Если вы хотите отобразить более сложное представление, найдите FrameLayout под названием «body» и добавьте в него свое представление:

FrameLayout fl = (FrameLayout) findViewById(R.id.body);
fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));

Во-первых, совершенно очевидно, что add() - это опечатка, и она должна быть addView().

Я смущен первой строкой, использующей R.id.body. Кажется, что это элемент body AlertDialog ... но я не могу просто указать, что в моем коде b/c выдается ошибка компиляции. Где R.id.body определяется или назначается или как?

Вот мой код Я пытался использовать setView(findViewById(R.layout.whatever) на компоновщик, но это не сработало. Я предполагаю, потому что я не раздувал это вручную?

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title")
    .setCancelable(false)
    .setPositiveButton("Go", new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int id) {
        EditText textBox = (EditText) findViewById(R.id.textbox);
        doStuff();
    }
});

FrameLayout f1 = (FrameLayout)findViewById(R.id.body /*CURRENTLY an ERROR*/);
f1.addView(findViewById(R.layout.dialog_view));

AlertDialog alert = builder.create();
alert.show();
101
stormin986

Вы правы, это потому, что вы не раздували это вручную. Похоже, что вы пытаетесь «извлечь» идентификатор «body» из макета вашего Activity, и это не сработает.

Вы, вероятно, хотите что-то вроде этого:

LayoutInflater inflater = getLayoutInflater();
FrameLayout f1 = (FrameLayout)alert.findViewById(Android.R.id.body);
f1.addView(inflater.inflate(R.layout.dialog_view, f1, false));
47
synic

Вы можете создать свой вид непосредственно из Inflater Layout, вам нужно только использовать имя XML-файла макета и идентификатор макета в файле.

Ваш XML-файл должен иметь такой идентификатор:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              Android:id="@+id/dialog_layout_root"
              Android:orientation="vertical"
              Android:layout_width="fill_parent"
              Android:layout_height="wrap_content"
              Android:padding="10dp"
              />

И тогда вы можете установить свой макет на компоновщик с помощью следующего кода:

LayoutInflater inflater = getLayoutInflater();
View dialoglayout = inflater.inflate(R.layout.dialog_layout, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialoglayout);
builder.show();
156
Andrewx2

Android.R.id.custom возвращал для меня ноль. Мне удалось заставить это работать на случай, если кто-то столкнется с той же самой проблемой,

AlertDialog.Builder builder = new AlertDialog.Builder(context)
            .setTitle("My title")
            .setMessage("Enter password");
final FrameLayout frameView = new FrameLayout(context);
builder.setView(frameView);

final AlertDialog alertDialog = builder.create();
LayoutInflater inflater = alertDialog.getLayoutInflater();
View dialoglayout = inflater.inflate(R.layout.simple_password, frameView);
alertDialog.show();

Для справки, R.layout.simple_password:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
          Android:orientation="vertical"
          Android:layout_width="match_parent"
          Android:layout_height="match_parent">

<EditText
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:id="@+id/password_edit_view"
        Android:inputType="textPassword"/>
<CheckBox
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="@string/show_password"
        Android:id="@+id/show_password_checkbox"
        Android:layout_gravity="left|center_vertical"
        Android:checked="false"/>

</LinearLayout>
19
John Rellis

Документы Android были отредактированы для исправления ошибок.

Представление внутри AlertDialog называется Android.R.id.custom

http://developer.Android.com/reference/Android/app/AlertDialog.html

17
Dapp

Это сработало для меня:

dialog.setView(dialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null));
12
Sergio Viudes

Простейшие строки кода, которые работают для меня, следующие:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(R.layout.layout_resource_id);
builder.show();

Независимо от типа макета (LinearLayout, FrameLayout, RelativeLayout) будет работать setView И будет просто отличаться по внешнему виду и поведению.

4
kenix

AlertDialog.setView (представление View) действительно добавляет данное представление к R.id. custom FrameLayout. Ниже приведен фрагмент исходного кода Android из AlertController.setupView (), который, наконец, обрабатывает это (mView - это представление, данное методу AlertDialog.setView).

...
FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.**custom**);
custom.addView(**mView**, new LayoutParams(FILL_PARENT, FILL_PARENT));
...
2
Jung Soo Kim

Самый простой способ сделать это - использовать Android.support.v7.app.AlertDialog вместо Android.app.AlertDialog, где public AlertDialog.Builder setView (int layoutResId) можно использовать ниже API 21.

new AlertDialog.Builder(getActivity())
    .setTitle(title)
    .setView(R.layout.dialog_basic)
    .setPositiveButton(Android.R.string.ok,
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                //Do something
            }
        }
    )
    .setNegativeButton(Android.R.string.cancel,
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                //Do something
            }
        }
    )
    .create();
2
flanaras

После изменения идентификатора Android.R.id.custom мне нужно было добавить следующее, чтобы отобразить представление:

((View) f1.getParent()).setVisibility(View.VISIBLE);

Однако это привело к тому, что новое представление отображалось в большом родительском представлении без фона, разрывая диалоговое окно на две части (текст и кнопки с новым представлением между ними). Я наконец получил эффект, который я хотел, вставив мой вид рядом с сообщением:

LinearLayout f1 = (LinearLayout)findViewById(Android.R.id.message).getParent().getParent();

Я нашел это решение, изучив дерево View с помощью View.getParent () и View.getChildAt (int). Хотя и не очень доволен. Ничего из этого нет в документах по Android, и если они когда-либо изменят структуру AlertDialog, это может сломаться.

1
Black Mantha

Пользовательский AlertDialog

Этот полный пример включает передачу данных обратно в Activity.

 enter image description here

Создать собственный макет

В этом простом примере используется макет с EditText, но вы можете заменить его на что угодно.

custom_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
              Android:orientation="vertical"
              Android:paddingLeft="20dp"
              Android:paddingRight="20dp"
              Android:layout_width="match_parent"
              Android:layout_height="match_parent">

    <EditText
        Android:id="@+id/editText"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"/>

</LinearLayout>

Используйте диалог в коде

Ключевые части

  • используя setView, чтобы назначить пользовательский макет AlertDialog.Builder
  • отправка любых данных обратно в действие, когда нажата диалоговая кнопка.

Это полный код примера проекта, показанного на рисунке выше: 

MainActivity.Java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void showAlertDialogButtonClicked(View view) {

        // create an alert builder
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Name");

        // set the custom layout
        final View customLayout = getLayoutInflater().inflate(R.layout.custom_layout, null);
        builder.setView(customLayout);

        // add a button
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // send data from the AlertDialog to the Activity
                EditText editText = customLayout.findViewById(R.id.editText);
                sendDialogDataToActivity(editText.getText().toString());
            }
        });

        // create and show the alert dialog
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    // do something with the data coming from the AlertDialog
    private void sendDialogDataToActivity(String data) {
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
    }
}

Заметки

  • Если вы обнаружите, что используете это в нескольких местах, подумайте о создании подкласса DialogFragment, как описано в документации .

Смотрите также

1
Suragch

Было бы разумно сделать это таким образом, наименьшее количество кода.

new AlertDialog.Builder(this).builder(this)
        .setTitle("Title")
        .setView(R.id.dialog_view)   //notice this setView was added
        .setCancelable(false)
        .setPositiveButton("Go", new DialogInterface.OnClickListener() {
            @Override 
            public void onClick(DialogInterface dialog, int id) {
                EditText textBox = (EditText) findViewById(R.id.textbox);
                doStuff();
            }
        }).show();

Для расширенного списка вещей, которые вы можете установить, начните вводить .set в Android Studio

0
StackAttack