- Dialog :Builder模式建立
- Dialog常用的方法
- setButton(…)
- dialog消失的2種方法的差別!
- Dialog效果圖
- AlertDialog:基本對話框
- 效果圖:
- 相關的類
- Builder的相關的方法
- 代碼:
- 注意:
- Dialog添加清單
- AlertDialog:單選對話框
- 效果圖:
- 相關的方法
- 代碼:
- AlertDialog多選對話框
- 效果圖:
- Builder的相關的方法
- 點開dialog顯示上一次退出時選中的按鈕
- 代碼:
- ProgressDialog:進度條對話框
- 效果圖:
- 相關的方法
- 設定進度條:
- 代碼:
- 自定義Dialog
- 效果圖:
- 相關
- 代碼:
- 自定義Dialog:加 動畫 + 設定寬高 + style
- 效果圖:
- 相關
- 設定寬 + 高
- 添加動畫
- 代碼:
- Dialog:構造方法建立
- ProgressDialog
- DatePickerDialog
- DatePickerDialog 不重寫setButton()
- 效果圖
- 代碼
- DatePickerDialog 重寫setButton()
- 效果圖
- 代碼
- DatePickerDialog 不重寫setButton()
- TimePickerDialog
- TimePickDialog:不重寫setButton()
- 效果圖
- 代碼
- TimePickDialog:重寫setButton()
- 效果圖
- 代碼
- TimePickDialog:不重寫setButton()
- 其它
- DialogFragment
- 建立dialog
- 顯示dialog
- Demo
- DialogFragment01
- DialogFragment02
- DialogFragment03
- 使用DialogFragment怎麼把value傳給Activity?
- 仿ios透明加載框
- 一
- 效果圖
- 工具類
- WindowManager.LayoutParams.FLAG_DIM_BEHIND
- 二:采用了幀動畫
- 需要複制的内容
- progress_drawable_list.xml 幀動畫
- ProgressDialogUtil2
- 一
- 系統級的Dialog
- 效果圖
- 權限+Type
- 其它
- 注意
- dialog的Context不能使用getApplicationContext()
- dialog.setCanceledOnTouchOutside(false)無效
參考:
Android API 指南:Dialog: https://developer.android.google.cn/guide/topics/ui/dialogs.html#ShowingADialog
Dialog :Builder模式建立
dialog的監聽可以為null,按“确定”、“取消”仍然有效。
對話框分類 | 含義 |
---|---|
Dialog | 基類:非抽象 |
AlertDialog | 提醒對話框 |
ProgressDialog | 進度條對話框 |
Dialog背景色是黑色,這是因為style的原因:
這些對話框都繼承自Dialog,API18:
見圖:
Dialog常用的方法
方法 | 含義 |
---|---|
setContentView(View or resId) | 填充布局 |
findViewById(resId) | 找到布局中的控件,可以用dialog調用 |
setTitle(character char) | 設定比提提 |
setIcon(resId) | 設定圖示 |
show() | 顯示 |
dismiss() | 消失:從螢幕中移除 |
hide() | 隐藏 |
isShow() | dialog是否正在顯示 |
getWindow() | 得到目前dialog所在的activity的窗體 |
類Dialog是沒有方法:setMessage(charseQuence char),但是子類AlertDialog + ProgressDialog有此方法。
setButton(…)
dialog.setButton(…)
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", dialog);
dialog.setButton(DialogInterface.BUTTON_NEUTRAL, "中立", dialog);
dialog.setButton("自定義Button:确定", dialog);
dialog.setButton2("自定義Button:取消", dialog);
builder.setPositiveButton(…)
builder.setTitle("選擇時間")
.setCancelable(false)
.setIcon(android.R.drawable.ic_dialog_info)
.setSingleChoiceItems(times, , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//
}
})
.setNegativeButton("選擇日期", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//
}
});
dialog消失的2種方法的差別!
setCancelable(boolean flag) :點選back鍵dialog是否消失
setCanceledOnTouchOutside(boolean cancel) : 點選dialog意外的區域dialog是否消失
見developer
Dialog效果圖
AlertDialog:基本對話框
繼承自Dialog,預設顯示在螢幕中間,左右兩邊距離螢幕有間隔。
效果圖:
相關的類
類 | 含義 |
---|---|
AlertDialog | 提醒對話框 |
AlertDialog.Builder | 對話框構造器 |
Builder的相關的方法
方法 | 含義 |
---|---|
setPositiviButton(String ,DialogInterface.onClickListener(..)) | 設定确定按鈕 |
setNogetiveButton(String ,DialogInterface.onClickListener(..)) | 設定取消按鈕 |
setMessage(charseQuence char) | 設定dialog内容 |
crete() | 建立dialog對象 |
代碼:
// 普通對話框
private void initAlertDialog() {
Builder builder = new AlertDialog.Builder(context);
builder.setTitle("更新提示");
builder.setMessage("這是知乎最新版本,請更新!");
builder.setIcon(R.drawable.ic_launcher);
builder.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ToastUtil.showShortToast(context, "确定" + which);
// dialog.dismiss();//可以不調用dismiss(),dialog會自動消失
}
});
builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ToastUtil.showShortToast(context, "取消" + which);
// dialog.dismiss();可以不調用dismiss(),dialog會自動消失
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
注意:
AlertDialog的方法setNegativeButton(CharSequence text, OnClickListener listener) + setPositiveButton(CharSequence text, OnClickListener listener) + setPositiveButton(CharSequence text, OnClickListener listener) 會自動調用dialog的dismiss(),除此之外均如果需要讓dialog消失,都必須調用dismiss().
設定單選對話框和多選對話框時,不能調用方法setMessage(charseQuence char),否則選擇清單不會顯示。
Dialog添加清單
可通過 AlertDialog API 提供三種清單:
- 傳統單選清單
- 永久性單選清單(單選按鈕)
- 永久性多選清單(複選框)
checkedItem:預設選中的position。-1表示預設不選中任何一個。
.setSingleChoiceItems(provinces, -, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//which表示選中的item在items中的角标
}
})
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle("Title")
.setIcon(R.mipmap.ic_launcher_round)
.setSingleChoiceItems(provinces, -, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "singleChoice,which=" + which);
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "Positive,which=" + which);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "Negative,which=" + which);
}
})
.create();
dialog.show();
AlertDialog:單選對話框
效果圖:
相關的方法
類 | 含義 |
---|---|
setSingleChoiceItems(CharSequence[] items, int checkedItem, OnClickListener listener) | 設定單選對話框 |
items | 所有選項 |
checkedItem | 預設選中哪一個,-1:預設都沒選 |
代碼:
private void initSingleChoiceDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("标題");
// builder.setMessage("message--message");//設定message就沒有了單選清單
builder.setIcon(R.drawable.ic_launcher);
final String[] items = new String[] { "item1", "item2", "item3", "item4", "item5" };
final boolean[] checkedItem = new boolean[]{false,false,false,false,false};
builder.setSingleChoiceItems(items, -,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
checkedItem[which] = true;
ToastUtil.showShortToast(context, items[which]);
dialog.dismiss();// 點選單選按鈕,dialog不會自動消失
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
AlertDialog多選對話框
效果圖:
Builder的相關的方法
方法 | 含義 |
---|---|
setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener) | 多選方法 |
參數 | 含義 |
items | 多選清單的内容 |
checkedItems | ,預設選中的内容 |
點開dialog顯示上一次退出時選中的按鈕
把checkedItems 的建立放在類中,作為類變量。
代碼:
private void initMultiChoiceDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Title");
// builder.setMessage("message--message");//設定message就沒有了單選清單
builder.setIcon(R.drawable.ic_launcher);
items = new String[] { "item1", "item2", "item3", "item4", "item5" };
final boolean[] checkedItems = new boolean[] { false, false, false,
false, false };
builder.setMultiChoiceItems(items, checkedItems,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
ToastUtil.showShortToast(context, items[which]);
}
});
builder.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ToastUtil.showShortToast(context, "取消");
// dialog.dismiss();//可以不調用dismiss(),dialog會自動消失
}
});
builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
StringBuffer sb = new StringBuffer();
for (int i = ; i < checkedItems.length; i++) {
if (checkedItems[i]) {
sb.append(items[i]);
}
}
ToastUtil.showShortToast(context, "确定" + sb.toString());
// dialog.dismiss();可以不調用dismiss(),dialog會自動消失
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
如何獲選中的資料?
除了周遊
boolean[] checkedItems
外,還可以建立一個List,選中時添加到List,取消後從List中清除
ArrayList<String> selectedList = new ArrayList<>();
selectedList.clear();
builder.setMultiChoiceItems(provinces, null, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
Log.d(TAG, "MultiChoice,which=" + which + ",isChecked=" + isChecked);
if (isChecked) {
selectedList.add(provinces[which]);
} else if (selectedList.contains(provinces[which])) {
selectedList.remove(provinces[which]);
}
}
})
ProgressDialog:進度條對話框
分為線性和圓形,沒有Builder.
效果圖:
相關的方法
類 | 含義 |
---|---|
setProgressStyle(int style) | 設定進度條樣式 |
setMax(int max) | 進度最大值 |
setProgress(int value) | 設定目前進度 |
設定進度條:
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 水準線進度條
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 圓形進度條
代碼:
private void initProgressDialog() {
final ProgressDialog dialog = new ProgressDialog(context);
dialog.setTitle("Title");//設定标題
dialog.setMessage("message----message");//設定dialog内容
dialog.setIcon(R.drawable.ic_launcher);//設定圖示,與為Title左側
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 水準線進度條
// dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);//圓形進度條
dialog.setMax();//最大值
new Thread() {
public void run() {
for (int i = ; i <= ; i++) {
SystemClock.sleep();
dialog.setProgress(i);//每隔50毫秒設定目前進度
}
dialog.dismiss();// for執行完成後dialog預設不消失
};
}.start();
dialog.show();
}
自定義Dialog
需要自己設定布局
效果圖:
相關
類 | 含義 |
---|---|
window | 窗體 |
方法 | 含義 |
setGravity(int gravity) | 設定窗體位置 |
類 | 含義 |
Dialog | |
方法 | 含義 |
requestWindowFeature(int featureId) | 窗體的title是否顯示 |
代碼:
private void initCustomDialog() {
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉dialog的title,放在設定布局前
dialog.setContentView(R.layout.custom_dialog);
dialog.getWindow().setGravity(Gravity.BOTTOM);
Button btn_ok = (Button) dialog.findViewById(R.id.btn_ok);
Button btn_cancle = (Button) dialog.findViewById(R.id.btn_cancle);
btn_ok.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
btn_cancle.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
自定義Dialog:加 動畫 + 設定寬高 + style
效果圖:
相關
類:Window
方法 | 含義 |
---|---|
方法 | 含義 |
setGravity(int gravity) | 設定窗體位置 |
getAttributes() | 擷取目前窗體的參數 |
setAttributes(LayoutParams a) | 設定窗體寬高 |
setWindowAnimations(int resId) | 給窗體添加動畫 |
類:Dialog
方法 | 含義 |
---|---|
requestWindowFeature(int featureId) | 窗體的title是否顯示 |
setCanceledOnTouchOutside(boolean cancel) | 點選dialog意外的區域,dialog是否消失 |
設定寬 + 高
//設定 寬 + 高
LayoutParams params = window.getAttributes();//擷取目前窗體的參數
view.measure(, );
params.width = getResources().getDisplayMetrics().widthPixels;
params.height = view.getMeasuredHeight();//不設定高的話,dialog會充滿螢幕,下方是白色,即使在布局中設定了高的具體值
window.setAttributes(params);
添加動畫
DialogAnimationStyle:
<style name="DialogAnimationStyle" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/dialog_enter</item>
<item name="android:windowExitAnimation">@anim/dialog_exit</item>
</style>
dialog_enter.xml:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromYDelta="100%" >
</translate>
dialog_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:toYDelta="100%" >
</translate>
MyStyle.xml
<style name="MyStyle">
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
代碼:
private void initCustomDialog2() {
final Dialog dialog = new Dialog(context , R.style.MyStyle);//去掉dialog的title,dialog區域外是灰色
// dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉dialog的title,放在設定布局前
View view = View.inflate(context, R.layout.custom_dialog2, null);
dialog.setContentView(view);
dialog.setCanceledOnTouchOutside(true);//點選dialog意外的區域,dialog是否消失
Window window = dialog.getWindow();//建立目前窗體
window.setGravity(Gravity.BOTTOM);//目前床底位于底部
//添加動畫
window.setWindowAnimations(R.style.DialogAnimationStyle);
//設定 寬 + 高
LayoutParams params = window.getAttributes();//擷取目前窗體的參數
view.measure(, );
params.width = getResources().getDisplayMetrics().widthPixels;
params.height = view.getMeasuredHeight();//不設定高的話,dialog會充滿螢幕,下方是白色,即使在布局中設定了高的具體值
window.setAttributes(params);
Button btn_camera = (Button) dialog.findViewById(R.id.btn_camera);
Button btn_gallery = (Button) dialog.findViewById(R.id.btn_gallery);
Button btn6_cancle = (Button) dialog.findViewById(R.id.btn6_cancle);
btn_camera.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ToastUtil.showShortToast(context, "btn_camera");
dialog.dismiss();
}
});
btn_gallery.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ToastUtil.showShortToast(context, "btn_gallery");
dialog.dismiss();
}
});
btn6_cancle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ToastUtil.showShortToast(context, "btn6_cancle");
dialog.dismiss();
}
});
dialog.show();//顯示dialog
}
源碼:https://github.com/s1168805219/DialogDemo
再魅族手機中,虛拟按鍵會遮擋bottomDialog的下方,解決的方法是在設定window的高度是加上虛拟鍵的高度
public class VirtualHeightUtil {
public static int getDpi(Activity activity) {
Display display = activity.getWindowManager().getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
int height = ;
@SuppressWarnings("rawtypes")
Class c;
try {
c = Class.forName("android.view.Display");
@SuppressWarnings("unchecked")
Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
method.invoke(display, dm);
height = dm.heightPixels;
} catch (Exception e) {
e.printStackTrace();
}
return height;
}
public static int[] getScreenWH(Context poCotext) {
WindowManager wm = (WindowManager) poCotext.getSystemService(Context.WINDOW_SERVICE);
if (wm == null) {
return new int[]{, };
} else {
int width = wm.getDefaultDisplay().getWidth();
int height = wm.getDefaultDisplay().getHeight();
return new int[]{width, height};
}
}
/**
* 擷取魅族手機的虛拟鍵高度
* @param poCotext
* @return
*/
public static int getVirtualBtnHeight(Context poCotext) {
int location[] = getScreenWH(poCotext);
int realHeiht = getDpi((Activity) poCotext);
int virtualHeight = realHeiht - location[];
return virtualHeight;
}
}
Dialog:構造方法建立
我們知道設定模式有建構者模式,也就是Builder模式,上面我們建立Dialog就是這麼做的。其實采用構造方法也可以建立Dialog。
比如:
Dialog
、
ProgressDialog
、
DatePickerDialog
、
TimePickerDialog
都可以采用構造方法建立dialog,但是
AlertDialog
不可以。
其中:
DatePickerDialog
、
TimePickerDialog
也可以使用fragment來顯示,見:Android_UI:Date & Time元件(下)
ProgressDialog
見上面
DatePickerDialog
**注意:**DatePickerDialog和TimePickerDialog 都有方法,當我們重寫該方法後,那麼監聽
setButton(...)
、
OnDateSetListener
就無效了,不會走這2個監聽,下面在重寫
OnTimeSetListener
中會有說明
setButton()
DatePickerDialog 不重寫setButton()
效果圖
代碼
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(context, onDateSetListener, year, month, dayOfMonth);
datePickerDialog.setCanceledOnTouchOutside(false);
datePickerDialog.setCancelable(false);
datePickerDialog.show();
DatePickerDialog 重寫setButton()
重寫, 通過
setButton()
擷取到
getDatePicker()
對象,進而擷取到year+month+day,是以不需要
DatePicker
注意:
OnDateSetListener
确沒有相似的方法
TimePickDialog
,是以需要
getTimePicker()
重寫
OnTimeSetListener
後,監聽
setButton(...)
、
OnDateSetListener
OnTimeSetListener
就無效了。是以如果重寫剛方法,那麼不需要寫listener,直接傳null。
dialog預設有2個Button,如果我們隻重寫了一個
,那麼另一個“确定”/“取消”也會顯示出來,那麼怎麼不讓它顯示出來呢,還是不設定為 “”,會顯示預設文字
setButton(...)
dialog.setButton2("", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//不寫
}
});
但是不能是:
dialog.setButton2("",null);
效果圖
代碼
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
MyOnDateSetListener onDateSetListener = new MyOnDateSetListener();
//可以不傳參數OnDateSetListener, 第2個參數: int themeResId, 第三個參數:OnDateSetListener
final DatePickerDialog dialog = new DatePickerDialog(context, , null, year, month, day);
dialog.setButton("自定義Button:确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog2, int which) {
DatePicker datePicker = dialog.getDatePicker();
int year = datePicker.getYear();
int month = datePicker.getMonth() + ;
int dayOfMonth = datePicker.getDayOfMonth();
Log.d(TAG, "日期:" + year + "年" + month + "月" + dayOfMonth + "日");
}
});
dialog.setButton2("自定義Button:取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "取消" + ",which=" + which);
}
});
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
TimePickerDialog
TimePickDialog:不重寫setButton()
效果圖
代碼
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
MyOnTimeSetListener timeSetListener = new MyOnTimeSetListener();
TimePickerDialog dialog = new TimePickerDialog(context, timeSetListener, hour, minute, true);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
TimePickDialog:重寫setButton()
效果圖
代碼
DatePickerDialog
通過方法
getDatePicker()
擷取
DatePicker
對象,今兒擷取year+month+day,但是
TimePickDialog
沒有方法
getTimePicker()
,是以我們不能像DatePickerDialog那樣擷取hour+minute,那麼該怎麼做呢,就是修改
SetButton()
的第二個參數,不傳
OnClickListener
,直接傳入
TimePickDialog
對象。
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
MyOnTimeSetListener timeSetListener = new MyOnTimeSetListener();
TimePickerDialog dialog = new TimePickerDialog(context, timeSetListener, hour, minute, true);
//有效方法,第2個參數不傳OnClickListener,直接傳入dialog本身
dialog.setButton("自定義Button:确定", dialog);
dialog.setButton2("自定義Button:取消", dialog);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.show();
MyOnTimeSetListener:
private class MyOnTimeSetListener implements TimePickerDialog.OnTimeSetListener {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Log.d(TAG, "時間:" + hourOfDay + "時" + minute + "分");
}
}
其它
Demo: http://git.oschina.net/AndroidUI/DatePickerDialogTimePickerDialog
參考:
Android程式設計之TimePickerDialog設定确定鍵導緻OnTimeSetListener不響應問題
Android:Picker(DatePicker、TimerPicker、NumberPicker)
重寫DatePickerDialog 解決OnDateSetListener隻有完成,沒有取消回調問題
DialogFragment
自定義類繼承,重寫
DialogFragment
或者
onCreateDialog()
onCreateView()
建立dialog
第一種:
onCreateDialog()
中建立
dialog
第二種:
onCreateDialog()
中建立
dialog
第三種:在
onCreateView()
中自定義
view
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.frag_dialog_3, container, false);
return rootView;
}
顯示dialog
DialogFragment01 frag = new DialogFragment01();
frag.show(getSupportFragmentManager(), "frag");
Demo
DialogFragment01
public class DialogFragment01 extends DialogFragment implements View.OnClickListener {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setTitle("Title");
dialog.setContentView(R.layout.frag_dialog_3);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
TextView tv1 = dialog.findViewById(R.id.tv1);
TextView tv2 = dialog.findViewById(R.id.tv2);
tv1.setOnClickListener(this);
tv2.setOnClickListener(this);
return dialog;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv1:
Toast.makeText(getActivity(), "tv1", Toast.LENGTH_SHORT).show();
break;
case R.id.tv2:
Toast.makeText(getActivity(), "tv2", Toast.LENGTH_SHORT).show();
break;
}
}
}
DialogFragment02
public class DialogFragment02 extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog dialog = new AlertDialog.Builder(getActivity())
.setTitle("Title")
.setMessage("message")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setCancelable(false)
.create();
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
}
DialogFragment03
public class DialogFragment03 extends DialogFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE,);//去掉dialog的Title,也可以使用style
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.frag_dialog_3, container, false);
return rootView;
}
}
Demo:https://git.oschina.net/AndroidUI/dialogfragment01.git
使用DialogFragment怎麼把value傳給Activity?
采用的接口的方式,讓Activity實作給接口,把DialogFragment對象返給Activity
public class NoticeDialogFragment extends DialogFragment {
private static final String TAG = "Fragment";
private String[] provinces;
public String province="京";//預設
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
provinces = ((MainActivity) getActivity()).provinces;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle(R.string.app_name)
.setSingleChoiceItems(provinces, -, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
province = provinces[which];
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mListener.onDialogNegativeClick(NoticeDialogFragment.this);
}
});
return builder.create();
}
interface DialogListener {
void onDialogPositiveClick(DialogFragment dialog);
void onDialogNegativeClick(DialogFragment dialog);
}
DialogListener mListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (DialogListener) context;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(context.toString()
+ " must implement NoticeDialogListener");
}
}
}
@Override
public void onDialogPositiveClick(DialogFragment dialog) {
Log.d(TAG, ((NoticeDialogFragment)dialog).province);
}
@Override
public void onDialogNegativeClick(DialogFragment dialog) {
}
仿ios透明加載框
一
效果圖
工具類
為了友善以後使用,寫成工具類。
public class ProgressDialogUtil {
private static Dialog mDialog;
private static ProgressDialogUtil dialogUtil;
private ProgressDialogUtil() {
super();
}
public static ProgressDialogUtil getInstance(Context context) {
if (mDialog == null) {
dialogUtil = new ProgressDialogUtil();
AlertDialog.Builder mBuilder = new AlertDialog.Builder(context, R.style.full_screen_dialog);
View view = LayoutInflater.from(context).inflate(R.layout.custom_progress_dialog_2, null);
mBuilder.setView(view);
mBuilder.setCancelable(true);
mDialog = mBuilder.create();
mDialog.setCanceledOnTouchOutside(false);
Window win = mDialog.getWindow();
//顯示對話框時,後面的Activity不變暗,可選操作。
win.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
//擷取對話框目前的參數值,下面代碼不加也可以
// WindowManager.LayoutParams params = win.getAttributes();
// params.gravity = Gravity.CENTER;
// win.setAttributes(params);
}
return dialogUtil;
}
public void showProgressDialog() {
if (!mDialog.isShowing()) {
mDialog.show();
}
}
public void dismissProgressDialog() {
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
}
**R.style.full_screen_dialog**
<style name="full_screen_dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
</style>
**R.layout.custom_dialog**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:background="#78909C"
android:padding="5dp"
android:orientation="horizontal">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加載中..."
android:layout_marginLeft="5dp"
android:textSize="16sp"/>
</LinearLayout>
custom_progress_dialog_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#80000000" />
<corners android:radius="8dip" />
</shape>
顯示和隐藏
ProgressDialogUtil.getInstance(context).showProgressDialog();
ProgressDialogUtil.getInstance(context).dismissProgressDialog();
WindowManager.LayoutParams.FLAG_DIM_BEHIND
當使用系統的progressDialog時,目前的activity會變暗,這是因為預設的
WindowManager.LayoutParams.FLAG_DIM_BEHIND
,DIM是
dimmed
的縮寫,是變暗的意思
二:采用了幀動畫
需要複制的内容
下載下傳Demo複制
- mipmap中的12張圖檔
- drawable中2個檔案,
、progress_drawable_list.xml
custom_progress_dialog_bg.xml
- dialog的自定義布局
- color
- style
- ProgressDialogUtil2
progress_drawable_list.xml 幀動畫
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@mipmap/app_loading_001"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_002"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_003"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_004"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_005"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_006"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_007"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_008"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_009"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_0010"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_0011"
android:duration="100"/>
<item
android:drawable="@mipmap/app_loading_0012"
android:duration="100"/>
</animation-list>
ProgressDialogUtil2
public class ProgressDialogUtil2 {
private static ProgressDialogUtil2 instance = null;
private static Dialog dialog;
private static View view;
private TextView tv;
public synchronized static ProgressDialogUtil2 getInstance(Context context) {
if (instance == null) {
instance = new ProgressDialogUtil2();
dialog = new Dialog(context, R.style.CustomDialogStyle);
view = LayoutInflater.from(context).inflate(R.layout.custom_progress_dialog_1, null);
dialog.setContentView(view);
ImageView progressImageView = (ImageView) view.findViewById(R.id.iv_loading);
AnimationDrawable animationDrawable = (AnimationDrawable) progressImageView.getDrawable();
animationDrawable.start();
//要放在動畫後面,否則無效
dialog.setCanceledOnTouchOutside(false);
}
return instance;
}
public void show() {
dialog.show();
}
public void showstr(String str) {
if (tv == null) {
tv = (TextView) view.findViewById(R.id.tv_loading);
tv.setText(str);
} else {
tv.setText(str);
}
dialog.show();
}
public void cancle() {
if (dialog == null) {
return;
} else {
dialog.cancel();
}
}
}
顯示和隐藏
ProgressDialogUtil2.getInstance(context).show();
ProgressDialogUtil2.getInstance(context).cancle();
Demo: http://git.oschina.net/AndroidUI/customdialog01
系統級的Dialog
我們都知道dialog是依賴activity而存在的,但是系統級的Dialog不依賴Activity,是以當按下Button的同時,我們彈出此Dialog,同時進入MainActivity2頁面,這是會發現,在activity的切換過程中,Dialog一直都存在。
效果圖
權限+Type
需要權限:
需要設定
TYPE_SYSTEM_ALERT
設定完type後,在360、小米、魅族手機上
dialog
仍然不顯示,這是因為廠家對系統走了修改,解決方方法是在設定
TYPE_TOAST
下面來自android不用context彈dialog
無意中用了一個4.0系統(<19)的手機測試了一下,dialog能彈出來,但是界面裡面的button根本不能點選!這就尴尬了!經過一番資料的查找問題終于找到了:
1.WindowManager.LayoutParams.TYPE_TOAST僅在 API level >= 19 時可以正常顯示,API level 19 以下因無法接收無法接收觸摸(點選)和按鍵事件!
2.API level 19 後做了調整,當我們使用 TYPE_TOAST, Android 會偷偷給我們加上 FLAG_NOT_FOCUSABLE 和 FLAG_NOT_TOUCHABLE , 4.0.1 開始, 會額外再去掉FLAG_WATCH_OUTSIDE_TOUCH。 這樣真的是什麼事件都沒了。
3.對于 API level < 19 的機器(MIUI除外),想要達到目的,需要:
a.要有 android.permission.SYSTEM_ALERT_WINDOW 權限
b.将 type 設定為 WindowManager.LayoutParams.TYPE_PHONE 或者 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//解決Android 起不能再用Toast的問題(先解決crash)
if(Build.VERSION.SDK_INT > ){
md.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
}else{
md.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
}
} else {
md.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
}
其它
參考:android不用context彈dialog
Demo:https://git.oschina.net/AndroidUI/buglyupdate01
注意
dialog的Context不能使用 getApplicationContext()
getApplicationContext()
dialog
中不能使用
getApplicationContext()
,會報錯。因為
dialog
是依附于
activity
而存在的。
dialog.setCanceledOnTouchOutside(false)無效
原因:
1. 在dialog.show()之前調用無效
2. 自定義的dialog有動畫
animation-list
也會導緻其無效
解決方法:
在show()後面
dialog.show();
dialog.setCanceledOnTouchOutside(false);
在動畫後面
AnimationDrawable animationDrawable = (AnimationDrawable) progressImageView.getDrawable();
animationDrawable.start();
dialog.setCanceledOnTouchOutside(false);