2010-05-08 7 views
96

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

If you want to display a more complex view, look up the FrameLayout called "body" and add your view to it:

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(); 
+0

Чтобы найти и использовать свои объекты на диалоге, выполните следующие четыре шага: http://stackoverflow.com/a/18773261/1699586 – Sara

+3

Однострочный ответ: добавьте '.setView (getLayoutInflater(). Inflate (R.layout.dialog_view, null))' к строителю. Подчеркните Серхио Виудесу, ниже. –

ответ

47

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

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

LayoutInflater inflater = getLayoutInflater(); 
FrameLayout f1 = (FrameLayout)alert.findViewById(android.R.id.body); 
f1.addView(inflater.inflate(R.layout.dialog_view, f1, false)); 
+15

Интересно, что тело не определено как константа в android.R.id. Я все еще не понимаю, как получить доступ к элементу body созданного AlertDialog. Я все еще хотел бы знать, как это сделать, но сейчас я просто попытаюсь раздуть представление и использовать setView в построителе. – stormin986

+2

На самом деле это все равно оставляет меня вопросом (я новичок в раздувании взглядов). Используя 'builder.setView (inflater.inflate (R.id.dialog, ROOT_VIEWGROUP [, ATTACH_TO_ROOT]))', документы говорят, что корневая группа просмотра является необязательной. Должно ли это быть использовано в этом случае? Если это так ... еще нужно выяснить, как получить ссылку на AlertDialog ... – stormin986

+2

Это необязательно, но тогда у вас не будет ссылки на родителя изнутри раздуваемого макета. Такие вещи, как android: layout_gravity не будут работать на верхнем уровне ... и, возможно, вам не нужны они. Когда вы вызываете AlertDialog alert = builder.create(), у вас есть ссылка на ваш AlertDialog. длинный ответ короткий, это * есть * продается отдельно. Попробуйте, в зависимости от того, что вы делаете в своем настраиваемом макете, это, вероятно, сработает. – synic

152

Вы можете создать вид непосредственно из макета Inflater, вам нужно использовать только имя файла 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(); 
+4

А где R.id.dialog_layout_root в этом примере? Разве это не вид в текущей деятельности? –

+5

@AlexPretzlav: dialog_layout_root в этом примере не требуется. Все, что вам нужно, это имя вашего xml-файла для R.layout. [Name_of_xml_file]. –

+0

Я только что проверил код выше, и он не работает. Не уверен, почему люди продолжают его продвигать. – Temperage

17

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> 
+0

John Rellis. Ваше решение отлично работает. Просто есть что-то в этом. Мы должны раздуть перед созданием builder.create и установить frameView.setLayoutParams (новые LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); или что-то в первую очередь, что предотвратит некоторые ошибки, которые не ожидаются – MOBYTELAB

+0

спасибо за отзыв. Как вы надуваете перед builder.create()? надувание называется надувом диалога, и у меня есть только диалог, потому что я вызвал builder.create() –

+0

, мы можем использовать надувной элемент активности и не прикрепляться к FrameLayout, поэтому мы можем уменьшить небольшой код, подобный this.AlertDialog.Builder builder = новый AlertDialog.Builder (новый ContextThemeWrapper (getActivity(), android.R.style.Theme_Holo)) \t \t \t .setTitle ("название") \t \t \t .setIcon (R.drawable.sample_icon); \t \t \t View problemView = inflater.inflate (R.layout.sample_layout, null, false); \t \t builder.setView (problemView); \t \t alert = builder.create(); Извините, я не знаю, как четко писать код на комментарии – MOBYTELAB

11

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

dialog.setView(dialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null)); 
+0

спасибо..и работал для меня .. – John

+0

Чистота и эффективность, спасибо! – portfoliobuilder

2

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

... 
FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.**custom**); 
custom.addView(**mView**, new LayoutParams(FILL_PARENT, FILL_PARENT)); 
... 
1

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

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

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

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

я нашел это решение, исследуя вид дерева с View.getParent() и View.getChildAt (INT). Не очень-то даже довольный. Ничто из этого не содержится в документах Android, и если они когда-либо изменят структуру AlertDialog, это может сломаться.

2

Самый простой способ сделать это с помощью 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(); 
+0

Любой, кто читал это после API 21, был представлен, должен использовать этот метод. Как говорится в ответе, если ваше приложение minSDKversion меньше 21, используйте AlerDialog из пакета поддержки. Вуаля !!! – Dibzmania

4

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

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

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

+0

awesome, simple and easy – cubycode

0

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

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

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(); 
    } 
} 

Notes

  • Если вы нашли себя с помощью этого в нескольких местах, затем рассмотрите возможность создания подкласса DialogFragment, как описано в documentation.

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

+0

'EditText editText = customLayout.findViewById (R.id.editText);' должен быть 'EditText editText = (EditText) customLayout.findViewById (R.id.editText);' – philcruz

+3

@philcruz, Если вы обновление до Android Studio 3.0, вам больше не нужно явно отображать представление. IDE может вывести тип. Это очень приятная функция. Это помогает очистить код. – Suragch

 Смежные вопросы

  • Нет связанных вопросов^_^