Android 自定义 DialogFragment 宽度问题

今天在做检查更新功能的时候遇到一个问题,是关于DialogFragment实现自定义对话框样式(主要是宽度)的,这里记录一下。

需要实现的效果

设计图如下

Android 自定义 DialogFragment 宽度问题_第1张图片

在检查到有新版本之后需要弹出一个对话框,内容自定义,这里用AlertDialog比较困难了,因此我用的是DialogFragment实现。

最初的实现

首先定义一个XML布局文件,如下所示


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:gravity="center_horizontal"
              android:orientation="vertical"
              android:paddingLeft="16dp"
              android:paddingRight="16dp">

    <TextView
        android:id="@+id/version_tip_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="16dp"
        android:gravity="center"
        android:text="1.2版本发布"
        android:textColor="@color/primary_dark"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/version_description_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="首页百变"
        android:textColor="@color/primary"/>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="32dp"
        android:src="@mipmap/pic_eab"/>

    <Button
        android:id="@+id/submit_button"
        style="@style/Button"
        android:text="立即更新"/>
LinearLayout>

以上代码只是列出基本结构,样式定义什么的没有贴出。

有了自定义布局文件,然后自定义 DialogFragment 类代码如下

package com.witmoon.eab.ui.fragment.dialog;

import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;

import com.witmoon.eab.R;

/**
 * 检查更新时有新版本发布弹出对话框
 * Created by zhyh on 2015/11/16.
 */
public class NewVersionDialogFragment extends DialogFragment {

    private String mVersionCode;
    private String mDescription;

    private OnUpdateListener mOnUpdateListener;

    public void setOnUpdateListener(OnUpdateListener onUpdateListener) {
        mOnUpdateListener = onUpdateListener;
    }

    public interface OnUpdateListener {
        void onUpdate(Dialog dialog);
    }

    public static NewVersionDialogFragment newInstance(String versionCode, String description) {
        NewVersionDialogFragment fragment = new NewVersionDialogFragment();
        Bundle bundle = new Bundle();
        bundle.putString("version", versionCode);
        bundle.putString("description", description);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        mVersionCode = bundle.getString("version");
        mDescription = bundle.getString("description");
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return super.onCreateDialog(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        View view = inflater.inflate(R.layout.dialog_new_version, null);

        TextView versionTipText = (TextView) view.findViewById(R.id.version_tip_text);
        versionTipText.setText(String.format("%s版本发布", mVersionCode));
        TextView versionDescriptionText = (TextView) view.findViewById(R.id.version_description_text);
        versionDescriptionText.setText(mDescription);

        Button button = (Button) view.findViewById(R.id.submit_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnUpdateListener != null) {
                    mOnUpdateListener.onUpdate(getDialog());
                }
            }
        });

        return view;
    }
}

根据设计图,Dialog不能有标题,因此在代码中用getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);去掉了对话框标题栏,这时如果运行程序,显示效果如下所示

Android 自定义 DialogFragment 宽度问题_第2张图片

很明显能看出对话框布局是WRAP_CONTENT,这样显得很拥护,如果版本描述内容更简短的话,这个对话框还会更窄。这样显示效果很难看,因此,我想要是能让对话框占用固定比例的屏幕宽度会显得更美观一些。

下面记录一下在网络上搜到的各种解决方式,代码都是基于上面完整的自定义 DialogFragment 并略有改动。

使对话框充满屏幕宽度

这种方式是使对话框充满屏幕的宽度,通过设置 Diaglog 样式实现;在onCreate方法中修改如下:

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        mVersionCode = bundle.getString("version");
        mDescription = bundle.getString("description");
        setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_MinWidth);
    }

注意最后一行代码,这里设置了无标题样式(此时onCreateView的getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);就没有必要了,可以删掉了),并保证对话框的最小宽度,效果如下

Android 自定义 DialogFragment 宽度问题_第3张图片

可以看到,这种对话框其实就是默认的AlertDialog样式,宽度充满屏幕,左右保留一些外边距。

但是对照着设计图看还不太满足要求,这种效果显得太宽了,也不美观,最好是能让对话框占用屏幕宽度的一定比例,比如70%的屏幕宽度。

占用屏幕宽度一定比例

后来又找到另外一种方式,这种方式是自己计算屏幕宽度并设置到对话框,重写onStart方法,实现如下

@Override
public void onStart() {
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null) {
        DisplayMetrics dm = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
        dialog.getWindow().setLayout((int) (dm.widthPixels * 0.75), ViewGroup.LayoutParams.WRAP_CONTENT);
    }
}

从代码可以看出,首先计算屏幕的宽度,然后将宽度的75%设置到对话框的Window上,高度为WRAP_CONTENT。

记得要在onCreateView方法中加上

getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);

不然标题栏又要出现了。

这时实现的效果如下图所示:
Android 自定义 DialogFragment 宽度问题_第4张图片

这样就显得很接近设计图的样式了。

对话框圆角

如果要实现自定义对话框圆角,可以加入下面的代码使对话框背景透明

getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);

然后将自定义布局设置为圆角就可以了,在drawable目录中定义XML如下


<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="8dp"/>
    <stroke android:color="#FDFFFFFF"/>
    <solid android:color="#FDFFFFFF"/>
shape>

然后将自定义布局的根布局background属性设置为该xml就可以了。

你可能感兴趣的:(Android)