1. 程式人生 > >DialogFragment 的使用和一些坑點

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 中遇到的問題,有些言辭可能不太準確,歡迎指正。