1.需求:应用中需要用到的Dialog的场景,提示用户信息并需要用户做出选择。
比如:
返回键退出提示,让用户确认是否退出。
当前网络提示,让用户确认是否网络异常,是否继续使用移动网络。
是否清空某些信息,让用户根据提示并确认当前操作是否继续。
提示用户输入密码等相关信息的底部提示框。
2.封装Dialog
①需要设置的基本属性:layout布局、宽、高、风格、是否可点击dialog以外的区域、点击事件监听等。
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import static android.content.ContentValues.TAG;
/**
* @author zhou.jn on 2019/3/24.
*/
public class CustomDialog extends Dialog {
private int mWidth;
private int mHeight;
private int mGravity;
private View mView;
private boolean isCancelTouchout;
public CustomDialog(Builder builder) {
super(builder.context);
mWidth = builder.width;
mHeight = builder.height;
mGravity = builder.gravity;
mView = builder.view;
isCancelTouchout = builder.isCancelTouchout;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(mView);
setCanceledOnTouchOutside(isCancelTouchout);
Window window = getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
Log.i(TAG, "onClick: lp.height: "+ lp.height + " lp.width: "+lp.width);
lp.height = mHeight;
lp.width = mWidth;
lp.gravity = mGravity;
window.setAttributes(lp);
}
public CustomDialog(Builder builder, int resStyle) {
super(builder.context, resStyle);
mWidth = builder.width;
mHeight = builder.height;
mGravity = builder.gravity;
mView = builder.view;
isCancelTouchout = builder.isCancelTouchout;
}
public static final class Builder {
private int width;
private int height;
private int gravity;
private View view;
private Context context;
private int resStyle = -1;
private boolean isCancelTouchout;
public Builder(Context context) {
this.context = context;
}
public Builder gravity(int g) {
gravity = g;
return this;
}
public Builder view(View v) {
view = v;
return this;
}
public Builder view(int id) {
view = LayoutInflater.from(context).inflate(id, null);
return this;
}
public Builder widthdp(int w) {
width = w;
return this;
}
public Builder heightdp(int h) {
height = h;
return this;
}
public Builder style(int style) {
resStyle = style;
return this;
}
public Builder cancelTouchout(boolean iscancelTouchout) {
isCancelTouchout = iscancelTouchout;
return this;
}
public CustomDialog build() {
if (resStyle != -1) {
return new CustomDialog(this, resStyle);
} else {
return new CustomDialog(this);
}
}
}
}
3.使用 MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private CustomDialog dialog;
private Button btn_showDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initDialog();
btn_showDialog = (Button) findViewById(R.id.btn_showDialog);
btn_shoDwialog.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "onClick: show");
if (dialog != null) {
dialog.show();
}
}
});
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//这里一定需要调用show以后,控件可见后才可以进行动态布局,
dialog.show();
changeDialogLandscape();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
dialog.show();
changeDialogPortrait();
}
}
private void changeDialogPortrait() {
Log.i(TAG, "changeDialogPortrait: ");
if (dialog != null)
Window window = dialog.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.height = 300;
lp.width = 250;
lp.gravity = Gravity.CENTER;
window.setAttributes(lp);
}
}
private void changeDialogLandscape() {
Log.i(TAG, "changeDialogLandscape: ");
if (dialog != null) {
Window window = dialog.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.height = 500;
lp.width = 450;
lp.gravity = Gravity.CENTER;
window.setAttributes(lp);
}
}
private void initDialog() {
CustomDialog.Builder builder = new CustomDialog.Builder(this);
dialog = builder
.style(R.style.Dialog)
.widthdp(300)
.heightdp(150)
.view(R.layout.dialog_main)
.gravity(Gravity.CENTER)
.cancelTouchout(false)
.build();
}
Dialog style
<style name="Dialog" parent="android:style/Theme.Dialog">
//设置为透明背景
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
</style>
AndroidManifest.xml
<!-- 注意 configChanges 配置当该Activity发生以下的活动的时候不重新启动Activity-->
<activity android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
总结:①Window绘制主要包括Activity、Dialog、Toast。当时不知道window的属性,且不知道控件可见后再进行设置属性。两个坑导致试了很久。相关详细内容可见《Android开发艺术探索》第八章。
②封装Dialog后使用时觉得方便很多,但一味在Activity中进行这样初始化并使用,当该Activity需要两个及以上的Dialog的时候,就会显得特别混乱,所以建议还是写在单独的Dialog类中,不要直接在Activity中进行初始化。