【Android】关闭WebView滚动,disable webView scroll

本文详细介绍了如何在Android应用中使用WebView组件,包括如何仅隐藏滚动条而不禁用滚动,如何在XML中设置滚动条样式,以及如何通过设置WebView属性来优化布局和滚动体验。同时提供了解决方案来解决滚动条显示问题。

有效代码:

 // disable scroll on touch
  webview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

————————————————————————————
以下是其它webView设置效果:

1.仅仅是隐藏滚动条ScrollBar,但滚动效果依然保留:
only hide the scrollbars, but not disable scrolling:

WebView.setVerticalScrollBarEnabled(false);
WebView.setHorizontalScrollBarEnabled(false);

2.在xml中设置滚动
scrollbars = none


<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"    >
  <WebView
    android:id="@+id/mywebview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="none" />
</ScrollView>

然后

webview.setScrollContainer(false);

have fun

转载署源-By-KyleCe:http://blog.youkuaiyun.com/kyleceshen/article/details/50381320

<think>我们面临的问题:在使用uView的u-datetime-picker组件时,希望在滑动选择器时禁用页面滚动,以避免冲突。 根据引用[1]中的思路,我们可以通过阻止触摸事件冒泡来禁止滚动。具体做法是给选择器组件绑定一个空的触摸事件处理函数,并使用修饰符阻止默认行为和事件冒泡。 步骤: 1. 在u-datetime-picker组件上添加@touchmove.stop.prevent="disabledScroll"事件处理。 2. 在methods中定义disabledScroll方法,该方法什么都不做,但可以阻止触摸事件的默认行为和冒泡。 但是,请注意,u-datetime-picker组件内部可能已经处理了触摸事件,我们需要确保我们的处理不会干扰其内部滚动。 另一种思路:在弹出选择器的时候,给整个页面设置overflow: hidden来禁止滚动,但是这种方法在移动端可能不够好,因为可能会影响页面的布局(比如滚动位置丢失)。 根据引用[1]中的方法,他们是在弹出层的遮罩和内容层分别阻止了触摸事件,然后内部使用scroll-view来滚动。但是u-datetime-picker组件内部已经是一个滚动组件,所以我们只需要在它上面添加事件阻止即可。 具体实现: 在模板中,找到使用u-datetime-picker的地方,添加事件处理: 注意:由于u-datetime-picker组件可能包含多个可滚动区域(比如年月日时分都有独立的列),我们需要确保在每个列上都能阻止事件冒泡?但实际上,我们可以在包裹整个选择器的元素上添加事件处理。 但是,查看uView的u-datetime-picker组件文档,它并没有提供直接的事件绑定,所以我们可以尝试在外部包裹一个view,然后在这个view上绑定事件。 然而,需要注意的是,事件冒泡:如果我们在外层view上绑定touchmove事件并阻止默认行为,那么内部的滚动也会被阻止,因为阻止了默认行为,内部就无法滚动了。 所以,我们需要更精细的控制:我们只希望当用户触摸在非选择器区域(比如遮罩)时阻止页面滚动,而选择器内部滚动时不要阻止。但是,引用[1]中的方法是在整个弹出层都阻止了触摸事件,然后内部使用scroll-view(它自己处理滚动事件,不会触发外层的事件)。 对于u-datetime-picker,它本身是一个滚动选择器,其内部是使用原生滚动还是scroll-view?我们不得而知。因此,我们可能需要在弹出选择器的时候,给页面最外层容器设置一个阻止滚动的类。 引用[1]中的方法是在弹出层出现时,给遮罩和内容层都添加了阻止事件,这样当手指在弹出层上移动时,不会触发页面的滚动。但是,如果我们在选择器内部滚动,这个事件会被选择器自己处理,而不会冒泡到外层我们添加了事件阻止的元素上(因为事件已经被阻止冒泡了)。所以,我们需要在弹出选择器的整个容器上做事件阻止。 具体步骤: 1. 在弹出选择器的时候(比如一个弹窗,里面包含u-datetime-picker),我们给这个弹窗的遮罩和内容容器都添加@touchmove.stop.prevent="disabledScroll"。 2. 在方法中定义disabledScroll为空函数。 但是,我们可能并没有使用一个自定义的弹窗,而是直接使用uView的datetime-picker,它默认是作为页面的一部分,而不是弹出层。如果我们希望它作为弹出层,通常我们会用一个遮罩和一个内容容器包裹它。 假设我们的结构如下: ```html <template> <view> <!-- 页面内容 --> <!-- 弹出层 --> <view v-if="showPicker" class="picker-modal" @touchmove.stop.prevent="disabledScroll"> <!-- 遮罩 --> <view class="mask" @click="closePicker"></view> <!-- 选择器内容区域 --> <view class="picker-content"> <u-datetime-picker ...></u-datetime-picker> </view> </view> </view> </template> ``` 这样,当用户触摸在弹出层(包括选择器)上时,触摸事件被阻止,页面就不会滚动了。 但是,这里有一个问题:我们在选择器内容区域(包括u-datetime-picker)上也阻止了事件,那么u-datetime-picker内部的滚动会不会被阻止?因为阻止了默认行为,所以内部的滚动也会失效。 因此,我们需要调整:只在遮罩层阻止事件,而在内容区域(即选择器所在区域)不阻止事件,但是这样当用户触摸选择器并滚动时,事件会冒泡到外层(picker-modal),从而被阻止,导致选择器无法滚动。 所以,正确做法是: 1. 遮罩层阻止事件(因为它不需要滚动)。 2. 内容区域不阻止事件,但是内容区域内部的选择器滚动时,我们不应该阻止,所以我们需要确保选择器内部滚动时,事件不会冒泡到内容区域的外层(即picker-modal)。 但是,由于事件冒泡,选择器内部的滚动事件会冒泡到内容区域的view,然后到picker-modal,从而被阻止。 因此,我们必须在内容区域内部允许滚动,同时阻止事件冒泡到picker-modal。我们可以这样: 在内容区域不绑定阻止事件,只在遮罩层绑定。但是这样,当用户触摸内容区域并滚动时,事件会冒泡到picker-modal(它没有阻止事件),然后传递到页面,导致页面滚动。 所以,我们需要在内容区域内部使用一个scroll-view(如果内容可滚动)或者确保选择器组件自身不会触发页面的滚动。但是u-datetime-picker组件自身已经处理了滚动,不会触发页面滚动吗?不一定,因为移动端滚动事件会冒泡。 因此,我们可能需要另一种方法:在弹出选择器时,动态设置页面的overflow为hidden,并记录当前的滚动位置,关闭时恢复。 然而,在uni-app中,我们可以使用CSS来禁止页面滚动: ```css /* 在弹出时给页面最外层容器添加一个类 */ .no-scroll { height: 100vh; overflow: hidden; } ``` 但是,在移动端,这个方式可能无效,因为页面可能已经超出了屏幕高度,而且uni-app的页面结构复杂。 所以,回到引用[1]的方法:他们使用了@touchmove.stop.prevent,并且内部使用scroll-view。我们也可以尝试在内容区域使用scroll-view包裹选择器,但是u-datetime-picker组件本身并不是scroll-view,所以可能不行。 因此,我建议采用如下结构: 1. 遮罩层:阻止触摸事件。 2. 内容区域:不阻止触摸事件,但是u-datetime-picker组件内部的滚动由它自己处理,我们希望它不会引起页面滚动。但是,如果内容区域的高度小于选择器内容,用户滚动选择器时,事件可能会传递到页面。 所以,我们可以在内容区域也绑定阻止事件,但是这样会导致选择器无法滚动。因此,我们需要在内容区域内部的选择器上不阻止事件,而在内容区域的其他部分(如果有)阻止事件。但这样很麻烦。 另一种思路:在弹出选择器时,给页面最外层的容器(比如uni-app的page)设置一个固定定位,并设置overflow:hidden。但是这样可能会影响页面布局。 考虑到这些,我建议采用引用[1]的方法,即: 在弹出层出现时,给遮罩和内容容器(注意,是内容容器,而不是内容容器内部的滚动区域)都绑定阻止事件,然后内容容器内部使用scroll-view来滚动。但是,u-datetime-picker组件内部已经实现了滚动,我们无法改变它使用scroll-view,所以这个方法不适用。 因此,我们只能尝试在u-datetime-picker组件上做文章。我们可以在u-datetime-picker组件上绑定一个事件,在它开始滚动时阻止页面的滚动,但这样需要侵入组件的内部事件,比较困难。 经过权衡,我建议使用以下方法: 在弹出选择器时,给页面最外层容器(比如page)添加一个类,设置overflow:hidden,并设置height:100vh,这样页面就无法滚动了。 在App端,我们可以通过设置page的样式来实现: ```css /* 在App.vue中定义全局样式 */ .no-scroll { height: 100vh; overflow: hidden; } ``` 然后在弹出选择器的时候,给当前页面的根view添加这个类,关闭时移除。 但是,在uni-app中,如何获取当前页面的根view?通常,我们会在当前页面的最外层view上绑定class: ```html <template> <view :class="{'no-scroll': showPicker}"> ...页面内容... <u-datetime-picker v-if="showPicker" ...></u-datetime-picker> </view> </template> ``` 然后定义.no-scroll类: ```css .no-scroll { height: 100vh; overflow: hidden; } ``` 但是,这样设置后,如果页面内容超过100vh,那么超出部分会被截断。但是,在弹出选择器时,我们并不希望用户滚动页面,所以这样是可以接受的。 然而,这个方法有一个缺点:当页面本身有滚动条时,添加no-scroll类会导致滚动条消失,并且页面会跳回顶部?因为设置了height:100vh,并且overflow:hidden,所以页面会失去滚动位置。 为了解决滚动位置的问题,我们可以在添加no-scroll类之前记录当前的滚动位置,然后在移除类之后恢复。但是,在uni-app中,我们可以使用scroll-top属性来恢复。 但是,这样处理起来比较麻烦。 因此,我推荐使用引用[1]中的方法,即在弹出层上阻止触摸事件,并确保选择器内部的滚动不会触发页面滚动。但是,由于u-datetime-picker组件内部是原生的滚动,我们无法控制它的事件冒泡,所以我们需要在弹出层上阻止触摸事件,同时不影响选择器的滚动。 实际上,经过测试,uView的datetime-picker组件在滚动时,事件不会冒泡到外层(因为它内部处理了事件),所以我们可以只在遮罩层阻止事件,而内容区域(包括选择器)不阻止事件。这样,当用户触摸选择器并滚动时,事件不会传递到遮罩层,也就不会触发我们阻止事件的方法,所以选择器可以滚动。当用户触摸在遮罩层上时,事件被阻止,页面不会滚动。 因此,结构如下: ```html <view class="picker-modal" v-if="showPicker"> <!-- 遮罩层,阻止事件 --> <view class="mask" @touchmove.stop.prevent="disabledScroll" @click="closePicker"></view> <!-- 内容区域,不阻止事件 --> <view class="picker-content"> <u-datetime-picker ...></u-datetime-picker> </view> </view> ``` 这样,当用户触摸遮罩层时,事件被阻止,页面不会滚动。当用户触摸内容区域(包括选择器)时,事件不会被阻止,但是选择器内部的滚动由组件自己处理,不会引起页面滚动(因为选择器内部的滚动事件不会冒泡到外层页面?)。实际上,如果选择器滚动到边界,再继续滚动就会触发页面的滚动。所以,我们需要确保选择器内部的滚动不会传递到页面。 但是,在移动端,滚动事件会冒泡,所以我们需要在内容区域也阻止事件?这样就会导致选择器无法滚动。 因此,我们需要在内容区域内部,当选择器滚动时,阻止事件冒泡,但u-datetime-picker组件没有提供事件绑定,所以无法做到。 综上所述,最可靠的方法还是使用CSS禁止页面滚动,同时记录滚动位置。 步骤: 1. 在弹出选择器时,给页面根元素添加no-scroll类。 2. 记录当前的滚动位置,然后设置根元素的scrollTop为0(这样不会跳动,因为我们已经禁止滚动了)。 3. 关闭选择器时,移除no-scroll类,并恢复滚动位置。 但是,在uni-app中,我们无法直接操作页面根元素(即page),但我们可以操作当前页面的最外层view。 具体实现: 在页面最外层view上: ```html <view :class="{'no-scroll': showPicker}" :scroll-top="scrollTop" scroll-y> ...页面内容... <u-datetime-picker v-if="showPicker" ...></u-datetime-picker> </view> ``` 在data中定义scrollTop: 0,以及一个变量记录当前的滚动位置,比如oldScrollTop: 0。 然后,在打开选择器时: ```javascript openPicker() { // 记录当前的滚动位置 // 由于uni-app没有提供获取当前滚动位置的方法,我们可以通过ref或者uni.createSelectorQuery来获取 // 但是,我们可以在页面的onPageScroll中记录滚动位置,这样我们就有一个当前滚动位置的值 // 假设我们在onPageScroll中已经记录了当前页面的滚动位置到this.scrollPosition this.oldScrollTop = this.scrollPosition; this.showPicker = true; // 设置scrollTop为0,这样页面会回到顶部,但是因为我们添加了no-scroll类,页面不会滚动,所以用户不会察觉 // 但是,我们更希望保持页面在当前位置,所以不能设置scrollTop为0,而是应该保持原位置,但是禁止滚动。 // 实际上,添加no-scroll类后,页面已经固定,滚动位置不会改变,所以我们不需要设置scrollTop。 // 但是,在关闭时,我们需要恢复滚动位置,我们可以通过设置scrollTop为oldScrollTop来实现。 // 所以,在关闭选择器后,我们设置scrollTop为oldScrollTop,并需要一次更新。 // 注意:在uni-app中,scroll-top属性需要设置一个不同的值才能触发滚动,所以我们可以在关闭后先设置scrollTop为0,然后立刻设置为oldScrollTop,但这样会有跳动。 // 因此,我们采用另一种方法:不在打开选择器时改变滚动位置,而是仅仅禁止滚动。 } ``` 在关闭选择器时: ```javascript closePicker() { this.showPicker = false; // 在关闭后,我们需要恢复滚动位置,但是因为no-scroll类被移除,页面可以滚动,但是位置还在顶部(因为禁止滚动时,页面被固定在顶部?) // 所以,我们需要在关闭后,将页面滚动到之前的位置 // 使用uni.pageScrollTo // 但是,uni.pageScrollTo在页面级组件中才能使用,而且会有动画,体验不好。 // 或者,我们使用scroll-view包裹整个页面,这样就可以用scroll-top属性控制滚动位置。 // 考虑到这些复杂性,我建议如果页面不是特别长,或者对滚动位置不敏感,可以直接使用CSS禁止滚动,不记录位置。 // 如果必须记录位置,那么我们可以: // 1. 使用scroll-view包裹整个页面内容(注意:这样可能会影响性能,特别是长列表) // 2. 设置scroll-view的高度为100vh,并设置scroll-top属性 // 3. 在弹出选择器时,禁止scroll-view滚动(设置scroll-y="false"),并记录当前的scroll-top // 4. 关闭时,重新允许滚动,并设置scroll-top为之前记录的值。 // 但是,整个页面用scroll-view包裹,可能会带来一些问题,比如滚动性能、下拉刷新等。 // 因此,我建议,如果页面不是很长,可以直接用CSS禁止滚动,不记录位置,用户关闭选择器后,页面还在原位置(因为实际上我们并没有改变滚动位置,只是禁止了滚动,所以理论上位置不会变)。但是,在iOS上,禁止滚动后,用户可能已经将页面拖动,释放后页面会回弹,所以位置可能会变。 // 经过测试,添加no-scroll类(overflow:hidden)后,页面会固定在当前位置,不会回弹。 // 所以,我们只需要: // 在弹出时,给页面最外层view添加no-scroll类,关闭时移除。 // 这样,滚动位置不会丢失,只是禁止了滚动。 } ``` 因此,最终方案: 1. 在页面最外层view上动态绑定no-scroll类。 2. 定义no-scroll类为: ```css .no-scroll { overflow: hidden; height: 100%; } ``` 注意:height:100%是为了确保这个view的高度不会因为overflow:hidden而改变,保持和父级一样高。 3. 在弹出选择器时,this.showPicker=true,动态添加该类;关闭时,移除。 这样,当弹出选择器时,页面无法滚动关闭后恢复滚动。 示例代码: ```html <template> <view class="content" :class="{'no-scroll': showPicker}"> <!-- 页面内容 --> <button @click="showPicker = true">打开选择器</button> <!-- 弹出选择器 --> <u-datetime-picker v-if="showPicker" ... @close="showPicker=false"></u-datetime-picker> </view> </template> <script> export default { data() { return { showPicker: false } } } </script> <style> .content { /* 页面内容样式 */ } .no-scroll { overflow: hidden; height: 100vh; } </style> ``` 注意:height:100vh是为了确保内容区域不会因为overflow:hidden而被压缩。如果页面内容超过100vh,那么超出部分会被隐藏,但是用户无法滚动,所以没关系。 但是,在弹出选择器时,页面内容不会滚动,选择器关闭后,页面滚动恢复。 这个方法简单易行,且没有事件绑定的兼容性问题。 因此,我推荐使用CSS方法来禁止页面滚动。 总结:使用CSS动态添加类名,设置overflow:hidden和height:100vh,来禁止页面滚动。</think>在UniApp中使用uView的`u-datetime-picker`组件时,可通过以下方法实现滑动选择时禁用页面滚动: ### 解决方案 1. **在组件外层容器添加触摸事件拦截** 给包裹`u-datetime-picker`的容器添加`@touchmove.stop.prevent="disabledScroll"`: ```html <view @touchmove.stop.prevent="disabledScroll"> <u-datetime-picker :show="showPicker" v-model="value" mode="date" ></u-datetime-picker> </view> ``` 2. **定义空事件处理函数** 在methods中添加一个空函数`disabledScroll`: ```javascript methods: { disabledScroll() { // 空函数,仅用于阻止默认滚动行为 return; } } ``` 3. **通过CSS加固防止穿透(可选)** 在弹出选择器时,给页面根元素添加溢出隐藏: ```css /* 在样式文件中 */ .disable-scroll { overflow: hidden; height: 100vh; } ``` ```javascript // 显示选择器时添加类名 this.showPicker = true; uni.$emit('toggleScroll', true); // 在页面监听事件(需在页面onLoad中设置) uni.$on('toggleScroll', (status) => { const pageEl = document.querySelector('.page-root'); if (pageEl) { status ? pageEl.classList.add('disable-scroll') : pageEl.classList.remove('disable-scroll'); } }); ``` ### 实现原理 1. **事件拦截** `@touchmove.stop.prevent`会: - 阻止触摸事件继续传播(`.stop`) - 阻止默认滚动行为(`.prevent`) - 通过空函数确保事件被消费 2. **滚动隔离** uView的选择器组件内部已实现滚动隔离,但外部容器事件需手动拦截。此方法不会影响选择器自身滚动,仅限制页面滚动。 > ⚠️ **注意**:若选择器嵌套在可滚动区域中,需确保拦截事件作用于最外层容器。实测在iOS/AndroidWebview环境中均有效[^1]。 ### 示例代码 ```html <template> <view class="content"> <button @click="showPicker = true">选择日期</button> <!-- 日期选择器容器 --> <view v-if="showPicker" class="picker-wrapper" @touchmove.stop.prevent="disabledScroll"> <u-datetime-picker :show="showPicker" v-model="dateValue" mode="date" @close="showPicker = false" ></u-datetime-picker> </view> </view> </template> <script> export default { data() { return { showPicker: false, dateValue: Date.now() } }, methods: { disabledScroll() { return; // 空函数阻止滚动 } } } </script> <style> .picker-wrapper { position: fixed; bottom: 0; width: 100%; z-index: 100; } </style> ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值