与Dialog的区别在于更加方便的添加布局
<style name="DialogTheme" parent="Theme.AppCompat.Dialog">
<!-- 边框 -->
<item name="android:windowFrame">@null</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<!-- 半透明 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 无标题 -->
<item name="android:windowNoTitle">true</item>
<!-- <item name="android:background">@mipmap/menu_bg</item>-->
<item name="background">@color/transparent</item>
<!-- 背景透明 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 模糊 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 遮罩层 -->
<item name="android:backgroundDimAmount">0.4</item>
</style>
public class LocationDialogFragment extends DialogFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int theme = R.style.DialogTheme;
//一定是在onCreate 里面设置 style,在 onCreateView 里面设置是没有效果的。
setStyle(STYLE_NORMAL, theme);//STYLE_NORMAL=0
}
@Override
public void onStart() {
super.onStart();
Window win = getDialog().getWindow();
// 一定要设置Background,如果不设置,window属性设置无效
if (win == null){
return;
}
win.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
//设置弹出位置
win.setGravity(Gravity.BOTTOM);
//设置弹出动画
win.setWindowAnimations(R.style.main_menu_animStyle);
DisplayMetrics dm = new DisplayMetrics();
if (getActivity() == null){
return;
}
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
WindowManager.LayoutParams params = win.getAttributes();
params.gravity = Gravity.BOTTOM;
// 使用ViewGroup.LayoutParams,以便Dialog 宽度充满整个屏幕
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
win.setAttributes(params);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_location_dialog, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
init();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}
<style name="DialogTheme" parent="Theme.AppCompat.Dialog">
<!-- 边框 -->
<item name="android:windowFrame">@null</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<!-- 半透明 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 无标题 -->
<item name="android:windowNoTitle">true</item>
<!-- <item name="android:background">@mipmap/menu_bg</item>-->
<item name="background">@color/transparent</item>
<!-- 背景透明 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 模糊 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 遮罩层 -->
<item name="android:backgroundDimAmount">0.4</item>
</style>
/ main_menu_animStyle
<!-- dialog的动画 -->
<style name="main_menu_animStyle">
<item name="android:windowEnterAnimation">@anim/dialog_in_anim</item>
<item name="android:windowExitAnimation">@anim/dialog_out_anim</item>
</style>
/dialog_in_anim
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXDelta="0"
android:fromYDelta="1000"
android:toXDelta="0"
android:toYDelta="0" />
/ dialog_out_anim
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="1000" />
显示
private void showLocation() {
FragmentManager fm = getSupportFragmentManager();
locationDialogFragment = new LocationDialogFragment();
locationDialogFragment.setOnCityClickListner(new OnCitySelectListener() {
@Override
public void onCitySelect(CityBean.RowsBean bean) {
}
@Override
public void onCitySeletList(ArrayList<CityBean.RowsBean> mAddTabList) {
}
});
locationDialogFragment.show(fm.beginTransaction(),"location");
fm.beginTransaction().commitAllowingStateLoss();
}
效果图
1使用
private void showReplyEdit() {
NiceDialog.init()
.setLayoutId(R.layout.reply_layout) //设置dialog布局文件
.setConvertListener(new ViewConvertListener() { //进行相关View操作的回调
@Override
public void convertView(ViewHolder holder, final BaseNiceDialog dialog) {
final EditText editText = holder.getView(R.id.answer_edit_input);
final TextView textView = holder.getView(R.id.ensure);
//弹出输入框
editText.post(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, 0);
}
});
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
String strReply = editText.getText().toString().trim();
addCommentService(strReply);
}
});
}
})
.setDimAmount(0.1f)//调节灰色背景透明度[0-1],默认0.5f
.setShowBottom(true) //是否在底部显示dialog,默认flase
.show(getSupportFragmentManager());
}
replay_layout
<?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="#ffffff"
android:paddingBottom="15dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp">
<TextView
android:id="@+id/ensure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingLeft="12dp"
android:paddingRight="6dp"
android:text="发送"
android:textColor="@color/main"
android:textSize="16sp"/>
<EditText
android:id="@+id/answer_edit_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/ensure"
android:background="@drawable/answer_edit_bg"
android:gravity="top"
android:maxLength="100"
android:hint="说你想说的..."
android:padding="10dp"
android:textSize="14sp"/>
</RelativeLayout>
2 共5个文件
@1 Utils
public class Utils {
public static int dp2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
public static int getScreenWidth(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return displayMetrics.widthPixels;
}
}
@2 ViewHolder
public class ViewHolder {
private SparseArray<View> views;
private View convertView;
private ViewHolder(View view) {
convertView = view;
views = new SparseArray<>();
}
public static ViewHolder create(View view) {
return new ViewHolder(view);
}
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = convertView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
public View getConvertView() {
return convertView;
}
public void setText(int viewId, String text) {
TextView textView = getView(viewId);
textView.setText(text);
}
public void setText(int viewId, int textId) {
TextView textView = getView(viewId);
textView.setText(textId);
}
public void setTextColor(int viewId, int colorId) {
TextView textView = getView(viewId);
textView.setTextColor(colorId);
}
public void setOnClickListener(int viewId, View.OnClickListener clickListener) {
View view = getView(viewId);
view.setOnClickListener(clickListener);
}
public void setBackgroundResource(int viewId, int resId) {
View view = getView(viewId);
view.setBackgroundResource(resId);
}
public void setBackgroundColor(int viewId, int colorId) {
View view = getView(viewId);
view.setBackgroundColor(colorId);
}
}
@3 ViewConvertListener
public abstract class ViewConvertListener implements Parcelable {
protected abstract void convertView(ViewHolder holder, BaseNiceDialog dialog);
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
public ViewConvertListener() {
}
protected ViewConvertListener(Parcel in) {
}
public static final Creator<ViewConvertListener> CREATOR = new Creator<ViewConvertListener>() {
@Override
public ViewConvertListener createFromParcel(Parcel source) {
return new ViewConvertListener(source){
@Override
protected void convertView(ViewHolder holder, BaseNiceDialog dialog) {
}
};
}
@Override
public ViewConvertListener[] newArray(int size) {
return new ViewConvertListener[size];
}
};
}
@4 BaseNiceDialog
public abstract class BaseNiceDialog extends DialogFragment {
private static final String MARGIN = "margin";
private static final String WIDTH = "width";
private static final String HEIGHT = "height";
private static final String DIM = "dim_amount";
private static final String BOTTOM = "show_bottom";
private static final String CANCEL = "out_cancel";
private static final String THEME = "theme";
private static final String ANIM = "anim_style";
private static final String LAYOUT = "layout_id";
private int margin;//左右边距
private int width;//宽度
private int height;//高度
private float dimAmount = 0.5f;//灰度深浅
private boolean showBottom;//是否底部显示
private boolean outCancel = true;//是否点击外部取消
@StyleRes
protected int theme = R.style.NiceDialogStyle; // dialog主题
@StyleRes
private int animStyle;
@LayoutRes
protected int layoutId;
public abstract int intLayoutId();
public abstract void convertView(ViewHolder holder, BaseNiceDialog dialog);
public int initTheme() {
return theme;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, initTheme());
//恢复保存的数据
if (savedInstanceState != null) {
margin = savedInstanceState.getInt(MARGIN);
width = savedInstanceState.getInt(WIDTH);
height = savedInstanceState.getInt(HEIGHT);
dimAmount = savedInstanceState.getFloat(DIM);
showBottom = savedInstanceState.getBoolean(BOTTOM);
outCancel = savedInstanceState.getBoolean(CANCEL);
theme = savedInstanceState.getInt(THEME);
animStyle = savedInstanceState.getInt(ANIM);
layoutId = savedInstanceState.getInt(LAYOUT);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
layoutId = intLayoutId();
View view = inflater.inflate(layoutId, container, false);
convertView(ViewHolder.create(view), this);
return view;
}
@Override
public void onStart() {
super.onStart();
initParams();
}
/**
* 屏幕旋转等导致DialogFragment销毁后重建时保存数据
*
* @param outState
*/
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(MARGIN, margin);
outState.putInt(WIDTH, width);
outState.putInt(HEIGHT, height);
outState.putFloat(DIM, dimAmount);
outState.putBoolean(BOTTOM, showBottom);
outState.putBoolean(CANCEL, outCancel);
outState.putInt(THEME, theme);
outState.putInt(ANIM, animStyle);
outState.putInt(LAYOUT, layoutId);
}
private void initParams() {
Window window = getDialog().getWindow();
if (window != null) {
WindowManager.LayoutParams lp = window.getAttributes();
//调节灰色背景透明度[0-1],默认0.5f
lp.dimAmount = dimAmount;
//是否在底部显示
if (showBottom) {
lp.gravity = Gravity.BOTTOM;
if (animStyle == 0) {
animStyle = R.style.DefaultAnimation;
}
}
//设置dialog宽度
if (width == 0) {
lp.width = Utils.getScreenWidth(getContext()) - 2 * Utils.dp2px(getContext(), margin);
} else if (width == -1) {
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
} else {
lp.width = Utils.dp2px(getContext(), width);
}
//设置dialog高度
if (height == 0) {
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
} else {
lp.height = Utils.dp2px(getContext(), height);
}
//设置dialog进入、退出的动画
window.setWindowAnimations(animStyle);
window.setAttributes(lp);
}
setCancelable(outCancel);
}
public BaseNiceDialog setMargin(int margin) {
this.margin = margin;
return this;
}
public BaseNiceDialog setWidth(int width) {
this.width = width;
return this;
}
public BaseNiceDialog setHeight(int height) {
this.height = height;
return this;
}
public BaseNiceDialog setDimAmount(float dimAmount) {
this.dimAmount = dimAmount;
return this;
}
public BaseNiceDialog setShowBottom(boolean showBottom) {
this.showBottom = showBottom;
return this;
}
public BaseNiceDialog setOutCancel(boolean outCancel) {
this.outCancel = outCancel;
return this;
}
public BaseNiceDialog setAnimStyle(@StyleRes int animStyle) {
this.animStyle = animStyle;
return this;
}
public BaseNiceDialog show(FragmentManager manager) {
FragmentTransaction ft = manager.beginTransaction();
if (this.isAdded()) {
ft.remove(this).commit();
}
ft.add(this, String.valueOf(System.currentTimeMillis()));
ft.commitAllowingStateLoss();
return this;
}
}
@5 NiceDialog
public class NiceDialog extends BaseNiceDialog {
private ViewConvertListener convertListener;
public static NiceDialog init() {
return new NiceDialog();
}
@Override
public int initTheme() {
return theme;
}
@Override
public int intLayoutId() {
return layoutId;
}
@Override
public void convertView(ViewHolder holder, BaseNiceDialog dialog) {
if (convertListener != null) {
convertListener.convertView(holder, dialog);
}
}
public NiceDialog setTheme(@StyleRes int theme) {
this.theme = theme;
return this;
}
public NiceDialog setLayoutId(@LayoutRes int layoutId) {
this.layoutId = layoutId;
return this;
}
public NiceDialog setConvertListener(ViewConvertListener convertListener) {
this.convertListener = convertListener;
return this;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
convertListener = savedInstanceState.getParcelable("listener");
}
}
/**
* 保存接口
*
* @param outState
*/
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("listener", convertListener);
}
@Override
public void onDestroyView() {
super.onDestroyView();
convertListener = null;
}
}
style
<style name="NiceDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowSoftInputMode">adjustPan</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="DefaultAnimation" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/enter_anim</item>
<item name="android:windowExitAnimation">@anim/exit_anim</item>
</style>
enter_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200">
<translate
android:fromYDelta="100%p"
android:toYDelta="0%p" />
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
exit_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200">
<translate
android:duration="@android:integer/config_mediumAnimTime"
android:fromYDelta="0%p"
android:toYDelta="100%p" />
<alpha
android:duration="@android:integer/config_mediumAnimTime"
android:fromAlpha="1.0"
android:toAlpha="0.3" />
</set>