自定义Dialog
2016.09.29
xiazdong
 热度
℃
基本框架
这里假设要构造的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); } 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); } 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> <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>
|