Android自定义Dialog以及横竖屏切换时动态更改大小

1.需求:应用中需要用到的Dialog的场景,提示用户信息并需要用户做出选择。
比如:
返回键退出提示,让用户确认是否退出。
当前网络提示,让用户确认是否网络异常,是否继续使用移动网络。
是否清空某些信息,让用户根据提示并确认当前操作是否继续。
提示用户输入密码等相关信息的底部提示框。
2.封装Dialog
①需要设置的基本属性:layout布局、宽、高、风格、是否可点击dialog以外的区域、点击事件监听等。


import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import static android.content.ContentValues.TAG;

/**
 * @author zhou.jn on 2019/3/24.
 */

public class CustomDialog extends Dialog {
    private int mWidth;
    private int mHeight;
    private int mGravity;
    private View mView;
    private boolean isCancelTouchout;

    public CustomDialog(Builder builder) {
        super(builder.context);
        mWidth = builder.width;
        mHeight = builder.height;
        mGravity = builder.gravity;
        mView = builder.view;
        isCancelTouchout = builder.isCancelTouchout;
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(mView);
        setCanceledOnTouchOutside(isCancelTouchout);
        Window window = getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();
        Log.i(TAG, "onClick: lp.height: "+ lp.height + " lp.width: "+lp.width);
        lp.height = mHeight;
        lp.width = mWidth;
        lp.gravity = mGravity;
        window.setAttributes(lp);
    }

    public CustomDialog(Builder builder, int resStyle) {
        super(builder.context, resStyle);
        mWidth = builder.width;
        mHeight = builder.height;
        mGravity = builder.gravity;
        mView = builder.view;
        isCancelTouchout = builder.isCancelTouchout;

    }

    public static final class Builder {
        private int width;
        private int height;
        private int gravity;
        private View view;
        private Context context;
        private int resStyle = -1;
        private boolean isCancelTouchout;

        public Builder(Context context) {
            this.context = context;
        }

        public Builder gravity(int g) {
            gravity = g;
            return this;
        }

        public Builder view(View v) {
            view = v;
            return this;
        }

        public Builder view(int id) {
            view = LayoutInflater.from(context).inflate(id, null);
            return this;
        }

        public Builder widthdp(int w) {
            width = w;
            return this;
        }

        public Builder heightdp(int h) {
            height = h;
            return this;
        }

        public Builder style(int style) {
            resStyle = style;
            return this;
        }

        public Builder cancelTouchout(boolean iscancelTouchout) {
            isCancelTouchout = iscancelTouchout;
            return this;
        }

        public CustomDialog build() {
            if (resStyle != -1) {
                return new CustomDialog(this, resStyle);
            } else {
                return new CustomDialog(this);
            }
        }
    }


}

3.使用 MainActivity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private CustomDialog dialog;
    private Button btn_showDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initDialog();
        btn_showDialog = (Button) findViewById(R.id.btn_showDialog);
        btn_shoDwialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "onClick: show");
                if (dialog != null) {
                    dialog.show();
                }
            }
        });
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            //这里一定需要调用show以后,控件可见后才可以进行动态布局,
            dialog.show();
            changeDialogLandscape();
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        	dialog.show();
            changeDialogPortrait();
        }
    }

    private void changeDialogPortrait() {
        Log.i(TAG, "changeDialogPortrait: ");
        if (dialog != null) 
            Window window = dialog.getWindow();
            WindowManager.LayoutParams lp = window.getAttributes();
            lp.height = 300;
            lp.width = 250;
            lp.gravity = Gravity.CENTER;
            window.setAttributes(lp);
        }
    }

    private void changeDialogLandscape() {
        Log.i(TAG, "changeDialogLandscape: ");
        if (dialog != null) {
            Window window = dialog.getWindow();
            WindowManager.LayoutParams lp = window.getAttributes();
            lp.height = 500;
            lp.width = 450;
            lp.gravity = Gravity.CENTER;
            window.setAttributes(lp);
        }
    }

    private void initDialog() {
        CustomDialog.Builder builder = new CustomDialog.Builder(this);
        dialog = builder
                .style(R.style.Dialog)
                .widthdp(300)
                .heightdp(150)
                .view(R.layout.dialog_main)
                .gravity(Gravity.CENTER)
                .cancelTouchout(false)
                .build();
    }

Dialog style

 <style name="Dialog" parent="android:style/Theme.Dialog">
       //设置为透明背景
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowNoTitle">true</item>
    </style>

AndroidManifest.xml

 <!-- 注意 configChanges 配置当该Activity发生以下的活动的时候不重新启动Activity-->
        <activity android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

总结:①Window绘制主要包括Activity、Dialog、Toast。当时不知道window的属性,且不知道控件可见后再进行设置属性。两个坑导致试了很久。相关详细内容可见《Android开发艺术探索》第八章。
②封装Dialog后使用时觉得方便很多,但一味在Activity中进行这样初始化并使用,当该Activity需要两个及以上的Dialog的时候,就会显得特别混乱,所以建议还是写在单独的Dialog类中,不要直接在Activity中进行初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值