android适配 ios

2019-07-26 11:29:55 SmallWalnutBG 阅读数 640

起因:Android和ios最新发布的全面屏手机概览

之前大部分手机屏占比是16:9,但是以上占比达到了19.5:9,所以会让布局高度不足。弹框的位置和安全域也是将要面临的问题,故做以下适配;

ios:

方法1:SafeArea()====》优点:方便;缺点:不灵活(不能自定义上下适配);

import 'package:flutter/material.dart';

void main()=> runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "适配全面屏",
      home: Container(
          decoration: BoxDecoration(
            color: Colors.blue,
          ),
          child: SafeArea(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text(
                  "上",
                  style: TextStyle(color: Colors.red, fontSize: 30),
                ),
                Text(
                  "下",
                  style: TextStyle(color: Colors.red, fontSize: 30),
                ),
              ],
            ),
          )),
    );
  }
}

方法二:MediaQuery====》优点:可控制上下适配与否(如不适配其中一项,将其置为0);缺点:相对一麻烦;

import 'package:flutter/material.dart';

void main()=> runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "适配全面屏",
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final EdgeInsets padd = MediaQuery.of(context).padding;
    // TODO: implement build
    return Container(
      padding: EdgeInsets.fromLTRB(0, padd.top, 0, padd.bottom),
        decoration: BoxDecoration(
          color: Colors.blue,
        ),
        child: SafeArea(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Text(
                "上",
                style: TextStyle(color: Colors.red, fontSize: 30),
              ),
              Text(
                "下",
                style: TextStyle(color: Colors.red, fontSize: 30),
              ),
            ],
          ),
        ));
  }
}

Android:

相对于ios的flutter代码相同,区别在于在Android的AndroidManifest文件加上高宽比配置:

<manifest...
 <application...
   <meta-data
                android:name="android.max_aspect"
                android:value="2.2"/>
  </application>
</manifest>

说明:2.2的来源是19.9/9约为2.16,我们设置这个数值是高宽比的最大值,所以你也可设为2.3等;

2017-09-23 11:47:40 tuhuolong 阅读数 853

按基准设计,出图(切图和标注图)

iOS:2x设计,出2x3x的图和标注图
android:1080p设计, 出xxhdpi、xhdpi的图和标注图
绝对长度

iOS:pt
android:dp
基准

iOS: 750p 2x (px/2)
android:1080p (px/3)
加载

iOS+android: (运行时)根据当前配置选择资源



浅谈iOS屏幕适配



2017-06-09 17:10:06 hao_pei 阅读数 480

在很多公司开发,可能公司只提供一套ios 1@,2@,3@图片。本文以苹果6为设计标准


1.首先解释下android系统下dpi

dpi是“dot per inch”的缩写,每英寸像素数。

google以160dpi为基准  设为1

对照得 ldpi是120,mdpi是160,hdpi是240,xhdpi是320  xxhdpi 480dpi

iphone 6 4.7英寸所支持  分辨率1334×750像素

我们计算它得dpi

1334²+750² 开根号 /4.7    325.6dpi  直接可以将其放入xhdpi使用。


手机尺寸比例感兴趣得可以去查,比例也几乎相同




2018-07-06 14:50:58 weixin_41809141 阅读数 2652
 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框架这么爽,分分钟做一个页面出来,哈哈哈。
2016-08-03 14:32:09 qq_24731595 阅读数 4876

前言

说实话 开发Android 到现在 第一次遇到这么毫无头绪的问题  Emoji
IOS 各种版本的Emoji
Android 想要一一对应实在是太难了
网上查阅各种资料 下面介绍几个 讲解十分详细的

连接地址:
首先是Android GitHub上的开源项目:https://github.com/rockerhieu/emojicon
这是一个Android Studio项目,并没有提供esclipe的集成方式

(ps: 图片引用GitHub上面的)

其次是一个对GitHub上项目进行 简化的版本

因为我是项目结束才写的这篇文章,其中查阅了好多文章现在想一一找回明显有点不现实。依稀记得提供这个简化版的是我们大CSDN的一个免费下载资源。

资源名称:Emoji表情TextView以及EditText
如果作者看见这篇博客可以在文章的结尾提供链接,我会及时修改我的博客

下面是看过人家的各种资料:

Unified Emoji表情for Android
http://www.cnblogs.com/stay/archive/2012/10/30/2746489.html

Emoji表情符号兼容方案
http://blog.csdn.net/qdkfriend/article/details/7576524

IOS小伙伴给我的一个IOS端的开源项目 讲解的真的是非常详细 不仅仅详细讲解了 IOS如何使用 连Android 的各种坑都有填上
必须点个赞
https://github.com/vbonluk/iOS_Emoji

看人家做的那么好是不是有点小激动,下面开始简单讲些我是怎么集成的

首先自定义EditText TextView分别用于 输入表情和显示表情 直接上重要代码

重写了EditText的onTextChange方法用于输入表情 及时转换成项目统一的表情 由于Emoji有不同的版本
@Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        EmojiHandler.addEmojis(getContext(), getText(), mEmojiconSize);
    }

EmojiHanler 是一个Emoji的帮助类
首先 他会把表情和Unicode编码建立一个SparseIntArray集合 至于为什么不用HashMap 当然是它性能更好咯

直接上代码 太多了就不全复制了

 private static final SparseIntArray sEmojisMap = new SparseIntArray(846);
 private static final SparseIntArray sSoftbanksMap = new SparseIntArray(471);

    static {
        // People
        sEmojisMap.put(0x1f604, R.drawable.emoji_1f604);
        sEmojisMap.put(0x1f603, R.drawable.emoji_1f603);
        sEmojisMap.put(0x1f600, R.drawable.emoji_1f600);
        sEmojisMap.put(0x1f60a, R.drawable.emoji_1f60a);
        sEmojisMap.put(0x263a, R.drawable.emoji_263a);
        sEmojisMap.put(0x1f609, R.drawable.emoji_1f609);
        sEmojisMap.put(0x1f60d, R.drawable.emoji_1f60d);
        sEmojisMap.put(0x1f618, R.drawable.emoji_1f618);
        sEmojisMap.put(0x1f61a, R.drawable.emoji_1f61a);
        sEmojisMap.put(0x1f617, R.drawable.emoji_1f617);
        ...

之后就是要把EditText中输入的表情转换成对应的图片 不过在转之前我们需要知道 他转的是Unicode编码 为什么防止转换问题 我们直接对EditText所有输入的内容进行Unicode编码

/**
     * 字符串转换unicode
     */
    public static String string2Unicode(String string) {

        StringBuffer unicode = new StringBuffer();

        for (int i = 0; i < string.length(); i++) {

            // 取出每一个字符
            char c = string.charAt(i);

            // 转换为unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }

        return unicode.toString();
    }

对输入的Unicode 进行筛查

public static void addEmojis(Context context, Spannable text, int emojiSize) {
        int length = text.length();
        EmojiSpan[] oldSpans = text.getSpans(0, length, EmojiSpan.class);
        for (int i = 0; i < oldSpans.length; i++) {
            text.removeSpan(oldSpans[i]);
        }

        int skip;
        for (int i = 0; i < length; i += skip) {
            skip = 0;
            int icon = 0;
            char c = text.charAt(i);
            if (isSoftBankEmoji(c)) {
                icon = getSoftbankEmojiResource(c);
                skip = icon == 0 ? 0 : 1;
            }

            if (icon == 0) {
                int unicode = Character.codePointAt(text, i);
                skip = Character.charCount(unicode);

                if (unicode > 0xff) {
                    icon = getEmojiResource(context, unicode);
                }

                if (icon == 0 && i + skip < length) {

                    int followUnicode = Character.codePointAt(text, i + skip);
                    if (followUnicode == 0x20e3) {
                        int followSkip = Character.charCount(followUnicode);
                        switch (unicode) {
                            case 0x0031:
                                icon = R.drawable.emoji_0031;
                                break;
                            case 0x0032:
                                icon = R.drawable.emoji_0032;
                                break;
                            case 0x0033:
                                icon = R.drawable.emoji_0033;
                                break;
                            case 0x0034:
                                icon = R.drawable.emoji_0034;
                                break;
                            case 0x0035:
                                icon = R.drawable.emoji_0035;
                                break;
                            case 0x0036:
                                icon = R.drawable.emoji_0036;
                                break;
                            case 0x0037:
                                icon = R.drawable.emoji_0037;
                                break;
                            case 0x0038:
                                icon = R.drawable.emoji_0038;
                                break;
                            case 0x0039:
                                icon = R.drawable.emoji_0039;
                                break;
                            case 0x0030:
                                icon = R.drawable.emoji_0030;
                                break;
                            case 0x0023:
                                icon = R.drawable.emoji_0023;
                                break;
                            default:
                                followSkip = 0;
                                break;
                        }
                        skip += followSkip;
                    } else {
                        int followSkip = Character.charCount(followUnicode);
                        switch (unicode) {
                            case 0x1f1ef:
                                icon = (followUnicode == 0x1f1f5) ? R.drawable.emoji_1f1ef_1f1f5 : 0;
                                break;
                            case 0x1f1fa:
                                icon = (followUnicode == 0x1f1f8) ? R.drawable.emoji_1f1fa_1f1f8 : 0;
                                break;
                            case 0x1f1eb:
                                icon = (followUnicode == 0x1f1f7) ? R.drawable.emoji_1f1eb_1f1f7 : 0;
                                break;
                            case 0x1f1e9:
                                icon = (followUnicode == 0x1f1ea) ? R.drawable.emoji_1f1e9_1f1ea : 0;
                                break;
                            case 0x1f1ee:
                                icon = (followUnicode == 0x1f1f9) ? R.drawable.emoji_1f1ee_1f1f9 : 0;
                                break;
                            case 0x1f1ec:
                                icon = (followUnicode == 0x1f1e7) ? R.drawable.emoji_1f1ec_1f1e7 : 0;
                                break;
                            case 0x1f1ea:
                                icon = (followUnicode == 0x1f1f8) ? R.drawable.emoji_1f1ea_1f1f8 : 0;
                                break;
                            case 0x1f1f7:
                                icon = (followUnicode == 0x1f1fa) ? R.drawable.emoji_1f1f7_1f1fa : 0;
                                break;
                            case 0x1f1e8:
                                icon = (followUnicode == 0x1f1f3) ? R.drawable.emoji_1f1e8_1f1f3 : 0;
                                break;
                            case 0x1f1f0:
                                icon = (followUnicode == 0x1f1f7) ? R.drawable.emoji_1f1f0_1f1f7 : 0;
                                break;
                            default:
                                followSkip = 0;
                                break;
                        }
                        skip += followSkip;
                    }
                }
            }

            if (icon > 0) {
                text.setSpan(new EmojiSpan(context, icon, emojiSize), i, i + skip, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }

网络上获取回来的String 转回Unicode的方法 空格是:\u20

 /**
     * unicode 转字符串
     */
    public static String unicode2String(String unicode) {

        StringBuffer string = new StringBuffer();

        String[] hex = unicode.split("\\\\u");

        for (int i = 1; i < hex.length; i++) {

            if(hex[i].equals("20")){
                string.append(" ");
            }else {
                // 转换出每一个代码点
                int data = Integer.parseInt(hex[i], 16);
                // 追加成string
                string.append((char) data);
            }

        }
        return string.toString();
    }

因为技术有限如果有更好的方式希望可以在博客下面留言 我会及时查阅。谢谢!

贴下需要用的源代码:

class EmojiSpan extends DynamicDrawableSpan {
    private final Context mContext;
    private final int mResourceId;
    private final int mSize;
    private Drawable mDrawable;

    public EmojiSpan(Context context, int resourceId, int size) {
        super();
        mContext = context;
        mResourceId = resourceId;
        mSize = size;
    }

    public Drawable getDrawable() {
        if (mDrawable == null) {
            try {
                mDrawable = mContext.getResources().getDrawable(mResourceId);
                int size = mSize;
                mDrawable.setBounds(0, 0, size, size);
            } catch (Exception e) {
                // swallow
            }
        }
        return mDrawable;
    }
}

因为项目保密的原因 具体代码 不方便分享 有需要demo的小伙伴可以留邮箱。