如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
编者按:作为今年大热的设计趋势,响应式已然是设计师的标配技能。今天阿里的同学从响应式设计的布局类型、布局实现两方面深入讲解,有哪些实现布局的方式,该采用何种方式,都有相当专业细致的解答,不多说,来收 >>>
Heyuchan :在谈响应式布局前,我们先梳理下网页设计中整体页面排版布局,常见的主要有如下几种类型:
采用何种方式实现布局设计,也有不同的方式,这里基于页面的实现单位而言,分为四种类型:固定布局、可切换的固定布局、弹性布局、混合布局。
➤固定布局:以像素作为页面的基本单位,不管设备屏幕及浏览器宽度,只设计一套尺寸;
➤可切换的固定布局:同样以像素作为页面单位,参考主流设备尺寸,设计几套不同宽度的布局。通过设别的屏幕尺寸或浏览器宽度,选择最合适的那套宽度布局;
➤弹性布局:以百分比作为页面的基本单位,可以适应一定范围内所有尺寸的设备屏幕及浏览器宽度,并能完美利用有效空间展现最佳效果;
➤混合布局:同弹性布局类似,可以适应一定范围内所有尺寸的设备屏幕及浏览器宽度,并能完美利用有效空间展现最佳效果;只是混合像素、和百分比两种单位作为页面单位。
可切换的固定布局、弹性布局、混合布局都是目前可被采用的响应式布局方式。
其中可切换的固定布局的实现成本,但拓展性比较差;而弹性布局与混合布局效果具响应性,都是比较理想的响应式布局实现方式。
只是对于不同类型的页面排版布局实现响应式设计,需要采用不用的实现方式。通栏、等分结构的适合采用弹性布局方式、而对于非等分的多栏结构往往需要采用混合布局的实现方式。
布局响应 对页面进行响应式的设计实现,需要对相同内容进行不同宽度的布局设计,有两种方式:
桌面优先(从桌面端开始向下设计);
移动优先(从移动端向上设计);
无论基于那种模式的设计,要兼容所有设备,布局响应时不可避免地需要对模块布局做一些变化(发生布局改变的临界点称之为断点), 我们通过JS获取设备的屏幕宽度,来改变网页的布局,这一过程我们可以称之为布局响应屏幕。
常见的主要有如下几种方式:
布局不变,即页面中整体模块布局不发生变化,主要有:
➤模块中内容:挤压-拉伸;
➤模块中内容:换行-平铺;
➤模块中内容:删减-增加;
布局改变,即页面中的整体模块布局发生变化,主要有:
➤模块位置变换;
➤模块展示方式改变:隐藏-展开;
➤模块数量改变:删减-增加;
很多时候,单一方式的布局响应无法满足理想效果,需要结合多种组合方式,但原则上尽可能时保持简单轻巧,而且同一断点内(发生布局改变的临界点称之为断点)保持统一逻辑。
否则页面实现得太过复杂,也会影响整体体验和页面性能。
大部分视觉设计师在工作中都会遇到logo UI设计,每个UI设计师都有自己独特的思路和方法。在设计过程中有理性的方法也有感性的发挥,我接下来讲的理性的部分比较多,因为感性的东西跟个人平时的积累、经验、生活阅历等等相关。不是什么大神,写的都是自己慢慢沉淀下来的方式方法。Logo的意义和重要性,在这不再赘述,我主要讲logo设计的每个阶段个人觉得比较重要的几点。
promise的概念和实现最初来源于社区,用于解决异步编程的回调嵌套问题,即将多级的嵌套改良成顺序的代码行。ES6将其写入了语言标准,统一了用法,提供了原生的Promise。
Promise是一个构造函数,用于生成一个Promise实例。Promise实例代表一次异步操作。 它只可能有3种转态,分别是Pending(未决议), Resolved(完成) 和 Rejected(出错) 。
创建一个Promise实例时,其处于Pending状态,当异步操作完成,执行回调函数的时候,根据回调函数中的err
的值,如果err
为空则异步操作成功,否则异步操作失败。此后,Promise实例的状态将不再改变。
var pro = function () { return new Promise(function(resolve, reject) { fs.readdir(_dirname, function(err, data) { if (err) {
reject(err); //失败则将Promise对象置为rejected状态 } else {
resolve(data); //成功则将Promise对象置为resolved转态 }
});
});
} /*pro是一个函数
调用该函数返回一个Promise实例
*/ var promiseObject = pro(); /*then方法执行Resolved和Rejected状态的回调函数*/ promiseObject
.then(doneCallbacks, failCallbacks)
.catch(function(err) { console.log(err);
}); var doneCallbacks = function(data) { console.log(data);
}; var failCallbacks = function(err) { console.log(err)
};
catch是then的一个语法糖,相当于
promiseObject.then(undefined, function(err) {
console.log(err)
});
Promise对象的错误具有向后传递的性质,因此,如果在调用过程抛出异常,则异常总能被最后一个catch捕获。这也是为什么我们习惯在then的调用后跟随一个catch调用。
then 方法是定义在构造函数Promise 的原型对象上的。这个方法为Promise实例添加状态改变时的回调函数。then方法返回一个新的Promise实例,因此then方法后面可以调用then()方法。传给then()方法的函数,可返回三类值,分别如下:
如果返回的是一个新的Promise对象,则下一级的then接收函数在这个Promise实例 状态发生改变时被触发执行。因此,then的链式写法,可以按顺序执行一系列的异步操作,并且后一个异步操作在前一个完成之后开始。如下代码实例所示:
var fs = require('fs'); var pro = function () { return new Promise(function(resolve, reject) { fs.readdir(_dirname, function(err, data) { if (err) {
reject(err); //失败则将Promise对象置为rejected状态 } else {
resolve(data); //成功则将Promise对象置为resolved转态 }
});
});
} var newPro = function(data) { return new Promise(function(resolve, reject) { setTimeout(function(){ resolve(data);
},2000);
});
}; /*pro是一个函数
调用该函数返回一个Promise实例
*/ var promiseObject = pro(); /*then方法执行Resolved和Rejected状态的回调函数*/ promiseObject
.then(function(data){ console.log("fisrt sync op");
console.log(data); return newPro(data);//返回一个新的Promise对象 })
.then(function(data) { console.log("second sync op");
console.log(data);//两秒钟后才会被执行 })
.catch(function(err) { console.log(err);
});
promiseObject.then(undefined, function(err) { console.log(err)
}); var doneCallbacks = function(data) { console.log(data);
}; var failCallbacks = function(err) { console.log(err)
};
把上一级异步调用的结果返回给下一级调用,then这样的链式写法,解决了回调函数的多层嵌套调用。
多层嵌套
当我还是一枚单纯的p图师的时候,谁要是叫我美工,我是拒绝的!我跟他们讲,我是设计师,是能duang的一下就加的设计师。突然有一天,有人问起我什么是UI,作为一枚经历了岁月沉沦能写点代码能P图的大美工(此刻我已经不拒绝美工的称呼了,因为要做到好看真的不那么简单)我告诉他,我就是,然而他不信,他觉得UI设计师该是高大上的,是美工需要仰视的!
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
随着越来越的的app使用沉浸式状态栏,有必要对沉浸式状态栏学习一下,查看了很多资料,沉浸式状态栏重要的无法三点:1.实现全屏 (Android4.4跟5.0全屏处理方式有别需分开处理 )2.设置全屏之后为了保证自己写的布局不与状态栏重叠,需要在跟xml的跟布局设置android:fitsSystemWindows=”true” 。基于这几点处理方式可能很多,但是为了便于项目中工具类封装,本编实现方式均已代码方式呈现,xml设置方式可以自行查阅相关资料 3.改变状态栏颜色
—1.全屏设置
对于4.4以上系统,因4.4以上系统是可以设置全屏,代码如下:
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
对于5.0系统 具体代码
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS|WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_STABLE|View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
仅仅做全屏处理,我们会发现不管是在4.4系统上还是在5.0系统上,我们的布局内容会与状态栏内容出现重叠。
下图为4.4系统
下图为8.0系统
为了解决全屏设置重叠状态栏,我们需要在全屏之上预留状态栏的高度以便正常显示状态栏,而处理方式也很简单 activity layout根目录添加下面代码
android:fitsSystemWindows=”true” 而此处我建议用代码设置,因为通常我们项目中会提取BaseActivity基类抽出一些共性,这种方式比在每个xml中设置属性更方便
rootView.setFitsSystemWindows(true) 此处的rootView指的就是activity对应的跟布局;
进行以上处理之后我们会发现现在状态栏跟我们的布局内容不再重叠了,接下来我们就只需要处理状态栏的颜色问题了。具体代码如下
ViewGroup content= (ViewGroup) findViewById(android.R.id.content); ViewGroup childView= (ViewGroup) content.getChildAt(0); if(childView!=null){
childView.setFitsSystemWindows(true); }
对于4.4系统因为没有改变状态栏颜色的api,我们可以通过添加一个与状态栏等高的View到根布局的父容器中,而根布局的父容器就是一个ID为android.R.id.content的帧布局被装饰的容器中,这样只需要设置View的颜色即可。对于5.0及以上系统,因已提供设置状态栏和导航栏颜色的api,直接设置即可;
对于4.4以上5.0一下系统
View view=new View(this); view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusHeight())); view.setBackgroundColor(Color.RED); content.addView(view);
对于5.0及以上系统
window.setStatusBarColor(Color.RED);
获取状态栏高度
private int getStatusHeight() { int statusHeight=-1; int resourceId=getResources().getIdentifier("status_bar_height","dimen","android"); if(resourceId>0){ return getResources().getDimensionPixelSize(resourceId);
} return 0;
}
以上就是实现沉浸式状态栏的具体过程。整体代码如下:
package com.example.administrator.myjavadeamo.activity; import android.graphics.Color; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import com.example.administrator.myjavadeamo.R; public class StatusBarActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题栏 setContentView(R.layout.activity_status_bar); initWindow(); }
private void initWindow() {
Window window=getWindow(); if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
//5.0以上的手机
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS|WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_STABLE|View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); ViewGroup content= (ViewGroup) findViewById(android.R.id.content); ViewGroup childView= (ViewGroup) content.getChildAt(0); if(childView!=null){
childView.setFitsSystemWindows(true); }
window.setStatusBarColor(Color.GREEN); }else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
//4.4以上5.0一下的手机
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); ViewGroup content= (ViewGroup) findViewById(android.R.id.content); ViewGroup childView= (ViewGroup) content.getChildAt(0); if(childView!=null){
childView.setFitsSystemWindows(true); }
View view=new View(this); view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusHeight())); view.setBackgroundColor(Color.GREEN); content.addView(view); }
} /**
* 获取状态栏高度
* @return
*/ private int getStatusHeight() {
int statusHeight=-1; int resourceId=getResources().getIdentifier("status_bar_height","dimen","android"); if(resourceId>0){
return getResources().getDimensionPixelSize(resourceId); }
return 0; }
}
最终实现结果:
4.4系统
8.0系统
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
在前不久,蓝蓝参观了中国国际广播展览会,这个中国广电大伽云集的展会上,许多企业都在播放智能电视端,我拍了一些,做为以后设计的参考,同时也在收集大屏电视设计的资料。
以下为蓝蓝设计收集的文章之一,这篇文章的好处是总结了硬件交互的特点和各种电视上常见的表现方式,并配以图片说明,虽然对于专业的设计师而言,tab/磁贴/列表/滑动换换幻灯片式等都是常见的方式,本能直观就会做出选择,也不会仅限于此,但对非从业者来讲,这样列有概括启蒙的作用,各个例子取的很全。
- 硬件+远距离操控——基本交互 -
基于桌面资料研究以及设计经验,总结了基本交互主要包含以下几个关键内容:遥控器输入、导航和菜单、信息展现、控件摆放和焦点状态。
一 、遥控器输入
当我们用手指快速便捷地在手机屏幕上点击或滑动时,主流电视大屏及应用的操作还是:使用遥控器进行操作。而市面上不同电视生产商生产的遥控器也有着不同的造型和按键数量,如图1,分别展示了:苹果、谷歌、小米、乐视和中兴机顶盒的遥控器。
图1 不同厂商的遥控器
尽管有着千奇百怪的造型和按键数量,但几乎全部的遥控器都有几个相同的按键:上、下、左、右、返回键和OK键,如图2。它们也够成了遥控器输入的基本交互方式:通过“上下左右键”移动焦点位置,选中界面元素,按“OK键”进行相关操作,按“返回键”返回。
而上图中还有一些按键,如数字键、菜单键,有些遥控器是没有它们的。这里强调下“菜单键”,比如之前的一个设计,将不常用的操作隐藏到菜单键中,当用户按菜单键时再唤出操作(如安卓端的“长按”,iOS端的“左滑”等)。后来,才发现并不是所有遥控器都有该按键,只能在后续版本中迭代优化。因此,在设计之前,不妨研究一下你的输入硬件设备,避免因“刻板印象”造成不必要的坑。
遥控器输入的特性决定了用户在输入时的效率和便捷程度都大打折扣,因此,在这样的局限下,设计师只能通过各种不同的方式来尽量减弱这种不便捷:
1. 减少用户输入
能不让用户输入就不输入,尽量只让用户去做“选择型”输入,避免大量“文字型”输入,比如电视上的搜索功能中,及时联想、热搜词就变得极为重要,如图3右图所示。
图3 键盘输入的优化
2. 优化输入模式
结合项目情况,去尝试优化输入模式,比如充分利用遥控器数字键输入、重新设计键盘以减少用户操作,如图3所示。
3. 将输入转移
越来越多的产品开始将一些输入转移并引导到手机端进行操作,甚至将手机端直接做为遥控器,比如最常见的扫码登录和TV助手类APP。输入转移能大大提升用户操作效率,但设计时还是要结合具体场景,避免用户过多地在手机和遥控器间切换。
4. 创新的输入方式
随着各种技术的发展,在未来,电视端也会有越来越多的输入方式,而不仅限于遥控器输入,如智能语音输入,而我们也需要了解这些新技术,才能帮助我们不断的创新并给用户带来优秀的体验。
二、导航和菜单
电视端的导航和菜单大多数和手机端、PC端是类似的,但因遥控器输入的特性或多或少的有些差异,主要分为以下几类:
1. 十字
十字导航在国内的产品中比较少见,但因它的主导航和二级导航同时展开,能与十字方向键完美契合,用户可通过方向键在主导航和二级导航之间以最的方式切换,如图4所示。但它最多展现2级菜单,即纵向菜单和横向菜单,又浪费了大量界面空白,因此针对国内大而全的产品而言,往往不是特别适用。
图4 十字导航
2. 磁贴
磁贴广泛应用于各种电视应用产品,一般包含主导航和二级磁贴,往往二级磁贴的展现能使信息更加扁平、直观及可视化,且相比于十字导航,操作的方向不会受到限制;但往往焦点从磁贴移回到左侧/上侧导航需要更多的操作成本,如图5所示。磁贴的信息展现能够充分利用界面空间,并把信息前置,因此,对很多内容型产品而言,磁贴可以很好的适用内容露出,吸引用户进入。
3. Tab
广泛应用于手机端和PC端,当然在电视端中也经常使用,往往起到一级导航的作用,在告知用户所处位置的同时,很好的引导用户进行模块间的切换,如图6所示。然而,Tab导航也有一些基本的设计要求,比如尽量不使用多层Tab套用,即使不得已套用也需尽量保证表现形式不同;另外,在“焦点”的章节,也还会提到Tab切换时的加载问题。
4. 列表
列表也是手机端最常用的菜单展现形式,在电视端同样适用,如电视直播类产品,主功能就利用了多层列表套用的展现形式,详见图7所示。而在电视端,列表的样式也是多种多样的:如纯文字列表(可配按钮)、图文列表(可配按钮)、展示型列表(不可操作)、横向列表(选集列表)等。
图7 图文列表和展示型列表
5. 其他
电视产品上最常用的菜单和导航模式一般都可以总结为以上4种,当然还有一些其他的方式。随着用户多设备的使用,越来越多的手机端和PC端的设计模式开始在电视上出现;而更多的产品界面因其复杂的功能无法只使用1种菜单和导航模式,往往是混合型设计,如图8所示。不过,无论使用何种导航和菜单类型,电视大屏幕的菜单和导航的设计目标终归是:用户可以快速定位,并且能够预测出操作结果。因此,灵活使用导航和菜单,使用户不会迷失在功能繁多的界面信息中就尤为重要。
三、信息展现
在前面的文字中,我在“电视”这个词后面都紧跟了“大屏”这个词,电视的屏幕是比PC还要大的屏幕;而用户也因为如此大的屏幕,往往是坐在两三米之外。因此,电视端的信息设计有着两个显著的特质:为大屏幕而设计和为远距离而设计,有着以下几个注意事项:
1. 重视信息的识别性和简洁易懂
文字、图标和按钮,乃至toast提示,在电视端的识别性问题比手机和PC端更为凸显。因为远距离、大屏幕,加上电视本身的休闲属性,使得用户的注意力较为分散,因此,界面中的信息和元素就需要适当放大,至少保证用户能够在两三米之外能清晰看到,如图9所示。
2. 提前露出信息和多露出点信息
在“遥控器输入”章节中有提到,提前露出信息能够在一定程度上减少用户输入,并在产品层面吸引用户进入。不过,和手机端设计类似,还是需要甄别哪些信息需要提前露出、怎么露出以及露出信息后对产品稳定性和性能的影响;这些都需要基于产品特点,并与产品、视觉和开发共同协商确定。而“多露出点信息”却相对容易理解,主要是告知用户右边/下边“还有一些内容,快去看看”,如图10所示。
3. 避免过多无模块信息的展示
相比于手机端,因屏幕较大,与PC端类似,往往需将屏幕划分为多个排列整齐的小屏幕来进行设计,即模块化、区域化的设计信息展现。通过这种方式,可以使信息布局更为规整,用户不容易迷失在繁杂的信息中,如图11所示。
四、控件位置
控件的位置问题是初期开始电视产品设计时非常容易犯的错误,如图12所示。左图中的“添加股票”按钮,当已添加的股票过多时,可能会看不到该按钮,或需用户按很多下才能使焦点移动到“添加股票”;右图中的文字浏览,完全不知道如何浏览,也不知道如何将焦点从文字移动到“查看票种”按钮。这两个案例阐述了:按钮的位置导致按钮丢失或操作效率较低;电视端文字阅读也得遵守焦点浏览原则,如每行1个焦点或整篇1个焦点,若是后者,就得保证可见范围内文字已展示全。因此,在电视大屏中放置交互控件,需充分考虑是否符合电视端的使用方式以及用户的操作效率。
五、焦点状态
前文提到过很多次的“焦点”,它其实是电视大屏用户体验的第一要素,而在交互说明中最常出现的也是“焦点怎么样了”。无论是交互还是视觉,在初期接触电视产品设计时,可能都会因为“焦点”的设计失误引发用户体验问题,比如:焦点的移动顺序不一致(从哪里来未回到哪里去,焦点在界面中乱跳)使用户认知错乱;焦点的不够醒目或样式不统一使用户无法找到焦点等,如图13所示。
电视端焦点也是有着各种不同的状态的,如图14所示,“焦点状态”一般采用“描边、放大、高亮等”方式使其明显,而“按下状态”可能不一定有,或者是和其他几个状态相同。
可能需要简单讲述一下“标记状态”和“半选中状态”:“标记状态”在PC和手机端也非常常见,比如告知用户所在位置在哪里的Tab标记;而“半选中状态”是“焦点状态”的一种情况,即移动到某个焦点后,不进行加载或触发操作,需按“OK键”才触发,如图15所示。这种状态在早期电视盒子性能不足、在Tab切换时经常需要使用,因为如果直接切换焦点时就加载,可能会造成卡顿。
图15 标记状态和半选中状态案例
六、结语
我总结和归纳的这些基本知识和注意事项,虽然它们能够帮助我们快速了解电视大屏的基本交互知识,避免一些不必要的坑;但还远远不够,更多的是需要在实际参与项目中快速学习、快速应用,因此,之后我将会基于我参与的项目再次进行电视大屏的实战总结,欢迎下次再与大家一同交流和成长。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
JavaScript 创建动态页面。事件是可以被 JavaScript 侦测到的行为。 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件。比如说,当用户单击按钮或者提交表单数据时,就发生一个鼠标单击(onclick)事件,需要浏览器做出处理,返回给用户一个结果。主要事件表总结如下:
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com