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