首页

TinyUI-TUIListView最简单的使用

seo达人

      在TinyUI简介的博客中提到其特点中包含一条,即多数大控件的使用方法和android一直,除了语言差异之外,本篇我们就介绍列表控件TUIListView最简单的使用方法。



        列表组件/控件作为目前Android/iOS的APP中最常用的控件,该控件的设计同时参考Android、windows、Qt等使用的经验进行筛选,最终选择了Android的ListView设计,其他平台的列表中使用难以程度或设计上略逊于Android,因为Android给与了开发者最大的发挥控件,你可以在列表中可以显示任何控件。



        TUIListView中的每一行每一列你可以放置任何UI组件,使用TUIListView需要配合TUIAdapter进行使用,而TinyUI和Android一样提供了内置的简单使用的TUISimpleAdapter。TUISimpleAdapter主要用于显示文本(即每一行都是只能显示文字),如果需要在列表中显示其他UI组件,则需要自定义一个Adapter,关于自定义Adapter将在后续进行详细讲解。



        本篇既然是TUIListView最简单的使用,我们就使用TUISimpleAdapter来显示文本你列表,TUISimpleAdapter最好只用于数据步发生变化的情况,因为其存放的数据使用了C++标准库的vector容器,而非使用list容器,vector容器的特点是访问速度快,但其缺点是vector的内存是连续的,因此内容发生变化可能会造成内存申请和拷贝的动作;而list容器使用的双向链表,其特点是插入数据快,但访问速度慢。



        本篇我们仍然使用上一篇中自定义的MyWindow来显示TUIListView。



使用方法/步骤

  1. 定义listView和andapter



            MyWindow中包含TUISimpleAdapter.h的头文件,并定义listView和adapter



    MyWindow.h


    ifndef MY_WINDOW_H

    define MY_WINDOW_H

    include <TUIWindow.h>

    include <TUISimpleAdapter.h>

     

     

     

    class MyWindow : public TUIWindow

    {

    public:

        MyWindow(TUIWindow* parent = nullptr);

        virtual ~MyWindow();

     

        void onShow();

        void onClose();

     

    private:

        TUIListView listView;

        TUISimpleAdapter adapter;

    };

     

    endif // !MY_WINDOW_H

     


  2. 填充数据,并把adapter设置到listView中



    MyWindow.cpp


    include "MyWindow.h"

     

     

     

    MyWindow::MyWindow(TUIWindow* parent)

        : TUIWindow(parent)

    {

        setContentView(&this->listView); // 把listView作为当前窗口的内容视图

     

     

        vector<string> data; // 使用vector<string>类型的data存放数据

     

        for (int32_t i = 0; i < 20; i++)

        {

            data.push_back(to_string(i)); // 生成0~20的数值-转换成字符串,放到data中

        }

     

        this->adapter.setData(data); // 把data设置到adapter中

     

        this->listView.setAdapter(&this->adapter); // 把adapter设置到listView,作为listView数据来源和操作对象

    }

     

    MyWindow::~MyWindow()

    {

    }

     

    void MyWindow::onShow()

    {

    }

     

    void MyWindow::onClose()

    {

    }

    到目前为止窗口显示列表控件已全部完成,接下来和上一篇一样调用MyWindow的show()方法即可显示,最终结果如下图所示:


call、apply、bind 原理实现

seo达人

目录

  1. call 的模拟实现
  2. apply 的模拟实现
  3. bind 的模拟实现
  4. 三者异同



    学习并参考于:



    JavaScript深入之call和apply的模拟实现



    JS的call,apply与bind详解,及其模拟实现





    (一)call的模拟实现

    call 用法 : MDN Function.prototype.call()



    call() 方法使用一个指定的 this 值和可选的参数列表来调用一个函数。



    call() 提供新的 this 值给当前调用的函数/方法。


  5. call 实现主要思路:

    将函数设为对象的属性



    执行该函数



    删除该函数



    另外还有考虑:



    call 函数还能给定参数执行函数

    this 参数不传,或者传null,undefined, this指向window对象

    函数是可以有返回值的
  6. 实现:

    Function.prototype.myCall = function () {

      if (typeof this !== 'function') {

        throw new TypeError('error!')

      }

      let context = arguments[0] || window   //this 参数可以传 null,当为 null 的时候,视为指向 window

      context.fn = this  // 首先要获取调用call的函数,用this可以获取

      let args = [...arguments].slice(1) //从 Arguments 对象中取值,取出第二个到最后一个参数   

      let result = context.fn(...args)  //函数是可以有返回值的

      delete context.fn

      return result

    }


  7. 测试:

    // 测试一下上面实现的myCall

    var value = 2;



    var obj = {

        value: 1

    }



    function bar(name, age) {

        console.log(this.value);

        return {

            value: this.value,

            name: name,

            age: age

        }

    }



    bar.call(null); // 2



    console.log(bar.myCall(obj, 'kevin', 18));

    // 1

    // Object {

    //    value: 1,

    //    name: 'kevin',

    //    age: 18

    // }



    (二)apply 的模拟实现

    apply 用法:MDN Function.prototype.apply()



    apply() 方法使用一个指定的 this 值和可选的参数数组 来调用一个函数。



    apply 的实现跟 call 类似。


  8. 实现:

    Function.prototype.myApply = function () {

      if (typeof this !== 'function') {

        throw new TypeError('error!')

      }

      let context = arguments[0] || window

      context.fn = this

      let result = arguments[1] ? context.fn(...arguments[1]) : context.fn()

      delete context.fn

      return result

    }


  9. 测试:

    var foo = {

        value: 1

    }

    function bar(name, age) {

        console.log(name)

        console.log(age)

        console.log(this.value);

    }

    bar.myApply(foo, ['black', '18']) // black 18 1



    (三)bind 的模拟实现

    bind 用法:MDN Function.prototype.bind()



    bind()方法会创建一个新函数,称为绑定函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。



    bind是ES5新增的一个方法,不会执行对应的函数,而是返回对绑定函数的引用。


  10. 实现:

    Function.prototype.customBind = function () {

      if (typeof this !== 'function') {

        throw new TypeError('error!')

      }

      const that = this   // 首先要获取调用bind的函数,用this获取并存放在that中

      let context = arguments[0] || window

      const args = [...arguments].slice(1)

      return function() {

        return that.apply(context, args.concat([...arguments]))

      }

    }



    (四)三者异同
  11. 相同:

    改变函数体内 this 的指向
  12. 不同:

    call、apply的区别:call方法接受的是参数列表,而apply方法接受的是一个参数数组。

    bind不立即执行。而call或apply会自动执行对应的函数。


JavaScript 的简述与基础语法

前端达人

目录

JavaScript

  1. JS 发展历史
  2. JS 的特点
  3. JS 的组成
  4. JS 的基础语法

    a. 两种引入方式 type src

    b. 三种输出方式 console.log document.write alert

    c. 变量声明 var let const typeof undefined

    d. 数据类型简介 string number boolean object undefined

    e. 运算符 + - * / % = < > && || !

    i. 全等符与不全等符 === !==

    f. 流程控制语句

    i. 条件语句 if else switch case default break

    ii. 循环语句 while dowhile fori forin forof



    JavaScript

    • JS 用于完成页面与用户的交互功能;

    1. JS 发展历史
    JavaScript 在 1995 年由 Netscape 公司的 Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为 Netscape 与 Sun 合作,Netscape 管理层希望它外观看起来像 Java,因此取名为 JavaScript。但实际上它的语法风格与 Self 及 Scheme 较为接近;
    欧洲计算机制造联盟(ECMA)在 1997 制定脚本语言规范 ECMA Script1 (ES1),2009 年发布了 ECMA Script5(ES5),在 2015 年发布了 ECMA Script 2015(ES6),所有的浏览器的都支持 ES6;

  5. JS 的特点

    JS 设计模仿了 Java 语言,不同如下:

    JS 不需要编译,由浏览器直接解释执行;

    JS 是弱类型语言,JS 变量声明不需要指明类型,不同类型的数据可以赋值给同一变量;
  6. JS 的组成

    ECMA Script 是 JS 的基础语法;

    BOM(Brower Object Model)是浏览器对象模型;

    DOM(Document Object Model)是文档对象模型;
  7. JS 的基础语法

    a. 两种引入方式 type src




    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS两种引入方式</title>
    </head>
    <body>
    <!-- JS两种引入方式:JS和CSS一样都需要引入到html页面中,浏览器才会解释执行,JS有两种引入方式:
        1.内嵌(内部)脚本:在script标签中写js代码,script标签推荐放置在body标签的底部,理论上和style标签一样可以放置位置任意;
        2.外部脚步:使用script标签的src属性引入外部js文件,使用注意事项: script标签使用了src属性以后内部的代码不再被浏览器解释执行,script引入外部脚本时不能使用自闭合格式 -->
    <!--告诉浏览器把解析器切换为js解析器 type="text/javascript"可以省略-->
    <script type="text/javascript"> document.write("<h1>内部脚本</h1>");//向body中追加html内容 </script>
    <script src="../js/外部脚本.js"></script>
    </body>
    </html>
    






    b. 三种输出方式 console.log document.write alert

    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS三种输出方式</title>
    </head>
    <body>
    <!-- JS三种输出方式:
        1.输出到浏览器控制台;
        2.输出html内容到页面;
        3.浏览器弹框输出字符 -->
    <script>
    //1.输出到浏览器控制台
    console.log("1. 输出到浏览器控制台");//开发者专用
    //2.输出html内容到页面
    document.write("2. 输出html内容到页面");//向body中追加html内容
    //3.浏览器弹框输出字符
    alert("3. 浏览器弹框输出字符");//阻塞执行
    </script>
    </body>
    </html>
    


    c. 变量声明 var let const typeof undefined


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS变量</title>
    </head>
    <body>
    <!-- JS变量用来存放数据;
        es5以前变量声明使用var;
        es6之后变量声明使用let,常量声明使用const。他们用于替代es6的var声明方式;
     JS是弱类型语言: 
        声明变量时不知道变量的类型(undefined),只有在赋值之后js变量才确定类型;
        typeof(a) 或 typeof a 输出变量的类型;
        undefined表示变量未赋值,未知类型 -->
    <script>
    //字符串 Java声明 String str ="张三";
    let str ="张三";
    console.log(str);
    //整数 Java声明 int k = 5;
    let k = 5;
    console.log(k);
    //小数 Java声明 float f = 7.5;
    let f = 7.5;
    console.log(f);
    //常量 Java声明 final Integer PI = 3.14;
    const PI = 3.14;
    console.log(PI);
    //演示弱类型语言
    let a;//声明变量不需要指明类型
    console.log(typeof a);//undefined 未赋值类型,未知类型
    a = "你好";
    console.log(typeof a);//string
    a = 123;
    console.log(typeof a);//number
    a = true;
    console.log(typeof a);//boolean
    a = new Object();
    console.log(typeof a);//object
    </script>
    </body>
    </html>
    


    d. 数据类型简介 string number boolean object undefined


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS数据类型</title>
    </head>
    <body>
    <!-- JS数据类型,常用数据类型:
        1.string 字符串类型;
        2.number 数字.包括整数和小数类型;
        3.boolean 布尔类型.值只有true和false两个;
        4 object 对象类型,空对象使用null表示,有两种格式:
            new Object(); 
            JSON格式.例如:{name:"张三",age:18};
        5.undefined 变量未赋值 -->
    <script>
    //1. string 字符串
    let str = "你好";
    console.log(str);
    console.log(typeof str);//string
    // 2. number 数字
    let n = 123.456;
    console.log(n);
    console.log(typeof n);//number
    // 3. boolean 布尔类型
    let boo = false;
    console.log(boo);
    console.log(typeof boo);//boolean
    // 4. object 对象类型,空对象使用 null表示
    let obj = null;//或 new Object();
    console.log(obj);
    console.log(typeof obj);//object
    // 5. undefined 变量未赋值
    let u = undefined;
    console.log(u);//值是undefined
    console.log(typeof u);//类型是undefined
    // Object类型
    let stu = new Object();//创建一个js对象,js对象的属性想要直接加上
    stu.id = 1;
    stu.name = "刘一";
    stu.age = 18;
    console.log(stu);//{id: 1, name: "刘一", age: 18}
    console.log(typeof stu);//object
    // JS对象取属性值有两种方式:
    // 1. obj.key
    console.log(stu.name);//刘一
    // 2. obj["key"]
    console.log(stu["name"]); //刘一 == stu.name
    let b = "age";
    console.log(stu[b]);//可以取不定属性的值
    </script>
    </body>
    </html>
    


    e. 运算符 + - * / % = < > && || !


    i. 全等符与不全等符 === !==


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
       <title>JS运算符</title>
    </head>
    <body>
    <!--
    JS运算符
    js运算符和Java运算符基本相同
    只有一个特殊的比较运算符
    === 判断js变量的值和类型都相等才为true
    !== 不全等,判断js变量的值和类型有一个不等就为true
    -->
    <script> let a = 3;
    let b = "3";
    console.log(a == b);//true
    // 全等 运算符 ===
    console.log(a === b);//false
    // 不全等 运算符 !==
    console.log(a !== b);//true
    // 三元(三目)运算符 布尔表达式?真:假
    let str = a===b?"全等":"不全等";
    console.log(str);//不全等
    </script>
    </body>
    </html>
    


    f. 流程控制语句

    i. 条件语句 if else switch case default break


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>条件语句</title>
    </head>
    <body>
    <!-- 条件语句JS的条件语句和Java语法基本一样,但是对数据类型的真假判断有些区别 JS中对各种数据类型作为布尔值的特点:(重点掌握) 1. string 空字符串""为false,其余都为true 2. number 数字 只有0为false,其余数字都为true 3. boolean 布尔类型 值只有 true和false 两个
    循环语句
  8. object 对象类型 空对象null表示false,其它对象都是true 5. undefined 变量未赋值 为false 常用语法格式 if ... else if ... else switch case break default -->
    <script>
    //if ... else
    //if(true){
    //if(""){// string 只有空字符为假
    //if(0){number 只有0为假
    //if(false){//boolean false为假 true为真
    //if(null){//object null为假
    //if(undefined){//undefined永为假
    if("undefined"){//undefined永为假
    console.log("满足条件");
    }else{
    console.log("不满足条件");
    }

    //switch case break default
    let k =1;
    switch (k) {
    case 1:
    console.log("111");break;
    case 2:
    console.log("222");break;
    default: console.log("其它情况"); }
    </script>
    </body>
    </html>


    ii. 循环语句 while dowhile fori forin forof


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>循环语句</title>
    </head>
    <body>
    <!-- 循环语句
        while,do while,fori 和Java一样;
        forin
            1.遍历出数组中的索引和元素
            2.遍历出对象中的属性和元素
        forof 
            1.遍历出数组中的元素
        forin 与 forof 区别:
            1.forin可以遍历对象,forof不能遍历对象
            2.forin可以遍历出数组中的索引,forof只能遍历出数组中的元素 -->
    <script>
    //while 和Java一样
    let k=1;
    while (k<3){
        console.log(k++);
    }
    
    //do while 和Java一样
    k =1;
    do{
        console.log(k++);
    }while (k<3)
    
    //fori 和Java一样
    for(let i=0;i<3;i++){
        console.log(i);
    }
    
    //forin 可以遍历数组和对象
    let arr = ["刘一","陈二","张三"];//JS数组使用中括号[]定义
    let stu = {id:5,name:"李四",age:18};//JS对象使用大括号定义
        //1.forin 遍历出数组中的索引
    for(let index in arr){
        console.log(index);//数组的索引 0,1,2
        console.log(arr[index]);//数组中的元素
    }
        //2.forin 遍历出对象中的属性名key
    for(let k in stu){
        console.log(k);//字符串属性 id,name,age
        console.log(stu[k]);//对象中的属性值
    }
    
    //forof 可以遍历数组
    for(let e of arr){
        console.log(e);//数组中的元素
    }</script>
    </body>
    </html>
    
    
    
    
    
    ————————————————
    版权声明:本文为CSDN博主「Regino」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Regino/article/details/105321573
    

原文链接:https://blog.csdn.net/Regino/article/details/105321573 





产品简化改版怎么做?

涛涛

编者按:这篇文章来自 Taras Bakusevych 的文章《How to simplify your design》

如今的数字产品,在不断迭代过程中,会加入更多功能,添加更多的技术支持,更新进阶的特性。而另一方面,企业对于构建简单实用的产品,也同样非常着迷。这当中当中毫无疑问是存在微妙的对抗和冲突的——如何让更好更多的信息,以更加轻量易用的方式呈现出来?这就涉及到产品的简化改版的技巧了。

到底怎么算是简单?

让产品变简单,其实一件困难的事情。

我们可以将「简单」定义为「更加易于理解或完成」,或者是「不困难」。值得一提的是,简单与否,它是主观的,对于一个人而言简单,对于另一个人而言不一定简单。通常,我们是通过下面的三个步骤来判断一件事情是简单还是困难:

在《简单法则》当中,John Maeda 提供了10条法则,这些法则能够帮你平衡商业、技术、设计所带来的复杂性——更通俗的来说,就是如何合理简化但是又能收获更多。

The Laws of Simplicity, John Maeda

Meada,作为麻省理工多媒体实验室的教授,他也是举世闻名的平面设计师。在书中,他非常慎重地探讨了「改进」这一概念,在他看来,它通常并不总意味着「更多」。无论是对于复杂度,还是简化,都只是相对概念。结合合理的培训,培养制造火箭的科学家也不是难事,但是总会有一些关键的因素,会让简单的事情变复杂,在设计中我们应该尽量去规避它们:

那么,我们在具体的产品改版中,要如何合理地简化呢?下面,是我结合这些原则来总结的21条建议:

1、创造有焦点价值的产品

有太多的产品试图让你更用户做更多的事情,每个企业都试图成为行业中的瑞士军刀。但是,如果你希望产更加简单,那么你需要有一个核心价值,并且确定产品真正针对的是谁,并非每个产品都应该成为 Facebook。你的产品的核心价值是什么?

2、删除所有不必要的内容

想要简化产品,最简单的方法,是经过深思熟虑之后再进行简化和删除。如果组件或者模块的功能、价值存疑,那么请删除。次要信息、不常用的控件、分散注意力的样式,都在这个范畴内。就这么简单。一旦采用这一的方式,你会立刻马上看到结果。当然,删除的时候,请务必深思熟虑。

「简单并非完全没有混乱,因为杂乱必然会伴随简化而存在。简单本质上是对产品的定位和目的有更精准的描述。而没有杂乱仅仅意味着这是一件不杂乱的产品,但是这并非简单。」

——乔纳森·艾维

3、将数据转换为有意义的样式

我们日常设计的绝大多数产品,都涉及到需要用户理解大量数据。当用户对于趋势和变化感兴趣的时候,请尽量使用可视化的方式来呈现信息,而不是一堆数字。尝试从数据中提取有效的内容,可视化地呈现在用户眼前,这才是有意义的简化。

4、提供对快速决策的支持

用户长期遭受复杂决策机制的折磨,帮助用户看清各种信息,更好的决策是简化的方向之一。席克定律曾经对此作出过非常经典的解释:用户做选择所需要花费的时间和精力往往会随着选项数量的增加而增加。因此,如果你希望用户决策变得简单,那么你需要简化选择,消除不必要的选项,来帮助用户进行选择。

5、太多选择会吓走用户

当前心理学理论和调研肯定了一件事,就是足够多的选择可能会给人带来积极的情绪,相应的衍生出一个流行的观点,就是选择越多越好,但是人类天性中的管理能力是不足以支撑过多选择的。

果酱实验是消费心理学当中最著名的实验之一:为消费者提供更少的选择,对于销售更加有利。这一点是至关重要的——更少的选择,能够带来更多的销量。

在这个实验当中,选择较少所带来的转化率几乎是更多选择的转化率的10倍。这是一个选择过载带来不良后果的一个重要范例——过多选择抑制了用户选择购买的想法。

6、在提供多种选择的时候,给用户以建议

如果多个选择总是无法避免,那么不妨给用户提供建议,或者告诉用户多数用户的选择。向用户清楚地传达选项之间的差别,这在定价策略上会带来更多积极的效果。

7、将用户注意力吸引到对的区域

当你了解用户流程的时候,就应该有针对性将用户注意力引导到的对的目标上去,找到关键区域,让用户在界面中优先注意到它们。

8、使用色彩和版式来呈现内容的结构层次

你应该经常会听到类似「可读性很差」这样的表述。有很多设计的确存在这样的问题。在设计当中,有太多的因素会影响信息的传达——字体的选取,大小变化、间距、大小写和配色,都会影响到层次结构,影响到用户汲取信息的方式。使用正确的配色和版式,让内容的层次结构更加清晰,最好还能反映出品牌特征,这样就更能增强吸引力和用户对它的印象了。

9、优化组织结构,便于管理

下面两张图当中,要你数清楚有多少个圆点,哪一张图会让你这个过程更快?

如同你所看到的,无序的点状方阵和有序的是截然不同的,后者的认知负担更低,识别速度更快。面对无序的信息和内容,我们需要逐个计数,但是面对有序的信息,则截然不同。

有组织的元素不仅有着更高的识别度,也更容易被记住。在数字产品当中,记住常见控件的位置和功能无疑是重要的。同样是上面这张图,如果不是计数,而是记住每个点的位置,你能不能做到?毫无疑问,缺少组织结构,这是一件艰难的事情。

10、给相关内容分组

在简化复杂页面结构的时候,对组件和内容进行分组通常是最为有效的方法之一。通过层级划分,用户每次需要处理的信息量都会更小,而不是在无关的组件中来回穿梭寻找。借助边框和卡片将相关度更高的内容整合到一起,这是非常便捷的方法。此外,关于关于分组,格式塔原理中的分组原则是非常值得借鉴的:接近性、相似性、连续性、闭合性和连通性。

11、拆分任务,按列布局

几乎任何产品当中都会涉及到不同类别的表单,这是获取用户信息的一种方式。有的时候,即使删除掉一些不必要的字段,表单依然会很长。因此,我们可以将巨大的表单或者任务拆分开来,这样一来,整个执行过程会变得简单不少。

设计表单的时候,尽量使用单列而非多列,这样更加顺畅、易于填写。用户无需思考接下来要填写什么,而是按照一条线继续操作下去即可。

12、透明清晰地展现路径和状态

不确定性让人感到焦虑,尽可能地在设计当中规避这种不确定性。这就是为什么要让用户在任何时候都清晰地知道他在流程中所处的位置,以及接下来会发生什么。总结之前所提供的信息也是个好主意,能够减轻用户的负担,避免反复检查之前的内容。

13、替用户进行计算

人脑对于涉及计算的部分通常会比较费力,对于这些不太占用计算力的内容可以交由系统来进行计算,和计算相比,人的大脑在处理具象化的信息的时候更加擅长。尝试利用系统,而不是将压力转嫁给用户。

14、用逐步展现来隐藏复杂性

渐进式的展开是用户体验设计当中的一种范式,这种方法能够让界面更容易被理解。当涉及到多屏、大量信息和操作的时候,这种逐步展现的机制,可以避免让用户感到不知所措,也可以隐藏一些无关的信息,直到最后用户可以清晰明白内在的关联性为止。逐渐展现的方法,遵循着「从抽象到具体」这样的一种概念,而 iOS 系统当中,所采用的导航方式,无疑就是这种思路的典范。一屏一个步骤,逐渐展现,最后给用户一个确切的结果。

15、善用通用的交互模式和设计范式

用户将绝大多数的精力都耗费在各种各样的其他数字产品上,这意味着用户对于其他的网站和APP的交互模式、使用方法都有着清晰的了解,对于特定的模式有具体的预期。因此,无论你是设计网站,某个 APP ,甚至是冰箱上的控制系统,都可以遵循既有的设计和交互模式。这并不是意味着停止创新,而是在很多事情上,你无需重新造轮子。

16、初次体验应当精简

在设计任何产品的时候,都应该让用户尽快感知到产品的价值。因此,除非是满足功能性的需求,在用户初次打开应用的时候,都尽量把其他的干扰去掉,因为这都是让用户了解产品价值的障碍。第一印象很重要,如果不满意,很多用户会立即离开。

如果你第一次尝试,即使是最简单的操作,可能也是有挑战性的,有时候新手使用 APP 的时候需要引导,但是最好的方法是尽量让体验和功能一目了然,搭配上下文环境的说明引导,而不是提供复杂繁琐的学习材料。

17、结合使用场景,巧用人体工程学

简约易用的产品大多能够合理地结合人体工程学的设计。绝大多数人可能会想到诸如汽车座椅、控制面板和手柄这样的案例,但实际其实远远不止。人体工程学适用于几乎所有涉及人的产品设计。

1954 年,心理学家 Paul Fitts 仔细了解了人的运动系统,并且提出了费茨定律——移动到目标所需要的时间取决于和目标之间的距离,并且和目标大小成反比。这个定律反馈到具体的界面设计上,就是尽可能让常用元素更大,并放置到更容易被触及的地方。

18、提供直接编辑功能和推荐参数

删除不必要的交互组件、视图或者是步骤,是简化过程中必不可少的部分呢。用户应该可以以最快的速度进行操作,比如在表单中直接操作,而不是在弹出框中进行编辑,这个被称为「流程状态」,「流程状态」不应当被弹出框打破。此外,对于很多需要填写的部分,最好提供参数推荐建议功能,就像搜索的实时推荐,让用户可以更为准确地输入。

19、使用智能默认值,减少认知负荷

智能默认值——或者说智能占位符是一个非常有用的策略。一方面可以帮助用户更快更精准的填写表单,另一方面,也给用户提供了相对准确的范例。只不过,默认参数的确定,需要设计师和开发团队对用户的使用场景等信息进行研究,通过测试和调研,确定用户使用状况,以此来确定默认参数应该是多少。如果需要明确地参数或者选项,那么可以将默认值设置为 90% 用户可能会选的选项,并辅以说明。

20、防止出错

出错信息会给用户带来很大的压力,为了避免用户陷入这样的状况,防止用户无法完成任务,请使用数据输入检查的功能,对于格式输入错误的表单和内容,对用户予以警报和提醒,避免错误发生。对于极为重要的操作,在用户提交之前,让用户二次确认信息,做好检查。对于某些强制性、破坏性乃至于不可恢复的操作,确保用户知道这一操作带来的影响。

21、无障碍设计

数字产品的可访问性是老话题了,要让产品和设计对于所有人——包括有视觉障碍的用户,都可以轻松地使用。最常见的,就是不要使用色彩来作为传达信息的唯一途径,确保文本和背景之间有足够的对比度,支持键盘导航操作等等。可访问性问题并不限于特定的群体,坚持不断的改善和提升,有助于每一个用户的体验。

结语

简化并创造易于理解的产品并不容易,但是这是一条几乎任何产品都要走的必经之路,简化的方法和技巧有很多,虽然零碎,但是它们最终会带着产品走向一条更好的道路。

文章来源:优设    作者:Taras Bakusevych

这份上万字的指南,帮你学会用栅格系统构建响应式设计

涛涛

今天,90% 的媒体互动都是基于屏幕的,通过手机,平板,笔记本电脑,电视和智能手表来与外界产生联系。多屏设计已成为商业设计中不可或缺的一部分,响应式设计正迅速成为常态。作为 UI 设计师,我们希望为我们的产品在不同尺寸下都能为用户提供良好的用户体验,栅格系统可以帮助我们做到这一点。

即使是我们只针对一个尺寸进行设计,我们也经常面临设计布局方面的问题。合理运用栅格系统可以帮助我们控制布局结构并实现一致和有组织的设计。栅格系统就像无形的胶水一样凝聚一个设计,即使元素看上去是彼此分离,但通过网格将它们连接在一起,实现良好的层次结构,位置关系和一致性。

设计师和开发者之间的协作过程中,栅格系统在前端开发中是被应用的很广泛一套体系,许多优秀的设计都使用了栅格系统,使用栅格系统可以加速开发并保证视觉还原。栅格系统虽然是传统设计方法中的一部分,但它仍旧能帮助我们去设计这个多终端的世界。看到这里,你可能非常想知道栅格系统在页面中是如何运作的,那么今天我们一起来学习并且实践我们的格栅系统。

「The grid system is an aid, not a guarantee. It permits a number of possible uses and each designer can look for a solution appropriate to his personal style. But one must learn how to use the grid; it is an art that requires practice.」

「栅格系统可以帮助我们设计,但却不能保证我们的设计。它有多种可能的用途,并且每个设计师都可以寻找适合其个人风格的解决方案。但是必须学习如何使用网格。这是一门需要实践的艺术。」

——Josef Müller-Brockmann《平面设计中的网格系统》作者

什么是栅格系统?

栅格系统可以让你依靠秩序与逻辑去完成设计。

早在 20 世纪初,德国、荷兰、瑞士等国的平面设计师们发现通过维持视觉秩序,从而使版面能更加清晰有效地传递信息,二战后这种理念在瑞士得到了良好的发展,直到 20 世纪 40 年代后期,第一次出现了使用网格进行辅助设计的印刷作品。由瑞士设计师大师 Josef Müller-Brockmann(约瑟夫·米勒-布罗克曼)所著的《平面设计中的网格系统》一书,自 1961 年出版以来畅销至今,对设计界有着深远的影响。史称 Swiss Typography Movement (瑞士新浪潮平面设计运动),后来成为全球风靡的 International Typographic Style (国际主义设计风格))。

△ 约瑟夫·米勒一布罗克曼 (Josef Muller-brockmann, 1914-1996)

瑞士的一位平面设计师和教师。1958 年任《新平面设计》(New Graphic Design)主编 1966 年被任命为 IBM 的欧洲设计顾问。布罗克曼因他的极简主义设计与简洁的排版、图形和色彩而闻名,他的设计对 21 世纪的众多平面设计师都产生了重大影响。

栅格系统的优势

1. 减少决策成本提高设计理解力

栅格系统在页面排版布局、尺寸设定方面给了设计者直观的参考,它让页面设计变得有规律,从而减少了设计决策成本;UI 设计也是需要理性的、客观的、具有数学逻辑美感的。熟练运用网格系统能够让你的设计更有秩序和节奏感,页面信息的展现更加清晰,提高阅读效率,从而提供给用户舒适的使用体验。加快认知速度。这意味着用户在使用产品完成特定的任务时,例如发送消息,预订酒店房间或乘车。用户能够连贯地理解并找到下一条信息或下一步要采取的步骤。

2. 响应化

因为人们使用不同类型的设备与产品进行互动,从智能手表的小屏幕到超宽屏电视,交互是流畅的,并且没有固定的尺寸。使用产品时,人们通常会在多个设备之间切换,以完成该产品的单个任务。所以响应式设计不应该是一种品,而是一种必需品。这意味着设计师不能再为单个设备的屏幕构建。多设备环境迫使设计人员根据动态网格系统进行思考,而不是固定宽度。使用网格可以跨不同屏幕尺寸的多个设备创建连贯的体验。

3. 加速团队协作设计

当多位设计师共同设计产品时,一个统一标准就变得尤为重要。如果没有一个统一的框架去约束的话,我们的产品的页面和组件的标准可能各式各样,这样的话整个产品的页面都会比较混乱。因此,网格系统有助于将界面设计工作分开,因为多位设计师可以在统一的布局下进行不同部分工作,并且无缝集成并保持连贯。

4. 加速开发并保证视觉还原

大多数设计项目的实施,涉及到设计者和开发者之间的协作。栅格化提高了页面布局的一致性和复用性;避免了设计师与开发者在细节上的反复沟通确认,从而提升了整个设计开发流程的效率、并能帮助开发者实现较为理想的设计还原。

栅格系统的基本构成

1. 列和槽(Columns and Gutters)

列(Columns) 和槽(Gutters)。列(Column)是内容的容器,水槽(Gutter)用来调节相邻两个列的间距,把控页面留白;列和列间距加上页面边距(Margin)加起来屏幕的水平宽度。列和列间距的内容区域(Content width)由 N个列和(N-1)个水槽组成。通常情况下,web 端采用 12 列,平板采用 8 列,手机采用 4 列。当然,你可以根据项目特点来设计你的网格系统,列和水槽的宽度我们可以利用 8 点网格系统来定义,下面会讲到。列的数量越多,页面就会被分割得越「碎」,在页面设计时就会越难把控,适用于业务信息量大、信息分组较多、单个盒子内信息体积较小的页面设计,列间距宽度数值对页面的影响,与外边距大体类似,即间距越大页面越轻松简单,反之亦然。用户已经习惯通过鼠标滚轮或滚动条(scrollbar)来纵向浏览页面内容,因此竖直方向可以无限延伸,所以栅格系统在竖直方向的栅格可以不体现出来,我们在执行设计时只要在水平方向保持规律的变化就可以了。

2. 页面边距(Side Margins)

页面边距就是内容区域(Content field)以外的空间,比较推荐的设计就是页面边距可以随着屏幕尺寸的增大而增大。页面边距在移动设备上通常是 12Px到 40Px 之间,在平板设备和桌面设备页面边距变化就相当多了。在响应式设计中,你选择了一个页面边距之后,缩小页面宽度时页面还是会有你设置的最小页面边距,直到到达下一个响应点(breakpoint)。当你增大页面宽度时,页面就有更多的页面边距,直到页面宽度到达下一个响应点(breakpoint)。

3. 模块(Field Elements)

模块就是你的设计区块,可以是一段文字,一张图片,或是其他更加丰富的元素。背景元素并不能算作是设计模块,所以并不需要遵循栅格系统。模块的定义是很灵活的,它可以是个小的单位或是元素,也可以是一个元素丰富的区块。

以 12 栅格系统为例,一个 12 栅格系统可以根据业务需要被 2 等分、3 等分、4 等分、6 等分、12 等分,还可以被 1:1:1、1:2:1、1:3:2、2:3:3、1:2、1:3、1:5、3:5 等不对称分割,具体采用哪种比例的组合需要我们根据自己业务需求来定。

4. 8 点网格(8pt spatial system)

栅格系统大的层面可以帮助设计者更好的进行版式设计与内容布局,而小的方面可以辅助设计师规范页面内各种元素的对齐与间距的设定。从用户体验角度来讲,这两者同等重要,从执行层面来讲,我们一般先做版式设计与布局,然后再填充内容、调整细节。

由于列跟水槽的宽度是以网格作为基本单位来增加或者减小,所以栅格化的重要一步就是需要先定义好栅格的原子单位「网格」的大小。目前最普适易用的就是 8 点网格。我们也可以利用 8 点网格法来制定产品中的间距,建立 8 点为一个单位的网格,使用 8 的倍数来定义模块的间距与元素的尺寸。8 点网格有如下几点优势:

  • 目前主流桌面设备的屏幕分辨率在竖直与水平方向基本都可以被 8 整除,使用 8 作为最小原子足够普适。可以确保不同布局之间的视觉一致性,同时可以灵活的适配多种尺寸的设计。以 8 为单位符合「偶数原则」。偶数原则可以在页面缩放中的避免类似于 0.5、0.75、1.25 等次像素的出现,从而使页面各类元素在大多数场景下都能有比较精致的细节表现。
  • 在网格系统中应该更加注重的是间距,而间距要遵循网格系统(例如使用 4、8、16、24、32 等和 8 具有规律的数字)同时在产品中的各类元素也要遵循这类原则(例如图标大小、组件大小等)。所以布局的水平和垂直节奏和各个组件的节奏会相互重叠,整体的设计将更加完整。
  • 开发工程师使用的前端开源组件库比如 Metronic、Antdesign 等也是基于 8 的原子单位来设计,因此如果设计师也使用以 8 为基本单位的栅格系统,开发与设计师相互对接就会更加方便,开发实现页面时也能更高品质地去还原我们的设计。

如果设计上没有立即可识别的间距系统时,这种设计可能会让用户感觉廉价、不一致,而且通常不值得信任。如果设计上遵循一个 8pt 网格系统时,节奏变得可预测和视觉上的愉悦。对于用户来说,这种体验是经过修饰和可预测的,这增加了用户对品牌的信任和喜爱。

无论有多少个设计师在协同合作,现在都有一个一致的间距规范,决策成本将大大降低。设计师可以轻松地从另一个设计师停止的地方开始设计,或者轻松地并行构建。我们定义下规范可以及时和开发同学沟通,因此可以为工程师节省时间。

5. 基线网格(Baseline Grid)

基线网格由密集的水平行组成,这些行提供文本的对齐和间距准则,类似于您在直纹纸上书写的方式。在下面的示例中,每 8px 行在红色和白色之间交替。

△ 基线网格

提示:将所有行高设置为基本单位(8x 或 4px)的增量非常重要,这样您的文本才能与基线网格完美对齐。

△ 字体行高

响应式设计

1. 什么是响应式?

设计师需要通过设计让内容在不同的平台上体验最大化,确保让用户在任何一个屏幕上看到内容的时候,会觉得这些内容就是为这个平台而设计的,而不是单纯的缩放而来。这种无缝的体验,才是跨屏幕设计的真正难点所在。想要制定一套针对不同设备和屏幕的设计方案,你需要一整套的策略。用户体验同时包含了性能、交互、效率等多方面内容,也就是说,对于一个线上的响应式页面,我们不仅要关注视觉上看到的,也要关注我们操作、使用时的感受,这些综合因素最终影响着用户使用时的效率与体验。

2. 响应式设计的核心步骤

确保核心的用户体验

虽然用户体验是无处不在的,但是对于特定产品,最核心的体验是存在的。产品通常是用来解决用户所面临的特定问题的,它的这一特质让产品变得有意义。关键的内容和关键的功能的组合,通常构成了产品的核心用户体验。如果你并没有想明白这个问题,不妨问问自己:用户需要完成哪些最常见/最重要的任务?找到问题的答案之后,你的产品就应当从各个方面、各个渠道,完整而全面地支撑这些功能,帮助用户完成这些任务。举个例子,Uber 的核心用户体验是随时随地叫车,无论设备的屏幕大小如何,你进行的设计全部都应该围绕着这个需求和功能来进行。叫车是 Uber 的核心功能,即使使用 Apple Watch 这种极小的屏幕尺寸都应该顺利地完成这个任务。

敲定你的产品所覆盖的设备类型

现在的移动端设备屏幕尺寸各不相同,单独为某一个设备设计内容无疑是不现实的。根据你的产品覆盖人群、受众分类、使用场景,综合考虑你的内容会优先呈现在哪些设备和平台上,然后有意识地筛选出常见的设备类型:手机,平板,桌面端,智能电视,智能手表……

不同的设备组合通常是基于不同的场景、需求和服务来构成的,用户会针对不同的屏幕进行不同模式的交互,甚至处理的内容也会有差异。比如说,在手机上,用户更加倾向于使用轻量级的任务,并且进行一定量的沟通和交流。在平板上,用户行为更多集中在内容消费上,并且目前平板的使用量被认为在逐步降低。桌面端依然是用户完成较为专业、复杂任务的首选平台,足以应付复杂多样的内容。了解各种设备类型和使用场景是用来构建用户体验的关键。

针对不同内容来匹配用户体验

并非所有的内容都符合不同设备的使用场景,比如智能手表就不适合展示大量的文本内容。你的产品所覆盖的设备组当中,每种设备的使用场景不同,应该匹配的用户体验也不一样。移动端用户和桌面端用户的需求就是不同的,场景差异也很大。以 Evernote 为例,它可以在多种不同类型的设备之间同步和切换,其桌面端版本就针对用户的内容需求进行了优化:Evernote 的桌面端应用程序针对阅读性的内容和多媒体进行了优化,而移动端的 Evernote 则强化了拍摄记录、图片和音频记录的功能:其次,不同的设备屏幕具备不同的输入方式,设计师如果忽略输入方式上的独特性,也常常会出现许多问题,这里就不扩展开来了。

优先为最小的屏幕做设计

一直以来,设计师都习惯从最大的屏幕着手设计,最后考虑最小的屏幕上的显示效果,这意味着绝大多数的设计都是从桌面端开始设计的,通常桌面端的内容和功能更全面。当桌面端的整体设计完成之后,再推进到其他设备端的设计。然而,在进行桌面端设计的时候,我们常常会遭遇「厨房水槽」困境:由于产品通常会牵涉到多个利益相关方,许多多余的功能会被加入进来。而实践经验表明,移动端优先的设计往往能够更好的专注于核心功能,更适合作为产品设计的起点。当你优先设计最小屏幕所需要的界面的时候,这种局面会强制你从最关键最重要的地方开始设计。这也是之前设计圈和产品开发领域一直所强调的「移动端优先」的策略的由来。在此之后,再进行平板、桌面和电视端的设计,就是一个自然地做加法的过程了。在绝大多数的案例当中,最小屏幕通常是手机屏幕。

测试你的设计

产品的测试环境并不一定都得是在现实世界中寻找,但是在尽可能让真实的用户来做可用性测试,并且在产品发布之前解决所有的用户体验上的问题。

3. 为何要利用栅格系统来进行响应式设计?

响应式可以响应的前提有两点:1、页面布局具有规律性、2、元素宽高可用百分比代替固定数值,而这两点正是栅格系统本身就具有的典型特点,所以利用栅格系统进行响应式的设计是顺理成章的,也比较快捷,所以响应式与栅格化天生一对好搭档。

如何建立栅格系统

第1步:确定列的数量

第一阶段先不要限制自己的列数。首先,创建一个低保真或高保真的原型。设计一些基本元素和用户流程。在此之后,就开始设计最优的列数和大小。如果在项目开始设计之后不得不改变我们的栅格系统,不要有负担,我们需要有一些试错的空间。

我们在设计页面时,用到最多的布局方式就是等分布局,即页面内容区域被 N 等分,每一份的宽度则根据屏幕宽度自适应调整。那么就从这个角度出发,思考一下页面的网格应该设置为多少列,才能的满足各种等分布局的需要。与 web 类似,移动端最方便的网格之一是 12 列网格。这个网格将允许我们在一行中同时放置偶数和奇数个元素。

对于移动端来说,12 列网格的缺点是一个列的宽度太小,你可能很少创建一个列宽度的元素。如果你选择 2、4 或 8 列网格,请记住在一行中放置奇数个元素可能会出现的问题。

Pro-Tip:

界面设计通常包含数百个不同的页面,因此,一个网格可能不适合所有的页面。如果需要,创建额外的栅格系统,但不要忘记设计的一致性。网格系统的一致性:相同的布局边距、列之间相等或成比例的水槽,以及更改列本身的宽度时其他模块也需要保持相同的比例。

第2步:定义水槽和边距

首先,让我们先翻阅目标屏幕的设计 Guideline,以找出通常页面边距(Side Margins)。目前,Android 和 iOs 的最小推荐布局边距为 16pt。web 端则依照屏幕尺寸不同而不同。这意味着,如果你希望遵循系统指南,则页面边距不应小于 16pt。(但可以更大的)

在选择 12 列网格时,列之间的水槽不应该太大,因为由于列的宽度小和它们之间的大宽度的水槽,列将在视觉上产生分裂的感觉。同时我建议你选择与8pt 间距系统成比例的水槽大小。所以布局的水平和垂直节奏会相互重叠。水槽与页面边距成比例。那么网格更加一致,也将允许我们轻松地在其中放置特殊元素,如轮播(carousel)。

第3步:定义 8pt间距系统

了帮助不同设计能力的设计者们在界面布局上的一致性和韵律感,统一设计到开发的布局语言,减少还原损耗。在大量的实践中,我们提取了一组可以用于 UI 布局空间决策的数组,他们都保持了 8 倍数的原则、具备动态的韵律感。经过验证,可以在一定程度上帮助我们更快更好地实现布局空间上的设计决策。定义网格系统方法很多,如运用 8 点网格系统、斐波那契数列、某最小原子单位的增量、从底层系统参数化定义间距等,我们以最小原子单位的增量为例去定义网格系统。最小单元格的数值选择需要从两方面考虑:

  • 一方面是该数值是否能被大多数手机屏幕的宽度整除,即广泛的适用性;
  • 另一方面是在具体使用时是否具有一定的灵活性。

在适用性方面,4、6、8、10 这四个数值都是基本可以满足的,在灵活性方面,4px 表现最佳,但是页面就会被分割的非常细碎,在设计时比较难于把控。因此我们需要根据 APP 的实际情况选择合适的数值,4px 或 6px 单元格比较适合页面内容信息较多,布局排版比较复杂的产品。而 8px 单元格对一般的设计场景都可以很好的满足,比较适合大多数的 项目,因此是比较推荐使用的。

那么假设我们以 8 为基准的去延展系统间距,得到如下间距系统:

1、2、8、16、24、32、40、48、56、64、72、80、88、96、192 等,这里都是 8 的倍数或能被 8 整除

但是目前间距数量太多,过于细碎也会导致间距比较乱,所以我们继续优化梳理(以 6 为基准,前面个数是后面个数的 2 倍递增),得到以下间距系统:

1、2、8、16、24、32、48、64、80、96

第4步:sketch布局设置

利用 sketch 的布局设置功能,即可快速搭建出网格系统的参考布局,在平时做设计的过程中,可以经常使用 Ctrl+L 快捷键切换布局的显示,提高设计效率。

我们来解释一下这些设置分别是什么:

  • Total Width:就是内容区域(Container)的值;
  • Offset:表示栅格的偏移量,我们只要设定完成以后按 Center 按钮即可,会自动居中;
  • Number of Columns:就是栅格数;
  • Gutter on outside:是非常重要的设置,勾选以后才能跟前端的栅格算法匹配;
  • Gutter Width:就是栅格之间的间距;
  • Columns Width:就是栅格的宽度。

如何做到响应式?

在传统的栅格化系统设计中,列的宽度和水槽的宽度是保持不变的,只是列的「数量」发生变化。为什么要这么处理呢?这是为了让设计更简单。如果一组三张卡片分别放在桌面的四列上,那么在平板电脑上,会显示两张卡片,并把第三张卡片进行折行显示在第二行上。不需要做任何的调整,因为已经知道它位于第四列上了。在手机上,答案也很简单,只需要一张卡片,其他的就会自动堆到下面的行中。但是目前我有更多的响应策略,例如当视窗(Viewport)发生变化时,内容区域的元素如何去响应,具体到我们当前的栅格系统,就是 Columns、Gutters、Margins 以及由 Columns 跟 Gutter 组成的盒子(BOX)四者的值(主要是宽度)如何变化,以及在这种变化之下我们页面的布局如何调整。

1. 固定栅格或是断点系统(Fixed boxes or breakpoint system)

固定网格,列宽和水槽宽不会改变,只是改变列的数目,当窗口缩放时,排版布局不会发生任何改变,只有当达到一个临界值(开发那边设置好的固定的值),界面才会发生改变。在此之前界面排版都是不变的,就像一部分被切掉了。

如果开发那边写了一个固定栅格,当你从桌面缩小到平板电脑,就像是在桌面的浏览器宽度时,你不会看到任何变化,设计就像是被剪掉了一样。但当达到平板屏幕尺寸临界点时,设计布局马上就会改变,平板电脑上的显示效果就会好起来。如果继续减小这个值,同样的事情也会发生,在到达另一个临界值之前,设计看起来都是不变的。下面是常见的断点系统(Breakpoint System)

如图,响应式是以视窗的最小宽度作为基本依据来制定每种宽度下 Columns、Gutters、与 Margins 的响应策略,也就是说 Viewport Min-width 是做出响应的触发条件,视窗每达到一个最小宽度,就会触发该宽度下预设的页面布局方式,而每种布局都是在该宽度下的最佳布局,也是因此,响应式才会在各种复杂分辨率条件下都能给用户比较好的体验。
每个视窗宽度的最小值是触发响应的关键值,因此我们给这些用于触发的关键值起了个名字叫「Breakpoint」,每个 Breakpoint 触发一种响应策略。

2. 流动栅格(Fluid Grid)

流动栅格系统是编辑内容,仪表板,图像,视频,数据可视化等理想的响应策略。当窗口缩小时,内容将动态地发生变化,文本会进行换行,元素也会变窄。然而,这些元素在内容宽度缩小到下一个临界值之前,布局是不会变化的。在各种情况下,对用户来说,扩展内容的大小比扩展可见内容的数量更有用。

所以我想说的是,断点 BreakPoint 只是一个更改布局的参考点。这就是为什么列宽和水槽的数量不会改变的原因,因为我们想让设计师在考虑布局时能够更容易地创建一致性。内容宽度会随着窗口的缩放而发生改变,例如图片会缩小,文本会换行。水槽的宽度不一定是固定的,可以随着页面宽度变化。

在每个断点处,列计数是固定的,列宽度是最小网格 8PT 的倍数。行高是列大小的倍数,遵循推荐的纵横比。边距和填充是小单位的固定倍数。在断点之间,实际列宽是网格区域的百分比,而不是一个小的单位倍数。内容尺度流畅。

首先从所以屏幕大小中选择一个基本尺寸,然后按照推荐的纵横比以基本大小的倍数构建每个响应式尺寸。当每个块使用相同基础大小的倍数时,就会出现网格。遵循此方法可确保栅格系统一致性,甚至跨产品的一致性。

3. 混合栅格(Hybrid Boxes)

在实际项目中,使用流动网格和固定网格的组合也是常见的做法。网站通常是流动网格,因为它要去适应各种不同终端的大小。后台系统设计、工具型的界面设计就比较经常使用网格和流动网格组合的形式。例如的后台管理系统(dashboard)侧边栏是固定网格,右侧内容是流动网格。混合栅格在每个维度上有不同的缩放规则,所以它们不使用统一的缩放比。当用户需要调整浏览器的大小以使内容在一个维度上伸缩而在另一个维度上不伸缩时,便使用混合网格。

面板对栅格系统的影响

1. 灵活面板(Flexible panels)

灵活的面板允许折叠和扩展状态。面板的展开状态为固定宽度,用户无法调节。当用户将鼠标悬停在折叠的面板上时,面板就会展开。当灵活的面板扩展时,它们要么压缩内容和网格,要么将内容推到浏览器边缘之外。

2. 固定面板(Fixed panels)

固定面板保持静态宽度,不能折叠,也存在于响应网格之外。

3. 悬浮面板(Floating panels)

此面板样式漂浮在主要内容区域之上,不影响响应网格。浮动面板将任何 UI 元素隐藏在其下方,用户必须将其移除。内联菜单、下拉菜单和工具提示也是浮动的。

总结

写这篇文章的目的是想提供一些关于如何在响应式设计中使用栅格系统,我知道对于我自己来说,我花了很多时间理解网格是如何工作的。我在 YouYube 上看了很多视频,也阅读了大量的文章,但每个人都在关注它为什么重要,却不去注重到底怎么在自己的项目中使用这些原则。

你要做的最好的事情就是从现在开始注意那些优秀设计是如何对齐元素的,你将会开始阅读这些设计系统。为了帮助理解,这里有一些设计系统概述了它们的网格使用:

在完全理解了网格的工作原理之后,你将成为了一名更好的设计师,因为你知道了你的设计将如何在临界值之间进行转换。你也可以落地你的设计,使它们能够达到像素级完美。这样的规范带来了更一致,更简洁的设计,当用户从一个界面到另一个界面流转时,这真的提升了产品的档次。我建议在你的设计中去应用这些网格,并和开发同学一起,以实践的方式将它们落地,这将会是一个非常不错的进步。

文章来源:优设    作者:IvanZheng

免费可商用!这款中文楷体太适合做封面字了!

涛涛

有时候做国风的设计作品,如果选择黑体和宋体可能太过端正,但选择书法字体的话,可能因为飞白或过度连笔导致字体不容易识别,那选什么字体呢?我建议大家选择楷体,注意不是选系统自带的楷体,而是今天推荐的演示悠然小楷,字体手稿由一位美丽女生书写,其字体有着悠然自得、闲情逸致的气质。

「演示悠然小楷」是由 keynote 研究所 x 秋叶 PPT 联合发布的一款免费商用字体,推荐设计师们收藏或下载。下载地址见文末。

字体案例演示

1. 青春/知识

△ By@伟崇

2. 文学/历史

△ By@伟崇

3. 游戏/小说

△ By@小敏

4. 中式地产

△ By@伟崇

5. 商务风

△ By@伟崇

8. 主视觉设计

△ By@画生

△ By@画生

9. 海报物料

△ By@画生

△ By@画生

△ By@画生

10. 电商广告

△ By@画生

△ By@画生

△ By@画生

11.文字排版

△ By@画生

△ By@画生

12. 品牌形象设计延展

△ By@画生

△ By@画生

△ By@画生

字体搭配

1. 思源宋体

△ By@澄音

2. 方正宋刻本秀楷

清刻本悦宋用得多了,不如试试这款有些相似但又有不同的「方正宋刻本秀楷」,较之前者字形更为周正,笔画更为果决,娟秀之中蕴藏力量。

△ By@画生

3. Garamond

Garamond 是一款古朴传统的衬线字体,在西文体系中历史悠久,恰因没有特殊的个性而被广泛使用,是老式衬线体中最具代表性的字体,与同样以端正工整为名的楷书作搭,最能相互映衬。

△ By@画生

4. 阿里巴巴普惠体

基础黑体的字体没有复杂的修饰,进一步弱化次要信息,强烈对比下让主角得以更好的突显,也让画面层次感更加丰富,而基础型的黑体,必然首推阿里巴巴普惠体。

△ By@画生

字体下载

  • 字体名称:演示悠然小楷字体
  • 系统名称:slideyouran(有的软件显示不出中文字体,就用这个来搜索)
  • 网页 CSS 字体属性:font-family:slideyouran
  • 字体版权:永久免费,包括商用

下载地址:https://pan.baidu.com/s/1ohOK2RSEA9vsfHAbfvpZmw 提取码:ypae

如何让深色模式更精致?

涛涛

通过一些案例进行比较与实验,探索如何将 UI 深色模式设计得更好。

iOS 作为 UI/UE 设计的风向标,一直是行业的引领者,不管你愿不愿意承不承认,他的每一次更新变化总能带动 UI 设计行业的一些大大小小的变革,并且产生更多的追随者,比如当年的 iOS7 开始的扁平化设计风格,对后续设计风格的影响直到现在已经 7 年了。

在最近半年,iOS 在 UI 设计风格上最大的变革莫过于 DarkMode(深色模式),在 DarkMode 之前,我们熟悉的 UI 界面往往都是浅白色界面为主,而从 iOS13 开始正式使用了 DarkMode,界面突然可以变深色了,苹果官方说这样设计可以让眼睛更舒服地长时间阅读,为革命保护视力,而且更加省电增长续航,具体结果我们不得而知,需要科学家们去验证了,但是对于我们设计师来说带来的挑战就是要「黑白无常」了。

其实 DarkMode 从测试版算起已经差不多推出了有半年的时间了,一些知名的 APP 产品早已经有了自己的兼容方案,同时 iOS 原生界面也给了我们很多最佳实践案例,按道理大家对于 DarkMode 的设计方式方法应该已经掌握了差不多了,但直到这几天微信正式推出了自己的 DarkMode 兼容方案,才发现对 DarkMode 的探索还需要设计师们多多努力。谨以此文表达一下自己的观点,不妥之处敬请海涵。

从一个「列表页面」说起

列表视图(TableView)是 iOS 中最常见的界面组件,一般常见于设置与栏目列表页面:

iOS 设置界面的浅色模式和深色模式看起来都非常协调。

下面我们看看微信发现页面,这个页面和 iOS 设置是很相似的。

如果单独看微信发现页面的浅色模式实际效果还是不错的。

但是直接转换到深色模式下就感觉突然差的很多了,甚至可以说是有点难看,这次微信真的做了一次黑天鹅?

到底是什么原因让微信发现页面在深色模式下视觉体验如此之差呢?

我们不妨将两个功能布局都相似的深色进行放在一起进行一下比较:

组成色彩分析:

在色彩这块在这两个页面中微信和 iOS 基本保持一致,四层灰度设计能更好的保持页面整体干净整洁且层次分明,但是在 A 背景色上,微信的背景色选择了黑色偏绿的颜色,应该是微信设计师还是想体现出产品的标志色原色。

文字的颜色也较 iOS 略微深一点,但是在整体上影响并不大。

看来在主要色彩上并没有什么问题,那么为什么微信这个界面与 iOS 界面比起来视觉上要感觉差一些呢?

下面来看一下图标

图标设计分析:

图标上的差别主要在于线宽与外框,微信采用无外框统一线宽的线形图标,iOS 采用的是有外框剪影图标。

我们我们把图标进行互换会怎么样呢?

观察到了吗?别看错了!

是的,我故意把位置做了对调,左边是 iOS,右边是微信。替换图标后的微信明显加分不少,整个界面都整齐多了,而 iOS 换了图标后明显变得不够整齐了,潦草很多。

那么结论是微信的无框线性图标在深色模式下兼容有问题?是的,的确如此。但是等一下,还有一些细节你注意到吗?换了图标的微信界面和之前的 iOS 界面比起来明显还是有点不够整齐,为什么呢 ?

我们回过头来从细节再看一下 iOS 界面。

我们按照这个思路把刚才微信替换图标界面再排序一下!

△ 界面视觉体验明显整齐了很多是不是!

疑问:

为什么细线图标和无框图标会在深色背景表现不够好,而在浅色背景下就没问题呢?

是不是所有的 UI 都会存在这样的问题呢?

我们再来看一些例子:

看来结论是一样的,线性图标在深色背景下的表现都是差强人意,反观带框图标适应性很强,浅色和深色模式下均能良好的适配,我来分析一下原因。

当年伽利略用望远镜往天上看,发现木星比金星大,换成肉眼看后金星则比木星大。他认为是眼睛的某种视觉特性造成了这种现象。

德国物理学家赫尔曼把这种错觉称为辐照错觉,就是说在黑暗背景下,亮度越高的物体看起来面积越大。

再来看一张图片

哪个圆圈看起来更大,显然是黑色背景下的白色圆形,实际上这只是一种错觉,所有圆圈是一样大。

光亮刺激会使得神经元产生非线性放大作用,导致刺激比实物本身看起来更大,白色圆形更亮,所以看起来更大一些。

线性图标是用线条勾画图案达到隐喻效果,一般线粗是 2px~6px 像素。

设计师在设计时都是以最终视觉作为参考,而设计稿本身多是浅色背景,所以在浅色背景的映衬下图标视觉会显得稍大,视觉基本是平衡的,假如设计是 4px 而呈现出的效果其实是 6px 左右。

是不是觉得哪里有点不对了?按照这个逻辑黑色背景下白色线图标不应该是视觉更大、更明显吗?

我们还需要考虑一个因素,那就是色彩,之前的几个界面案例的线性图标都是彩色的,特别是黑色背景下,不同色彩的图标放在一起,会有明显的忽大忽小的感觉,会让界面感觉非常凌乱。

是不是感觉黄色最大,红色的最小?但是其实是一样的,这还是相同形状的,要是图标形状不同感受会更明显。

看一个实际中的例子:

由于都是单色线性图标,在浅色和深色下表现还都不错的,但是单色图标略显界面单调,并不太建议这么设计。

毫无疑问,未来的 UI 场景需要适配多背景色风格,图标除了具备好看隐喻之外,更需要具备抗干扰性。

带框图标是一个不错的解决方法,大胆预测带框图标会将成为未来一段时间图标设计主流!

结论

  • 深色模式中灰度色阶在一个界面最多可分为四层。
  • 为了适配深色模式,今后有框图标将会成为图标设计风格主流。
  • 同样为了适配深色模式,细线图标将会被淘汰,剪影和粗线图标会流行起来。

  • 图标除了个体设计上用心,在排列上也会极大影响到页面的整合视觉,光谱排列法是个不错的选择。

  • 文章来源:优设    作者:残酷de乐章

关于HTTP请求出现 405状态码 not allowed的解决办法

seo达人

发现httppost请求目标网站会出现405 状态码,原因为 Apache、IIS、Nginx等绝大多数web服务器,都不允许静态文件响应POST请求

所以将post请求改为get请求即可

跨域,请求按要求配置完毕之后,options预请求老是报错。原因是webapi 默认的web.config有配置

有这么个配置,导致不行。要把他删掉,还要加上

浅谈JavaScript实现可视化展示冒泡排序过程

seo达人



<!DOCTYPE html>

<html>

<head>

<title>JavaScript实现可视化展示冒泡排序过程</title>

<style>

#boxes{

border:1px solid grey;

width:1320px;

height:300px;

margin-top:10px;

position:relative;

}

.box{

background:red;

width:20px;

line-height:30px;

text-align:center;

font-family:Microsoft Yahei;

font-size:15px;

color:white;

margin:0 1px;

position:absolute;

}

</style>

</head>

<body>

<div id="boxes"></div>

<script>

function random(){

var numbers = [];

for (var i = 0; i < 60; i++) {

var number = Math.floor(Math.random() 90 + 10);

numbers.push(number);

var divElement = document.createElement("div");

var parentElement = document.getElementById("boxes");

divElement.style.left = i
20 + i 2 + "px";

divElement.style.top = 300 - 3
number + "px";

divElement.style.height = 3 number + "px";

divElement.setAttribute("class","box");

parentElement.appendChild(divElement);

}

return numbers;

}

function sort(){

var numbers = random();

var parentElement = document.getElementById("boxes");

var i = 0, j = 0;

var time = setInterval(function() {

if (i < numbers.length) {

if (j < numbers.length - i) {

if (numbers[j] > numbers[j + 1]) {

var temp = numbers[j];

numbers[j] = numbers[j + 1];

numbers[j + 1] = temp;

parentElement.innerHTML = "";

for (var k = 0; k < numbers.length; k++) {

var textNode = document.createTextNode(numbers[k]);

var divElement = document.createElement("div");

divElement.appendChild(textNode);

divElement.style.left = k
20 + k 2 + "px";

divElement.style.top = 300 - 3
numbers[k] + "px";

divElement.style.height = 3 * numbers[k] + "px";

divElement.setAttribute("class","box");

parentElement.appendChild(divElement);

}

}

j++;

}

else{

i++;

j = 0;

}

}

else {

clearInterval(time); 

return;

}

}, 100);  

}

sort();

</script>

</body>

</html>

————————————————

版权声明:本文为CSDN博主「筱葭」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/zhouziyu2011/java/article/details/53899692

http的状态码(中英文)

seo达人

 1**:请求收到,继续处理

2**:操作成功收到,分析、接受

3**:完成此请求必须进一步处理

4**:请求包含一个错误语法或不能完成

5**:服务器执行一个完全有效请求失败

100——客户必须继续发出请求

101——客户要求服务器根据请求转换HTTP协议版本

200——交易成功

201——提示知道新文件的URL

202——接受和处理、但处理未完成

203——返回信息不确定或不完整

204——请求收到,但返回信息为空

205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件

206——服务器已经完成了部分用户的GET请求

300——请求的资源可在多处得到

301——删除请求数据

302——在其他地址发现了请求数据

303——建议客户访问其他URL或访问方式

304——客户端已经执行了GET,但文件未变化

305——请求的资源必须从服务器指定的地址得到

306——前一版本HTTP中使用的代码,现行版本中不再使用

307——申明请求的资源临时性删除

400——错误请求,如语法错误

401——请求授权失败

402——保留有效ChargeTo头响应

403——请求不允许

404——没有发现文件、查询或URl

405——用户在Request-Line字段定义的方法不允许

406——根据用户发送的Accept拖,请求资源不可访问

407——类似401,用户必须首先在代理服务器上得到授权

408——客户端没有在用户指定的饿时间内完成请求

409——对当前资源状态,请求不能完成

410——服务器上不再有此资源且无进一步的参考地址

411——服务器拒绝用户定义的Content-Length属性请求

412——一个或多个请求头字段在当前请求中错误

413——请求的资源大于服务器允许的大小

414——请求的资源URL长于服务器允许的长度

415——请求资源不支持请求项目格式

416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求

也不包含If-Range请求头字段

417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下

一级服务器不能满足请求

500——服务器产生内部错误

501——服务器不支持请求的函数

502——服务器暂时不可用,有时是为了防止发生系统过载

503——服务器过载或暂停维修

504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长

505——服务器不支持或拒绝支请求头中指定的HTTP版本

==========================================================

英文版:

100:Continue

101:Switching Protocols

102:Processing

200:OK

201:Created

202:Accepted

203:Non-Authoriative Information

204:No Content

205:Reset Content

206:Partial Content

207:Multi-Status

300:Multiple Choices

301:Moved Permanently

302:Found

303:See Other

304:Not Modified

305:Use Proxy

306:(Unused)

307:Temporary Redirect

400:Bad Request

401:Unauthorized

402:Payment Granted

403:Forbidden

404:File Not Found

405:Method Not Allowed

406:Not Acceptable

407:Proxy Authentication Required

408:Request Time-out

409:Conflict

410:Gone

411:Length Required

412:Precondition Failed

413:Request Entity Too Large

414:Request-URI Too Large

415:Unsupported Media Type

416:Requested range not satisfiable

417:Expectation Failed

422:Unprocessable Entity

423:Locked

424:Failed Dependency

500:Internal Server Error

501:Not Implemented

502:Bad Gateway

503:Service Unavailable

504:Gateway Timeout

505:HTTP Version Not Supported

507:Insufficient Storage

完整的 HTTP 1.1规范说明书来自于RFC 2616,你可以在rfc-editor在线查阅。HTTP 1.1的状态码被标记为新特性,因为许多浏览器只支持 HTTP 1.0。你应只把状态码发送给支持 HTTP 1.1的客户端,支持协议版本可以通过调用request.getRequestProtocol来检查。

本部分余下的内容会详细地介绍 HTTP 1.1中的状态码。这些状态码被分为五大类:

100-199 用于指定客户端应相应的某些动作。

200-299 用于表示请求成功。

300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。

400-499 用于指出客户端的错误。

500-599 用于支持服务器错误。

HttpServletResponse中的常量代表关联不同标准消息的状态码。在servlet程序中,你会更多地用到这些常量的标识来使用状态码。例如:你一般会使用response.setStatus(response.SC_NO_CONTENT)而不是 response.setStatus(204),因为后者不易理解而且容易导致错误。但是,你应当注意到服务器允许对消息轻微的改变,而客户端只注意状态码的数字值。所以服务器可能只返回 HTTP/1.1 200 而不是 HTTP/1.1 200 OK。

100 (Continue/继续)

如果服务器收到头信息中带有100-continue的请求,这是指客户端询问是否可以在后续的请求中发送附件。在这种情况下,服务器用100(SC_CONTINUE)允许客户端继续或用417 (Expectation Failed)告诉客户端不同意接受附件。这个状态码是 HTTP 1.1中新加入的。

101 (Switching Protocols/转换协议)

101 (SC_SWITCHING_PROTOCOLS)状态码是指服务器将按照其上的头信息变为一个不同的协议。这是 HTTP 1.1中新加入的。

200 (OK/正常)

200 (SC_OK)的意思是一切正常。一般用于相应GET和POST请求。这个状态码对servlet是缺省的;如果没有调用setStatus方法的话,就会得到200。

201 (Created/已创建)

201 (SC_CREATED)表示服务器在请求的响应中建立了新文档;应在定位头信息中给出它的URL。

202 (Accepted/接受)

202 (SC_ACCEPTED)告诉客户端请求正在被执行,但还没有处理完。

203 (Non-Authoritative Information/非官方信息)

状态码203 (SC_NON_AUTHORITATIVE_INFORMATION)是表示文档被正常的返回,但是由于正在使用的是文档副本所以某些响应头信息可能不正确。这是 HTTP 1.1中新加入的。

204 (No Content/无内容)

在并没有新文档的情况下,204 (SC_NO_CONTENT)确保浏览器继续显示先前的文档。这各状态码对于用户周期性的重载某一页非常有用,并且你可以确定先前的页面是否已经更新。例如,某个servlet可能作如下操作:

int pageVersion =Integer.parseInt(request.getParameter("pageVersion"));

if (pageVersion >;= currentVersion) {

response.setStatus(response.SC_NO_CONTENT);

} else {

// Create regular page

}

但是,这种方法对通过刷新响应头信息或等价的HTML标记自动重载的页面起作用,因为它会返回一个204状态码停止以后的重载。但基于JavaScript脚本的自动重载在这种情况下仍然需要能够起作用。可以阅读本书7.2 ( HTTP 1.1 Response Headers and Their Meaning/HTTP 1.1响应头信息以及他们的意义)部分的详细讨论。

205 (Reset Content/重置内容)

重置内容205 (SC_RESET_CONTENT)的意思是虽然没有新文档但浏览器要重置文档显示。这个状态码用于强迫浏览器清除表单域。这是 HTTP 1.1中新加入的。

206 (Partial Content/局部内容)

206 (SC_PARTIAL_CONTENT)是在服务器完成了一个包含Range头信息的局部请求时被发送的。这是 HTTP 1.1中新加入的。

300 (Multiple Choices/多重选择)

300 (SC_MULTIPLE_CHOICES)表示被请求的文档可以在多个地方找到,并将在返回的文档中列出来。如果服务器有首选设置,首选项将会被列于定位响应头信息中。

301 (Moved Permanently)

301 (SC_MOVED_PERMANENTLY)状态是指所请求的文档在别的地方;文档新的URL会在定位响应头信息中给出。浏览器会自动连接到新的URL。

302 (Found/找到)

与301有些类似,只是定位头信息中所给的URL应被理解为临时交换地址而不是永久的。注意:在 HTTP 1.0中,消息是临时移动(Moved Temporarily)的而不是被找到,因此HttpServletResponse中的常量是SC_MOVED_TEMPORARILY不是我们以为的SC_FOUND。

注意

代表状态码302的常量是SC_MOVED_TEMPORARILY而不是SC_FOUND。

状态码302是非常有用的因为浏览器自动连接在定为响应头信息中给出的新URL。这非常有用,而且为此有一个专门的方法——sendRedirect。使用response.sendRedirect(url)比调用response.setStatus(response.SC_MOVED_TEMPORARILY)和response.setHeader("Location", url)多几个好处。首先,response.sendRedirect(url)方法明显要简单和容易。第二,servlet自动建立一页保存这一连接以提供给那些不能自动转向的浏览器显示。最后,在servlet 2.2版本(J2EE中的版本)中,sendRedirect能够处理相对路径,自动转换为绝对路径。但是你只能在2.1版本中使用绝对路径。

如果你将用户转向到站点的另一页中,你要用 HttpServletResponse 中的 encodeURL 方法传送URL。这么做可预防不断使用基于URL重写的会话跟踪的情况。URL重写是一种在你的网站跟踪不使用 cookies 的用户的方法。这是通过在每一个URL尾部附加路径信息实现的,但是 servlet 会话跟踪API会自动的注意这些细节。会话跟踪在第九章讨论,并且养成使用 encodeURL 的习惯会使以后添加会话跟踪的功能更容易很多。

核心技巧

如果你将用户转向到你的站点的其他页面,用 response.sendRedirect(response.encodeURL(url)) 的方式事先计划好会话跟踪(session tracking)要比只是调用 response.sendRedirect(url) 好的多。

这个状态码有时可以与301交换使用。例如,如果你错误的访问了某路径信息不完整),有些服务器就会回复301状态码而有些则回复302。从技术上说,如果最初的请求是GET浏览器只是被假定自动转向。如果想了解更多细节,请看状态码307的讨论。

303 (See Other/参见其他信息)

这个状态码和 301、302 相似,只是如果最初的请求是 POST,那么新文档(在定位头信息中给出)药用 GET 找回。这个状态码是新加入 HTTP 1.1中的。

304 (Not Modified/为修正)

当客户端有一个缓存的文档,通过提供一个 If-Modified-Since 头信息可指出客户端只希望文档在指定日期之后有所修改时才会重载此文档,用这种方式可以进行有条件的请求。304 (SC_NOT_MODIFIED)是指缓冲的版本已经被更新并且客户端应刷新文档。另外,服务器将返回请求的文档及状态码 200。servlet一般情况下不会直接设置这个状态码。它们会实现getLastModified方法并根据修正日期让默认服务方法处理有条件的请求。这个方法的例程已在2.8部分(An Example Using Servlet Initialization and Page Modification Dates/一个使用servlet初始化和页面修正日期的例子)给出。

305 (Use Proxy/使用代理)

305 (SC_USE_PROXY)表示所请求的文档要通过定位头信息中的代理服务器获得。这个状态码是新加入 HTTP 1.1中的。

307 (Temporary Redirect/临时重定向)

浏览器处理307状态的规则与302相同。307状态被加入到 HTTP 1.1中是由于许多浏览器在收到302响应时即使是原始消息为POST的情况下仍然执行了错误的转向。只有在收到303响应时才假定浏览器会在POST请求时重定向。添加这个新的状态码的目的很明确:在响应为303时按照GET和POST请求转向;而在307响应时则按照GET请求转向而不是POST请求。注意:由于某些原因在HttpServletResponse中还没有与这个状态对应的常量。该状态码是新加入HTTP 1.1中的。

注意

在 HttpServletResponse 中没有 SC_TEMPORARY_REDIRECT 常量,所以你只能显示的使用307状态码。

400 (Bad Request/错误请求)

400 (SC_BAD_REQUEST)指出客户端请求中的语法错误。

401 (Unauthorized/未授权)

401 (SC_UNAUTHORIZED)表示客户端在授权头信息中没有有效的身份信息时访问受到密码保护的页面。这个响应必须包含一个WWW-Authenticate的授权信息头。例如,在本书4.5部分中的“Restricting Access to Web Pages./限制访问Web页。”

403 (Forbidden/禁止)

403 (SC_FORBIDDEN)的意思是除非拥有授权否则服务器拒绝提供所请求的资源。这个状态经常会由于服务器上的损坏文件或目录许可而引起。

404 (Not Found/未找到)

404 (SC_NOT_FOUND)状态每个网络程序员可能都遇到过,他告诉客户端所给的地址无法找到任何资源。它是表示“没有所访问页面”的标准方式。这个状态码是常用的响应并且在HttpServletResponse类中有专门的方法实现它:sendError("message")。相对于setStatus使用sendError得好处是:服务器会自动生成一个错误页来显示错误信息。但是,Internet Explorer 5浏览器却默认忽略你发挥的错误页面并显示其自定义的错误提示页面,虽然微软这么做违反了 HTTP 规范。要关闭此功能,在工具菜单里,选择Internet选项,进入高级标签页,并确认“显示友好的 HTTP 错误信息”选项(在我的浏览器中是倒数第8各选项)没有被选。但是很少有用户知道此选项,因此这个特性被IE5隐藏了起来使用户无法看到你所返回给用户的信息。而其他主流浏览器及IE4都完全的显示服务器生成的错误提示页面。可以参考图6-3及6-4中的例子。

核心警告

默认情况下,IE5忽略服务端生成的错误提示页面。

405 (Method Not Allowed/方法未允许)

405 (SC_METHOD_NOT_ALLOWED)指出请求方法(GET, POST, HEAD, PUT, DELETE, 等)对某些特定的资源不允许使用。该状态码是新加入 HTTP 1.1中的。

406 (Not Acceptable/无法访问)

406 (SC_NOT_ACCEPTABLE)表示请求资源的MIME类型与客户端中Accept头信息中指定的类型不一致。见本书7.2部分中的表7.1(HTTP 1.1 Response Headers and Their Meaning/HTTP 1.1响应头信息以及他们的意义)中对MIME类型的介绍。406是新加入 HTTP 1.1中的。

407 (Proxy Authentication Required/代理服务器认证要求)

407 (SC_PROXY_AUTHENTICATION_REQUIRED)与401状态有些相似,只是这个状态用于代理服务器。该状态指出客户端必须通过代理服务器的认证。代理服务器返回一个Proxy-Authenticate响应头信息给客户端,这会引起客户端使用带有Proxy-Authorization请求的头信息重新连接。该状态码是新加入 HTTP 1.1中的。

408 (Request Timeout/请求超时)

408 (SC_REQUEST_TIMEOUT)是指服务端等待客户端发送请求的时间过长。该状态码是新加入 HTTP 1.1中的。

409 (Conflict/冲突)

该状态通常与PUT请求一同使用,409 (SC_CONFLICT)状态常被用于试图上传版本不正确的文件时。该状态码是新加入 HTTP 1.1中的。

410 (Gone/已经不存在)

410 (SC_GONE)告诉客户端所请求的文档已经不存在并且没有更新的地址。410状态不同于404,410是在指导文档已被移走的情况下使用,而404则用于未知原因的无法访问。该状态码是新加入 HTTP 1.1中的。

411 (Length Required/需要数据长度)

411 (SC_LENGTH_REQUIRED)表示服务器不能处理请求(假设为带有附件的POST请求),除非客户端发送Content-Length头信息指出发送给服务器的数据的大小。该状态是新加入 HTTP 1.1的。

412 (Precondition Failed/先决条件错误)

412 (SC_PRECONDITION_FAILED)状态指出请求头信息中的某些先决条件是错误的。该状态是新加入 HTTP 1.1的。

413 (Request Entity Too Large/请求实体过大)

413 (SC_REQUEST_ENTITY_TOO_LARGE)告诉客户端现在所请求的文档比服务器现在想要处理的要大。如果服务器认为能够过一段时间处理,则会包含一个Retry-After的响应头信息。该状态是新加入 HTTP 1.1的。

414 (Request URI Too Long/请求URI过长)

414 (SC_REQUEST_URI_TOO_LONG)状态用于在URI过长的情况时。这里所指的“URI”是指URL中主机、域名及端口号之后的内容。该状态是新加入 HTTP 1.1的。

415 (Unsupported Media Type/不支持的媒体格式)

415 (SC_UNSUPPORTED_MEDIA_TYPE)意味着请求所带的附件的格式类型服务器不知道如何处理。该状态是新加入 HTTP 1.1的。

416 (Requested Range Not Satisfiable/请求范围无法满足)

416表示客户端包含了一个服务器无法满足的Range头信息的请求。该状态是新加入 HTTP 1.1的。奇怪的是,在servlet 2.1版本API的HttpServletResponse中并没有相应的常量代表该状态。

注意

在servlet 2.1的规范中,类HttpServletResponse并没有SC_REQUESTED_RANGE_NOT_SATISFIABLE 这样的常量,所以你只能直接使用416。在servlet 2.2版本之后都包含了此常量。

417 (Expectation Failed/期望失败)

如果服务器得到一个带有100-continue值的Expect请求头信息,这是指客户端正在询问是否可以在后面的请求中发送附件。在这种情况下,服务器也会用该状态(417)告诉浏览器服务器不接收该附件或用100 (SC_CONTINUE)状态告诉客户端可以继续发送附件。该状态是新加入 HTTP 1.1的。

500 (Internal Server Error/内部服务器错误)

500 (SC_INTERNAL_SERVER_ERROR) 是常用的“服务器错误”状态。该状态经常由CGI程序引起也可能(但愿不会如此!)由无法正常运行的或返回头信息格式不正确的servlet引起。

501 (Not Implemented/未实现)

501 (SC_NOT_IMPLEMENTED)状态告诉客户端服务器不支持请求中要求的功能。例如,客户端执行了如PUT这样的服务器并不支持的命令。

502 (Bad Gateway/错误的网关)

502 (SC_BAD_GATEWAY)被用于充当代理或网关的服务器;该状态指出接收服务器接收到远端服务器的错误响应。

503 (Service Unavailable/服务无法获得)

状态码503 (SC_SERVICE_UNAVAILABLE)表示服务器由于在维护或已经超载而无法响应。例如,如果某些线程或数据库连接池已经没有空闲则servlet会返回这个头信息。服务器可提供一个Retry-After头信息告诉客户端什么时候可以在试一次。

504 (Gateway Timeout/网关超时)

该状态也用于充当代理或网关的服务器;它指出接收服务器没有从远端服务器得到及时的响应。该状态是新加入 HTTP 1.1的。

505 (HTTP Version Not Supported/不支持的 HTTP 版本)

505 (SC_HTTP_VERSION_NOT_SUPPORTED)状态码是说服务器并不支持在请求中所标明 HTTP 版本。该状态是新加入 HTTP 1.1的。


日历

链接

个人资料

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

存档