本文最后更新于:星期四, 六月 18日 2020, 9:01 上午

记录自定义Dialog的一个天坑。

/**
 * Created by 黄伟杰 on 2018/7/17.
 */
public class MyDialog extends Dialog {
    private Context context;

    public MyDialog(@NonNull Context context) {
        super(context);
        this.context=context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.dialog);//放在onCreate里去调用,文档里就是这么写的。
        locateWindow(Gravity.TOP|Gravity.CENTER_HORIZONTAL);
    }

    //如果这个方法不在setContentView后面调用,params.width和params.height的设置将会失效
    private void locateWindow(int gravity){
        Window window = getWindow();
        Objects.requireNonNull(window).setGravity(gravity);
        WindowManager.LayoutParams params = Objects.requireNonNull(window).getAttributes();
        params.y = DensityUtil.dip2px(context, 49);
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        window.setAttributes(params);
    }
}

附带一个Dialog的由创建到展现给用户的流程:

贴出的源码都是浓缩版代码


构造方法:

    Dialog( Context context, int themeResId, boolean createContextThemeWrapper) {
        ...
        //获取单例类WindowManager。
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        //创建PhoneWindow对象
        final Window w = new PhoneWindow(mContext);
        mWindow = w;
      ...
    }

创建完后,我们代码里调用Dialog#show

public void show(){
    dispatchOnCreate(null);//  ==>调用onCreate();
    onStart();
    mDecor=mWindow.getDecorView();//获取我们Dialog所在的Window上的DecorView。
    mWindowManager.addView(mDecor, l);//把顶级DecorView放到Window上。
  //至此,Dialog显示出来了。准确地说,是刚才创建的PhoneWindow上的View显示出来了。
}

在onCreate()中,按照谷歌文档的推荐,在此处调用setContentView();


要深入去看Window的一些东西,看这个大神的文章:
Android Window 机制探索 - 凶残的程序员


View     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

为git设置文本编辑器。 上一篇
RecyclerView的复用 下一篇