2018-07-06 14:50:58 weixin_41809141 阅读数 2251
 rem移动端布局怎么适配IOS和Android
        昨天“佬大”问我做的h5页面在ios上面显示正常,但是Android就变惨不忍睹了,于是我又开始了度量之路,几个小时过去了......“佬大”问好了没。我说:“还没”那你还是问下“俊伟”吧,果然一问牛逼的同事,迎刃而解的快感你感受到了没。做为一个程序员一定要学会问问问。

  我当时用的是这种方式

     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" id="vp" />
    <script type="text/javascript">
    // 把尺寸放大N倍(N是window.devicePixelRatio)
    var wd = document.documentElement.clientWidth*window.devicePixelRatio/10;
    //物理像素*设备像素比=真实像素
    document.getElementsByTagName("html")[0].style.fontSize = wd + "px";
    // 把屏幕的倍率缩小到N分之一(N是window.devicePixelRatio)
    var scale = 1/window.devicePixelRatio;
    var mstr = 'initial-scale='+ scale +', maximum-scale='+ scale +', minimum-scale='+ scale +', user-scalable=no';
    document.getElementById("vp").content = mstr;
    </script>

只能兼容ios,android失效

在实际项目开发中,我有用到的两种比较有效的方式(兼容ios和Android)

方法一:

案例实战

了解Flexible相关的知识之后,咱们回到文章开头。我们的目标是制作一个适配各终端的H5页面。别的不多说,动手才能丰衣足食。

创建HTML模板

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta content="yes" name="apple-mobile-web-app-capable">

meta content="yes" name="apple-touch-fullscreen">

<meta content="telephone=no,email=no" name="format-detection">

<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>

<title>再来一波</title>

</head>

<body><!-- 页面结构写在这里 --></body>

</html>

正如前面所介绍的一样,首先加载了Flexible所需

这个时候可以根据设计的图需求,在HTML文档的<body></body>中添加对应的HTML结构

这仅是一个示例文档,大家可以根据自己风格写模板

为了能更好的测试页面,给其配置一点假数据:

//define data
var pageData = {
    sections:[{
        "brannerImag":"http://xxx.cdn.com/B1PNLZKXXXXXaTXXXXXXXXXXXX-750-481.jpg",
        items:[{
            "itemLink": "##",
            "imgSrc": "https://placeimg.com/350/350/people/grayscale",
            "poductName":"Carter's1年式灰色长袖连体衣包脚爬服全棉鲸鱼男婴儿童装115G093",
            "price": "299.06",
            "preferential": "满400减100",
            "activityType": "1小时内热卖5885件",
            "shopLink":"##",
            "activeName": "马上抢!"
        }
            ....
        }]
    }]
}

接下来的工作就是美化工作了。在写具体样式之前,有几个点需要先了解一下。

把视觉稿中的px转换成rem

读到这里,大家应该都知道,我们接下来要做的事情,就是如何把视觉稿中的px转换成rem。在此花点时间解释一下。

首先,目前日常工作当中,视觉设计师给到前端开发人员手中的视觉稿尺寸一般是基于640px750px以及1125px宽度为准。甚至为什么?大家应该懂的(考虑Retina屏)。

正如文章开头显示的示例设计稿,他就是一张以750px为基础设计的。那么问题来了,我们如何将设计稿中的各元素的px转换成rem

如何快速计算

在实际生产当中,如果每一次计算px转换rem,或许会觉得非常麻烦,或许直接影响大家平时的开发效率。为了能让大家更快进行转换,我们团队内的同学各施所长,为px转换rem写了各式各样的小工具。

CSSREM

CSSREM是一个CSS的px值转rem值的Sublime Text3自动完成插件。这个插件是由@正霖编写。先来看看插件的效果:

Flexible实现手淘H5页面的终端适配

有关于CSSREM如何安装、配置教程可以点击这里查阅

CSS处理器

除了使用编辑器的插件之外,还可以使用CSS的处理器来帮助大家处理。比如说Sass、LESS以及PostCSS这样的处理器。我们简单来看两个示例。

Sass

使用Sass的同学,可以使用Sass的函数、混合宏这些功能来实现:

@function px2em($px, $base-font-size: 16px) {
    @if (unitless($px)) {
        @warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
        @return px2em($px + 0px); // That may fail.
    } @else if (unit($px) == em) {
        @return $px;
    }
    @return ($px / $base-font-size) * 1em;
}

除了使用Sass函数外,还可以使用Sass的混合宏:

@mixin px2rem($property,$px-values,$baseline-px:16px,$support-for-ie:false){
    //Conver the baseline into rems
    $baseline-rem: $baseline-px / 1rem * 1;
    //Print the first line in pixel values
    @if $support-for-ie {
        #{$property}: $px-values;
    }
    //if there is only one (numeric) value, return the property/value line for it.
    @if type-of($px-values) == "number"{
        #{$property}: $px-values / $baseline-rem;
    }
    @else {
        //Create an empty list that we can dump values into
        $rem-values:();
        @each $value in $px-values{
            // If the value is zero or not a number, return it
            @if $value == 0 or type-of($value) != "number"{
                $rem-values: append($rem-values, $value / $baseline-rem);
            }
        }
        // Return the property and its list of converted values
        #{$property}: $rem-values;
    }
}

有关于更多的介绍,可以点击这里进行了解。

PostCSS(px2rem)

除了Sass这样的CSS处理器这外,我们团队的@颂奇同学还开发了一款npm的工具px2rem。安装好px2rem之后,可以在项目中直接使用。也可以使用PostCSS。使用PostCSS插件postcss-px2rem

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var px2rem = require('postcss-px2rem');

gulp.task('default', function() {
    var processors = [px2rem({remUnit: 75})];
    return gulp.src('./src/*.css')
        .pipe(postcss(processors))
        .pipe(gulp.dest('./dest'));
});

除了在Gulp中配置外,还可以使用其他的配置方式,详细的介绍可以点击这里进行了解。

配置完成之后,在实际使用时,你只要像下面这样使用:

.selector {
    width: 150px;
    height: 64px; /*px*/
    font-size: 28px; /*px*/
    border: 1px solid #ddd; /*no*/
}

px2rem处理之后将会变成:

.selector {
    width: 2rem;
    border: 1px solid #ddd;
}
[data-dpr="1"] .selector {
    height: 32px;
    font-size: 14px;
}
[data-dpr="2"] .selector {
    height: 64px;
    font-size: 28px;
}
[data-dpr="3"] .selector {
    height: 96px;
    font-size: 42px;
}

在整个开发中有了这些工具之后,完全不用担心px值转rem值影响开发效率。

字号不使用rem

前面大家都见证了如何使用rem来完成H5适配。那么文本又将如何处理适配。是不是也通过rem来做自动适配。

显然,我们在iPhone3G和iPhone4的Retina屏下面,希望看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本,以及,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px24px,所以我们不希望出现13px15px这样的奇葩尺寸

如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。

div {
    width: 1rem; 
    height: 0.4rem;
    font-size: 12px; // 默认写上dpr为1的fontSize
}
[data-dpr="2"] div {
    font-size: 24px;
}
[data-dpr="3"] div {
    font-size: 36px;
}

为了能更好的利于开发,在实际开发中,我们可以定制一个font-dpr()这样的Sass混合宏:

@mixin font-dpr($font-size){
    font-size: $font-size;

    [data-dpr="2"] & {
        font-size: $font-size * 2;
    }

    [data-dpr="3"] & {
        font-size: $font-size * 3;
    }
}

有了这样的混合宏之后,在开发中可以直接这样使用:

@include font-dpr(16px);

当然这只是针对于描述性的文本,比如说段落文本。但有的时候文本的字号也需要分场景的,比如在项目中有一个slogan,业务方希望这个slogan能根据不同的终端适配。针对这样的场景,完全可以使用rem给slogan做计量单位。

CSS

本来想把这个页面的用到的CSS(或SCSS)贴出来,但考虑篇幅过长,而且这么简单的页面,我想大家也能轻而易举搞定。所以就省略了。权当是给大家留的一个作业吧,感兴趣的可以试试Flexible能否帮你快速完成H5页面终端适配。

方法二:
使用微信的官方框架WeUI

用代码来征服你吧,来感受它的强大之处



  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" charset="utf-8">
  5. <title></title>
  6. <link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/1.1.2/weui.min.css">
  7. <script type="text/javascript" href="https://res.wx.qq.com/open/libs/weuijs/1.1.3/weui.min.js"></script>
  8. </head>
  9. <body>
  10. <div class="weui-cells__title">新增会员</div>
  11. <div class="weui-cell">
  12. <div class="weui-cell__hd"><label class="weui-label">姓名</label></div>
  13. <div class="weui-cell__bd">
  14. <input class="weui-input" type="text" placeholder="请输入姓名"/>
  15. </div>
  16. </div>
  17. <div class="weui-cell weui-cell_select weui-cell_select-after">
  18. <div class="weui-cell__hd">
  19. <label for="" class="weui-label">性别</label>
  20. </div>
  21. <div class="weui-cell__bd">
  22. <select class="weui-select" name="select2">
  23. <option value="1"></option>
  24. <option value="2"></option>
  25. </select>
  26. </div>
  27. </div>
  28. <div class="weui-cell">
  29. <div class="weui-cell__hd"><label class="weui-label">身份证号</label></div>
  30. <div class="weui-cell__bd">
  31. <input class="weui-input" type="text" placeholder="请输入身份证号"/>
  32. </div>
  33. </div>
  34. <div class="weui-cell">
  35. <div class="weui-cell__hd"><label class="weui-label">手机号</label></div>
  36. <div class="weui-cell__bd">
  37. <input class="weui-input" type="tel" placeholder="请输入手机号"/>
  38. </div>
  39. </div>
  40. <div class="weui-cell">
  41. <div class="weui-cell__hd"><label class="weui-label">地址</label></div>
  42. <div class="weui-cell__bd">
  43. <input class="weui-input" type="tel" placeholder="请输入地址"/>
  44. </div>
  45. </div>
  46. <div class="weui-btn-area">
  47. <a class="weui-btn weui-btn_primary" href="javascript:" id="showTooltips">确定</a>
  48. </div>
  49. </body>
  50. </html>
原来用好UI框架这么爽,分分钟做一个页面出来,哈哈哈。
2018-07-23 10:46:01 baozisss 阅读数 382

问题描述:

官网在ios手机上打开时,没有填充整个屏幕大小,出现滚动条,可以左右滑动。

在Android手机上则没有这个问题。

 

问题解决:

/**
 * MobileWeb 通用功能助手,包含常用的 UA 判断、页面适配、search 参数转 键值对。
 * 该 JS 应在 head 中尽可能早的引入,减少重绘。
 *
 * fixScreen 方法根据两种情况适配,该方法自动执行。
 *      1. 定宽: 对应 meta 标签写法 -- <meta name="viewport" content="width=750">
 *          该方法会提取 width 值,主动添加 scale 相关属性值。
 *          注意: 如果 meta 标签中指定了 initial-scale, 该方法将不做处理(即不执行)。
 *      2. REM: 不用写 meta 标签,该方法根据 dpr 自动生成,并在 html 标签中加上 data-dpr 和 font-size 两个属性值。
 *          该方法约束:IOS 系统最大 dpr = 3,其它系统 dpr = 1,页面每 dpr 最大宽度(即页面宽度/dpr) = 750,REM 换算比值为 16。
 *          对应 css 开发,任何弹性尺寸均使用 rem 单位,rem 默认宽度为 视觉稿宽度 / 16;
 *              scss 中 $ppr(pixel per rem) 变量写法 -- $ppr: 750px/16/1rem;
 *                      元素尺寸写法 -- html { font-size: $ppr*1rem; } body { width: 750px/$ppr; }。

 */

window.mobileUtil = (function(win, doc) {
    var UA = navigator.userAgent,
        isAndroid = /android|adr/gi.test(UA),
        isIos = /iphone|ipod|ipad/gi.test(UA) && !isAndroid, // 据说某些国产机的UA会同时包含 android iphone 字符
        isMobile = isIos;  // 粗略的判断

    return {
//      isAndroid: isAndroid,
        isIos: isIos,
        isMobile: isMobile,

        isNewsApp: /NewsApp\/[\d\.]+/gi.test(UA),
        isWeixin: /MicroMessenger/gi.test(UA),
        isQQ: /QQ\/\d/gi.test(UA),
        isYixin: /YiXin/gi.test(UA),
        isWeibo: /Weibo/gi.test(UA),
        isTXWeibo: /T(?:X|encent)MicroBlog/gi.test(UA),

        tapEvent: isMobile ? 'tap' : 'click',

        /**
         * 缩放页面
         */
        fixScreen: function() {
            var metaEl = doc.querySelector('meta[name="viewport"]'),
                metaCtt = metaEl ? metaEl.content : '',
                matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/),
                matchWidth = metaCtt.match(/width=([^,\s]+)/);

            if ( !metaEl && isMobile) { // REM
                var docEl = doc.documentElement,
                    maxwidth = docEl.dataset.mw || 750, // 每 dpr 最大页面宽度
                    dpr = isIos ? Math.min(win.devicePixelRatio, 3) : 1,
                    scale = 1 / dpr,
                    tid;

                docEl.removeAttribute('data-mw');
                docEl.dataset.dpr = dpr;
                metaEl = doc.createElement('meta');
                metaEl.name = 'viewport';
                metaEl.content = fillScale(scale);
                docEl.firstElementChild.appendChild(metaEl);

                var refreshRem = function() {
                    var width = docEl.getBoundingClientRect().width;
                    if (width / dpr > maxwidth) {
                        width = maxwidth * dpr;
                    }
                    var rem = width / 16;
                    docEl.style.fontSize = rem + 'px';
                };

                win.addEventListener('resize', function() {
                    clearTimeout(tid);
                    tid = setTimeout(refreshRem, 300);
                }, false);
                win.addEventListener('pageshow', function(e) {
                    if (e.persisted) {
                        clearTimeout(tid);
                        tid = setTimeout(refreshRem, 300);
                    }
                }, false);

                refreshRem();
            } else if ( isMobile && !matchScale && ( matchWidth && matchWidth[1] != 'device-width' ) ) { // 定宽
                var    width = parseInt(matchWidth[1]),
                    iw = win.innerWidth || width,
                    ow = win.outerWidth || iw,
                    sw = win.screen.width || iw,
                    saw = win.screen.availWidth || iw,
                    ih = win.innerHeight || width,
                    oh = win.outerHeight || ih,
                    ish = win.screen.height || ih,
                    sah = win.screen.availHeight || ih,
                    w = Math.min(iw,ow,sw,saw,ih,oh,ish,sah),
                    scale = w / width;

                if ( scale < 1 ) {
                    metaEl.content = metaCtt + ',' + fillScale(scale);
                }
            }

            function fillScale(scale) {
                return 'initial-scale=' + scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale + ',user-scalable=no';
            }
        },

        /**
         * 转href参数成键值对
         * @param href {string} 指定的href,默认为当前页href
         * @returns {object} 键值对
         */
        getSearch: function(href) {
            href = href || win.location.search;
            var data = {},reg = new RegExp( "([^?=&]+)(=([^&]*))?", "g" );
            href && href.replace(reg,function( $0, $1, $2, $3 ){
                data[ $1 ] = $3;
            });
            return data;
        }
    };
})(window, document);

// 默认直接适配页面
mobileUtil.fixScreen();

 

方案来源:

https://www.cnblogs.com/Sroot/p/5922937.html

https://blog.csdn.net/cmyh100/article/details/76999250

2016-07-21 12:14:30 jiang314 阅读数 5353

①iPhone的设计尺寸

iPhone界面尺寸:

设备 分辨率 状态栏高度 导航栏高度 标签栏(工具栏)高度
iPhone6 plus设计版 1242 × 2208 60px 132px 146px
iOS APP设计一稿支持iPhone5/iPhone6/Plus设计流程
一套完整的UI设计规范手册(IOS版)
移动端界面设计之尺寸篇(淘宝版)
图说: iPhone 6 (plus) 没那么容易搞定
设计尺寸回顾:iOS设计规范整理汇总
iPhone6 plus物理版 1080 × 1920 54px 132px 146px
iOS APP设计一稿支持iPhone5/iPhone6/Plus设计流程
一套完整的UI设计规范手册(IOS版)
移动端界面设计之尺寸篇(淘宝版)
图说: iPhone 6 (plus) 没那么容易搞定
设计尺寸回顾:iOS设计规范整理汇总
iPhone6 750 × 1334 40px 88px 98px(88px)
iPhone5s 640 × 1136 40px 88px 98px(88px)
iPhone5c 640 × 1136 40px 88px 98px(88px)
iPhone5 640 × 1136 40px 88px 98px(88px)
iPhone4s 640 × 960 40px 88px 98px(88px)
iPhone4 640 × 960 40px 88px 98px(88px)

iPhone图标尺寸:

系统 分辨率 圆角大小
iOS 6- 90px - 1024px 约为图标宽度 × 0.175
iOS 7+ 90px - 1024px 约为图标宽度 × 0.225
Asset iPhone 6 Plus (@3x) iPhone 6 and iPhone 5 (@2x) iPhone 4s (@2x) iPad and iPad mini (@2x) iPad 2 and iPad mini (@1x)
App icon
(required for all apps)
180 × 180 120 × 120 120 × 120 152 × 152 76 × 76
App icon for the App Store
(required for all apps)
1024 × 1024 1024 × 1024 1024 × 1024 1024 × 1024 1024 × 1024
Launch file or image
(required for all apps)
Use a launch file
(see Launch Images)
For iPhone 6, use a launch file
(see Launch Images)
For iPhone 5, 640 × 1136
640 × 960 1536 × 2048 (portrait)
2048 × 1536 (landscape)
768 × 1024 (portrait)
1024 × 768 (landscape)
Spotlight search results icon
(recommended)
120 × 120 80 × 80 80 × 80 80 × 80 40 × 40
Settings icon
(recommended)
87 × 87 58 × 58 58 × 58 58 × 58 29 × 29
Toolbar and navigation bar icon
(optional)
About 66 × 66 About 44 × 44 About 44 × 44 About 44 × 44 About 22 × 22
Tab bar icon
(optional)
About 75 × 75
(maximum: 144 × 96)
About 50 × 50
(maximum: 96 × 64)
About 50 × 50
(maximum: 96 × 64)
About 50 × 50
(maximum: 96 × 64)
About 25 × 25
(maximum: 48 × 32)
Default Newsstand cover icon for the App Store
(required for Newsstand apps)
At least 1024 pixels on the longest edge At least 1024 pixels on the longest edge At least 1024 pixels on the longest edge At least 1024 pixels on the longest edge At least 512 pixels on the longest edge
Web clip icon
(recommended for web apps and websites)
180 × 180 120 × 120 120 × 120 152 × 152 76 × 76


②iPad的设计尺寸

iPad界面尺寸:

设备 分辨率 状态栏高度 导航栏高度 标签栏高度
iPad6/iPad Air2 2048 × 1536 40px 88px 98px
iPad5/iPad Air/ipad mini 2 2048 × 1536 40px 88px 98px
iPad4/ipad mini 2048 × 1536 40px 88px 98px
iPad3/the new iPad 2048 × 1536 40px 88px 98px
iPad2 1024 × 768 20px 44px 49px
iPad1 1024 × 768 20px 44px 49px
iPad Mini 1024 × 768 20px 44px 49px

iPad图标尺寸:

系统 分辨率 圆角大小
iOS 6- 90px - 1024px 约为图标宽度 × 0.175
iOS 7+ 90px - 1024px 约为图标宽度 × 0.225
Asset iPhone 6 Plus (@3x) iPhone 6 and iPhone 5 (@2x) iPhone 4s (@2x) iPad and iPad mini (@2x) iPad 2 and iPad mini (@1x)
App icon
(required for all apps)
180 × 180 120 × 120 120 × 120 152 × 152 76 × 76
App icon for the App Store
(required for all apps)
1024 × 1024 1024 × 1024 1024 × 1024 1024 × 1024 1024 × 1024
Launch file or image
(required for all apps)
Use a launch file
(see Launch Images)
For iPhone 6, use a launch file
(see Launch Images)
For iPhone 5, 640 × 1136
640 × 960 1536 × 2048 (portrait)
2048 × 1536 (landscape)
768 × 1024 (portrait)
1024 × 768 (landscape)
Spotlight search results icon
(recommended)
120 × 120 80 × 80 80 × 80 80 × 80 40 × 40
Settings icon
(recommended)
87 × 87 58 × 58 58 × 58 58 × 58 29 × 29
Toolbar and navigation bar icon
(optional)
About 66 × 66 About 44 × 44 About 44 × 44 About 44 × 44 About 22 × 22
Tab bar icon
(optional)
About 75 × 75
(maximum: 144 × 96)
About 50 × 50
(maximum: 96 × 64)
About 50 × 50
(maximum: 96 × 64)
About 50 × 50
(maximum: 96 × 64)
About 25 × 25
(maximum: 48 × 32)
Default Newsstand cover icon for the App Store
(required for Newsstand apps)
At least 1024 pixels on the longest edge At least 1024 pixels on the longest edge At least 1024 pixels on the longest edge At least 1024 pixels on the longest edge At least 512 pixels on the longest edge
Web clip icon
(recommended for web apps and websites)
180 × 180 120 × 120 120 × 120 152 × 152 76 × 76


③Android的设计尺寸

屏幕尺寸

指实际的物理尺寸,为屏幕对角线的测量。
为了简单起见,Android把实际屏幕尺寸分为四个广义的大小:小,正常,大,特大。

像素(PX)

代表屏幕上一个物理的像素点代表屏幕上一个物理的像素点。

屏幕密度

为解决Android设备碎片化,引入一个概念DP,也就是密度。指在一定尺寸的物理屏幕上显示像素的数量,通常指分辨率。 为了简单起见,Android把屏幕密度分为了四个广义的大小:低(120dpi)、中(160dpi)、高(240dpi)和超高(320dpi) 像素= DP * ( DPI / 160 ) 例如,在一个240dpi的屏幕里,1DP等于1.5PX。
于设计来说,选取一个合适的尺寸作为正常大小和中等屏幕密度(尺寸的选取依据打算适配的硬件,建议参考现主流硬件分辨率),然后向下和向上 做小、大、特大和低、高、超高的尺寸与密度。

典型的设计尺寸

• 320dp:一个普通的手机屏幕(240X320,320×480,480X800)
• 480dp:一个中间平板电脑像(480×800)
• 600dp:7寸平板电脑(600x1024)
• 720dp:10寸平板电脑(720x1280,800x1280)

相关阅读

一套完整的UI设计规范手册(Android版) 移动端界面设计之尺寸篇(淘宝版)

Android安卓系统dp/sp/px换算表

名称 分辨率 比率 rate (针对320px) 比率 rate (针对640px) 比率 rate (针对750px)
idpi 240 × 320 0.75 0.375 0.32
mdpi 320 × 480 1 0.5 0.4267
hdpi 480 × 800 1.5 0.75 0.64
xhdpi 720 × 1280 2.25 1.125 1.042
xxhdpi 1080 × 1920 3.375 1.6875 1.5

主流Android手机分辨率和尺寸

设备 分辨率 尺寸 设备 分辨率 尺寸
三星Galaxy S3 4.8英寸 720 × 1280 三星Galaxy S4 5英寸 1080 × 1920
三星Galaxy S5 5.1英寸 1080 × 1920 三星Galaxy S6 4.5英寸 1200 × 1920
小米1 4英寸 480 × 854 小米1s 4英寸 480 × 854
小米2 4.3英寸 720 × 1280 小米2s 4.3英寸 720 × 1280
小米3 5英寸 1080 × 1920 小米3s(概念) 5英寸 1080 × 1920
小米4 5英寸 1080 × 1920 红米 4.7英寸 720 × 1280
红米Note 5.5英寸 720 × 1280      
OPPO Find 7 5.5英寸 1440 × 2560 OPPO Find 7 轻装版 5.5英寸 1080 × 1920
OPPO N1 mini 5英寸 720 × 1280 OPPO R3 5英寸 720 × 1280
OPPO R1S 5英寸 720 × 1280      
锤子 Smartisan T1 4.95英寸 1080 × 1920      
华为 Ascend P7 5英寸 1080 × 1920 华为 Ascend Mate7 6英寸 1080 × 1920
华为 荣耀6 5英寸 1080 × 1920 华为 Ascend Mate2 6.1英寸 720 × 1280
华为 C199 5.5英寸 720 × 1280      
HTC One (M8) 5英寸 1080 × 1920 HTC Desire 820 5.5英寸 720 × 1280
魅族 MEIZU MX4 5.36英寸 1152 × 1920 魅族 MEIZU MX3 5.1英寸 1080 × 1800

④Web的设计尺寸

Windows XP任务栏的高度30px  Windows 7任务栏的高度40px

主流浏览器的界面参数

浏览器 状态栏 菜单栏 滚动条
Chrome浏览器 22px(浮动出现) 60px 15px
火狐浏览器 状态栏高度 导航栏高度 标签栏高度
IE浏览器 状态栏高度 导航栏高度 标签栏高度
360浏览器 状态栏高度 导航栏高度 标签栏高度

系统分辨率统计

安全分辨率为1024 × 768 px  可建议大分辨率为1280 × 800 px

综合分辨率及浏览器下的统计数据

网页宽度与首屏高度

安全宽度1002 px  可建议较大宽度1258 px

Window XP首屏大小580 px  Window 7 首屏大小710 px



2016-10-12 17:32:11 azhenplus 阅读数 1226

移动端的适配真是一件让人头疼的事情,本小白一直在摸索前进,因为最近在做移动端的H5页面,为了响应领导的号召,尽量适配各种手机抓狂,抓狂一段时间后,参考前辈经验,总结出以下3套方案。

一:固定宽度,让显示内容根据设备的大小缩放,不考虑苹果设备的高清显示。

代码如下:

<span style="font-family:Times New Roman;font-size:18px;">if(/Android (\d+\.\d+)/.test(navigator.userAgent)){   
    var version = parseFloat(RegExp.$1);  
    if(version>2.3){  
        var phoneScale = parseInt(window.screen.width)/640;  
        document.write('<meta name="viewport" content="width=640, minimum-scale = '+ phoneScale +', maximum-scale = '+ phoneScale +', target-densitydpi=device-dpi">');  
        }else{     
            document.write('<meta name="viewport" content="width=640, target-densitydpi=device-dpi">');  
            }
    }else{
    document.write('<meta name="viewport" content="width=640, user-scalable=no, target-densitydpi=device-dpi">');
    
}​</span>

这是比较常见的一种做法,简单粗暴,最大的好处就是设置元素大小的时候可以直接根据设计稿的大小进行设置,不同屏幕自动实现缩放,很多人在用,包括公司的前任前端。缺点嘛,可能就是Retina屏幕下不能高清显示,不过对于750的设计稿来说,用户体验也差不到哪里去咧。

二:rem方式

rem是CSS3的新属性,rem和em单位一样,都是一个相对单位,不同的是em是相对于元素的父元素的font-size进行计算,rem是相对于根元素html的font-size进行计算,根据这个特性可以根据设备屏幕的大小动态添加html元素的font-size大小。

 <span style="font-size:18px;">(function (doc, win) {
        var docEl = doc.documentElement,
            resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
            recalc = function () {
                var clientWidth = docEl.clientWidth;
                if (!clientWidth) return;
                if(clientWidth>=640){
                    docEl.style.fontSize = '100px';
                }else{
                    docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
                }
            };

        if (!doc.addEventListener) return;
        win.addEventListener(resizeEvt, recalc, false);
        doc.addEventListener('DOMContentLoaded', recalc, false);
    })(document, window);​</span>
三:终极版本

手淘团队开发的flexible.js,本人做了微调,对于750px的设计图,把原本的基准font-size:75px调成了100px;更便于计算。

(function(win, lib) {
    var doc=win.document;
    var docEl = doc.documentElement;
    var metaEl = doc.querySelector('meta[name="viewport"]');
    var flexibleEl = doc.querySelector('meta[name="flexible"]');
    var dpr = 0;
    var scale = 0;
    var tid;
    var flexible = lib.flexible || (lib.flexible = {});

    if (metaEl) {
        console.warn('将根据已有的meta标签来设置缩放比例');
        var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
        if (match) {
            scale = parseFloat(match[1]);
            dpr = parseInt(1 / scale);
        }
    } else if (flexibleEl) {
        var content = flexibleEl.getAttribute('content');
        if (content) {
            var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
            var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
            if (initialDpr) {
                dpr = parseFloat(initialDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
            if (maximumDpr) {
                dpr = parseFloat(maximumDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
        }
    }

    if (!dpr && !scale) {
        var isAndroid = win.navigator.appVersion.match(/android/gi);
        var isIPhone = win.navigator.appVersion.match(/iphone/gi);
        var devicePixelRatio = win.devicePixelRatio;
        if (isIPhone) {
            // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他设备下,仍旧使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
    }

    docEl.setAttribute('data-dpr', dpr);
    if (!metaEl) {
        metaEl = doc.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        if (docEl.firstElementChild) {
            docEl.firstElementChild.appendChild(metaEl);
        } else {
            var wrap = doc.createElement('div');
            wrap.appendChild(metaEl);
            doc.write(wrap.innerHTML);
        }
    }

    function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            width = 540 * dpr;
        }
<span style="white-space:pre">	</span>//<span style="font-family: Arial, Helvetica, sans-serif;"> var rem = width / 10;   原来的代码</span>
        var rem = width / 7.5;<span style="white-space:pre">		</span>//自己的改动
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }

    win.addEventListener('resize', function() {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
    }, false);
    win.addEventListener('pageshow', function(e) {
        if (e.persisted) {
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300);
        }
    }, false);

    if (doc.readyState === 'complete') {
        doc.body.style.fontSize = 12 * dpr + 'px';
    } else {
        doc.addEventListener('DOMContentLoaded', function(e) {
            doc.body.style.fontSize = 12 * dpr + 'px';
        }, false);
    }

    refreshRem();

    flexible.dpr = win.dpr = dpr;
    flexible.refreshRem = refreshRem;
    flexible.rem2px = function(d) {
        var val = parseFloat(d) * this.rem;
        if (typeof d === 'string' && d.match(/rem$/)) {
            val += 'px';
        }
        return val;
    };
    flexible.px2rem = function(d) {
        var val = parseFloat(d) / this.rem;
        if (typeof d === 'string' && d.match(/px$/)) {
            val += 'rem';
        }
        return val;
    }

})(window, window['lib'] || (window['lib'] = {}));

2018-12-06 22:20:16 AdrianAndroid 阅读数 5504

资源

完全参照 组合模式|菜鸟教程 ,但不包括IOS代码

适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。
我们通过下面的实例来演示适配器模式的使用。其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4 文件。

资源

意图: 将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要解决: 主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
何时使用:
1、系统需要使用现有的类,而此类的接口不符合系统的需要。
2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)

如何解决:继承或依赖(推荐)。
关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
应用实例:
1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。
2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。
3、在 LINUX 上运行 WINDOWS 程序。
4、JAVA 中的 jdbc。

优点:
1、可以让任何两个没有关联的类一起运行。
2、提高了类的复用。
3、增加了类的透明度。
4、灵活性好。

缺点:
1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。

实现

我们有一个 MediaPlayer 接口和一个实现了 MediaPlayer 接口的实体类 AudioPlayer。默认情况下,AudioPlayer 可以播放 mp3 格式的音频文件。
我们还有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的实体类。该类可以播放 vlc 和 mp4 格式的文件。
我们想要让 AudioPlayer 播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了 MediaPlayer 接口的适配器类 MediaAdapter,并使用 AdvancedMediaPlayer 对象来播放所需的格式。
AudioPlayer 使用适配器类 MediaAdapter 传递所需的音频类型,不需要知道能播放所需格式音频的实际类。AdapterPatternDemo,我们的演示类使用 AudioPlayer 类来播放各种格式。

Android

MediaPlayer.java

public interface MediaPlayer {
   public void play(String audioType, String fileName);
}

AdvanceMediaPlayer.java

public interface AdvancedMediaPlayer { 
   public void playVlc(String fileName);
   public void playMp4(String fileName);
}

VlcPlayer.java

public class VlcPlayer implements AdvancedMediaPlayer{
   @Override
   public void playVlc(String fileName) {
      System.out.println("Playing vlc file. Name: "+ fileName);      
   }
 
   @Override
   public void playMp4(String fileName) {
      //什么也不做
   }
}

Mp4Player.java

public class Mp4Player implements AdvancedMediaPlayer{
 
   @Override
   public void playVlc(String fileName) {
      //什么也不做
   }
 
   @Override
   public void playMp4(String fileName) {
      System.out.println("Playing mp4 file. Name: "+ fileName);      
   }
}

MediaAdapter.java

public class MediaAdapter implements MediaPlayer {
 
   AdvancedMediaPlayer advancedMusicPlayer;
 
   public MediaAdapter(String audioType){
      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();       
      } else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }  
   }
 
   @Override
   public void play(String audioType, String fileName) {
      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}

AudioPlayer.java

public class AudioPlayer implements MediaPlayer {
   MediaAdapter mediaAdapter; 
 
   @Override
   public void play(String audioType, String fileName) {    
 
      //播放 mp3 音乐文件的内置支持
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: "+ fileName);         
      } 
      //mediaAdapter 提供了播放其他文件格式的支持
      else if(audioType.equalsIgnoreCase("vlc") 
         || audioType.equalsIgnoreCase("mp4")){
         mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }
      else{
         System.out.println("Invalid media. "+
            audioType + " format not supported");
      }
   }   
}

AdapterPatternDemo.java

public class AdapterPatternDemo {
   public static void main(String[] args) {
      AudioPlayer audioPlayer = new AudioPlayer();
 
      audioPlayer.play("mp3", "beyond the horizon.mp3");
      audioPlayer.play("mp4", "alone.mp4");
      audioPlayer.play("vlc", "far far away.vlc");
      audioPlayer.play("avi", "mind me.avi");
   }
}

结果

Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported

IOS

AdvancedMediaPlayer.h

@protocol AdvancedMediaPlayer <NSObject>
-(void) playVlc:(NSString*) fileName;
-(void) playMp4:(NSString*) fileName;
@end

MediaPlayer.h

@protocol MediaPlayer <NSObject>
-(void)play:(NSString*)audioType fileName:(NSString*)fileName;
@end

VlcPlayer.h

#import <Foundation/Foundation.h>
#import "AdvancedMediaPlayer.h"

@interface VlcPlayer : NSObject <AdvancedMediaPlayer>
-(void) playVlc:(NSString*) fileName;
-(void) playMp4:(NSString*) fileName;
@end

VlcPlayer.m

#import "VlcPlayer.h"
#import "AdvancedMediaPlayer.h"
@interface VlcPlayer () 
@end
@implementation VlcPlayer
- (void)playMp4:(NSString *)fileName {
    //什么也不做
}
- (void)playVlc:(NSString *)fileName {
    NSLog(@"Playing vlc file. Name: %@", fileName);
}
@end

Mp4Player.h

#import <Foundation/Foundation.h>
#import "AdvancedMediaPlayer.h"

@interface Mp4Player : NSObject <AdvancedMediaPlayer>
-(void) playVlc:(NSString*) fileName;
-(void) playMp4:(NSString*) fileName;
@end

Mp4Player.m

#import "Mp4Player.h"
#import "AdvancedMediaPlayer.h"
@interface Mp4Player () 
@end
@implementation Mp4Player
- (void)playMp4:(NSString *)fileName {
    NSLog(@"Playing mp4 file. Name:%@", fileName);
}
- (void)playVlc:(NSString *)fileName {
    //什么也不做
}
@end

MediaAdapter.h


#import <Foundation/Foundation.h>
#import "MediaPlayer.h"

@interface MediaAdapter : NSObject <MediaPlayer>
-(instancetype)initWithAudioType:(NSString*)aduioType;
-(void)play:(NSString*)audioType fileName:(NSString*)fileName;
@end

MediaAdapter.m

#import "MediaAdapter.h"
#import "MediaPlayer.h"
#import "VlcPlayer.h"
#import "Mp4Player.h"
#import "AdvancedMediaPlayer.h"

@interface MediaAdapter()
@property (nonatomic, strong) id <AdvancedMediaPlayer> advancedMusicePlayer;
@end
@implementation MediaAdapter

- (instancetype)initWithAudioType:(NSString *)aduioType{
    self = [super init];
    if(self) {
        if([aduioType isEqualToString:@"vlc"]){
            self.advancedMusicePlayer =  [[VlcPlayer alloc]init];
        } else if([aduioType isEqualToString:@"mp4"]) {
            self.advancedMusicePlayer = [[Mp4Player alloc] init];
        }
    }
    return self;
}

- (void)play:(NSString *)audioType fileName:(NSString *)fileName {
    if([audioType isEqualToString:@"vlc"]) {
        [self.advancedMusicePlayer playVlc:fileName];
    } else if([audioType isEqualToString:@"mp4"]) {
        [self.advancedMusicePlayer playMp4:fileName];
    }
}

@end

AudioPlayer.h


#import <Foundation/Foundation.h>
#import "MediaPlayer.h"
@interface AudioPlayer : NSObject <MediaPlayer>
- (void)play:(NSString *)audioType fileName:(NSString *)fileName;
@end

AudioPlayer.m

#import "AudioPlayer.h"
#import "MediaAdapter.h"
@interface AudioPlayer()
@property (nonatomic, strong) MediaAdapter *mediaAdapter;
@end
@implementation AudioPlayer

- (void)play:(NSString *)audioType fileName:(NSString *)fileName {
    //播放mp3音乐文件的内置支持
    if([audioType isEqualToString:@"mp3"]) {
        NSLog(@"Playing mp3 file. Name: %@", fileName);
    }
    //mediaPlayer提供了播放其他文件格式的支持
    else if([audioType isEqualToString:@"vlc"] || [audioType isEqualToString:@"mp4"]) {
        self.mediaAdapter = [[MediaAdapter alloc]initWithAudioType:audioType];
        [self.mediaAdapter play:audioType fileName:fileName];
    }
    else {
        NSLog(@"Invalid media. %@ format not supported.", audioType);
    }
}

@end

结果

Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name:alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported.

IOS屏幕适配

阅读数 352

没有更多推荐了,返回首页