DialogFragment 的使用和一些坑點

最近在使用 DialogFragment 的時候踩了一些坑,所以寫個博客記錄一下。

DialogFragment 使用起來和普通的 fragment 差不多,在普通 fragment 的基礎上 DialogFragment 可以通過 show() 和 dismiss() 方法來控制顯示和消失,並且自帶顯示的效果,相對與普通的 dialog,DialogFragment 可以支持自定義佈局,使用起來非常方便。

話不多說,直接上代碼。

package com.example.chen.test;

import android.app.DialogFragment;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


/**
 * Created by chen on 2018/8/3.
 */
public class NoticeDialogFragment extends DialogFragment {

    private TextView noticeTitle;
    private TextView noticeBody;
    private TextView noticeTime;
    private TextView btnKnow;
    private View mRootView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        //對話框的佈局
        if(mRootView==null){
            mRootView = inflater.inflate(R.layout.dialog_group_notice, container,false);
        }
        noticeTitle = mRootView.findViewById(R.id.group_notice_title);
        noticeBody = mRootView.findViewById(R.id.group_notice_body);
        noticeTime = mRootView.findViewById(R.id.group_notice_time);
        btnKnow = mRootView.findViewById(R.id.btn_know);

        //綁定監聽事件
        btnKnow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
        return mRootView;
    }
}

這裏的 DialogFragment 內控件的點擊事件的處理有兩種,上面那種是直接在 DialogFragment 內處理,另一種是在 DialogFragment 裏面寫個接口,然後在 activity 裏面做處理。
如:

package com.example.chen.test;

import android.app.DialogFragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


/**
 * Created by chen on 2018/8/3.
 */
public class NoticeDialogFragment extends DialogFragment {

    private TextView noticeTitle;
    private TextView noticeBody;
    private TextView noticeTime;
    private TextView btnKnow;
    private View mRootView;
    private onItemClickListener onItemClickListener;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        //對話框的佈局
        if(mRootView==null){
            mRootView = inflater.inflate(R.layout.dialog_group_notice, container,false);
        }
        noticeTitle = mRootView.findViewById(R.id.group_notice_title);
        noticeBody = mRootView.findViewById(R.id.group_notice_body);
        noticeTime = mRootView.findViewById(R.id.group_notice_time);
        btnKnow = mRootView.findViewById(R.id.btn_know);

        //綁定監聽事件
        btnKnow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //在activity裏面處理點擊事件
                onItemClickListener.onItemClick(v);
            }
        });
        return mRootView;
    }

    //監聽事件接口
    public interface onItemClickListener {
        void onItemClick(View v);
    }

    public void setOnItemClickListener(NoticeDialogFragment.onItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }
}

然後在activity裏面處理監聽事件

package com.example.chen.test;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements
        NoticeDialogFragment.onItemClickListener{

    NoticeDialogFragment fragment;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.btn_show);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //實例化對象
                fragment = new NoticeDialogFragment();
                //綁定監聽事件
                fragment.setOnItemClickListener(MainActivity.this);
                fragment.show(getFragmentManager(), "dialog");
            }
        });
    }

    @Override
    public void onItemClick(View v) {
        fragment.dismiss();
        Toast.makeText(this, "我知道了", Toast.LENGTH_SHORT).show();
    }
}

這樣,一個簡單的Dialog就完成了,來看一下運行效果。
這裏寫圖片描述
可以說是非常的不盡人意了,我們想要的效果是讓我們寫的佈局顯示在中間並且不要旁邊的邊框,但 DialogFragment 並不能讀懂我們的想法,所以我們需要寫一個 style 來告訴 DialogFragment 這個佈局應該如何顯示。

<style name="NoticeDialogStyle" parent="android:Theme.Holo.Light.Dialog">
       <item name="android:windowNoTitle">true</item>
       <item name="android:windowBackground">@null</item>
</style>

然後在 DialogFragment 的 onCreate 方法裏面調用 setStyle 來設置我們寫好的 style,一定是在onCreate 裏面設置 style,在 onCreateView 裏面設置是沒有效果的。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setStyle(DialogFragment.STYLE_NORMAL,R.style.NoticeDialogStyle);
}

這兩句代碼很簡單,就是告訴 DialogFragment 我的 dialog 沒有標題欄,並且背景也是空的,實際上如果只是想去掉邊框的話,只需要設置 windowNoTitle 爲 true 就可以了,但是考慮到默認的背景有點黑,設置背景爲空,下面是運行效果。
這裏寫圖片描述
新的問題又出現了,我們設置的圓角佈局出現了黑角,實際上是因爲我們把 DialogFragment 的背景設置爲空,所以纔會出現黑角,我們需要在 DialogFragment 的 onCreateView 裏面設置背景爲透明。

getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

到此,大功告成,來看效果圖。
這裏寫圖片描述
這篇博客只是記錄我在使用 DialogFragment 中遇到的問題,有些言辭可能不太準確,歡迎指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章