Android-->Dialog/DialogFragment宽度高度修改/全屏,自定义样式

其实Dialog, DialogFragment, Activity 能看到的界面,都是基于Window显示的;
也就是修改样式, 都是在修改window的样式;
所以,本质上方法都是一样的,唯一不同的就是获取window对象的方法不一样;


Dialog 通过, getWindow() 获取;
Activity 也是通过, getWindow() 获取;
DialogFragment 则是getDialog().getWindow()获取;


有了window对象, 就可以开始本文了:

1:修改Dialog中window宽度和高度

//public static final int FILL_PARENT = -1;
//public static final int MATCH_PARENT = -1;
//public static final int WRAP_CONTENT = -2;
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//注意此处
dialog.setContentView(textView, new ViewGroup.LayoutParams(-2, -2));
dialog.getWindow().setLayout(-1, -2);//setLayout必须 在 setContentView之后, 调用;并且 setBackgroundDrawable 必须设置
//这里的-1,-2可以设置为任意高度;

2:修改DialogFragment中window宽度和高度
在DialogFragment的onCreateView()方法中

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    final Window window = getDialog().getWindow();
    View view = inflater.inflate(R.layout.dialog_fragment_layout,  ((ViewGroup) window.findViewById(android.R.id.content)), false);//需要用android.R.id.content这个view
    window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//注意此处
    window.setLayout(-1, -2);//这2行,和上面的一样,注意顺序就行;
    return view;
}

3:附赠Activity中修改window的宽度和高度
在Activity的onAttachedToWindow方法中

@Override
public void onAttachedToWindow() {
    Window window = getWindow();
    WindowManager.LayoutParams attributes = getWindow().getAttributes();
    attributes.width = 460;
    attributes.height = 700;
    window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//注意此处
    getWindow().setAttributes(attributes);
    super.onAttachedToWindow();
}

Winodw的其实属性修改:

mWindow = getDialog().getWindow();
//无标题
mWindow.requestFeature(Window.FEATURE_NO_TITLE);//必须放在setContextView之前调用
rootView = (ViewGroup) inflater.inflate(R.layout.rsen_base_dialog_fragment_layout,
(ViewGroup) mWindow.findViewById(android.R.id.content));
//透明状态栏
mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//退出,进入动画
mWindow.setWindowAnimations(getAnimStyles());
//清理背景变暗 
mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
//点击window外的区域 是否消失
getDialog().setCanceledOnTouchOutside(canCanceledOnOutside());
//是否可以取消,会影响上面那条属性
setCancelable(canCancelable());
//window外可以点击,不拦截窗口外的事件
mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
//设置背景颜色,只有设置了这个属性,宽度才能全屏MATCH_PARENT
mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
WindowManager.LayoutParams mWindowAttributes = mWindow.getAttributes();
mWindowAttributes.width = getWindowWidth();//这个属性需要配合透明背景颜色,才会真正的 MATCH_PARENT
mWindowAttributes.height = WindowManager.LayoutParams.WRAP_CONTENT;
//gravity
mWindowAttributes.gravity = getGravity();
mWindow.setAttributes(mWindowAttributes);
//没啦,更多属性可以在API文档里面查看.
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN// 覆盖状态栏
                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL//窗口外可以点击
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE//不监听按键事件
//                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
//                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS//突破窗口限制
//                    | WindowManager.LayoutParams.FLAG_FULLSCREEN
        ;

至此: 文章就结束了,如有疑问: QQ群:274306954 欢迎您的加入.

<think>好的,我现在需要帮助用户将带有自定义插槽的van-dialog组件封装成函数式调用。首先,用户希望能够在函数调用时传入标题、内容和底部的自定义内容,并且保持复用的便利性。根据之前的引用,特别是引用[3]和[4],封装弹组件主要是为了统一样式、方便维护和适应多样化的需求。 首先,我需要确定如何将Vue组件转化为函数式调用。通常,这可以通过Vue的extend方法和手动挂载实例来实现。例如,创建一个构造函数,生成组件实例,并将其挂载到DOM中。 接下来,用户提到了自定义插槽,包括标题、内容和底部。这意味着在封装的时候,需要允许用户传入这些部分的模板或渲染函数。对于函数式组件,通常使用h函数或JSX来动态生成内容。因此,可能需要接收这些插槽的配置作为参数,并在渲染时处理它们。 然后,考虑到van-dialog可能需要通过v-model控制显示隐藏,函数式调用时需要能够手动控制对话框的显示和关闭。可能需要暴露open和close方法,或者在调用函数后返回一个包含这些方法的对象。 另外,引用[2]提到el-dialog的内容是懒渲染的,但组件的生命周期仍会执行。因此,在封装时需要注意性能问题,确保即使对话框未显示,也不会影响父组件的性能。可能需要使用v-if或手动管理组件的挂载和销毁。 还需要考虑样式的统一。根据引用[3],封装弹可以统一UI样式,减少重复代码。因此,在封装后的组件中,应该包含默认样式,同时允许用户通过传入props或插槽覆盖默认样式。 步骤可能包括: 1. 创建一个Vue组件,包含van-dialog,并定义插槽位置。 2. 将该组件封装成函数式调用,允许通过参数配置插槽内容、props和事件。 3. 使用Vue.extend创建组件构造器,手动挂载到DOM元素。 4. 处理对话框的显示和隐藏,确保在关闭时销毁实例,避免内存泄漏。 5. 提供方法让用户可以通过JavaScript调用,如Dialog(options).show()。 可能遇到的问题是如何处理插槽内容的动态渲染。因为函数式调用中,用户可能希望传入字符串、VNode或组件。需要将这些内容转换为插槽的渲染函数。例如,使用h函数或作用域插槽来处理传入的内容。 另外,还需要考虑如何在函数式调用中处理作用域样式,尤其是当使用scoped样式时。可能需要将样式全局化,或者确保封装后的组件能正确应用用户的样式。 最后,测试封装后的组件,确保各个插槽内容正确显示,事件正常触发,并且多次调用不会导致实例堆积或内存泄漏。</think>### 函数式封装 van-dialog 的实现步骤 #### 一、封装思路 1. **组件解耦**:将 van-dialog 的布局、插槽和样式进行二次封装,形成可配置化组件 2. **函数式调用**:通过 Vue.extend + 手动挂载实现即用即调的特性 3. **内存管理**:在关闭时自动销毁实例,避免内存泄漏[^2] #### 二、实现代码 ```javascript // dialog.js import Vue from 'vue' import VanDialog from 'vant/lib/dialog' import 'vant/lib/dialog/style' const DialogConstructor = Vue.extend({ render(h) { return h(VanDialog, { props: this.config, on: { // 处理关闭事件 input: val => { if (!val) this.$destroy() } } }, [ // 标题插槽 this.$slots.title && h('template', { slot: 'title' }, [this.$slots.title]), // 默认插槽(内容) h('template', { slot: 'default' }, [this.$slots.default]), // 底部插槽 this.$slots.footer && h('template', { slot: 'footer' }, [this.$slots.footer]) ]) } }) export default function createDialog(options) { const instance = new DialogConstructor({ propsData: options.config, slots: options.slots }).$mount() document.body.appendChild(instance.$el) return { show: () => instance.$children[0].show(), close: () => instance.$children[0].close() } } ``` #### 三、使用方法 ```javascript // 在组件中调用 import createDialog from './dialog.js' export default { methods: { showCustomDialog() { const dialog = createDialog({ config: { title: '操作确认', showConfirmButton: false }, slots: { title: '<div class="custom-title">⚠️ 重要提示</div>', default: '<p>确定要执行该操作吗?</p>', footer: ` <van-button type="primary" @click="dialog.close">取消</van-button> <van-button type="danger" @click="submit">确认</van-button> ` } }) dialog.show() } } } ``` #### 四、关键实现要点 1. **插槽动态渲染**:通过 `h()` 函数实现模板的动态编译,支持传入字符串模板或 VNode 对象[^4] 2. **样式隔离**:使用 `scoped` 样式配合深度选择器保证样式穿透 ```css /* 组件样式 */ .custom-title >>> .van-dialog__header { color: #f00; font-size: 18px; } ``` 3. **生命周期管理**:通过监听 `input` 事件自动销毁实例,保证内存安全[^2] 4. **API 兼容**:保留原 van-dialog 的 `show`/`close` 方法,保持调用一致性
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值