专为平板而生的Dialog(同样也支持手机)
因公司的业务需求变动,由手机开发转为手机,平板一起开发!导致项目之前写的Dialog在平板上出现很多兼容性问题,没办法只能一个一个的改了!但是,一查看代码发现,有太多太多的Dialog需要改动了,于是乎,为适配平板的Dialog基类(同样适用于手机端)就横空出世了!
特点
- 支持横竖屏切换
- 支持修改Dialog的宽高
- 支持修改Dialog的动画,样式
- 默认三种状态
BaseDialog代码如下
import android.app.Dialog;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetDialog;
import android.support.v7.app.AppCompatDialogFragment;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import com.app.myview.R;
public abstract class BaseDialog extends AppCompatDialogFragment implements View.OnClickListener,
AdapterView.OnItemClickListener {
/** 默认的Style */
final static int DIALOG_DEFAULT_STYLE = R.style.dialogStyle;
/** 弹窗的类型 */
protected int dialogType = -1;
/** 底部弹出 */
protected final static int DIALOG_BOTTOM = 0x0;
/** 顶部弹出 */
protected final static int DIALOG_TOP = 0x1;
/** 中心弹出 */
protected final static int DIALOG_CENTER = 0x2;
/** 默认弹窗的高 */
protected final static int DIALOG_DEFAULT_HEIGHT = ViewGroup.LayoutParams.WRAP_CONTENT;
/** 默认弹窗的宽 */
protected final static int DIALOG_DEFAULT_WIDTH = ViewGroup.LayoutParams.WRAP_CONTENT;
/** 根视图 */
protected View rootView;
protected DialogChildClickListener listener;
public void setDialogItemClickListener(DialogChildClickListener listener) {
this.listener = listener;
}
@Override
public final Dialog onCreateDialog(Bundle savedInstanceState) {
int type = getDialogType();
switch (type) {
case DIALOG_BOTTOM:
dialogType = DIALOG_BOTTOM;
/**
* 也可以这样 底部弹出的
*/
// return getDialogByType(getStyle(), DIALOG_BOTTOM);
return new BottomSheetDialog(getContext(), getTheme());
case DIALOG_CENTER:
dialogType = DIALOG_CENTER;
return new Dialog(getContext(), getStyle());
case DIALOG_TOP:
dialogType = DIALOG_TOP;
return getDialogByType(getStyle(), DIALOG_TOP);
default:
return super.onCreateDialog(savedInstanceState);
}
}
@Nullable
@Override
public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
int layoutID = getDialogView();
if (layoutID <= 0) {
throw new NullPointerException("Dialog layout is not null");
} else {
rootView = inflater.inflate(layoutID, container, false);
}
return rootView;
}
@Override
public final void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
initDialog(view, savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
setDialogProperty();
}
/** 获取弹窗的style,0默认为{@link #DIALOG_DEFAULT_STYLE} */
protected abstract int getDialogStyle();
/** 获取弹窗的类型 三种状态 DIALOG_BOTTOM,DIALOG_TOP,DIALOG_CENTER */
protected abstract int getDialogType();
/** 获取弹窗的Layout */
protected abstract int getDialogView();
/** 初始化弹窗 */
protected abstract void initDialog(View view, Bundle bundle);
/** 设置弹窗的属性,比如宽、高,动画等 */
protected abstract void setDialogProperty();
/** 切换竖屏调用此方法 */
protected abstract void changePORTRAIT();
/** 切换横屏调用此方法 */
protected abstract void changeLANDSCAPE();
/** 销毁 */
protected abstract void destroyAll();
/**
* 设置Dialog的宽高
* width 默认为{@link #DIALOG_DEFAULT_WIDTH}
* height 默认为{@link #DIALOG_DEFAULT_HEIGHT}
*/
protected final void setDialogWH() {
// 底部弹窗Dialog宽度默认为屏幕的宽度,或者根据自己需求改动
if (dialogType == DIALOG_BOTTOM) {
return;
}
Window window = getDialog().getWindow();
window.setLayout(DIALOG_DEFAULT_WIDTH, DIALOG_DEFAULT_HEIGHT);
}
/**
* 设置Dialog的宽高
* @param width 宽
* @param height 高
*/
protected final void setDialogWH(int width, int height) {
if (dialogType == DIALOG_BOTTOM) {
return;
}
if (width <= 0) {
throw new RuntimeException("Dialog width cannot be less than 0! You might need the setDialogWH () method");
}
if (height <= 0) {
throw new RuntimeException("Dialog height cannot be less than 0! You might need the setDialogWH () method");
}
Window window = getDialog().getWindow();
window.setLayout(width, height);
}
/**
* 得到Display
* @return Display
*/
protected final Display getDisplay() {
WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
return manager.getDefaultDisplay();
}
/**
* 得到屏幕的宽度
* @return width
*/
protected final int getWidth() {
Point point = new Point();
getDisplay().getSize(point);
return point.x;
}
/**
* 设置Dialog的进出动画
*/
protected final void setDialogAnim(int resId) {
getDialog().getWindow().setWindowAnimations(resId);
}
/**
* findViewById
*/
protected final <V extends View> V $(int id) {
if (rootView == null) throw new NullPointerException("rootView is not null!");
return (V) rootView.findViewById(id);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
changeLANDSCAPE();
} else {
changePORTRAIT();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
destroyAll();
}
@Override
public void onClick(View v) {
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
private int getStyle() {
int style = getDialogStyle();
return style <= 0 ? DIALOG_DEFAULT_STYLE : style;
}
private Dialog getDialogByType (int dialogType, int type) {
Dialog dialog = new Dialog(getContext(), dialogType);
Window window = dialog.getWindow();
if (window != null) {
if(type == DIALOG_TOP) {
window.setGravity(Gravity.TOP);
} else if (type == DIALOG_BOTTOM) {
window.setGravity(Gravity.BOTTOM);
}
}
return dialog;
}
public interface DialogChildClickListener {
/**
* Dialog点击事件
* @param view 当前视图
* @param values 任意类型的值
*/
void childClick(View view, Object... values);
}
}
默认的Dialog样式
<style name="dialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<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:windowIsTranslucent">true</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
PS:谷歌官方也推荐使用DialogFragment来创建Dialog
如何使用
// 继承BaseDialog,实现里面的抽象方法,layout_dialog布局文件就不发了
public class TestDialog extends BaseDialog {
public static TestDialog newInstance() {
Bundle args = new Bundle();
TestDialog fragment = new TestDialog();
fragment.setArguments(args);
return fragment;
}
@Override
protected int getDialogStyle() {
// 弹窗Style
return 0;
}
@Override
protected int getDialogType() {
// 弹窗类型
return DIALOG_CENTER;
}
@Override
protected int getDialogView() {
// 弹窗布局
return R.layout.layout_dialog;
}
@Override
protected void initDialog(View view, Bundle bundle) {
$(R.id.dialog_ok).setOnClickListener(this);
$(R.id.dialog_cancel).setOnClickListener(this);
}
@Override
protected void setDialogProperty() {
setDialogAnim(android.R.style.Animation_Translucent);
}
@Override
protected void changePORTRAIT() {
L.e("切换至竖屏");
setDialogWH();
}
@Override
protected void changeLANDSCAPE() {
L.e("切换至横屏");
setDialogWH(getWidth(), 600);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.dialog_ok:
if (listener != null) {
listener.childClick(v, id);
}
break;
case R.id.dialog_cancel:
Toaster.makeText("Dialog自己处理点击事件");
break;
}
dismiss();
}
@Override
protected void destroyAll() {
L.e("销毁Dialog");
}
}
Activity中
/**
* DialogActivity 布局就不发了
* 注意:DialogActivity一定要继承FragmentActivity
* 屏幕旋转,需要给DialogActivity设置android:configChanges="orientation|keyboardHidden|screenSize"
*/
public class DialogActivity extends FragmentActivity implements BaseDialog.DialogChildClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 不需要传值给Dialog
TestDialog dialog = new TestDialog();
// 传值给Dialog
// TestDialog dialog1 = TestDialog.newInstance();
Fragment fragment = getSupportFragmentManager().findFragmentByTag("testDialog");
if (fragment != null) {
//为了不重复显示dialog,在显示对话框之前移除正在显示的对话框
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
// Dialog与Activity交互
dialog.setDialogItemClickListener(DialogActivity.this);
// 显示Dialog
dialog.show(getSupportFragmentManager(), "testDialog");
}
});
}
@Override
public void childClick(View view, Object... values) {
int id = view.getId();
switch (id) {
case R.id.dialog_ok:
Toaster.makeText("Activity处理Dialog点击事件");
break;
}
}
}
DialogActivity 布局就不发了!注意:DialogActivity一定要继承FragmentActivity。屏幕旋转,需要给DialogActivity设置android:configChanges=”orientation|keyboardHidden|screenSize”。
没图我说个,下面是效果图,请忽略掉横屏时的样式问题!
写得不好呀,勿喷