Cómo implementar una vista AlertDialog personalizada

En los documentos de Android en AlertDialog , proporciona las siguientes instrucciones y ejemplos para configurar una vista personalizada en AlertDialog:

Si desea visualizar una vista más compleja, busque FrameLayout llamado “cuerpo” y agregue su vista a él:

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

En primer lugar, es bastante obvio que add() es un error tipográfico y está destinado a ser addView() .

Estoy confundido con la primera línea usando R.id.body. Parece que es el elemento del cuerpo de AlertDialog … pero no puedo ingresar eso en mi código b / c sino que da un error de comstackción. ¿Dónde se define o asigna R.id.body o lo que sea?

Aquí está mi código. Intenté usar setView(findViewById(R.layout.whatever) en el generador, pero no funcionó. ¿Lo asumo porque no lo he inflado manualmente?

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

Estás en lo correcto, es porque no lo inflaste manualmente. Parece que estás tratando de “extraer” la ID de “cuerpo” del diseño de tu Actividad, y eso no funcionará.

Probablemente quieras algo como esto:

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

Puede crear su vista directamente desde Layout Inflater, solo necesita usar el nombre de su archivo XML de diseño y el ID del diseño en el archivo.

Su archivo XML debe tener una ID como esta:

   

Y luego puede configurar su diseño en el generador con el siguiente código:

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

android.R.id.custom estaba volviendo nulo para mí. Logré hacer que esto funcione en caso de que alguien se encuentre con el mismo problema,

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

Como referencia, R.layout.simple_password es:

      

Los documentos de Android han sido editados para corregir los errores.

La vista dentro de AlertDialog se llama android.R.id.custom

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

Esto funcionó para mí:

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

Las líneas de código más simples que funcionan para mí son las siguientes:

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

Cualquiera que sea el tipo de diseño (LinearLayout, FrameLayout, RelativeLayout) funcionará por setView y solo diferirá en la apariencia y el comportamiento.

AlertDialog.setView (View view) agrega la vista dada a R.id. FrameLayout personalizado . El siguiente es un fragmento del código fuente de Android de AlertController.setupView () que finalmente maneja esto (mView es la vista dada al método AlertDialog.setView).

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

La forma más sencilla de hacerlo es mediante el uso de android.support.v7.app.AlertDialog lugar de android.app.AlertDialog donde se puede usar el public AlertDialog.Builder setView (int layoutResId) debajo de 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(); 

Después de cambiar el ID itroid.R.id.custom, necesitaba agregar lo siguiente para mostrar la Vista:

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

Sin embargo, esto hizo que la nueva Vista se procesara en una gran vista principal sin fondo, rompiendo el cuadro de diálogo en dos partes (texto y botones, con la nueva Vista entre ellos). Finalmente obtuve el efecto que quería insertando mi vista al lado del mensaje:

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

Encontré esta solución explorando el árbol de View con View.getParent () y View.getChildAt (int). Sin embargo, no estoy muy feliz con ninguno de los dos. Nada de esto está en los documentos de Android y si alguna vez cambian la estructura de AlertDialog, esto podría romperse.

Custom AlertDialog

Este ejemplo completo incluye pasar datos a la Actividad.

enter image description here

Crea un diseño personalizado

En este sencillo ejemplo, se utiliza un diseño con EditText , pero puede reemplazarlo con lo que desee.

custom_layout.xml

     

Usa el diálogo en el código

Las partes clave son

  • usando setView para asignar el diseño personalizado a AlertDialog.Builder
  • enviando datos a la actividad cuando se hace clic en un botón de diálogo.

Este es el código completo del proyecto de ejemplo que se muestra en la imagen de arriba:

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

Notas

  • Si te encuentras usando esto en varios lugares, entonces considera hacer una subclase DialogFragment como se describe en la documentación .

Ver también

  • Diálogo de alerta de Android con uno, dos y tres botones
  • ¿Cómo puedo mostrar una vista de lista en un Diálogo de alerta de Android?

Tendría más sentido hacerlo de esta manera, con la menor cantidad de código.

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

Para obtener una lista ampliada de cosas que puede establecer, comience a escribir .set en Android Studio