盒子
盒子
文章目录
  1. 基本框架
    1. 错误的框架
    2. 最终框架
  2. 其他的注意点

自定义Dialog

基本框架

这里假设要构造的Dialog的布局为R.layout.dialog_common,布局中只有一个TextView。

错误的框架

刚开始实现时,想当然的把导入布局并且setContentView()放在onCreate()中。

public class CommonDialog extends Dialog {
private TextView mTextView;
private String mText;
public CommonDialog(Context context) {
this(context, R.style.StyleableDialogTheme); //设置style
}
public CommonDialog(Context context, int themeResId) {
super(context, themeResId);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View rootView = LayoutInflater.from(mContext).inflate(R.layout.dialog_common, null);
mTextView = (TextView) rootView.findViewById(R.id.text);
setContentView(rootView);
}
public void setText(String text){
mTextView.setText(text)。//错误
}
@Override
public void show(){
super.show();
getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
}
}

然后很正常的使用它:

CommonDialog dialog = new CommonDialog(this);
dialog.setText("hello");
dilaog.show();

但是运行后,dialog.setText("hello")报空指针异常。经过研究发现Dialog直到show()中才调用了onCreate(),因此调用dialog.setText("hello")时还没有拿到UI组件。show()的内部实现如下:

public void show() {
...
if (!mCreated) {
dispatchOnCreate(null); //调用了onCreate()方法
}
onStart();
mDecor = mWindow.getDecorView();
WindowManager.LayoutParams l = mWindow.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
WindowManager.LayoutParams nl = new WindowManager.LayoutParams(); //创建一个新的LayoutParams,width和height默认值为-1,即MATCH_PARENT
nl.copyFrom(l);
l = nl;
}
...
}

可以看出:默认情况下,show()过程中会调用onCreate()方法,因此在show()之前是获得不到Dialog的布局的。

最终框架

public class CommonDialog extends Dialog {
private TextView mTextView;
private View mContentView;
public CommonDialog(Context context) {
this(context, R.style.StyleableDialogTheme); //设置style
}
public CommonDialog(Context context, int themeResId) {
super(context, themeResId);
mContentView = LayoutInflater.from(mContext).inflate(R.layout.dialog_common, null);
mTextView = (TextView) mContentView.findViewById(R.id.text);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(mContentView);
getWindow().setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
}
public void setText(String text){
mTextView.setText(text);
}
}

特点:在构造函数中提前映射布局。

这种实现方式能够通过如下方式使用:

CommonDialog dialog = new CommonDialog(this);
dialog.setText("hello");
dilaog.show();

其他的注意点

这里还需要提一下R.style.StyleableDialogTheme,该值如下:

<style name="StyleableDialogTheme">
<item name="android:windowBackground">@android:color/transparent</item> <!-- 设置dialog的背景,如果不设置为透明,那么圆角就显示不出来 -->
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowNoTitle">true</item> <!-- 如果不设置此句,部分机型会出现对话框标题栏还存在 -->
<item name="android:backgroundDimEnabled">true</item> <!-- 背景是灰的 -->
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
</style>
支持一下
扫一扫,支持xiazdong