赞
踩
在项目中我们经常会使用到自定义dialog,但是我们往往自定义了一个dialog,在show的时候,显示出来的效果却很奇葩,其显示出来的视图宽高,大小,里面控件大小等等属性都不对,甚至看起来效果惨不忍睹。 最近我也是被这问题搞的头大,在结合了网上一些文章案例,自己的实际操作后,终于总结出了怎么写好自定义dialog的方法,下面我们直接进入正题吧!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#aaa"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Admin Password" android:textSize="24sp" android:layout_marginLeft="50dp" android:layout_marginRight="50dp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#aaa"/> <EditText android:id="@+id/et_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" android:inputType="numberPassword" android:drawableLeft="@drawable/ic_hide_pwd" android:paddingLeft="10dp" android:layout_marginTop="20dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" /> <CheckBox android:id="@+id/cb_forget" android:layout_width="wrap_content" android:layout_height="24dp" android:textSize="12sp" android:text="forget password" android:layout_marginLeft="10dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center"> <Button android:id="@+id/button_ok" android:layout_width="wrap_content" android:layout_height="40dp" android:text="OK" android:textSize="12sp" android:layout_marginRight="10dp" /> <Button android:id="@+id/button_cancel" android:layout_width="wrap_content" android:layout_height="40dp" android:text="cancel" android:textSize="12sp" android:layout_marginLeft="10dp" /> </LinearLayout> </LinearLayout>
预览效果:
<style name="Dialog" parent="android:style/Theme.Dialog">
<item name="android:background">#ffffff</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
</style>
在(1)(2)步中,有个小细节可能很多人都注意不到,就是我没有在布局文件中写 background,但我在dialog 的style中,加了#ffffff 这个属性。
如果我把这个属性删掉,出来的弹窗的背景是透明的,就像下面这样:
此时的dialog style中样式为:
注意,没有了背景, 显示的是window的颜色,此时window为透明(因为android:windowBackground属性目前设的是透明)。 然后我将它换个颜色,那么window也会变颜色:
OK。 同理,如果我在布局文件中写了 background 。那么下面这两个属性忽略掉也可以(建议不要省略android:windowBackground属性,将它置为透明)。
private Dialog dialog; private void createDialog(){ if (dialog == null){ View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_dialogview, null); dialog = new Dialog(MainActivity.this, R.style.Dialog); EditText editPwdText = view.findViewById(R.id.et_text); CheckBox checkBox = view.findViewById(R.id.cb_forget); Button ok = view.findViewById(R.id.button_ok); Button cancel = view.findViewById(R.id.button_cancel); checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { //InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_CLASS_TEXT editPwdText.setInputType(InputType.TYPE_NUMBER_VARIATION_NORMAL | InputType.TYPE_CLASS_NUMBER); } else { //InputType.TYPE_TEXT_VARIATION_PASSWORD|InputType.TYPE_CLASS_TEXT editPwdText.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER); } } }); ok.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); dialog.setContentView(view);//将显示的内容替换为我们的自定义view setLocation();//改变弹窗弹出位置,默认是在中央位置弹出 dialog.show(); } else { dialog.show(); } } private void setLocation(){ if (dialog != null){ WindowManager.LayoutParams layoutParams = dialog.getWindow().getAttributes(); //layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;//此处可修改宽度 //layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;//此处可修改高度 layoutParams.x = -100; layoutParams.y = -400; dialog.getWindow().setAttributes(layoutParams); } } //写了个按钮 开关dialog findViewById(R.id.text_main).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (dialog == null || !dialog.isShowing()){ createDialog(); } else { dialog.dismiss(); } } });
这样我们自定义的弹窗效果就实现了。
弹出效果:
public class CustomDialog extends Dialog { public CustomDialog(@NonNull Context context) { super(context); } public CustomDialog(@NonNull Context context, int themeResId) { super(context, themeResId); } protected CustomDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { super(context, cancelable, cancelListener); } public static class Builder { private Context context; private View contentView; private String title; private String message; private int imageRes; //... public Builder(Context context){ this.context = context; } public Builder setView(View layout){ contentView = layout; return this; } public Builder setImageRes(int imageRes) { this.imageRes = imageRes; return this; } public Builder setTitle(String title){ this.title = title; return this; } public CustomDialog build(){ final CustomDialog dialog = new CustomDialog(context,R.style.Dialog); Button ok = contentView.findViewById(R.id.button_ok); Button cancel = contentView.findViewById(R.id.button_cancel); CheckBox checkBox = contentView.findViewById(R.id.cb_forget); EditText editPwdText = contentView.findViewById(R.id.et_text); checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { //InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD|InputType.TYPE_CLASS_TEXT editPwdText.setInputType(InputType.TYPE_NUMBER_VARIATION_NORMAL | InputType.TYPE_CLASS_NUMBER); } else { //InputType.TYPE_TEXT_VARIATION_PASSWORD|InputType.TYPE_CLASS_TEXT editPwdText.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER); } } }); ok.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); dialog.setContentView(contentView); dialog.setLocation(); return dialog; } } //更改弹窗位置的 private void setLocation(){ WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes(); layoutParams.x = 0; layoutParams.y = -300; this.getWindow().setAttributes(layoutParams); } }
通过builder模式,创建自定义dialog对象。 这里我只简单的写了下, 你可以通过title,message等是否有值,在build的时候选择是否显示相关视图。
private Dialog dialog2; private void createDialog2(){ if (dialog2 == null){ View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_dialogview, null); CustomDialog.Builder builder = new CustomDialog.Builder(MainActivity.this) .setView(view); dialog2 = builder.build(); dialog2.show(); } else { dialog2.show(); } } findViewById(R.id.text_main2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (dialog2 == null || !dialog2.isShowing()){ createDialog2(); } else { dialog2.dismiss(); } } });
效果如下:
好了,这就是本文的全部内容了。如果项目中有很多处用到自定义dialog,建议使用方式二,设计一个强大的dialog,然后就可以愉快的使用了。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。