我们在平常开发的时候,经常会用到对话框完成与用户的交互。如果对话框界面要求不复杂,直接采用AlterDialog就可以实现想要的交互效果。但是在我们需要定制一些对话框的时候,我们需要重写对话框,这里主要实现思路是继承Dialog类然后实现自定义的布局。
今天在实现对话框的时候,遇到了一个问题,这里简单提一下。在我对话框的控件进行一些值的初始化时每次都会报空指针异常,于是就查阅了android文档,发现是在初始化控件时出了问题,也就是说我在findViewById()的时候发生在了show()之后,后来通过实验发现了Dialog的生命周期原来是这样子的show()->onCreate()->onStart()
我们再来看文档上面是怎么写的
从show()方法的说明我们可以看出初始化推荐在onStart()方法中去实现,从show()方法的源码我们可以看到这样的语句。mWindowManager.addView(mDecor,l);其中mDecor是DecorView,l是LayoutParam,所以由此可知在show()方法调用后,才将DecorView加入到窗口内,于是当我们先于show()方法去初始化控件是就会报出空指针的错误。
public View findViewById (int id)
Finds a view that was identified by the id attribute from the XML that was processed in onStart()
.
Parameters
id | the identifier of the view to find |
---|
Returns
- The view if found or null otherwise.
也就是说文档内推荐findViewById()放到onStart()中去。所以当我把设置的内容放到show()以后,运行就畅通了,我们来看看打印的log,在show()以后是onCreate()和onStart()然后在设置控件的值时就可以了。
public class MyselfDialog extends Dialog {
private static final String TAG = "MyselfDialog";
private ImageView mImageView;
private TextView mTextView;
private Button mButton;
private Context mContext;
public MyselfDialog(Context context){
super(context);
mContext = context;
}
public interface DialogOnClickListener{
void dialogDismiss();
}
public void setListener(DialogOnClickListener listener) {
this.listener = listener;
Log.d(TAG,"setListener()");
}
DialogOnClickListener listener;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
requestWindowFeature(Window.FEATURE_NO_TITLE); //设置为没有title
setContentView(R.layout.layout_myself_dialog);
WindowManager mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
Display mDisplay = mWindowManager.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
mDisplay.getMetrics(metrics);
int screenWidth = metrics.widthPixels;
WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
layoutParams.width = (int)(screenWidth * 0.8); //设置为屏幕宽度的0.8
getWindow().setAttributes(layoutParams);
//initView();
}
@Override
protected void onStart(){
super.onStart();
Log.d(TAG, "onStart()");
initView();
}
@Override
protected void onStop(){
super.onStop();
Log.d(TAG, "onStop()");
}
private void initView(){
mImageView = (ImageView)findViewById(R.id.img_dog);
mTextView = (TextView)findViewById(R.id.tv_text);
mButton = (Button)findViewById(R.id.btn_button_dismiss);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.dialogDismiss();
}
});
}
public void setText(String text){
mTextView.setText(text);
Log.d(TAG,"setText()");
}
}
//自定义对话框的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/img_dog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/dog"/>
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="it is a dog"
android:textSize="18sp"/>
<Button
android:id="@+id/btn_button_dismiss"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="dismiss"/>
</LinearLayout>
运行截图: