Как установить фон диалогового окна прозрачным, не затрагивая его поля

В настоящее время у меня есть следующий диалог, в котором я выполню анимацию expand/ collapse для его элементов.

enter image description here

этот диалог создается с помощью следующего кода

import android.support.v7.app.AlertDialog;

final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final AlertDialog dialog = builder.setView(view).create();
final ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    public void onGlobalLayout() {
        ViewTreeObserver obs = view.getViewTreeObserver();
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
            obs.removeOnGlobalLayoutListener(this);
        } else {
            obs.removeGlobalOnLayoutListener(this);
        }

        // http://stackoverflow.com/questions/19326142/why-listview-expand-collapse-animation-appears-much-slower-in-dialogfragment-tha
        int width = dialog.getWindow().getDecorView().getWidth();
        int height = dialog.getWindow().getDecorView().getHeight();
        dialog.getWindow().setLayout(width, height);
    }
});

однако, когда анимация выполняется, вот побочный эффект.

enter image description here

обратите внимание, что нежелательная дополнительная белая область в диалоговом окне после анимации не вызвана нашим пользовательским представлением. Это системное окно белый фон самого окна.

Я склонен сделать фон системного окна диалога прозрачным.

final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
final AlertDialog dialog = builder.setView(view).create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

хотя нежелательный белый фон больше не отображается, исходное поле диалога также исчезло. (Ширина диалога теперь полная ширина экрана)

enter image description here

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

6 ответов


есть довольно простой способ сделать это:

вам нужно "изменить"Drawable что используется в качестве фона Dialog. Такие Dialogs использовать InsetDrawable в качестве фона.

API >= 23

к сожалению, только SDK для API>=23 позволяет получить источник Drawable обернутый InsetDrawable (getDrawable() метод). С этим вы можете делать все, что хотите-например, изменить цвет на что-то совершенно другое (например, RED или что-то). Если вы используете этот подход, помните, что обернутом Drawable это GradientDrawable, а не ColorDrawable!

API

для более низких API ваши ("элегантные") опции очень ограничены.

к счастью, вам не нужно менять цвет на какое-то сумасшедшее значение, вам просто нужно изменить его на TRANSPARENT. Для этого вы можете использовать setAlpha(...) метод on InsetDrawable.

InsetDrawable background = 
            (InsetDrawable) dialog.getWindow().getDecorView().getBackground();
background.setAlpha(0);

редактировать (в результате из Чок Янь Чэн комментарии):

или вы можете пропустить кастинг InsetDrawable и получить тот же результат. Просто помните, что это вызовет alpha быть измененным на , а не Drawable это обернуто InsetDrawable.


retaining spacings


попробуйте ниже тему:

<style name="TransaparantDialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowTitleStyle">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:backgroundDimEnabled">false</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>

попробуйте ниже кода, чтобы применить тему к AlertDialog.Builder:

final AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(activity, R.style.TransaparantDialog));
...
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);

Я надеюсь помочь вам !


фоновое изображение abc_popup_background_mtrl_mult который является частью библиотеки compat содержит уже поле в информации изображения.

abc_popup_background_mtrl_mult

вот почему поле уходит, когда вы удаляете фоновое изображение. Я настоятельно рекомендую не использовать ViewTreeObserver, он будет вызываться несколько раз и может вызвать проблемы с производительностью. Лучше работать с размером экрана:

Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

ваша проблема правильно в макете попробуйте проверить представления с иерархией зрителя.


просто добавьте эту строку после показа диалогового окна. Я бы предпочел использовать Dialog instedof с помощью AlertDialog

dialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

давайте начнем с рекомендации Google, в которой говорится использовать DialogFragment вместо простого диалога.

@rekire прав, что поля, установленные drawable, в дальнейшем он устанавливается либо 9 патч или программно в зависимости от темы.

таким образом, вы можете установить заполнение в представление содержимого или создать диалог с помощью DialogFragment вот пример, который изменяет высоту диалога на основе его содержимого, и обратите внимание, что вам не нужно использовать tree observer, который упомянутый выше может вызвать проблемы с производительностью.

так пример

dialog_confirm.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="20dp">

    <LinearLayout android:id="@+id/container"
                  xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:background="@android:color/white"
                  android:orientation="vertical"
                  android:animateLayoutChanges="true"
                  android:padding="15dp">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="10dp"
            android:text="A label text"
            android:textAppearance="?android:attr/textAppearanceLarge"/>

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:padding="10dp"
            android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque mauris mi, dictum a lectus ut, facilisis"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Remove Me"/>

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Remove Me"/>

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Remove Me"/>

        <!-- as much content as you need -->

    </LinearLayout>
</ScrollView>

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

ConfirmDialog.java

//here goes package name and  imports

/**
 * Created by Vilen - virtoos.com;
 * fragment dialog example
 */
public class ConfirmDialog extends DialogFragment implements View.OnClickListener {

    private Button button1;
    private Button button2;
    private Button button3;
    private LinearLayout containerLayout;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_TITLE, 0);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.dialog_confirm, container, false);
        containerLayout = (LinearLayout)v.findViewById(R.id.container);
        button1 = (Button)v.findViewById(R.id.button1);
        button2 = (Button)v.findViewById(R.id.button2);
        button3 = (Button)v.findViewById(R.id.button3);
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // make background transparent if you want
        //getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        return super.onCreateDialog(savedInstanceState);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button1:
                containerLayout.removeView(button1);
                break;
            case R.id.button2:
                containerLayout.removeView(button2);
                break;
            case R.id.button3:
                containerLayout.removeView(button3);
                break;
        }
    }
}

и, наконец, вы можете показать свой диалог с этим куском кода

ConfirmDialog confirmDialog = new ConfirmDialog();
confirmDialog.show(getSupportFragmentManager(), "dialog");

enter image description here

Я не буду вдаваться в подробности, почему фрагмент диалог лучше, но одна вещь ясно, что вы можете инкапсулировать логику для него и иметь отдельный класс. Надеюсь, это решит вашу проблему.


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

установите тему в диалог, который помещает всю активность в один диалог. Я не думаю, что ты это сделал, иначе AlertDialog не будет.

Я немного потерял ваше описание, но есть немного <shape/> XML, который намного мощнее, чем 9-патч, и использование RelativeLayout поможет.