(移动端)移动端问题整理(输入法,字符截断,禁止页面滚动)

这篇文章主要整理一下这次移动端项目中遇到的一些问题,以及相应的解决方案。闲话不多说了,看问题!

  1. 手机上输入内容的长度截断

    具体的需求是这样的,输入框输入的字母和汉字都不能超过 7 个,而且需要实时判断,超过限制就截断,并弹出提示弹窗。

    原本计划的解决方案:

    通过Html5的oninput对输入框的内容进行监听,同时动态计算输入内容的长度(由于这里对汉字和字母的长度做了统一要求,都是7,所以这里只是简单计算了字符串的长度,并没有针对字符长度进行计算,PS: 一个中文字符长度为2,一个英文字母字符长度为1)。

    然后如果得到的长度超过7,我就对接下来输入的内容进行判断,如果是删除按钮,就允许输入;否则就禁止用户的输入,我是用的是 return false;

    但是理想很丰满啊,return false 这里并不起作用,并不能阻止用户的默认输入行为。至于这里为什么不起作用,还没有搞懂,各位要是知道,不妨提点一下啊!

    于是想到了字符串的截取,具体就一行代码

        this.value = this.value.substr(0, 7);
    
  2. 手机上中文输入法的虚拟拼音也被 oninput 事件监听

    上面的问题搞定了英文字母的输入,但是手机上中文输入的时候,输入法会自动提供虚拟拼音。由于前面的字符截断,使得输入的中文 比如 "黄晓明",虚拟拼音却是huang'xiao'ming 这里就超过了 7,结果就出现了提示弹窗,以及字符截断。。。。

    我的内心是奔溃的

    于是就百度到了 compositionstart, compositionend 这两个事件!他们能够判断到中文输入开始和结束,这里主要参考了 手机上限制字符长度的正确姿势
    经验总结:应对中文输入法的字符串截断方案(带代码示例)

    具体解决方案,两篇文章介绍的很详细,我就不多介绍了。这里发下,我和他们差不多的处理代码吧,主要就是参考了他们代码,才使得我的项目问题得到解决。

        $( '.input').on( 'input', function( e ) {
          if ( $( this ).attr( 'inputstart' ) === 'no' ) {
          return false;
          }
          $( '.sure' ).attr( 'lengthok', 'yes' );
          if( getTextLength( this.value ) > 7 ) {
            if ( e.keyCode !== 8 ) {
              $( '.tiptext' ).html( '关键词长度不能超过7' );
              $( '.tip' ).show();
              setTimeout( function(){
                $( '.tip' ).hide();
              }, 1500 );
              this.value = this.value.substr( 0, 7 );
            }
          }
        } ).on( 'compositionstart', function() { // 判断中文输入开始
          $( this ).attr( 'inputstart', 'no' );
        } ).on( 'compositionend', function() {   // 判断中文输入结束,在此期间不触发 input 事件
          $( this ).attr( 'inputstart', 'yes' );
        } );
    
  3. 禁止页面的全局滚动

    移动端页面交互,通常有弹出层,背景需要遮罩。但出现这样情景的时候,我们其实应该禁止页面的整体滚动。

    关于这一点,刚开始我还没考虑太好,但和组里的同事请教,才明白!
    出现弹出层,我们是希望用户关注弹出层的内容和交互,所以用户不应该还能滚动遮罩层后面的内容。

    通过这个问题,我想我们平常做项目,实现交互的时候,其实除了沟通正常需求之外,还应该多站在用户的角度去思考问题。

    这个问题比较容易解决,当出现弹出层的时候,我们设置

        document.addEventListaner('touchmove',stopTouchMove,false);
    

    当弹出层被关闭的时候,再设置

        document.removeEventListaner('touchmove',stopTouchMove,false);
    

    这里还有一个小知识点,就是 removeEventListaner 这个事件,必须传入函数名,而不是具体的匿名函数才能正确执行。
    所以我们加一个处理函数就可以

        function stopTouchMove( e ) {
          e.preventDefault();
        }
    

### 今天就先写到这里了,后面要是还有其他的问题,我再来更新

更新,因为出现了新的问题,和新的解决方案

之前写的处理滚动方案,太简单了,随后我就遇到了更加复杂的问题,这里再做一下补充。。。

我们上面 3中的解决方案,遇到这种情况就不使用了。。。

图片来自http://www.haorooms.com/post/webapp_bodyslidebcdiv图片来自http://www.haorooms.com/post/webapp_bodyslidebcdiv

因为3中的解决方案,会使得全局禁止滑动,这样容器自身的滑动也不能实现了。因为我要处理的弹层是需要底部固定的,所以。。。

第一种思路
它来自于 移动端的touch事件处理,可以利用 event 这个工具去计算滑动的方向以及距离,当比如滑动到这部分的最上边和最下边的时候就有

event.preventDefault()

来组织容器内部的滑动。

这里我使用的思路和这个文章写的一样,但是具体 event 的用法不太一样,因为直接 event.pageY 这样使用会报错 undefined 的 所以,我列出一下我的代码

var start_pos;
$( '.container' ).on( 'touchstart', function( e ) {
  var touch = e.targetTouches[0];
  start_pos = touch.pageY;
  } ).on( 'touchmove', function( e ) {
  var touch = e.targetTouches[0];
  var down_or_up = ( touch.pageY - start_pos > 0 );
  var top_distance = $( this ).scrollTop();

  if ( down_or_up && top_distance <= 0 ) {
  e.preventDefault();
  }
} );

这里能够实现容器内部滑动顶部和底部禁止页面滚动,但是滑动容器过程中,如果我滑动遮罩层,还是能够上下滑动我的页面,因为我的页面高度一屏不够的,所以会看到我的弹层也在上下滑动。。。所以这种方案我并不适用

说说最终解决方案

看到了这个提问,移动端禁止遮罩层以下屏幕滑动,给我提供了一种新奇的思路,出现弹层的时候,设置页面最外层容器,也就是 body 内的第一层容器为 position fixed,取消弹层的时候,再修改为 position absolute 或者 relative 。这种方式果然一下就搞定了,由于外层都固定了,所以里面的容器自己滑动也不会影响整个页面的滑动了。

仔细想想,还是我的思路一直定位在了js 通过 e.preventDefault() 或 3中的解决方案。

其他遇到的问题有

输入框,一定要多考虑特殊的输入,比如空格啊,特殊字符啊!!!等等。。
输入框,一定要多考虑特殊的输入,比如空格啊,特殊字符啊!!!等等。。
输入框,一定要多考虑特殊的输入,比如空格啊,特殊字符啊!!!等等。。

今天先补充到这里,有感觉后面可能会再补充一些flex 布局的内容

posted @ 2016-05-17 09:28  StrongerSY  阅读(3556)  评论(0编辑  收藏  举报