024-Android自定义对话框(1):DialogFragment图文详解

1,796 阅读1分钟

1.简述

DialogFragment 是谷歌官方推荐的对话框,可以高度自定义,灵活方便,非常适合编写产品经理设计的任何UI。

AlertDialog在商业项目实际开发使用率已经低到忽略不计,了解基本使用即可。

2.创建方式的区别

1.onCreateDialog

该方式是在方法内部创建AlertDialog然后返回AlertDialog对象,定制性差,不推荐。

2.onCreateView--推荐方式

在onCreateView中渲染自定义的布局,并设置交互逻辑。

3.使用

3.1 自定义对话框UI

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/shape_white_bg_5_radius"
    android:paddingLeft="17dp"
    android:paddingRight="18dp"
    android:paddingBottom="20dp">
    <ImageView
        android:id="@+id/img"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="24dp"
        android:src="@mipmap/ic_launcher" />
    <EditText
        android:id="@+id/input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/img"
        android:layout_marginTop="8dp"
        android:background="@drawable/shape_gray_stroke_radius_5"
        android:hint="输入"
        android:inputType="text"
        android:minHeight="45dp"
        android:padding="8dp"
        android:textColor="#404040"
        android:textSize="14sp" />
    <Button
        android:id="@+id/btn_submit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/input"
        android:layout_marginTop="12dp"
        android:background="@drawable/shape_blue_radius_5"
        android:text="添加"
        android:textColor="#fff"
        android:textSize="18sp" />
</RelativeLayout>

3.2 继承DialogFragment

重点关注onStart()中对对话框的宽高设置、居中等处理,参数及方法见名知意。

同时关注build静态方法,这是一个开发规范。

package com.cupster.easydialogfragment;

import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;

public class AddInputDialog extends DialogFragment {

    public static final String KEY_NAME ="NAME";

    View mView;
    ImageView mImg;
    EditText mInput;
    Button mBtn;

    View.OnClickListener mConfirmListener;

    public  static AddInputDialog build(String name ){
        AddInputDialog dialog = new AddInputDialog();
        Bundle bundle = new Bundle();
        bundle.putString(KEY_NAME ,name);
        dialog.setArguments(bundle);
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mView == null) {
            mView = inflater.inflate(R.layout.dialog_add_input, container, false);
        }
        setStyle(STYLE_NORMAL, R.style.ConfirmDialogStyle);
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        return mView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        mImg = mView.findViewById(R.id.img);
        mBtn = mView.findViewById(R.id.btn_submit);
        mInput = mView.findViewById(R.id.input);

        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mConfirmListener != null){
                    view.setTag( mInput.getText().toString() );
                    mConfirmListener.onClick(view);
                }
                dismiss();
            }
        });

        initData();
    }

    private void initData() {
        Bundle bundle = getArguments();
        if (bundle != null) {
            String name = bundle.getString(KEY_NAME);
            if (!TextUtils.isEmpty(name)){
                mInput.setText(name);
            }
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        Window window = getDialog().getWindow();
        window.setDimAmount(0.2f);//设置亮度
        window.setGravity(Gravity.CENTER);
        window.setWindowAnimations(R.style.PopupAnimation);
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        layoutParams.width = (int) (0.85*deviceWidth(getContext()));
        window.setLayout(layoutParams.width, layoutParams.height);
        window.setBackgroundDrawableResource(android.R.color.transparent);
    }

    public static int deviceWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    public void setConfirmListener(View.OnClickListener listener){
        mConfirmListener = listener;
    }
}

3.3 调用

package com.cupster.easydialogfragment;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showDialog();
            }
        });
    }
    private void showDialog() {
        AddInputDialog dialog = AddInputDialog.build("请输入");
        dialog.setConfirmListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this ,"确认",Toast.LENGTH_LONG).show();
            }
        });
        dialog.show(getSupportFragmentManager() ,"input");
    }
}

3.4 其他相关代码

res/values/styles.xml

   <style name="ConfirmDialogStyle" parent="android:Theme.Holo.Light.Dialog">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@null</item>
    </style>
    <!-- 弹出窗体的动画 从底部弹出 -->
    <style name="PopupAnimation" parent="@android:style/Animation">
        <!-- 边框 -->
        <item name="android:windowFrame">@null</item>
        <!-- 设置dialog的背景 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 是否浮现在activity之上 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 半透明 -->
        <item name="android:windowIsTranslucent">false</item>
        <!-- 无标题 -->
        <item name="android:windowNoTitle">true</item>
        <!-- 模糊 -->
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:windowEnterAnimation">@anim/popup_enter</item>
        <item name="android:windowExitAnimation">@anim/popup_exit</item>
    </style>

popup_enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="600"
        android:fromXDelta="0.0%"
        android:fromYDelta="100%p"
        android:toXDelta="0.0%"
        android:toYDelta="0" />
</set>

popup_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="600"
        android:fromYDelta="0"
        android:toYDelta="100%p" />
</set>

shape_blue_radius_5.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="5dp"/>
    <solid android:color="#5577fb"/>
</shape>

shape_gray_stroke_radius_5.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:bottomLeftRadius="3dp"
        android:bottomRightRadius="3dp"
        android:topLeftRadius="3dp"
        android:topRightRadius="3dp"
        />
    <solid android:color="#fff"/>
    <stroke android:color="#bfbfbf" android:width="1dp"/>
</shape>

shape_white_bg_5_radius.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <solid android:color="#fff" />
    <corners android:radius="5dp"/>
</shape>