首页

调试移动端网页工具Weinre使用整理

seo达人

一、Weinre 说明



Weinre的本意是Web Inspector Remote,它是一种远程调试工具。功能与Firebug、Webkit inspector类似,可以帮助我们即时更改页面元素、样式,调试JS等。



使用Weinre工具,Weinre的本意是Web Inspector Remote,它是一种远程调试工具:



1.它可以将远程的页面经过代理在PC上调试页面元素、样式,JS。



2.可以监听页面内部的Ajax请求等。



3.可以监听页面加载成功时候的Console控制台输出



官网首页:http://people.apache.org/~pmuellr/weinre/docs/latest/



Weinre的原理







三个端的含义:客户端(client):本地的WebInspector,远程调试客户端。服务端(agent):本地的HTTPServer,为目标页面与客户端建立通信。目标页面(target):被调试的页面,页面已嵌入weinre的远程js。



调试过程:



客户端将指令(请求DOM、执行js)post到代理服务端,目标页面定时(大概5s)从服务端get指令,然后将结果post回服务端,最终客户端定时从服务端get结果。



PS:由于Weinre的客户端是基于Web Inspector开发,而Web Inspector只兼容WebKit核心的浏览器,所以只能在Chrome/Safari浏览器打开Weinre客户端进行调试。





二、Weinre安装和使用



1.weinre是基于NodeJs,因此首先要安装NodeJs,然后使用npm命令安装weinre



npm -g install weinre

2.运行,启动weinre服务器,默认端口8080



node.exe node_modules\weinre\weinre --boundHost -all-

node.exe node_modules\weinre\weinre --boundHost  192.168.1.125 

在windows下,系统防火墙可能会弹出是否允许其访问网络的提示,点击充许即可。

3.从浏览器访问,http://localhost:8080,或者,http://192.168.1.125:8080,显示如下表示启动服务器监视成功











三、Weinre需要监听调试的Web页面配置处理



1.在所有页面引入js文件



2.特别说明,当前js文件的域名需要指定为本机的IP地址,因为在手机模拟器中无法访问电脑‘localhost’



















更多:



cordova-plugin-whitelist 协议白名单配置整理 



VS Code插件安装位置



Visual Studio Code插件之Atom One Dark Syntax Theme



相关参考文章:



http://blog.csdn.net/freshlover/article/details/42640253



http://www.cnblogs.com/diva/p/3995674.html

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

豆瓣API实践项目-前言-0

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

这是一个 app从获取获取数据 用于显示的经典实践项目,数据来源于 豆瓣官方公开的api接口:https://developers.douban.com/wiki/?title=movie_v2



先上图:

      

   





项目使用了如下第三方library:

下拉刷新:Android-PullToRefresh

网络数据加载:android-async-http

图片加载:universal-image-loader



后面的博客,会把项目的制作流程发出来

豆瓣API实践项目-前言-0(可下载源码): http://blog.csdn.net/mario_faker/article/details/79618210

豆瓣API实践项目-数据api接口-1:http://blog.csdn.net/mario_faker/article/details/79618235

豆瓣API实践项目-搭建项目基本框架-2:http://blog.csdn.net/mario_faker/article/details/79618245

豆瓣API实践项目-导入第三方library-3:http://blog.csdn.net/mario_faker/article/details/79618261

豆瓣API实践项目-单页细讲4: http://blog.csdn.net/mario_faker/article/details/79618272

豆瓣API实践项目-apk打包:http://blog.csdn.net/mario_faker/article/details/79618291





项目源代码下载地址:

http://download.csdn.net/download/mario_faker/10253201

或github:https://github.com/MarioFaker/DBMovie

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

做人就象是一家客栈

蓝蓝设计的小编

作者:鲁米

做人就象是一家客栈

每个早晨,都是一位新来的客人

喜悦、沮丧、卑鄙

一瞬的觉悟来临

就像一个意外的访客

欢迎和招待每一位客人!

即使他们是一群悲伤之徒

来扫荡你的客房

将家具一扫而光

但你要款待每一位宾客

他或许会为你打扫

并带来新的喜悦

如果是阴暗的思想、 羞耻和怨恨

你也要在门口笑脸相迎

邀请他们进来

无论谁来,都要感激

因为每一位都是

由世外派来

指引你的向导

Android5.0以后,materialDesign风格的加阴影和裁剪效果

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

5.0以后,materialDesign风格,出现了立体这种概念,高光,阴影,也就是Z轴,凸显层次;同时,裁剪view也变得方便简单了很多。
1,先说说阴影的实现。
方案1:在xml中设置 
xml中设置有两个方式,android:elevation="2dp" 
android:translationZ="2dp"这两句代码是可以同时并存的,而且是叠加的效果;当然只使用其中一个属性进行z轴的阴影设置也是OK的。

方案2:在代码中设置 
(下面说这个实现方式,其实就是轮廓的实现)

设置阴影,有一个需要注意的地方:
①:view的大小要比它的父布局小,才会有阴影效果,如果相同大小,是看不到阴影效果的; 
②:给图片设置阴影的时候,如果这种图片的background属性是shape,那直接通过xml设置阴影是OK的,但是,如果是一张png或者其他格式的图片,直接通过xml设置android:elevation="2dp" 
android:translationZ="2dp"阴影是看不到效果的,得通过其他代码设置才行。。。**

2,view的轮廓,轮廓其实也是阴影
默认情况下,所有的view都是矩形的,虽然可以给view设置背景圆形的图片,即可以在界面显示出圆形的内容,但是view的大小实际上依然是矩形,并且设置的图片实际上也是矩形的,只是圆形以外的区域是透明色。 
如果根据view大小来生成对应的阴影,就会出现很奇怪的效果,(一个看起来圆形的view展示出的确实一个矩形的阴影)我了解决这个问题,view增加了一个新的描述来指明内容显示的形状,这就是 轮廓

轮廓的实现
①通过shape设置的背景,view会自动根据shape的形状进行轮廓判定,
②通过color设置的背景,view默认其轮廓和view的大小一样。
③但是通过图片进行背景设置,view则无法获知轮廓的形状,这个时候就需要手动进行指定了。
1
2
3
一:在xml中可以通过android:outlineProvider来指定轮廓的判定方式: 
1,none即使设置了Z属性,也不会显示阴影 
2,background会按照背景来设置阴影形状 
3,bounds会按照view的大小来描绘阴影

**对于①和②这种情况,也是可以通过设置`android:outlineProvider`
来改变阴影的形状以及轮廓外观的。**

对于③这种背景是一张png或者其他格式的图片的情况,
`android:outlineProvider=“background”`
是没有效果的,属性设置成`android:outlineProvider=bounds`
虽然也是有效果的,但是阴影轮廓是一个方形的轮廓,
并不是我们想要的效果了。

不设置`android:outlineProvider`属性就更没有效果了。
1
2
3
4
5
6
7
8
9
10
对于这种使用了png图片作为背景的view加阴影轮廓的时候情况解决办法也非常简单,解决办法就是:
就通过Java代码设置,也就是说,一个圆形的png图(我们知道,看起来是圆形的,
但是它其实还是方形的图片,只是圆形之外的区域是透明不可见的),
 通过Java代码设置轮廓,就会显示出圆形的阴影轮廓了。
1
2
3
具体实现,继续看: 
二:在代码中,课通过setOutlineProvider来指定一个view的轮廓。 
对于③这种情况在代码中设置轮廓才会有效果。

TextView textView= findViewById(R.id.tv);
ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
         //x,y轴表示位置,后两个参数表示长,宽 
               outline.setOval(0,0,textView.getWidth(),textView.getHeight());
            }
        };
textView.setOutlineProvider(viewOutlineProvider);
1
2
3
4
5
6
7
8
9
强调:
如果采用圆形图片作为背景,即使在xml布局中指定android:outlineProvider=“background”,也不会显示阴影,设置为android:outlineProvider=bounds,虽然也有效果,但是效果很差,所以一般都是通过代码来指定轮廓显示。

1,一个shape圆形作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:


2,一个圆形png作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:


3,一个png作为背景,设置阴影,通过代码设置的效果:


3,view的裁剪
裁剪,默认的ImageView是矩形的,很多时候,需要的是圆角的ImageView或者圆形的ImageView,这就需要裁剪view了。

实现,裁剪圆形:

final TextView textView= findViewById(R.id.tv);

ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //设置圆形oval
                outline.setOval(0,0,textView.getWidth(),textView.getHeight());
            }
        };
//设置裁剪
textView.setClipToOutline(true);
1
2
3
4
5
6
7
8
9
10
11
实现,裁剪圆角矩形:

final TextView textView= findViewById(R.id.tv);

ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //设置圆角矩形
               outline.setRoundRect(0,0,view.getWidth(),view.getHeight(),25);
            }
        };
textView.setOutlineProvider(viewOutlineProvider);
//设置裁剪
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

TabLayout 全面总结

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

一、简介

TabLayout提供了一个水平布局用于展示tabs,继承自HorizontalScrollView。一般与Viewpager结合使用实现页面和标签联动的效果,是时下APP中非常常用的一个控件



二、基本用法

  1. 添加design依赖

    compile 'com.android.support:design:25.3.1'

    1
  2. xml引用
  3. xml中添加tab

    <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab1"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab2"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab3"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab4"/>

    </android.support.design.widget.TabLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21
  4. 代码中添加tab

    <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">

    </android.support.design.widget.TabLayout>

    1

    2

    3

    4

    5

    // tablayout,Tab是TabLayout的内部类,且Tab的构造方法是包访问权限

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText("Tab1"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab2"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab3"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab4"));

    1

    2

    3

    4

    5

    6





    三、属性详解

    <declare-styleable name="TabLayout">

        <!--指示器颜色-->

        <attr name="tabIndicatorColor" format="color"/>

        <!--指示器高度-->

        <attr name="tabIndicatorHeight" format="dimension"/>

        <!--tabs距TabLayout开始位置的偏移量,但app:tabMode="scrollable"才生效-->

        <attr name="tabContentStart" format="dimension"/>

        <!--仅是Tab背景,设置TabLayout背景用android:background-->

        <attr name="tabBackground" format="reference"/>

        <!--默认fixed,所有Tab只能在屏幕内显示,超出会被挤压;scrollable,tab数量多会超出屏幕,可滑动-->

        <attr name="tabMode">

            <enum name="scrollable" value="0"/>

            <enum name="fixed" value="1"/>

        </attr>

        <!--默认fill,tab填满TabLayout,但tabMode=“fixed”才生效;center,tabs位于TabLayout的中间-->

        <attr name="tabGravity">

            <enum name="fill" value="0"/>

            <enum name="center" value="1"/>

        </attr>

        <!--Tab的最小宽度-->

        <attr name="tabMinWidth" format="dimension"/>

        <!--Tab的最大宽度-->

        <attr name="tabMaxWidth" format="dimension"/>

        <!--Tab文本设置样式-->

        <attr name="tabTextAppearance" format="reference"/>

        <!--Tab未选中字体颜色-->

        <attr name="tabTextColor" format="color"/>

        <!--Tab选中字体颜色-->

        <attr name="tabSelectedTextColor" format="color"/>

        <!--Tab内填充相关-->

        <attr name="tabPaddingStart" format="dimension"/>

        <attr name="tabPaddingTop" format="dimension"/>

        <attr name="tabPaddingEnd" format="dimension"/>

        <attr name="tabPaddingBottom" format="dimension"/>

        <attr name="tabPadding" format="dimension"/>

    </declare-styleable>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    使用示例



     <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:tabIndicatorColor="@color/colorPrimaryDark"

        app:tabIndicatorHeight="2dp"

        app:tabContentStart="50dp"

        app:tabBackground="@color/colorAccent"

        app:tabMode="scrollable"

        app:tabGravity="fill"

        app:tabTextAppearance="@style/MyTabTextAppearance"

        app:tabTextColor="@android:color/black"

        app:tabSelectedTextColor="@android:color/white"/>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    <style name="MyTabTextAppearance" parent="TextAppearance.Design.Tab">

        <item name="textAllCaps">false</item>

        <item name="android:textSize">18sp</item>

    </style>

    1

    2

    3

    4





    四、图文混排,Tab中添加图片
  5. 通过SpannableString设置图片

    @NonNull

    private SpannableString setImageSpan(String string,int drawableId) {

        SpannableString ss = new SpannableString("  "+string);

        Drawable drawable = ContextCompat.getDrawable(this, drawableId);

        drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());

        ImageSpan imageSpan = new ImageSpan(drawable);

        ss.setSpan(imageSpan,0,1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

        return ss;

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText(setImageSpan("Tab1",R.drawable.ic_home)));

    tabLayout.addTab(tabLayout.newTab().setText(setImageSpan("Tab2",R.drawable.ic_info)));

    ……

    1

    2

    3

    4





    我们会发现个问题,通过ImageSpan设置的图片和文字没有对齐,先百度到一个可用方法解决:重写ImageSpan的draw()方法



    package com.strivestay.tablayoutdemo;



    import android.graphics.Bitmap;

    import android.graphics.Canvas;

    import android.graphics.Paint;

    import android.graphics.drawable.Drawable;

    import android.support.annotation.NonNull;

    import android.text.style.ImageSpan;



    public class CenterImageSpan extends ImageSpan {

        public CenterImageSpan(Drawable drawable) {

            super(drawable);



        }



        public CenterImageSpan(Bitmap b) {

            super(b);

        }



        @Override

        public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,

                         @NonNull Paint paint) {



            Drawable b = getDrawable();

            Paint.FontMetricsInt fm = paint.getFontMetricsInt();

            int transY = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2;//计算y方向的位移

            canvas.save();

            canvas.translate(x, transY);//绘制图片位移一段距离

            b.draw(canvas);

            canvas.restore();

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    将上面的ImageSpan替换为现在的CenterImageSpan,即可实现图文混排时对齐






  6. 通过Tab.setCustomView()设置图片
  7. 自定义view布局

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:orientation="vertical"

        android:gravity="center">

        <ImageView

            android:id="@+id/iv"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:src="@drawable/ic_home"/>

        <TextView

            android:id="@+id/tv"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_margin="2dp"

            android:textSize="16sp"

            android:text="首页"/>

    </LinearLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20
  8. 代码设置

     TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_home,"首页")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_info,"资讯")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_live,"直播")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_me,"我")));

    1

    2

    3

    4

    5

     private View setCustomView(int drawableId,String tabText) {

        View view = View.inflate(this, R.layout.item_tab, null);

        ImageView iv = (ImageView) view.findViewById(R.id.iv);

        TextView tv = (TextView) view.findViewById(R.id.tv);

        iv.setImageResource(drawableId);

        tv.setText(tabText);

        return view;

    }

    1

    2

    3

    4

    5

    6

    7

    8





    五、TabLayout与Viewpager联动
  9. xml设置TabLayout和Viewpager

    第一种:TabLayout放置在Viewpager的上方,放在AppbarLayout中会有阴影效果



    <?xml version="1.0" encoding="utf-8"?>

    <android.support.design.widget.CoordinatorLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto"

        xmlns:tools="http://schemas.android.com/tools"

        android:id="@+id/main_content"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:fitsSystemWindows="true"

        tools:context="com.strivestay.tablayoutdemo.MainActivity">



        <android.support.design.widget.AppBarLayout

            android:id="@+id/appbar"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:paddingTop="@dimen/appbar_padding_top"

            android:theme="@style/AppTheme.AppBarOverlay">



            <android.support.v7.widget.Toolbar

                android:id="@+id/toolbar"

                android:layout_width="match_parent"

                android:layout_height="?attr/actionBarSize"

                android:background="?attr/colorPrimary"

                app:layout_scrollFlags="scroll|enterAlways"

                app:popupTheme="@style/AppTheme.PopupOverlay">



            </android.support.v7.widget.Toolbar>



            <android.support.design.widget.TabLayout

                android:id="@+id/tab_layout"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                app:tabIndicatorColor="@color/colorAccent"

                app:tabIndicatorHeight="2dp"

                app:tabBackground="@android:color/white"

                app:tabTextAppearance="@style/MyTabTextAppearance"

                app:tabTextColor="@android:color/black"

                app:tabSelectedTextColor="@android:color/holo_blue_light">

            </android.support.design.widget.TabLayout>



        </android.support.design.widget.AppBarLayout>



        <android.support.v4.view.ViewPager

            android:id="@+id/container"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>



        <android.support.design.widget.FloatingActionButton

            android:id="@+id/fab"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="end|bottom"

            android:layout_margin="@dimen/fab_margin"

            app:srcCompat="@android:drawable/ic_dialog_email"/>



    </android.support.design.widget.CoordinatorLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58





    第二种:TabLayout直接放在Viewpager,无阴影



    <android.support.v4.view.ViewPager

        android:id="@+id/container"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.design.widget.TabLayout

            android:id="@+id/tab_layout"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            app:tabIndicatorColor="@color/colorAccent"

            app:tabIndicatorHeight="2dp"

            app:tabBackground="@android:color/white"

            app:tabTextAppearance="@style/MyTabTextAppearance"

            app:tabTextColor="@android:color/black"

            app:tabSelectedTextColor="@android:color/holo_blue_light">

        </android.support.design.widget.TabLayout>

    </android.support.v4.view.ViewPager>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17




  10. 为Viewpager创建适配器

    /

      fragment

     
    /

    public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SECTION = "section";



        public PlaceholderFragment() {

        }



        public static PlaceholderFragment newInstance(String section) {

            PlaceholderFragment fragment = new PlaceholderFragment();

            Bundle args = new Bundle();

            args.putString(ARG_SECTION, section);

            fragment.setArguments(args);

            return fragment;

        }



        @Override

        public View onCreateView(LayoutInflater inflater, ViewGroup container,

                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            TextView textView = (TextView) rootView.findViewById(R.id.section_label);

            textView.setText(getArguments().getString(ARG_SECTION));

            return rootView;

        }

    }



    /


      pagerAdapter

     
    /

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        String[] tabs = {"首页","资讯","直播","我"};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

            return tabs[position];

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    主要是重写getPageTitle()方法


  11. 代码设置 TabLayout和Viewpager绑定

     // tablayout

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);



    // vp

    mViewPager = (ViewPager) findViewById(R.id.container);

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    mViewPager.setAdapter(mSectionsPagerAdapter);



    // 绑定,要在viewpager设置完数据后,调用此方法,否则不显示 tabs文本

    tabLayout.setupWithViewPager(mViewPager);

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    调用setupWithViewPager()方法,则使用TabLayout.addtab()方法无效,TabLayout会清除之前添加的所有tabs,并将根据Viewpager的页数添加Tab,Tab标题为对应页通过getPageTitle()返回的文本






  12. 图文混排
  13. 同上,使用SpannableString

    修改Adapter如下:



    /*

     
    pagerAdapter

     */

    public class SectionsPagerAdapter extends FragmentPagerAdapter {



        String[] tabs = {"首页","资讯","直播","我"};

        int[] imgs = {R.drawable.ic_home,R.drawable.ic_info,R.drawable.ic_live,R.drawable.ic_me};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

    //            return tabs[position];

            return setImageSpan(tabs[position],imgs[position]);

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    setImageSpan()方法同上






  14. 同上,使用Tab.setCustomView()

    修改pagerAdapter如下:



    /

      pagerAdapter

     
    /

    public class SectionsPagerAdapter extends FragmentPagerAdapter {



        String[] tabs = {"首页","资讯","直播","我"};

        int[] imgs = {R.drawable.ic_home,R.drawable.ic_info,R.drawable.ic_live,R.drawable.ic_me};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

    //            return tabs[position];

    //            return setImageSpan(tabs[position],imgs[position]);

            return null;

        }



        /


          设置自定义view

         
    @param position

          @return

         
    /

        public View setCustomView(int position) {

            View view = View.inflate(getApplicationContext(), R.layout.item_tab, null);

            ImageView iv = (ImageView) view.findViewById(R.id.iv);

            TextView tv = (TextView) view.findViewById(R.id.tv);

            iv.setImageResource(imgs[position]);

            tv.setText(tabs[position]);

            return view;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    代码修改如下:



    …………

    // 绑定,要在viewpager设置完数据后,调用此方法,否则不显示 tabs文本

    tabLayout.setupWithViewPager(mViewPager);



    // 为绑定viewpager后的TabLayout的tabs设置自定义view

    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {

        tabLayout.getTabAt(i).setCustomView(mSectionsPagerAdapter.setCustomView(i));

    }

    1

    2

    3

    4

    5

    6

    7

    8

    发现问题:我使用的仍然是上面的item_tab,但是只显示图片,不显示文字如下







    翻了翻源码,也没发现有对Tab的标题有特别的设置;后来,就感觉是不是颜色问题,给item_tab中的textview加上属性android:textColor="@android:color/black",就显示出来了







    六、FlycoTabLayout

    这是一个不错的TabLayout开源项目,效果挺好,可以了解一下。





    蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

一口吃下 iPhone设计规范

资深UI设计者

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

如果您不熟悉iPhone设计规范,请一口吃下本篇文章。伴随笔记吃下效果更佳:)

Image title

 

iPhone的历史


每次苹果发布会UI设计师可能是最睡不着觉的人啦。每次发布会苹果推出全新iPhone时,我们在iPhone平台上的APP应用程序必须跟随iPhone的尺寸、规范等特性调整设计稿。也就是说,几乎每次苹果发布会都是UI设计师加班的通知书!这不,2018年9月13日凌晨,苹果在Apple Park总部里的乔布斯剧院举行了2018苹果秋季新品发布会。这次苹果发布了全新的iPhone Xs、iPhone Xs Max,iPhone Xr三款手机。噢,不要忘记我们也不能怠慢还在服役的iPhone X、iPhone Plus、iPhone6/7/8、iPhone SE等苹果手机。作为一个移动端UI设计师,您必须对苹果所有生产过和现役的iPhone有所了解。

 

起源

谈到iPhone我们必须谈谈史蒂夫·乔布斯(Steve Jobs)。尽管乔布斯去世多年,但是他的理念仍然是现代智能手机设计的原则。乔布斯不仅重新定义了智能手机,也定义了移动端应用程序。这位被领养的犹太男孩在很早就对个人电脑产生了兴趣。在游历了印度和日本之后,他进入了大学校园。在校园里除了无线电和嬉皮士文化,他认为大学课程多半是无聊的。但他曾跑去特意选修了一门课程:字体设计。他所在大学的字体设计课是全美最著名的,在那个课堂上乔布斯学习到了网格设计、衬线体与无衬线体、字体的气质等设计知识。当然在前面讲过的具有摇滚精神的字体Helvetica也深深吸引了乔布斯。后来乔布斯选择大学肄业并在自家车库创立了苹果公司,自此“车库”也成了创业者最喜爱的地标。苹果公司的第一代个人电脑内置了非常出色的用户图形界面系统(即GUI),并且内置了Helvetica等漂亮的字体。但是这并不是乔布斯事业的终点,在经历了苹果公司的权利斗争后,成熟的乔布斯再次登上发布会的舞台,推出了真正能改变世界的产品 - iPhone。一般产品名都会用名字加上产品的类型命名,比如百事可乐、英雄钢笔等。而iPhone似乎本身就是一个类别。在那次发布会上,乔布斯指责当时的功能手机太“愚蠢”:当时的功能手机性能很差,并且屏幕很小,实体键盘占用了很大的空间。之后,他拿出了一部像外星科技的产品:iPhone。自此,苹果重新发明了手机。乔布斯如此强调用户界面和交互设计的重要性,这种理念改变了当时和现在的设计思维。乔布斯身后,移动端的格局在改变,接任乔布斯指挥棒的蒂姆·库克和首席设计官乔纳森·伊夫(Sir Jonathan Paul Ive)也陆续更新着苹果手机的产品线,延续着这些伟大的产品。

 

 Image title

年轻的乔布斯

 

初代iPhone

相关产品:iPhone(一代)、iPhone3G(二代)、iPhone3GS(三代)。

iPhone初代产品在2007年1月9日由史蒂夫·乔布斯在苹果发布会上正式发布。初代的iPhone产品的共同特点是:玻璃屏、屏幕清晰度普通、3.5英寸屏(注意:我们所说的手机尺寸都是测量屏幕的对角线得出的)。iPhone没有实体键而整体是屏幕的设计,在当时仿佛是外星科技降临一般令人惊艳。为了让大众习惯直接在手机上点图标(在此之前人机互动都是间接输入的:比如实体键盘、鼠标、触控笔等),乔布斯发布了革命性的操作系统iOS,手机的所有图标都是圆角:这样可以避免用户认为会刺到手指。所有图标和界面全部是拟物设计,这样可以更好地让用户理解哪些是可以点击操作的。按钮在手机上呈现的大小都是7mm左右,这是因为人类手指点击区域大概是7mm - 9mm。系统充分地应用了多点触控的功能,你不仅仅可以点手机里的按钮,还可以进行长按、滑动、捏等手势操作。这些用户体验和人性化的设计在当时具有划时代的意义。随后,第二代产品iPhone 3G、第三代产品iPhone3GS先后由乔布斯发布。这种能听歌、能打电话、能上网的手机真是太炸了!而且你可以在应用商店Appstore中下载第三方的应用程序,海量的第三方程序可谓是大千世界了。这块3.5英寸屏的手机截图出来后的实际分辨率是480x320px,所以如果你在当时做UI设计的话,那么做APP界面建图的尺寸就应该是480x320px。

 

Image title

 苹果初代产品 (2007)

 

iPhone 4

相关产品:iPhone 4(四代)、iPhone 4s(五代)。

iPhone 4于2010年6月8日发布。iPhone 4延续了iPhone一代的多点触摸(Multi-touch)屏界面,并首次加入视网膜屏幕、前置摄像头、陀螺仪、后置闪光灯,相机像素提高至500万。对我们设计师最重要的就是加上了视网膜屏Retina。Retina是苹果提出的标准,它的含义就是在应用场景的视距内让人无法看清单个像素。我们都知道如果你贴的够近,一般的屏幕上都会出现一格一格的像素矩阵。屏幕是由这些矩阵组成的。这种屏幕的问题就是稍微近一些我们就能看到那些网格和矩阵。如果我们希望用户得到最好的体验,自然是让用户看不到格子,那怎么办?答案就是:加大屏幕的密度。如果屏幕的密度到达一个指定的水平(当然也要取决于用户的视距,即用户与屏幕通常离多远),那么用户的眼睛就无法分辨出细小的像素颗粒了。这种屏幕就被称为Retina屏,也叫视网膜屏。这是用户体验的巨大进步,但是也是UI设计师的噩梦。原先的设计稿统统需要放大才可以在iPhone4里显示得完美:比如原来我们一个界面的尺寸是480x320px,现在因为屏幕密度增加了一倍,我们就需要设计640x960px才够用。在电脑上看这个尺寸要比手机大两倍!(当然啦,那时的电脑屏幕通常不是Retina屏)。而且3GS并没有完全被淘汰,那么如何让一个APP适配两个不同尺寸的手机呢?于是每个APP内预装了两套切图,一套480x320px尺寸,也就是一倍图(@1x);一套960x640px尺寸,也就是二倍图(@2x)。这两套图像资源的命名完全一样,只是二倍图结尾需要加上@2x标记它是高清尺寸,比如home_icon@2x.png。

Image title

 

 iPhone 4代产品 (2010)

 

逻辑像素和物理像素

逻辑像素(logic point):逻辑像素的单位是PT,它是按照内容的尺寸计算的单位。比如iPhone 4的逻辑像素是480x320pt。但是由于每个逻辑的点因为视网膜屏密度增加了一倍,即1pt=2px,那么其实iPhone 4的物理像素是960x640px。iOS开发工程师和使用Sketch和AdobeXD软件设计界面的设计师使用的单位都是PT。

 

物理像素的单位就是我们常说的pixel,简写成PX。它是我们在Photoshop和切图中使用的单位,屏幕设计中最小的单位就是1px不可再分割。使用Photoshop设计移动端界面和网站的设计师使用的单位是PX。在以下的文章中,如果您使用Photoshop设计界面,那么只需要记住所有px单位的数值和支持Photoshop的工具,如果使用Sketch或Adobe XD设计界面,那么只需要记住所有pt单位的数值和对应的工具即可。

 

 Image title

逻辑像素和实际像素计算方式不同

 

PPI

PPI(pixels per inch)指的是屏幕分辨率的单位,表示的是每英寸显示的像素密度。屏幕的PPI值越高,那么这个屏幕每英寸能容纳的像素颗粒也就越多,那这个产品的画面的细节度也就越丰富。PPI值大于300一般我们就无法用肉眼察觉出屏幕上的“马赛克”格子了。但是如果屏幕很大,那么需要呈现视网膜屏的PPI值也需要更大,所以iPhone Plus系列的PPI值比iPhone6/7/8要大。PPI在我们设计的工作中其实关系不大,但理解它对于帮助我们理解为什么iPhone4比iPhone3GS实际像素大一倍有帮助。

 Image title

PPI的计算公式

 

iPhone 5

相关产品:iPhone 5(六代)、iPhone 5s和iPhone 5c(七代)

iPhone 5于2012年9月13日正式发布。iPhone5在设计上带来了很多争议,因为iPhone5没有采用乔布斯认为人类最合适的手机尺寸3.5英寸屏,而是用了4英寸的屏幕。宽度没变而高度加长了。这样做的原因是市场上越大的手机越受欢迎。当时设计师也几近崩溃,因为又要搞适配了。原来960x640px的尺寸变为了1136x640px,但是这个变化其实不大,就是高了点儿。于是@2x高清图的设计稿就变成了640x1136px。因为iPhone4的手机看着也就是长了点儿,滑动不就完了嘛。除了闪屏这样的界面需要单独做iPhone4、iPhone5、3GS尺寸之外,其他界面仍然维持两套设计稿即可。

 

Image title

iPhone 5 (2012)

 

iPhone 6/7/8 和iPhone Plus

相关产品:iPhone6和iPhone6 Plus(八代)、iPhone 6s和iPhone 6s Plus(九代)、iPhone7和iPhone7 Plus(十代)、iPhone8和iPhone8 Plus(十一代)。

这个产品迭代周期值得大家留意,从iPhone6到iPhone8这段时间苹果新手机的物理像素都是750x1334px。而所有Plus手机的物理像素都是1242x2208px。如果按照逻辑像素来计算,那么iPhone6/7/8的逻辑像素就是375 x 667 pt(就是750x1334除以2);而iPhone Plus的逻辑像素就是414 x 736 pt(就是1242x2208除以3,因为这个屏幕太大了视距不同所以屏幕密度更高)。历史到这个时候,原来的手机全部被淘汰了。也就是说iPhone6/7/8成为了我们的设计标准,它的切图就是@2x,iPhone Plus(1242x2208)使用@3x。从此没有@1x倍图了,只存在一个假想的概念。

 Image title

iPhone 6/7/8  (自2014)

 

Image title

 

iPhone Plus (自2014)

 

 

iPhone X

相关产品:iPhone X(十一代)。

这四款手机全部是苹果的全面屏手机。全面屏并不是新概念了,因为从iPhone初代产品开始,手机业内就在构思如何把手机做成全部都是屏幕区域的技术了。但是这个技术有很多难题,比如前置摄像头和听筒怎么处理。那么苹果采用的方案是“齐刘海”,把四周处理成圆角的方式。IPhone X和后续三款全面屏我们设计师需要注意的就是齐刘海。因为需要规避摄像头和麦克风听筒,所以导航栏比其他iPhone系列产品要高;而底部Tab栏因为最下方有圆角同样比其他iPhone系列要高。而且这两个边界是不应该放置任何操作功能的。也就是说只有看的份儿。

iPhone X的物理像素是1125 x 2436 px,而逻辑像素是375 x 812 pt。也就是说如果你使用Sketch或者Adobe XD等工具设计界面的话,iPhone X的宽度和iPhone 6/7/8是相同的;只是高了一些。那么如果需要出一套iPhone X效果图只需要把头和尾巴替换成新版即可。而如果你用Photoshop设计界面的话,宽度变化还是比较大的。需要做放大处理然后单独调整那些乱了的尺寸。

 Image title

iPhone X(2017)

 

iPhone XS Max

相关产品:iPhone XS、iPhone XS Max、iPhone XR(十二代)。

这三款产品的像素分辨率听上去会比较眼晕:

iPhone XS Max:1242 x 2688 px

iPhone XS:1125 x 2436 px

iPhone XR:828 x 1792 px

但是如果我们用点的单位看就会得到:

iPhone XS Max:414 x 896 pt (iPhone Plus分辨率宽度)

iPhone XS:375x812 pt (iPhone 6/7/8分辨率宽度)

iPhone XR:414 x 896 pt (iPhone Plus分辨率宽度)

 

所以其实今年发布的iPhone都是比较友好的,如果使用矢量界面工具那么只需要调整设计稿头和尾巴即可,如果使用Photoshop的设计师需要放大缩小设计稿然后调整头和尾巴可以得到新版设计稿。而切图其实和之前没有变化,不管用什么工具设计还是得出两套切图:@2x(750x1334px)、@3x(1242x2208px)即可。

 Image title

iPhone XS Max (2018)

 

 

以iPhone6/7/8为基准设计

在开始比赛之前,由于iPhone 6、iPhone 6S、iPhone7、iPhone7S、iPhone8屏幕和分辨率都是一致的750X1334px,所以我们可以称它们为iPhone6/7/8。而iPhone 6 Plus、iPhone7 Plus、iPhone8 Plus、屏幕和分辨率都是一致的1242x2208,所以我们可以称它们为iPhone Plus。而iPhone XS、iPhone X屏幕和分辨率都是一致的1125x2436,所以我们可以称它们为iPhoneX。那这场比赛的赢家毫无疑问是价格美丽的iPhone6/7/8获胜啦。那么我们做界面设计时需要按照iPhone6/7/8为基准设计。如果使用Photoshop就建750x1334px尺寸的画布,如果是使用Sketch或Adobe XD等工具就建立375x667pt。当然如果要设计首页之类的界面,它的界面很长你可以设计一个长的设计稿,比如750x8000px。

 Image title

手机型号与像素对应图

 

Image title

 

HIG设计指南


上文说我们建立界面可以根据750x1334px或375x667pt来建立画布,但是具体状态栏的高度、导航栏的高度、tab栏的高度是多少?那些UIKit组件里的东西去哪里找呢?苹果已经为我们准备好了多个格式的规范了:

资源下载地址:https://developer.apple.com/design/resources/

 

设计方式

在iPhone6/7/8存量仍然很大的情况下,我们做设计稿仍然需要以iPhone6/7/8为尺寸来建图。从苹果官网下载好UIKit,上面有我们需要的一切元素。这些元素有PSD、Sketch以及XD版本,不管用什么设计软件均可找到对应版本。打开之后你会发现苹果已经将我们所需要的规范元素准备好了。如果你需要一些弹窗或者控件,那么就在UI Elements里找。如果需要界面的尺寸模板,就在Design Templates找。所有文件都有两份,结尾带有-iPhoneX的是为iPhone X系列设计的模板。没有标识的是为iPhone6/7/8设计的模板。

 Image title

UI Elements 文件夹中的源文件

 

Image title Design Templates中的源文件

 

状态栏和导航栏

状态栏(Status Bars)就是iPhone最上方用来显示时间、运营商信息、电池电量的那个很窄的区域。导航栏(Navigation Bars)就是状态栏之下的区域,一般来说导航栏中间是页面标题,左右是放置功能图标的区域。

在iPhone6/7/8设计中,状态栏的高度为20pt(40px)。导航栏的高度是44pt(88px)。这两个区域在iOS7代之后就进行了一体化设计。所以它们加起来的高度是64pt(128px)。

在iPhoneX设计中,状态栏的高度为40pt(132px)。导航栏的高度也是44pt(132px)。这两个区域同样要进行一体化设计。所以它们加起来的高度是84pt(264px)。这里注意一下,因为iPhone X的PPI值为458,所以并不是如iPhone6/7/8一样1pt=2px换算。

 

 Image title

iPhone6/7/8和iPhone X导航区域的差别

 

Image title

 部分优秀APP的导航区域设计

 

大标题导航栏

在的苹果设计中导航出现了一种新形式:大标题。出现这种形式就是为了减少视觉噪音,让内容更加突出。很明显大标题的设计很像报纸的版式设计,在第一眼我们就会明白页面的主题。大标题导航栏的高度一般为116pt(232px):这包括了20pt(40px)状态栏的高度,同时也能放得下34pt(68px)的大标题和辅助信息(如返回等图标)。但是注意一下,大标题并不应该像传统导航一样常驻在页面之上,因为它太占空间了。所以在滑动页面时大标题会变成正常导航栏的64pt(128px)的高度。当然如果设计稿为iPhone X那么数值需要另外换算。

 

 Image title

大标题的尺寸

导航栏图标

图标作为文字的补充,在移动端中应用非常广泛。在导航栏区域上的功能诸如搜索、添加、更多、返回等均需要用图标来表达。说明:@2x和@3x在逻辑像素单位是一样的,如果您使用如Sketch、Adobe XD等矢量工具设计,可以参照逻辑像素数值设计即可。但是如果您用Photoshop工具以iPhone6/7/8尺寸进行设计,就需按照@2x下的px单位数值设计。

 Image title

导航栏图标尺寸规范

 

标签栏 (Tab Bars)

Tab就是点击的意思,Tab栏(也叫标签栏)指的是APP底部的区域,如微信底部常驻有聊天、通讯录、发现、我的四个图标。iOS规范中Tab栏一般有五个、四个、三个图标的形式。也就是把宽度平分为五、四、三份。iPhone6/7/8设计中,标签栏的高度为49pt(98px)。Tab栏的操作是最常用的,因为手指最方便点击而且这个栏是常驻在页面之上的。所以Tab栏的图标至关重要,因为很多用户可能因为看不懂图标而找不到重要功能的入口,通常我们会在Tab栏图标之下加上11pt(22px)的注释文字,这个注释文字一般来说都是非常浅的浅灰色。

 

Image title

标签栏的尺寸

标签栏图标

我们在标签栏上的图标一般来说30pt(60px)大小左右,苹果给出了四种不同形状标签栏图标的尺寸参考供大家设计时考虑。其意义是让不同外形的图标看上去是差不多大的,保证图标的平衡。标签栏图标的选中态应该是一个彩色,来区别于非选中状态。

 Image title

真实设计中的标签栏

 

Image title

 

标签栏图标设计规范

Image title

 

标签栏图标应该尽量使用清晰地填充风格

 

 

工具栏 (ToolBars)

我们在苹果自带浏览器底部就能看到工具栏。工具栏提供了和当前任务相关的操作和按钮,在滑动时可以收起。工具栏同Tab栏一样都是位于底部,但是高度略窄,它的高度是44pt(88px)。

 

闪屏资源

由于闪屏是一张完整的静态满屏图片,而不是诸如其他页面一样是由切图和文本拼成的,所以闪屏的适配更简单粗暴:我们需要提供不同尺寸的闪屏效果。闪屏资源就是满尺寸的一张png,上端不需要状态栏里的信息,程序会在开发完毕时自动在闪屏中补上状态栏里的信息。我们需要提供的闪屏尺寸有:

 Image title

我们需要提供的闪屏尺寸 一共6张

 

安全距离

作为iPhone全面屏系列手机,齐刘海无疑是一个特征。但是全面屏给我们带来了使用上的问题:上下左右是圆角、顶部齐刘海使屏幕凹下一块。所以在带有圆角和齐刘海的红色标注区域不应该放置任何功能,仅可在上端放置状态栏,底部圆角区域留白。我们界面竖屏使用时左右临近手机边缘的区域不建议放任何操作,应留出一定的边距(Margin)。这个边距是多少呢?没有明确严格的规定,但是一般的APP会留出16pt-24pt不等的边距防止用户在屏幕边缘不好点击。不过内容展现却可以呈现在边距里。如果我们横屏使用手机时,左右同样不好点对吧?横屏同时还有令人闹心的“齐刘海”,所以同样左右需留出一定的边距来。所以我们就得到一个安全距离的矩形,内容可以完整地呈现在这个安全距离内。

 

 Image title

iPhone X系列由于全面屏上下出现不可操作区域

 

色彩

其实在iPhone上显示的色域要比我们作图时的RGB色域要广。所以在iPhone上设计怎样的颜色都可以。只要符合产品气质并且在色彩心理学理论上思考,用什么颜色是设计师的自由。官方建议的系统色彩如下:

 Image title

iPhone的系统色

 

字体

iOS中英文使用的是San Francisco (SF)字体。(下载地址:https://developer.apple.com/fonts

),中文使用的是苹方黑体。安装好以后你会发现中文苹方的字族有不少可供选择的粗细,那么我们设计界面时需要根据信息的逻辑权重分配粗细:标题应该较粗,而说明字体应该较细并且可以设计成灰色。其实字体的设计最重要的考量就是信息层级。苹果认为APP的字体信息层级有:大标题(Large Title)、标题一(Title 1)、标题二(Title 2)、标题三(Title 3)、头条(Headline)、正文(Body)、标注(Callout)、副标题(Subhead)、注解(Footnote)、注释一(Caption 1)、注释二(Caption 2)这几种。

 Image title

HIG对APP的字体建议(基于@2x)

 

注意一下,以上HIG的建议全部是针对英文SF字体而言的,中文字体需要我们灵活运用,以最终呈现效果为基准调整。在设计具体界面时我们一定要以用户的使用情景来考虑,把设计稿导入手机去思考行高与字体大小是否是可读的。10pt(20px)是手机上显示的最小字体,最大的应该是目前的大标题字体了,达到了34pt(68px)。

 

启动图标

在设计模板还没有如今这么发达时,设计师需要设计启动图标(1024x1024px)之后按照程序员的要求切出几十个不同尺寸的图标。比如,在手机中@3x情况下桌面图标尺寸为180x180px,在@2x情况下为120x120px;在应用商店图标需要使用的尺寸是1024x1024px;这个工作太烦人了,好在现在我们只需要专注在启动图标设计本身上了。在苹果给我们的这套资源中,有Template-AppIcons-iOS这个文件。打开这个文件,用我们自己设计的启动图标替换掉智能对象里的内容,你会发现所有尺寸的图标都变成了我们的图标。然后我们把背景隐藏,切出这些图标即可。图标设计建议使用AI等矢量软件,然后使用规范切出图像资源。

 

 Image title

Template-AppIcons-iOS

 

控件

控件包括:输入框、按钮、滑杆、页卡、开关等,在设计模板中已经全部列出。这里格外说明一下,为了让设计更符合整体产品品牌调性,这些控件都可以做成自定义的设计样式。但是会增加工作量和切图资源,所以一般我们在诸如设置界面这些无需太体现设计感的页面中都使用系统默认控件,而在一些品牌感需要强调的页面或产品(诸如白噪音产品、游戏等)则会使用自定义的样式。如果我们想自己设计控件,那么注意两件事:第一,点击区域基本符合44pt(88px)原则,也就是在手机上大小大概是7mm-9mm,适合手指点击。第二,要设计操作的不同状态,不要只设计一种状态。

 Image title

默认控件

 

Image title

 

自定控件和默认控件

 

控件中无处不在的44pt(88px)

之前我们介绍过,人手指点击区域为7mm - 9mm,在@2x中就是44pt(88px)。苹果的导航条、列表、工具栏都充满了44pt(88px)这个神秘数字。我们在设计时一定也要考虑到手指的点击区域。

 Image title

无处不见的44pt(88px)

 

键盘

在设计模板中您也可以找到键盘的设计。这里需要提醒的是,很多朋友做界面设计时不考虑输入时键盘会遮挡到的空间,如果考虑到键盘弹起遮挡住的内容,那么我们的一些界面中的输入框和信息可能都需要上移了。当然也不是说可能被键盘遮挡的地方不可以防止任何内容,也有一种方式就是当输入一个表单时,页面会垂直定位到当前输入的位置。

 Image title

键盘高度

 

iTunes 上传截图

在程序上传APPSTORE时我们需要提供多张APP截图,供用户了解APP的功能。很多设计师朋友不太清楚这个尺寸,这里我们需要提供1242 x 2688px和1125 x 2436px两套截图。有时我们也会在这个尺寸上做一些设计,让用户在APPSTORE打开APP介绍时获得最好的体验。

 Image title

ITunes上传用截图

 Image title


工作流程


前期调研阶段

在我们设计界面之前,我们必须做用户研究来了解产品的调性,比如用户研究手段中的用户画像、用户调研、用户使用场景分析、设计竞品分析等方法。不管工作再忙也建议大家做这些工作,他们对我们深入了解产品大有裨益。

 

原型图阶段

APP产品设计首先需要构建出原型图,之后再开始视觉设计。这个工作有些公司是由产品经理负责的,也有交互设计师负责的,还有的公司因为人手较少,也会出现由UI设计师来负责的情况。就算有产品经理或其他职能人员来完成原型图,那设计师也需要和产品经理等人员沟通需求和探讨原型图,并不是产品经理向设计师下发需求。设计师要站在视觉和交互的角度提出自己建设性的意见,而不是简单等原型图完成后照着上色而已。关于原型图的工具,我们不仅仅可以用Axure RP设计原型图,也可以使用像墨刀、Adobe XD等新工具来完成原型图。

 

 Image title

构建APP原型图(工具:Adobe XD )

 

视觉稿阶段

视觉稿阶段要根据原型图确定的内容和大体版式完成APP的界面设计。但是这里请大家注意一下:目前业界主要是以Sketch、Adobe XD、Photoshop这三个软件来完成APP的界面设计的。Sketch和Adobe XD都是以逻辑像素的单位(PT)来设计,然后导出图像的时候再进行放大两倍三倍来切图。这样做的好处是不用在设计的时候小心翼翼地使用偶数了。而Photoshop由于主要是处理图像而非矢量图形的软件,所以在设计移动端界面时如果做成一倍的话切图会变得很虚,所以要基于2倍图来进行界面设计。比如如果我们以iPhone6/7/8的界面来进行设计,那么在Sketch和Adobe XD中我们建立的画布就是375x667pt在Photoshop中则是750x1334px。

 

Image title 

视觉稿设计阶段(工具:Adobe XD)

 

Image title

 

视觉稿设计阶段(工具:Adobe Photoshop)

 

 

iPhone6/7/8尺寸

在iPhone6/7/8尺寸下,状态栏高度20pt(40px)、导航栏44pt(88px)、Tab栏49pt(98px)、导航标题字号建议17pt(34px)、导航栏图标建议22pt(44px)、Tab栏图标建议30pt(60px)、Tab栏图标注释文字11pt(22px)、左右安全距离建议12pt(24px)。字号从10pt(20px)到34pt(68px)均可,要视具体情况决定。

 

 Image title

在iPhone6/7/8尺寸下的设计尺寸

 

实时预览你的设计稿

我们在Sketch、Adobe XD、Photoshop等软件中设计界面时有一个问题:电脑上的效果总和手机上呈现的效果不同。这是由于尺寸和观察方式决定的,所以最好的方式是我们实时地查看设计稿在手机上的呈现效果。以下APP通过数据线或wifi链接电脑后,即可及时在手机中看到还没有保存的设计稿呈现在手机中的样子。

 

 Image title

Design Mirror:可实时预览Photoshop、XD等设计稿

 

Image title

 

Adobe XD:可实时预览你的XD画板

 

Image title

 Sketch Mirror:可实时预览你的Sketch画板

 

iPhoneX设计效果图

虽然程序员对于iPhoneX等全面屏手机的适配只需要设计师提供切图即可,但很多设计师比较青睐iPhone X和XR和XSM等的设计效果,也比较愿意把设计稿改成iPhoneX的设计图放到作品集或者在汇报时展示。那么我们应该怎么做呢?如果设计稿需要调整为iPhone X的显示效果,可以下载iOS 12设计源文件,把界面头和尾替换成iPhoneX专用头尾——专用头尾在刘海和圆角处做了留白。Sketch和XD都是用一倍图设计所以不涉及修改尺寸,改头尾即可。而PS比较复杂一点:需要先等比例变大整个设计稿,再把宽度改为1125宽度自适应即可。PS变大会虚还得一个一个调一下,然后再改头尾。

 

Image title

替换导航区域和Tab栏区域,即可得到iPhoneX设计效果

 

视觉规范

如果我们设计完了五六个主要界面,那么现在做什么呢?APP设计一套视觉规范是非常有必要的,有了视觉规范我们就可以把控整体的设计和语言。一般来说,一套APP应该有3-5种主题色和辅助色;5-10种不同变化的字体样式。这些如果没有落实到一套规范中,那么很容易跑偏。一套移动端应用的视觉规范应该包括:

 

主色/辅色/色彩规范: 规定APP所能使用的色彩种类;

文字颜色/大小规范: 规定APP主要使用文字的大小、颜色、应用场景等;

ICON规范: 规定APP的icon设计规范;

应用图标规范: 规定APP的应用图标使用规范;

按钮和交互态规范: 规定APP内所有按钮和交互态的样式;

间距规范: 规定APP内所有间距的尺寸。

 

 

Image title

设计规范的重要性

 

 

Image title

设计规范中的色彩规范

 

设计规范的类型可以是png或者多个页面组成的pdf文件。其他设计师打开我们制定的设计规范,可以清晰地找到当前项目适合使用的元素和字体大小、间距等。这样尽管是多人协同工作也可以保证项目设计风格的一致性。

 

切图

有了大小各异的iPhone尺寸,如果程序只有一套切图,那么一定会造成有的手机显示很差。所以我们要在程序里放置多套切图,然后让程序判断“主人”的手机是什么型号,显示不同的切图。这样才能够完美地呈现给用户最好的体验。切图的方法有很多种。Sketch和Adobe XD可以直接导出。Phtoshop不具备这个功能,但是我们可以使用cutterman、蓝湖等插件导出切图。不管是自带功能还是插件,导出切图都可以导出@2x和@3x图,而设计稿只需要iPhone6/7/8一套即可。

 

 

Image title

某项目中的切图文件

 

Adobe XD切图功能

在Adobe XD中将需要切出的元素在图层面板(Ctrl + Y)点击添加批量导出标记记录;然后点击 菜单 > 导出 > 所选画板 > 用于iOS > 导出所有画板 即可。

 

Image title

Adobe XD自带切图功能

 

使用Cutterman协助Photoshop切图

在Cutterman官网下载PS插件后,点击窗口 > 扩展功能 > Cutterman 调出面板;然后选择iOS 并高亮选中@3X和@2X;在图层面板里选中需要切图的元素,点击“导出选中图层”即可。

 

 

Image title

Photoshop中的Cutterman 插件

 

使用蓝湖切图

在蓝湖平台可以下载Sketch、Adobe XD或Photoshop对应的插件。然后在不同设计软件插件中将设计稿上传到蓝湖(PS需要用插件标记需要切出的元素),然后在蓝湖网页版点击切图按钮,选择视网膜@2x和高清视网膜@3x,再点击“下载该页全部切图”即可。

 

 

Image title

在蓝湖平台导出切图

 

切图命名规范

切图最后需要命名成规范的格式,这样方便程序员查找。切图命名的格式建议全英文,如果大家英文不好需要想办法提升一点简单的词汇量。借由上述工具切图后,需要整理切图命名,或在切图之前对图层命名亦可。以下是切图元素的中英文对照:

 Image title

切图命名对照表

 

然后我们要按照 功能_类型_名称_状态@倍数 来命名每个切图,比如我们导航条上有一个搜索图标,那么它的名称就是:

 

navi_icon_search_default@2x.png

(导航_图标_搜索_正常@2x.png)

 

iOS开发语言

作为iOS开发工程师,最重要的三个工具是:Obiective-C、Swift、UIKit框架。Obiective-C是目前最有效率的语言;而Swift开发非常。一般iOS工程师会在这两个语言中选择一种作为开发工具。UIKit是苹果系统自带的一套框架,这个框架里有设置按钮、滑竿、状态栏、电池电量、键盘等接口可供调用。所以我们看到很多第三方APP的界面中,有许多控件和苹果自带程序是一致的,这就是UIKit的功劳。

 

 

Image title

开发视角 By @alvaroreyes

 

了解开发工程师的语言和工具对我们做设计也格外有帮助,我们会知道哪些效果能做,哪些效果不能做,哪些效果能做不好做等等。我找了大家关注的九个问题请教了iOS资深开发工程师程威:

 

 

Image title

Image title

和iOS工程师沟通

 

沟通完是不是学到了不少?我们明白了iOS工程师工作的机制后再设计界面时就可以做到心中有数了。在平时工作中我们也应该多和开发小哥哥聊聊,学习一下他们实现的方式,以便我们的设计能够更好地落地。

 

标注

切图后程序员得到了什么?一大堆碎片。把这些碎片重新用OC或者Swift构建回我们设计的界面并没有想的那么简单。所以开发工程师可能会总是在思考构架层面的问题,而忽视了视觉还原。并且由于iOS的开发人员不会使用设计软件,所以很容易出现比如14pt或者28px的文字,实现后是16pt或者32px。那就乱了套了不是,那怎么办呢?我们可以通过一些标注软件把图标之间的位置、字体的高度、字体的大小和色彩进行标注,让程序员轻松省力地还原我们的设计稿。

 

蓝湖平台自动标注功能

将Sketch和Adobe XD、Photoshop的设计稿上传至蓝湖后,在蓝湖平台每个页面左侧有一个类似分享的图标,点击会获取一个网址,这个网址就是系统生成的自动标注。它会自动识别设计稿中字体大小和间距等,甚至有代码参考。

 

Image title

蓝湖自动标注工具

 

使用Px像素大厨标注

像素大厨同样提供了自动标注、手动标注两种标注方法。自动标注需要上传设计稿,手动标注需要设计师使用“尺子”来测量距离、“吸管”来吸取色号。在界面上部有单位选择,如果我们给iOS开发做标注,那么单位最好选择PT,与开发环境一致。

 

Image title

像素大厨标注工具

 

“标你妹啊”进行自动标注

国产标注在线神器。只需要登录网站后,上传设计稿可直接生成标注网址,发给程序员就可以啦。同样提供代码参考和自动标注间距尺寸等功能。

 

 

Image title

在线标注工具 - 标你妹啊

 

Markman 手动标注

Markman同样是国产标注神器。而且是我使用的第一个标注工具,选用底部工具可以进行手动标注,标注后导出png标注图即可。

 

 

Image title

Markman标注工具

 

动效

据资深iOS开发程威介绍,目前的iOS主流的动效实现方式有以下四种:第一种,设计师给到开发动效视频或gif,开发人员照着效果编写代码调用静态切图重新做一遍,这样的还原度可能会有问题,需要开发和设计师多沟通。第二种,可以使用序列帧的方式实现动画,原理是给到开发按顺序命名的png,比如1.png、2.png等,然后用代码将它们快速替换实现动画。第三种,我们也可以给到程序员avi等视频文件直接插入视频。第四种,使用Airbnb开源的Lottie(https://airbnb.design/lottie/)。具体来说是通过after effects来完成动效,然后通过BodyMovin插件导出json文件,里面记录的就是动画的细节,然后在安卓,iOS,React Native上都有一套对应的SDK,来解析这个json文件来还原成动画。这个方式的还原度很高,除了部分AE不支持外堪称完美。其实还有QuartzCode、CoreAnimator等工具,有兴趣的大家可以去尝试一下。但我认为不管使用什么方式,最优秀的动效还是要靠设计师和开发人员“真诚地交流”。


项目走查

当我们最终完成了界面设计,需要和我们的设计稿进行对照还原。除了用肉眼辨别之外,我们也可以把还原后的程序截图下来放到PS中对照,寻找问题。那么我们给程序员的反馈就是一个有截图对照和标注的文档,这个文档可以成为Buglist。

 

Image title

截图后可在软件中对比寻找问题

 

项目走查除了判断视觉还原程度,也要兼顾动效、点击状态等动态效果是否符合设计预期。如果有问题需要及时和技术反馈,反馈的方式建议是文档类型,保证有据可查。

 

 Image title


总结


我们一起来小结一下:当我们设计iOS平台的APP时,我们可以选择使用Sketch、Adobe XD、Photoshop等工具。为了切图和适配方便,设计时我们以iPhone6/7/8尺寸(750x1334px或375x667pt)为基准设计。设计过程中我们需要通过诸如Adobe XD或Mirror等工具随时在手机上预览设计效果。之后我们需要把图像资源输出成@2x视网膜屏幕和@3x高清视网膜屏幕两套图像资源,这时可以使用Cutterman或Sketch和XD自带的切图功能切图。为了保证开发工程师能够完美地还原我们的设计稿,我们需要提供标注。通过蓝湖或像素大厨、Markman、标你妹啊等工具我们可以把设计稿完美标注给到程序员,这时程序员就清晰地明白每个元素的大小和间距了。最后,我们要对完成的程序进行验收。本篇文章写于二零一八年,按照惯例,每年苹果都会举办两场发布会发布新产品。如果后面发布了新的手机,也希望大家能够理清脉络,透过现象看到本质,找出合适的设计适配方法。



参考资料

苹果开发者中心网址:

https://developer.apple.com/

苹果人机交互规范:

https://developer.apple.com/design/human-interface-guidelines/

iOS设计资源下载:

https://developer.apple.com/design/resources/

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

jQuery中的Ajax操作

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

jQuery对Ajax操作进行了封装,常用的方法包括 $.get(),$.post(),$.ajax()。 
分别对其进行介绍

$.get()
$.get()方法使用GET方式来进行异步请求。
$.get()结构
$.get(url,[. data][. callback][. type])
1
$.get()方法参数解释
参数名称 类型 说明
url String 请求的HTML页的url地址
data(可选) Object 发送至服务器的key/value数据会作为QueryString附加到请求的url中
callback(可选) Function 载入成功时回调函数(只有当Response的返回状态是success才调用该方法)自动将请求结果和状态传递给该方法
type(可选) String 服务器端返回内容的格式,包括xml、html、script、json、text和_default
示例 
json数据:data.json(后面的$.post()和$.ajax()方法都用这个数据)
{
    "name":"龙猫",
    "hobby":"睡觉",
    "friend":"加菲猫"
}

jq_get.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>

</head>
<body>
    <input type="button" value="$.get方法" id="jQget">
    <div id="content"></div>
</body>
</html>
<!-- 导入jquery.js文件 -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jQget').on('click',function(){

            /*

            参数1:url
                参数2:发送的数据 支持 直接写js对象的方式
                参数3:回调函数
                参数4:从服务端获取的 数据类型 可以不写
                注意
                    如果type 为json 
                        并且服务端返回的就是 json格式字符串
                        jq内部 会帮助我们自动转化
                        在回调函数中 获取的 实参 就是转化完成的 js对象 直接使用即可

                参数的 顺序 是更换的
                    但是 如果 把data 放到后面 会出现 无法传递数据的问题,
                    所以 不要擅自更换 严格按照 jq文档中的 顺序 进行使用
            */
            $.get('jq_get.php',{name:"jack",age:18},function(data){
                    console.log(data);

                    $('#content').html('name:'+data.name+'<br>'+'hobby:'+data.hobby+'<br>'+'friend:'+data.friend); 

            },'json');
        });

    });
</script>

jq_get.php (后面的$.post()和$.ajax()方法都用这个页面的内容,只是在html请求时分别对应的php页面)

<?php
    header('content-type:text/html;charset=utf-8');
    echo file_get_contents('datas/data.json');
?>

结果展示: 


$.post()方法
  它与$.get()方法的结构和使用方式都相同,不过它们之间仍然有以下区别:

GET请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送个Web服务器,当然,在Ajax中,这种区别对用户是不可见的。
GET方式对传输的数据有大小限制(通常不能大于2KB),而使用POST方式传递的数据量要比GET方式大得多(理论上不受限制,但是可以在服务端进行限制)。
GET方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全性问题,而POST方式相对来说就可以避免这些问题。(但是也是不安全的,所以密码之类的还是要加密的)
GET方式和POST方式传递的数据在服务器的获取方式也不相同。在PHP中,GET方式数据可以用$_GET[]获取,而POST可以用$_POST[]获取、两种方式都可以用$_REQUEST[]来获取。 
其实这完全是对这篇文章中post()和get()方法不同的总结啊!(点击查看) 
$.post()演示
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jQpost').on('click',function(){
            // 跟$.get用法及其类似
            /*
                参数1:url
                参数2:发送的数据 支持 直接写js对象的方式
                参数3:回调函数
                参数4:从服务端获取的 数据类型 可以不写,如果写为json jq内部 会帮我们进行一个 JSON.parse()的转化 
            */
             $.post('jq_post.php',{name:"kong",age:18},function(data){
                    console.log(data);
             },'json');
        });
    });
</script>

$.ajax()
$.ajax()方法是jQuery最底层的Ajax实现
其结构为
$.ajax(options)
1
该方法只有1个参数,但在这个对象里包含了$.ajax()方法所需要的请求设置以及回调函数等信息,参数以key/value的形式存在,所有参数都是可选的,只写几个常用的参数,如下:

参数名称 类型 说明
url String 请求的HTML页的url地址
type String 请求方式,默认GET。注意其他的HTTP请求方法,例如PUT和DELETE也可以使用,但仅部分浏览器支持
data Object或String 发送到服务器的数据,如果已经不是字符串,将自动转换为字符串格式。
dataType String 服务器端返回内容的格式,包括xml、html、script、json、jsonp 、jQuery
beforeSend Function 发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次Ajax请求。XMLHttpRequest对象的唯一参数。
success Function 请求成功后嗲用的回调函数,有两个参数。
(1)由服务器返回,并根据dataType参数进行处理后的数据。
(2)描述状态的字符串。
function(data,textStatus){
        //data可能是xmlDoc、jsonObj、html、text等等。
        this//调用本次Ajax请求时传递的options参数
  }
error Function 请求失败时被调用的函数,该函数有3个参数,即
XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。
Ajax事件函数如下。
function(XMLHttpRequest,textStatus,errorThrown){//通常情况下textStatus和errorThown只有其中一个包含信息
this;//调用本次Ajax请求时传递的options参数
}
示例
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jqAjax').on('click',function(){
    /*
                常见参数:
                    url:请求的地址
                    success:请求成功的回调函数
                    type:不写是get 可以指定 get,post
                    dataType:数据的类型
                    data:发数据 可以写js对象
                    beforeSend:发送之前调用的匿名函数
                        可以return false 阻止该次请求
                        验证用户的数据 是否填了
                    error:请求失败以后 会调用
            */
            $.ajax({
                url:'jq_ajax.php',
                success:function(data){
                    console.log(data);
                    $('#box').append(data.name+'<br>'+data.hobby);
                },
                type:'post',
                dataType:'json',
                data:{"name":"张信哲","skill":"情歌王子"},
                beforeSend:function(){
                    console.log('发送之前调用');
                },
                error:function(){
                    console.log('请求失败了');
                }
            });
        });

    });
</script>
--------------------- 
作者:diligentkong 
来源:CSDN 
原文:https://blog.csdn.net/diligentkong/article/details/72851443 
版权声明:本文为博主原创文章,转载请附上博文链接!
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

这4个最常见的 UI 组件,给你总结了这份使用指南

资深UI设计者

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

我们在看 App 时,有没有思考过这样的问题,同样都是提示弹窗为什么出现那么多不同的样式,亦或者同样都是让界面进行切换的导航为什么有的可以通过侧滑切换,有的却只能点击切换呢?最近在玩 App 时发现了几组这样的控件,下面就来和大家分享下我对他们的理解和选用。

目录:

  • 警告框与操作表
  • 标签栏与操作栏
  • Tabs与分段控件
  • Toast与Snackbar

一、警告框与操作表

1. 定义

警告框:是一种操作上的确认,只有当用户点击按钮后才算真的完成,才可以有其他操作,主要作用是警告或提示用户的。

警告框由三部分组成:标题、正文、按钮。有些简单的警告或提示只有正文和按钮即可。

操作表/ActionSheet:操作表通常会从屏幕底部边缘向上滑出一个面板,可提供2个以上的选择。呈现给用户的是简单、清晰、无须解释的一组操作,没有正文的描述内容(大部分)。另外重要的功能操作也会用红色文字展示。

2. 如何选用?

文字内容的重要性

文字内容的重要性:选择警示框和操作表时,要考虑的是两个弹窗文字内容对于用户的重要程度,如果内容极为重要则选用警示框,如果文字内容不重要甚至不需要描述文字我们就应该选择操作表。

案例:如下图,淘宝登录密码错误时,由于警示框更重要的是文字内容的体现,帮助用户找到问题所在,所以选用警示框。再看 QQ邮箱的垃圾箱中点击全部清空时,由于信息本身就在垃圾箱内,不需要对用户过多的文字提示,用户直接操作即可,所以最后选用操作表。

用户操作流畅性

用户操作流畅性:当我们需要让用户停止操作并必须点击当前界面的按钮时,要选择警示框,警示框对用户操作上的流畅性有着很严重的影响。如果不需要太过强硬,我们就选用只需在屏幕中任意位置点击就会消失的操作表。

数量

数量:这是最容易区分使用的方面,当弹窗中的按钮数量超过2个时我们一定选用操作表,因为警示框的按钮数量不可以超过两个。如果数量一样,可以根据上面两点择优使用。

案例:如下图,我们在得到App 中点击开通「推送通知」时,因为操作按钮只有一个,所以选择警示框。而点开微博中的更多按钮,用的则是操作表,因为操作按钮有三个。

二、标签栏与工具栏

1. 定义

标签栏:标签栏位于屏幕底部,它是悬浮在当前页面之上的,并且会一直存在,只有当用户点击跳转到二级菜单后才会消失。用户可以在不同的子任务、视图和模式中进行切换,并且切换按钮间都属于不同的内容。

当用户选中某个标签时,该标签呈现适当的高亮状态。数量也有限制,不能超过5个,如果存在5个以上的标签可以将最后的标签设计成「更多」标签。

工具栏:工具栏同样位于屏幕底部,悬浮在当前页面之上的,并且当用户不需要使用的时候,可以隐藏它。例如向上滑动界面时,工具栏会自动隐藏。工具栏的内容主要是对当前页面的相关操作按钮。

2. 如何选用?

切换状态

切换状态:当我们需要同级别界面切换时,应该选择标签栏,同时标签栏的切换通常为一级导航,工具栏的功能仅针对当前界面内容的相关操作。

案例:如下图,微信读书底部栏中是关于同级别的视图切换,所以选择标签栏,同时标签栏也常用于产品的一级导航。而 Safari浏览器底部的内容是针对当前界面的操作功能,所以使用了工具栏。

位置状态

位置状态:当底部导航始终在界面最上方时,上下滑动都不会消失,则选择标签栏;如果底部导航上滑随之消失则选择工具栏(说明:也有少数的工具栏是怎么滑动都不会消失的)。

案例:如下图,我们来看看百度的 App,当我向上滑动界面时,底部导航的位置是不会消失的,所以使用了标签栏。再看 Safari浏览器,因为上滑时底部栏会被隐藏,所以选用了工具栏。

选中状态

选中状态:当用户选中底部某一项时,如果需要高亮显示且显示的内容是不同子任务的视图,则使用标签栏;而当选择后,出现操作表等与当前界面相关的操作时,应该选择工具栏。

案例:如下图,我们还是来看百度App,当我点击底部的选项时,切换的同时,当前选中的「好看视频」需要变成选中的样式,来告知用户当前选中的是那个界面,所以使用了标签栏。再看 Safari浏览器,点击底部按钮后出现操作表且当前选中的按钮也不会变高亮,因为不会在当前切换界面,所以选择了工具栏。

三、Tabs与分段控件/Segment Control

1. 定义

Tabs:Tabs 来自 MD规范,早在 Android 2.0时代,官方的通讯录App 就使用顶部 Tab导航,可以滑动切换不同视图。Tabs 里 Tab 呈现的内容可以有很大的差别,而且数量没有限制,Tabs 不能作为表单的单选组件。

分段控件:iOS 原生控件之一,每个分段作用是互斥的,在分段控件里,所有的分段选项框在长度上要保持一致,同 iOS规范中对于分段控件的分段选项不得超过5个,每个分段选项可以是纯文字或者图片。

2. 如何运用?

来源不同

来源不同:分段控件来自 iOS规范,而 Tabs 来源于 MD规范。

案例:如图我们来看 iPhone 的日历界面点击收件箱,因为是 iOS系统配置的应用,所以界面中切换样式用的是分段控件,而反观安卓系统则用的是 Tabs切换。

内容不同

内容不同:分段控件主要起到分割和筛选同类数据,而 Tabs 则没有这样的限制,Tabs 里的每一项所呈现的内容可以有很大的差别。另外分段控件更多的是以单选功能出现在表单的使用中,而 Tab 则不能作为表单的单选组件。

案例:如下图鲨鱼记账中的图表页,支持、收入为整个界面展示项目,为了让用户查看起来更加方便,把数据分割为周、月、年的不同的数据展示,因为是同类数据切换,所以选择了分段控件。反观36氪首页的 Tabs栏,由于每个内容的差别都很大,所以使用了 Tab栏展示。

操作方式不同

操作方式不同:分段控件需要点击操作,而 Tabs 除了点击外还可以通过左右滑动切换不同视图。

案例:如下图,网易钱包App 界面中的切换控件,因为在表单中且是极为近似的数据图,不易让用户侧滑屏幕切换,需要让用户更精准的点击选择。所以使用了智能点击的分段控件,而优酷视频的切换页变化都比较明显,很容易区分,所以选择了可以侧滑屏幕切换的 Tabs。

数量

数量:分段控件数量不能超过5个,而 Tabs 没有数量限制。

案例:如下图网易云音乐中的消息界面,界面中因为分类的数量未超过五个(不是所有未超过5个的就要用分段控件,同时也要根据以上说的其他三种情况判断,这里只针对数量阐述而已),所以可以使用分段控件,而网易云音乐视频界面中因为分类数量过多且内容上有区别所以选择了 Tabs。

四、Toast与Snackbar

1. 定义

Toast:Toast 通常出现在顶部和中部,浮于页面上方,无法对其操作,出现一段时间后便会消失,并且在此期间不影响其他正常操作。

Snackbar:Snackbar 出自于安卓系统,是安卓系统的特色弹窗之一。它是由一段信息和一个按钮组成,他们会在超时或者用户在屏幕其他地方触碰后自动消失。Snackbar 可以在屏幕上滑动关闭。Snackbar 不会妨碍用户对产品的其他操作。

2. 如何选用?

操作不同

操作不同:Toast 弹窗没有任何操作键,而 Snackbar 是有操作键的。

案例:如图马蜂窝App 中给作者的文章点赞功能只需要告知用户,点赞已成功即可,不需要其他操作,所以选用 Toast弹窗。而携程中当进入酒店界面时,除了告知用户下面还有更多信息外,还想引导用户直接查看,所以选用了带操作功能的 Snackbar。

退出状态不同

退出状态不同:Toast弹窗完全是通过超时后自动消失,不存在任何操作,而 Snackbar 可以超时消失也可以用户主动上滑关闭。

案例:如下图豆瓣App 广播界面中,当我点击换一批后,换好的内容会自动刷新到最前面,所以用户不需要任何操作就可以看到内容,就可以选用无操作必须等待超时后才会消失的 Toast弹窗。

而携程App 中的酒店界面,因为更多精彩的内容在下面,并没有展示出来,为了不让用户在滑动浏览时造成视觉障碍。所以选择了 Snackbar,除了超时后自动关闭外,也可以通过滑动界面让弹窗主动关闭。

组成元素不同

组成元素不同:Toast弹窗主要是由文字和背景组成,也可以额外附加图标。而 Snackbar 除文字、背景,图标外还有操作键组成。

案例:如下图得到App 中只需要提示用即可,所以选用 Toast,组成元素选用背景+文字+图标,而小红书App 需要加入操作键,所以选择了 Snackbar。

总结

通过上面的分析,大家是不是对这八个组件有了更深的理解呢?

每个组件都有不可替代的作用,如果大家还有哪些不清楚的组件对比可以在文章下留言,之后我会选择一些整理出来再次和大家分享,感谢大家的耐心阅读。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

高手私藏的 UI 细节设计,这篇全都给你整理好了!

资深UI设计者

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

这篇文章渗透进页面中的每一个 Kit控件,深入的分析每一个控件所能带给用户的视觉以及心理感受。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档