h5制作的页面,有输入框的情况,在ios和android上截然不同,这就造成了这样那样的问题。
android上,软键盘弹起,页面高度会变化,这就引起定位在底部的按钮错位等问题。
今天主要说的是ios,ios上,页面高度不会因为软键盘而变化,但是软键盘弹起的时候,页面可以滑动,(并且软键盘弹起的时候,滑动list数据框的时候滑不到底部)如图:
- 正常样式,头部是定位元素
- 输入框聚焦后会出现两部分的滚动条,底下部分是元素的滚动条,滚动头部是页面的滚动条
思路
我个人的思路有两个方向
- 软键盘弹起的时候,改变页面的大小,使其类似于android,android的这个页面没有问题,但是考虑到还需要加插件,改个ios包不容易,就摒弃了
- 查看了下资料,看了下其他软件的input框,发现可以这样解决
在键盘弹起的时候,滑动list数据框,设置输入框失焦,使得软键盘消失
在键盘弹起的时候,滑动头部,使得元素默认的scroll滑动事件失效
所以,总结了下,最后直接写了个mousemove事件,在弹起软键盘的时候,滑动底部和头部,都会阻止滑动,使软键盘消失
难点
- 阻止默认行为写法,,必须加个参数才能实现
{passive: false}
- 取消默认行为写法,removeEventListener事件成功清除事件的写法
第二个参数必须是个方法,methods里面的方法,直接写没作用
在尝试了无数遍之后,才实现(vue项目)
<template>
<div class="searchCommon">
<div class="search_content">
<span class="search_icon"></span>
<span v-if="searchValue" class="clear_icon" @click="clearSearch"></span>
<input
ref="search_inp"
type="text"
maxlength="20"
placeholder="搜索"
id="searchInput"
v-model="searchValue"
>
</div>
<div class="search_cancel" @click="cancel">取消</div>
</div>
</template>
<script type="text/javascript">
export default {
name: "search-input",
data() {
return {
searchValue: ""
};
},
watch: {
searchValue() {
this.$emit("search", this.searchValue);
}
},
methods: {
cancel() {
this.searchValue = "";
this.$refs.search_inp.blur();
},
clearSearch() {
this.searchValue = "";
this.$refs.search_inp.focus();
},
blurEvent() {
this.$refs.search_inp.blur();
},
perventEvent(e) {
e.preventDefault();
this.blurEvent();
},
addPerventEvent() {
const _this = this;
if (this.isiOS && this.flag) {
this.flag = false;
this.flag_out = true;
this.removeEvent = false;
document.addEventListener("touchmove", _this.perventEvent, {
passive: false
});
}
},
removePerventEvent() {
const _this = this;
if (this.isiOS && this.flag_out) {
this.flag = true;
this.flag_out = false;
this.removeEvent = true;
document.removeEventListener("touchmove", _this.perventEvent, {
passive: false
});
}
}
},
mounted() {
const _this = this;
var u = navigator.userAgent;
this.isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
this.flag = true; //保证聚焦后只触发一次事件
this.flag_out = true;//保证失焦后只触发一次事件
this.removeEvent = true;//保证事件执行
document.body.addEventListener("focusin", _this.addPerventEvent);
document.body.addEventListener("focusout", _this.removePerventEvent);
},
beforeDestroy() {
const _this = this;
if(!this.removeEvent){
document.removeEventListener('touchmove', _this.perventEvent,{passive: false});
}
document.body.removeEventListener('focusin', _this.addPerventEvent)
document.body.removeEventListener('focusout', _this.removePerventEvent)
}
};
</script>
<style type="text/css" lang="scss">
.searchCommon {
position: relative;
padding: 0px 10px;
height: 31px;
box-sizing: content-box;
display: flex;
align-items: center;
margin: 10px 0;
.search_content {
flex: 1;
position: relative;
height: 31px;
}
input {
width: 100%;
border: none;
background: #ffffff;
height: 31px;
padding-left: 3rem;
border-radius: 1.25rem;
position: absolute;
left: 0;
top: 0;
z-index: 9;
}
.search_icon {
display: inline-block;
width: 1.375rem;
height: 1.375rem;
background: url("/images/search.png") no-repeat;
position: absolute;
left: 1.2rem;
top: 0.6rem;
background-size: contain;
z-index: 99;
}
.search_cancel {
color: #333;
margin-left: 5px;
font-size: 1rem;
padding: 5px 0 5px 5px;
}
.clear_icon {
display: inline-block;
width: 1.2rem;
height: 1.2rem;
background: url("/images/person/clear.png") no-repeat;
position: absolute;
right: 1.2rem;
top: 0.7rem;
background-size: contain;
z-index: 99;
}
}
</style>