Özel bir AlertDialog Görünümü nasıl uygulanır?


107

In AlertDialog Android dokümanlar , bir AlertDialog içinde özel bir görünüm ayarlamak için aşağıdaki talimat ve örnek verir:

Daha karmaşık bir görünüm görüntülemek istiyorsanız, "gövde" adlı Çerçeve Düzeni'ne bakın ve görünümünüzü buna ekleyin:

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

Öncelikle, bunun add()bir yazım hatası olduğu ve olması gerektiği çok açık addView().

R.id.body'yi kullanan ilk satır kafam karıştı. Görünüşe göre bu AlertDialog'un gövde öğesi ... ama bunu koduma giremem, b / c bir derleme hatası veriyor. R.id.body nerede tanımlanır veya atanır?

İşte kodum. setView(findViewById(R.layout.whatever)Oluşturucu üzerinde kullanmayı denedim ama işe yaramadı. Bunu manuel olarak şişirmediğim için mi varsayıyorum?

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

Nesnelerinizi bir İletişim Kutusunda bulmak ve kullanmak için şu dört adımı izleyin: stackoverflow.com/a/18773261/1699586
Sara

3
Tek satırlık cevap: kurucuya ekleyin .setView(getLayoutInflater().inflate(R.layout.dialog_view, null)). Aşağıdaki Sergio Viudes'e kredi.
1

Yanıtlar:


49

Haklısın, çünkü onu elle şişirmedin. Aktivitenizin düzeninden "gövde" kimliğini "çıkarmaya" çalıştığınız anlaşılıyor ve bu işe yaramayacak.

Muhtemelen şöyle bir şey istiyorsun:

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

17
İlginçtir ki, vücut android.R.id'de sabit olarak tanımlanmamıştır. Oluşturulan AlertDialog'un 'body' öğesine nasıl erişeceğim konusunda hala net değilim. Hala bunu nasıl yapacağımı bilmek istiyorum, ancak şimdilik sadece bir görünümü şişirmeye ve oluşturucuda setView kullanmaya çalışacağım.
stormin986

2
Aslında bu hala bana bir soru bırakıyor (görüşleri şişirmek konusunda yeniyim). Kullanarak builder.setView(inflater.inflate(R.id.dialog, ROOT_VIEWGROUP[, ATTACH_TO_ROOT])), dokümanlar, kök görünüm grubunun isteğe bağlı olduğunu söylüyor. Bu durumda bu kullanılmalı mı? Öyleyse ... hala AlertDialog'a nasıl referans
alınacağını bulmalıyız

2
Bu isteğe bağlıdır, ancak o zaman şişirdiğiniz düzenin içinden ebeveyne bir referansınız olmayacaktır. Android gibi şeyler: layout_gravity üst düzey görünümde çalışmaz ... ve belki onlara ihtiyacınız yoktur. AlertDialog alert = builder.create () 'i çağırdığınızda, AlertDialog'unuza bir referansınız olur. Uzun cevap kısası, bir isteğe bağlı. Bir deneyin, özel düzeninizde ne yaptığınıza bağlı olarak muhtemelen işe yarayacaktır.
synic

2
AlertDialog içinde görünüme nasıl başvurulacağı konusunda net değilim . Ebeveyne başvurmak isteseydim bu durumda ne yapmayı önerirsiniz? AlertDialog'da bir görünüm döndüren tek gördüğüm şey getCurrentFocus ()
stormin986

5
Şişirdiğinize tutun View. Çağrı findViewById()bu konuda Viewonun içeriğinden şeyler gerektiğinde. Bakınız: github.com/commonsguy/cw-android/tree/master/Database/Constants
CommonsWare

159

Görünümünüzü doğrudan Layout Inflater'dan oluşturabilirsiniz, sadece layout XML dosyanızın adını ve dosyadaki layout ID'sini kullanmanız yeterlidir.

XML dosyanızın aşağıdaki gibi bir kimliği olmalıdır:

<?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"
              />

Ardından, aşağıdaki kodla oluşturucuda düzeninizi ayarlayabilirsiniz:

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
Ve bu örnekte R.id.dialog_layout_root nerede? Bu, mevcut Aktivitede bir görünüm değil mi?
Alex Pretzlav

5
@AlexPretzlav: dialog_layout_root bu örnekte gerekli değildir. Tek ihtiyacınız olan R.layout için xml dosyanızın adıdır. [Name_of_xml_file].
IgorGanapolsky

7
@Temperage Sonuna builder.show'u eklediniz mi? Bu kodu denedim ve işe yaradı. Ayrıca infalter.inflate için ikinci parametre olarak null geçtim
Vinoth

2
Bu, En İyi Cevap olarak seçilmeliydi.
Salman Khakwani

2
Bu, özel düzen bir EditText içerdiğinde bir ClassCastException verir, çünkü getCurrentFocus()EditText'i döndürür ve EditText bir ViewGroup'a dönüştürülemez. nullİkinci argüman olarak kullanmak bunu düzeltir.
1

20

android.R.id.custom benim için boş dönüyordu. Herhangi birinin aynı sorunla karşılaşması durumunda bunun işe yaramasını sağladım.

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

Referans için, 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>

John Rellis. Çözümünüz iyi çalışıyor. Sadece içinde bir şey var. Builder.create ve frameView.setLayoutParams (yeni LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); veya önce bir şey, beklenmeyen bazı hataları önleyecek
MOBYTELAB

geri bildirim için teşekkürler..builder.create () 'den önce nasıl şişiriyorsunuz? şişirmek, iletişim kutusunun
şişiricisinde çağrılıyor

Aktivite şişiricisini kullanabiliriz ve FrameLayout'a eklemeyebiliriz, böylece bunun gibi küçük bir kodu azaltabiliriz.AlertDialog.Builder builder = new AlertDialog.Builder (new ContextThemeWrapper (getActivity (), android.R.style.Theme_Holo)) .setTitle ("başlık") .setIcon (R.drawable.sample_icon); SorunView = inflater.inflate (R.layout.sample_layout, null, false); builder.setView (troubleView); alert = builder.create (); Maalesef yorumda kodu net bir şekilde nasıl yazacağımı bilmiyorum
MOBYTELAB

Bu sadece tasarım hatasıyla ilgili, eğer hepsini layout xml'de toplarsak ve Framelayout'u diyalogun bir kökü olarak unutursak, xml'deki layout'un fill parent veya başka bir şey olup olmadığını merak edebiliriz, sadece bir durum.
MOBYTELAB

Benim için çalıştı, teşekkürler! Bu, bir başlık eklememe ve Hatasız Metni Düzenle dahil olmak üzere İptal ve Tamam düğmelerini eklememe olanak tanır. :) Tek soru, bu nasıl çalışıyor? FrameLayoutBir çeşit parça olarak mı hareket ediyor? Andrewx2'nin yukarıdaki cevabını denediğimde, iki düzeni şişirdiğimi düşündüğü için bir hata aldım (benim tahminim).
Azurespot


12

Bu benim için çalıştı:

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

8

Özel AlertDialog

Bu tam örnek, verilerin Aktiviteye geri aktarılmasını içerir.

görüntü açıklamasını buraya girin

Özel bir düzen oluşturun

EditTextBu basit örnek için bir düzen kullanılır, ancak onu istediğiniz herhangi bir şeyle değiştirebilirsiniz.

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>

İletişim kutusunu kodda kullanın

Anahtar parçalar

  • setViewözel düzeni atamak için kullanarakAlertDialog.Builder
  • bir iletişim düğmesi tıklandığında herhangi bir veriyi aktiviteye geri gönderme.

Bu, yukarıdaki resimde gösterilen örnek projeden alınan tam koddur:

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

Notlar

  • Bunu birden çok yerde kullanırken bulursanız DialogFragment, belgelerde açıklandığı gibi bir alt sınıf oluşturmayı düşünün .

Ayrıca bakınız


1
EditText editText = customLayout.findViewById(R.id.editText); olmalı EditText editText = (EditText) customLayout.findViewById(R.id.editText);
philcruz

4
@philcruz, Android Studio 3.0'a yükseltirseniz, artık görünümü açıkça yayınlamanız gerekmez. IDE türü çıkarabilir. Çok güzel bir özellik. Kodu temizlemeye çok yardımcı olur.
Suragch

harika cevap, gerçekten faydalı
Noor Hossain

4

Benim için çalışan en basit kod satırları şunlardır:

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

Düzen türü ne olursa olsun (LinearLayout, FrameLayout, RelativeLayout) işe yarayacak setView ve görünüş ve davranış açısından farklılık gösterecektir.


müthiş, basit ve kolay
Frank Eno

2

Bunu yapmanın en kolay yolu, API 21'in altında kullanılabilecek yerler android.support.v7.app.AlertDialogyerine kullanmaktır .android.app.AlertDialogpublic AlertDialog.Builder setView (int layoutResId)

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

API 21 tanıtıldıktan sonra bunu okuyan herkes bu yöntemi kullanmalıdır. Cevapta belirtildiği gibi, minSDKversion uygulamanız 21'den azsa, destek paketinden AlerDialog'u kullanın. Voila !!!
Dibzmania

2

AlertDialog.setView(View view)verilen görünümü R.id.custom FrameLayout. Aşağıda, AlertController.setupView()sonunda bunu işleyen Android kaynak kodunun bir snippet'i bulunmaktadır ( yönteme mViewverilen görünümdür AlertDialog.setView).

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

1

Kimliği değiştirdikten sonra android.R.id.custom, Görünümün görüntülenmesini sağlamak için aşağıdakileri eklemem gerekiyordu:

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

Ancak bu, yeni Görünümün arka planı olmayan büyük bir ana görünümde oluşturulmasına ve iletişim kutusunu iki parçaya (metin ve düğmeler, arada yeni Görünüm ile) ayırmasına neden oldu. Sonunda mesajın yanına Görünümümü ekleyerek istediğim etkiyi elde ettim:

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

View.getParent () ve View.getChildAt (int) ile View ağacını keşfederek bu çözümü buldum. Yine de ikisinden de pek memnun değil. Bunların hiçbiri Android dokümanlarında yoktur ve AlertDialog'un yapısını değiştirirlerse bu bozulabilir.


1

Bunu bu şekilde yapmak en mantıklı olacaktır, en az miktarda kod.

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

Ayarlayabileceğiniz şeylerin genişletilmiş bir listesi .setiçin Android Studio'da yazmaya başlayın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.