概述
最近在找工作,遇到不少挫折,也许是自己的工作经验不太足,而且说话的技巧没那么好,有些知识也不太记得,故将此面试的挫折整理起来,以免将来再范。
1.自我介绍
尽量简短,说下自己的安卓之路,再加点自己的兴趣爱好即可。在谈到缺点时,我说了会半途而废,一大败点,切忌说这些程序员讨厌的词语。应该将一些无关大雅的,或者是可以改正的,可以提升自己的缺点给说出来。
2.什么是多线程
回答时只说了Thread类,然后new Thread.start(),太过简洁,肯定跪。这是一题经常会问的问题,所以将答案记于此处,以免遗忘。
多线程主要用于处理并发问题。
——多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。 线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。
——一个采用了多线程技术的应用程序可以更好地利用系统资源。其主要优势在于充分利用了CPU的空闲时间片,可以用尽可能少的时间来对用户的要求做出响应,使得进程的整体运行效率得到较大提高,同时增强了应用程序的灵活性。更为重要的是,由于同一进程的所有线程是共享同一内存,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。
——多个线程的执行是并发的,也就是在逻辑上“同时”,而不管是否是物理上的“同时”。如果系统只有一个CPU,那么真正的“同时”是不可能的,但是由于CPU的速度非常快,用户感觉不到其中的区别,因此我们也不用关心它,只需要设想各个线程是同时执行即可。
Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。
1、继承Thread类实现多线程
继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如:
public class MyThread extends Thread {
public void run() {
System.out.println("MyThread.run()");
}
}
在合适的地方启动线程如下:
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
2、实现Runnable接口方式实现多线程
如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口,如下:
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
事实上,当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run(),参考JDK源代码:
public void run() {
if (target != null) {
target.run();
}
}
3、使用ExecutorService、Callable、Future实现有返回结果的多线程
ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。想要详细了解Executor框架的可以访问http://www.javaeye.com/topic/366591 ,这里面对该框架做了很详细的解释。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。
可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在JDK1.5下验证过没问题可以直接使用。代码如下:
import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
/**
* 有返回值的线程
*/
@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,
InterruptedException {
System.out.println("----程序开始运行----");
Date date1 = new Date();
int taskSize = 5;
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 创建多个有返回值的任务
List<Future> list = new ArrayList<Future>();
for (int i = 0; i < taskSize; i++) {
Callable c = new MyCallable(i + " ");
// 执行任务并获取Future对象
Future f = pool.submit(c);
// System.out.println(">>>" + f.get().toString());
list.add(f);
}
// 关闭线程池
pool.shutdown();
// 获取所有并发任务的运行结果
for (Future f : list) {
// 从Future对象上获取任务的返回值,并输出到控制台
System.out.println(">>>" + f.get().toString());
}
Date date2 = new Date();
System.out.println("----程序结束运行----,程序运行时间【"
+ (date2.getTime() - date1.getTime()) + "毫秒】");
}
}
class MyCallable implements Callable<Object> {
private String taskNum;
MyCallable(String taskNum) {
this.taskNum = taskNum;
}
public Object call() throws Exception {
System.out.println(">>>" + taskNum + "任务启动");
Date dateTmp1 = new Date();
Thread.sleep(1000);
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(">>>" + taskNum + "任务终止");
return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
}
}
代码说明:
上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
3.Android5.0新特性
首先,在感官界面设计上,我们彻底迎来了Android系统的扁平化时代,新的系统不仅使用了新的配色,同时看起来也很时尚。未来我们相信包括三星的TouchWiz或LG的Optimus自定义UI都会遵循Lollipop的新风格。此外,谷歌全面改善了原来乏味的通知中心,让原生系统也拥有了像第三方插件那样强大的功能。另外,多任务系统也加入了更多的卡片式风格,同时还有大量的其它新特性,包括64位编译器和增强电池续航能力能。目前,除了Nexus设备之外,包括摩托罗拉、HTC等都表示旗下的智能手机大部分都支持升级到Android Lollipop,相信不就的将来我们将迎来一阵升级的热潮。下面让我们一起来看看Android 5.0 Lollipop新增的十个最主要变化。
1、全新Material Design设计风格
Android Lollipop全新的设计语言是受到了多种因素影响,是一种大胆的平面化创新。换句话说,谷歌希望能够让Material Design给用户带来纸张化的体验。新的视觉语言,在基本元素的处理上,借鉴了传统的印刷设计,字体版式、网格系统、空间、比例、配色、图像使用等这些基础的平面设计规范。
另外,Material Design还推崇实体隐喻理念,利用实体的表面与边缘的质感打造出视觉线索,让用户感受到真实。熟悉的触感让用户可以快速的理解、认知。在设计中可以灵活的运用物质,在符合物理规律的基础上,打造出不同的使用体验。最后是是有意义而且更合理的动态效果,为了吸引用户的注意力,以及维持整个系统的连续性体验。
2、支持多种设备
现在无论是智能手机、平板电脑、笔记本电脑、智能电视、汽车、智能手表甚至是各种家用电子产品,谷歌的Android系统已经可以在所有设备的屏幕上出现。而这一概念与微软不谋而合,之前微软也宣布将会把Windows 10打造成跨设备跨平台的统一系统,帮助自己走出困境。
3、全新的通知中心设计
谷歌在Android Lollipop中加入了全新风格的通知系统。改进后的通知系统会优先显示对用户来说比较重要的信息,而将不太紧急的内容隐藏起来。用户只需要向下滑动就可以查看全部的通知内容。
新的通知系统另外一个很酷的新功能是在锁屏界面也可以直接查看通知消息了。不仅如此,用户还可以直接在锁屏的情况下就行回复或进入应用。另外,如果在操作手机的过程中有电话进入,也不会进行全画面切换,而是同样以弹出通知的方式告知用户。
4、支持64位ART虚拟机
新系统不仅在视觉效果上带来了巨大的变化,Android Lollipop还在内部的性能上进行了飞跃。首先,新系统放弃了之前一直使用的Dalvik虚拟机,改用了ART模式,实现了真正的跨平台编译,在ARM、X86、MIPS等,无处不在。
ART虚拟机编译器在内存占用及应用程序加载时间上进行了大幅提升,谷歌承诺所有性能都会比原来提升一倍。另外,对64位的支持也让ART虚拟机如鱼得水,开发者可以针对像ARM Cortex-A57这样的64位架构核心开发应用程序。
Android Lollipop支持更大的寄存器,支持新的指令集,提升了内存寻址空间,未来Android智能手机将支持4GB以上的内存。
5、Project Volta电池续航改进计划
Project Volta计划增加了新工具可以让开发者能够更容易的找出为何自己的应用程序会对电量产生比较大的影响,同时确保在执行某型任务时将手机电量的影响降至最低。首先,Battery Historian可以列出手机电量消耗的详细情况,帮助开发者识别电量消耗的原因或者是哪个硬件或任务对电池寿命的影响比较大;而Job Scheduler API则可以让开发者更容易的选择合适的时机触发电量消耗比较高的任务,避免在低电量或未完成充电时更新应用程序。
上面是针对开发者的改进,而在用户层面上,Android Lollipop增加了Battery Saver模式,这与三星和HTC上的超级省电模式有些类似。在低电量的时候系统会自动降低屏幕亮度、限制自动更换背景等功能。
6、全新的“最近应用程序”
除了界面风格设计的改变之外,新的最近应用界面还借鉴了Chrome浏览器的理念,采用单独的标签展示方式。更重要的是,谷歌已经向开发者开放了API,所以第三方开发人员可以利用这个改进为特定的应用增加全新的功能。
7、改进安全性
现在个人识别解锁还是一个比较新鲜的智能概念,当用户的蓝牙耳机连接到手机或平板电脑时,设备可以基于当前的位置或用户的声音自动解锁。比如当特定的智能手表出现在Android设备的附近,那么就会直接绕过锁屏界面进行操作。而Android Lollipop也增加了这种针对特定特任识别解锁的模式。换句话说,当设备没有检测到附近有可用的信任设备时,就会启动安全模式防止未授权访问。
另外,Android Lollipop还默认开启了系统数据加密功能,并且通过SELinux执行应用程序,这就意味着对于恶意软件来说,新系统变得更加安全。
8、不同数据独立保存
谷歌表示Android Lollipop将拥有一个全新的特性,让用户通过一台设备就可以搞定所有的工作和生活娱乐活动。该特性首先将各种数据独立保存,并且让所有新数据的生成都有依据。
我们已经看到谷歌已经与三星加强了合作,包括三星的Knox安全系统同样可以像Android Lollipop一样将重要数据和其它数据分开保存。另外谷歌还允许向三星以外的Android设备提供支持。
9、改进搜索
谷歌将新系统的搜索功能重点放在了“重新发现”上,因此这意味着Google Search将会更好的意识到用户正在做什么。比如系统会根据用户当前的位置自动过滤无关的搜索结果。
另外,当用户在进行应用搜索时,可以直接展示相似或部分提示,并且进入特定的应用程序而无需将内容全部输入。
10、新的API支持,蓝牙4.1、USB Audio、多人分享等其它特性
Android Lollipop还增加了多个新的API支持、蓝牙4.1、USB Audio外接音响及多人分享等功能。其中多人分享功能可以在用户手机丢失的情况下,使用其它Lollipop设备登录账户,从云端下载联系人、日历等资料,并且不影响其它设备的内容。
4.cookie与session机制
如何实现HTTP的状态管理?
Cookie: 把多次请求涉及到的数据保存到客户端
Session: 把多次请求涉及到的数据保存到服务端
Cookie机制
把多次请求涉及到的数据保存到客户端
1>客户端发送普通请求,服务端接收请求,并且
在响应数据包中向客户端添加cookie信息,
希望客户端保存该cookie信息:
Set-Cookie : cishu=10
2>客户端接收响应数据包,解析响应数据包中的
消息头,获取cookie信息,把cookie信息保存
到客户端中。
3>客户端发送后续请求时,需要在请求数据包中
携带cookie信息:
Cookie : cishu=10
4>服务端接收请求数据包,解析出cookie数据,
执行后续业务逻辑,完成HTTP状态管理。
Cookie的限制:
1. Cookie不能保存大数据量的数据。
2. Cookie不能保存中文。
3. Cookie不安全。
Session机制:
把多次请求涉及到的数据保存在了服务端。
Session机制是基于Cookie机制的。
Session机制执行的过程中需要向客户端添加cookie。
1>客户端发送第一次请求,服务端接收请求,
把涉及到的数据保存在服务端Session对象中。
分配一个唯一的JSESSIONID与该对象构成映射关系。
在返回的响应数据包中携带Cookie消息头:
Set-Cookie:JSESSIONID=abcd
2>客户端接收响应,解析后吧JSESSIONID保存在
客户端中。
3>当发送后续请求时,在请求数据包中需要把
JSESSIONID以cookie的形式发送给服务端:
Cookie: JSESSIONID=abcd
4>服务端接收请求获取cookie中的JSESSIONID,
通过JSESSIONID找到上次请求涉及到的数据,
执行后续业务,完成HTTP状态管理。
Session机制相对来说比Cookie安全。
5.Material Design
概述-中文版网站http://wiki.jikexueyuan.com/project/material-design/
我们挑战自我,为用户创造了崭新的视觉设计语言。与此同时,新的设计语言除了遵循经典设计定则,还汲取了最新的科技,秉承了创新的设计理念。这就是原质化设计(Material Design)。这份文档是动态更新的,将会随着我们对 Material Design 的探索而不断迭代、升级。
目标
我们希冀创造一种新的视觉设计语言,能够遵循优秀设计的经典定则,同时还伴有创新理念和新的科技。
materialdesign-goals
我们希望创造一种独一无二的底层系统,在这个系统的基础之上,构建跨平台和超越设备尺寸的统一体验。遵循基本的移动设计定则,同时支持触摸、语音、鼠标、键盘等输入方式。
materialdesign-goals-cutrectangles
设计原则
materialdesign-principles-layersquares
实体感就是(通过设计方式来表达)隐喻
通过构建系统化的动效和空间合理化利用,并将两个理念合二为一,构成了实体隐喻。与众不同的触感是实体的基础,这一灵感来自我们对纸墨的研究,但是我们相信,随着科技的进步,应用前景将不可估量。
实体的表面和边缘提供基于真实效果的视觉体验,熟悉的触感让用户可以快速地理解和认知。实体的多样性可以让我们呈现出更多反映真实世界的设计效果,但同时又绝不会脱离客观的物理规律。
光效、表面质感、运动感这三点是解释物体运动规律、交互方式、空间关系的关键。真实的光效可以解释物体之间的交合关系、空间关系,以及单个物体的运动。
materialdesign-principles-circleplus_large_mdpi.png
鲜明、形象、深思熟虑
新的视觉语言,在基本元素的处理上,借鉴了传统的印刷设计——排版、网格、空间、比例、配色、图像使用——这些基础的平面设计规范。在这些设计基础上下功夫,不但可以愉悦用户,而且能够构建出视觉层级、视觉意义以及视觉聚焦。精心选择色彩、图像、选择合乎比例的字体、留白,力求构建出鲜明、形象的用户界面,让用户沉浸其中。
Material Design 设计语言强调根据用户行为凸显核心功能,进而为用户提供操作指引。
materialdesign-principles-flyingsquare
有意义的动画效果
动画效果(简称动效)可以有效地暗示、指引用户。动效的设计要根据用户行为而定,能够改变整体设计的触感。
动效应当在独立的场景呈现。通过动效,让物体的变化以更连续、更平滑的方式呈现给用户,让用户能够充分知晓所发生的变化。
动效应该是有意义的、合理的,动效的目的是为了吸引用户的注意力,以及维持整个系统的连续性体验。动效反馈需细腻、清爽。转场动效需高效、明晰。
环境
三维世界(3D world)
光影关系(Light and shadow)
三维世界(3D world)
Material 环境是一个三维的空间,这意味着每个对象都有 x , y , z 三维坐标属性,z 轴垂直于显示平面,并延伸向用户视角,每个 material 元素在 z 轴上占据一定的位置并且有一个 1dp 厚度的标准。 在网页上,z 轴被用来分层而不是为了视角。3D 空间通过操纵 y 轴进行仿真。
具备 x,y 和 z 轴的 3D 空间
具备 x,y 和 z 轴的 3D 空间
光影关系(Light and shadow) 在 material 环境中,虚拟的光线照射使场景中的对象投射出阴影,主光源投射出一个定向的阴影,而环境光从各个角度投射出连贯又柔和的阴影。
material 环境中的所有阴影都是由这两种光投射产生的,阴影是光线照射不到的地方,因为各个元素在z轴上占据了不同大小的位置遮挡住了这些光线。
直射光投射的阴影
散射光投射的阴影
直射光和散射光混合投影
Material 属性
材料拥有确定不变的特性和固定的行为。了解这些特性将有助于你在一定程度上熟悉材料,这与 Material Design 的构想是一致的。
物理特性
材料具有变化的长宽尺寸(以 dp 为计)和均匀的厚度(1dp)。
正确:Material 的高度和宽度都可以变化。
材料的高度和宽度是可变的。
错误:Material 总是 1 dp 厚。
材料总是 1dp 厚。
材料会形成阴影。
阴影是由于材料元件之间的相对高度(Z 轴位置)而自然产生的。
阴影描述材料元件之间的相对高度。
阴影随着材料高度的变化而产生变化。
内容可被以任何形状和颜色显示在材料上。
内容并不会增加材料的厚度。
材料能展示任何形状和颜色。
内容的展示能够独立于材料,但要被限制在材料的范围里。
内容的行为能独立于材料的行为。
材料是实物。
输入事件不能穿过材料。
正确说法:输入事件只影响 material 的前景。
输入事件只影响材料的前景。
错误说法:输入事件不能通过 material。
输入事件不能从材料下面穿过。
多个材料元件不能同时占用相同的空间点。
正确说法:利用高度来区分material元素,是防止多个 material 元素同时占据空间中同一个点的一种方法。
利用不同的高度区分材料元件是防止多个材料元件同时占用相同空间点的一个方法。
错误说法:多个material元素不能同时占据空间中的同一个点。
多个材料元件不能同时占用相同的空间点。
材料不能穿过其他材料。
例如,一片材料不能在改变高度时穿过另一片材料。
材料不能穿过其他材料。
材料的变化
材料能改变形状。
材料能改变形状
材料仅沿着它的水平面增长和收缩。
材料决不能弯曲或折叠。
几片材料能合在一起组成一片材料。
当材料被割开时,它还能自己复原。例如,你从一片材料中移除了一部分,这一片材料将再次变为一块完整的材料。
材料能被割开,还能再度变为完整。
材料的移动
材料能在环境中的任何地方自动产生或消失。
材料能自动产生或消失。
材料能沿任何轴移动。
材料可以沿各个轴移动。
Z轴产生运动一般都是用户与材料交互而产生的。
Z 轴的运动是由于用户的交互而产生的提示。
高度和阴影
Material design 中的对象与现实生活中的对象具有相似的性质。在现实生活中,不同对象可以被堆积或粘贴起来,但是不能彼此交叉。对象自身塑造了自己的阴影并返回自己的光影。
依据这些性质所构造出来的空间模型对于用户来说是非常熟悉的,这一模型也可以被长期应用于移动应用当中。支撑这一空间模型的正是“高度”(Elevation)和“光影”(Shadows)这两个概念。
高度(安卓)
阴影
元素关系
高度(安卓)
高度是在 Z 轴上两个不同平面之间的一种相对深度或距离。
详述:
“高度”的度量单位与 XY 轴的度量单位相同,主要是 DP。由于所有 Material 元素都具有 1 单位 DP 的厚度,所以“高度”度量的是从一个平面顶部到另一个平面顶部的距离。
一个子对象的高度与其父对象的高度相关。
这里是一些与安卓应用相关的图表和数据。
阴影影响
为自定义元素定义“阴影”
两个对象间的多种高度度量
静止高度
所有 Material 对象除去大小之外,还有一个“静止高度”,或者称“默认高度”,它是不会变化的。当一个对象的高度产生变化时,它将会尽快恢复到自身的静止高度。
组件高度
某一元素类型的静止高度在移动应用中是一个常量。(比如,FAB 高度不会在某一个应用中是 6 dp 而在另一个应用中是 16 dp)
元素在某一平台中可能会存在多种静止高度,这取决于环境的深度。(比如,TV 相比于移动端和桌面来说就具有更深的层次)
感应高度与动态高度偏移
一些元素类型拥有感应高度,也就是说它们会根据用户的输入(比如常规的、关注的和压制的)或系统事件来改变高度。这些高度的变化会通过动态高度偏移而不断生成。
动态高度偏移是某一元素移动的目标高度,它与该元素的静止状态有关。可以确定的是高度的变化在事件和元素类型中是持久发生的。比如说,所有通过按压来提升的元素相对于其静态高度来说都具有相似的高度变化。
一旦输入事件完成或被取消,那么元素将会恢复到它的静止高度上。
避免高度冲突
处于感应高度的元素当它在静止高度与动态高度偏移之间移动的时候可能会遇到其他的元素。由于 Material 不能相互交叉,没有任何一种方式能够让元素之间产生冲突,无论是基于均元素基础(per-component basis)还是通过使用完整应用布局。
在某一个元素水平上,元素可以在它们产生冲突之前提前移动或被移动。比如说,一个“浮动动作按钮”(FAB)可以在用户选择一张卡片之前消失或移出屏幕,或者它也可以在某一个 “snack bar” 出现时移动。
在布局水平上,你需要通过设计你的应用布局来将产生冲突的机会降到最低水平。比如说,可以通过将 FAB 置于某个卡片流的一端来避免当用户尝试获取某个卡片时所产生的冲突。
元素高度比较
下面的图表对比了多种元素的静止高度和动态高度偏移。
在这一图表中,只有高度的尺寸和元素布局是精确的。其他尺寸和整体的元素布局只是为了说明而列出的。
一个包含卡片和FAB应用布局的实例与它在Z轴上元素高度的横截面图表。
一个包含开放导航抽屉的应用布局实例与它在Z轴上元素高度的横截面图表。
阴影
“阴影”提供了对象深度和方向性移动的重要视觉线索。它们是唯一一种标示不同平面之间分离程度的视觉线索。某一对象的“高度”决定了其具体“阴影”的表现形式。
否。一旦没有了阴影,没有什么可以标示浮动动作按钮是从背景层分离出来的。
否。卷曲的阴影说明浮动动作按钮与“蓝层”(blue sheet)是两个分离开来的元素。然而,由于它们的阴影非常的相似以至于会被误认为它们在同一高度上。
是。更柔和、更大的阴影说明浮动动作按钮相比于拥有更卷曲阴影的“蓝层”(blue sheet)处于更高的高度之上。
在运动中,阴影提供了关于某个对象移动方向以及不同平面之间距离是否正在增加或减少的有用线索。
否。如果没有一个阴影来说明高度,那么就不能明确一个方形到底是它的自身尺寸在增加还是它的高度在增加。
是。当某一个对象的高度增加时其阴影会变得更柔和、更大,当其高度减小时,阴影会变得更卷曲。
是。在这一实例中,连贯的阴影帮助用户明白某一个对象看起来好像是它的高度在增加其实是它的形状在改变。
元素参考阴影
下面的元素阴影应被用于标准参考。如果在说明中涉及任何关于下面的参考阴影和元素阴影的不同情况出现,那么都归于参考阴影。
应用条
4dp
浮动按钮
静态:2dp
敲击状态:8dp
浮动动作按钮(FAB)
静态:6dp
敲击状态:12dp
卡片
静态:2dp
选中状态:8dp
菜单和子菜单
菜单:8dp
子菜单:9dp(为子菜单增加 1dp)
对话框
24dp
导航抽屉和右抽屉
16dp
底部单页
16dp
刷新按钮
3dp
快速查询/搜索条
静止状态:2dp
滚动状态:3dp
Snackbar
6dp
切换按钮
1dp
对象关系
对象层次
你怎样去组织在某一应用中的对象或对象集合取决于它们怎样依据其他对象来移动。对象可以独立自主地移动或在受到比它更高层次对象限制的条件下移动。
所有对象都是以“父-子”关系描述的层级体系的一部分。“子”元素在这一关系体系中代表它们“父”元素的下级元素。对象可以是这一系统的“子”元素或其他对象的“子”元素。
“父-子”元素说明:
每一个对象只有一个“父”元素。
每一个对象可能会有任意数量的“子”元素。
“子”元素继承来自“父”元素的可以转移的属性,比如位置、循环、刻度和高度。
“兄弟”元素是指与某一对象处在同一层级的对象。
例外
项目以根元素为父元素,比如主 UI 元素,它们相比于其他对象来说会自主移动。比如说,浮动动作按钮不会与内容一起转动。其他元素包括:
一个应用的边导航抽屉
动作条
对话
交互
某个对象与其他对象交互的方式由它们在“父-子”层次中所处位置决定。
比如:
“子”元素与其“父”元素在Z轴上的分离距离最近;其他对象不能插入父子元素之间。
在一个滚动的卡片集合中,所有卡片之间都是同层次的“兄弟”元素,因此它们就像坐在同一马车上的两个对象一样共同移动。它们都是控制它们移动的卡片集合对象的子元素。
高度
你会如何确定某些对象的高度(即它们在 Z 空间的位置)取决于你想描述的内容层次以及某一个对象是否需要相对于其他对象自主移动。
随着父表的移动,升高的按钮(它的子元素)会伴随着它移出屏幕。
随着卡片集合卷出了屏幕,它的子卡片也会随之卷出屏幕。浮动动作按钮保留在某一地点因为它的父元素没有被卷动。