Android UI样式详解
Android 样式采用xml文件,本篇文章主要对res目录作详细解释,包括了layout布局文件、menu菜单文件、style样式文件、string字符串资源等等
--res
|--anim 存放tween animation(补间动画)和frame animation(逐帧动画)
|--animator 存放property animation(属性动画)
|--transition 过渡动画
|--drawable 管理图片资源和xml资源,xml资源包括selector、shape、vector等等
|--layout 管理UI布局
|--menu 管理菜单布局
|--mipmap App启动图标
|--navigation Jetpack navigation导航
|--raw 打包后会原封不动的保存在apk包中,不会被编译成二进制,与assets一样,但又有所区别
|--values 颜色、像素、字符串、样式等资源
|--xml 偶尔用到,会被编译成二进制格式
2
3
4
5
6
7
8
9
10
11
12
# anim(View动画)
anim主要存放逐帧动画(frame animation)和补间动画(tween animation)
# 逐帧动画(frame animation)
在res下anim文件夹下创建一个animation-list标签的文件frame_anim.xml,内容如下
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100" />
<item
android:drawable="@drawable/a_1"
android:duration="100" />
<item
android:drawable="@drawable/a_2"
android:duration="100" />
</animation-list>
2
3
4
5
6
7
8
9
10
11
12
让逐帧动画动起来
ImageView mImageView = findViewById(R.id.animation_frame_anim);
mImageView.setImageResource(R.anim.frame_anim);
AnimationDrawable mAnimationDrawable = (AnimationDrawable) mImageView.getDrawable();
mAnimationDrawable.start()
2
3
4
5
6
7
8
9
- 在animtion-list中使用item定义动画的全部帧,并指定各帧的持续时间
- 在需要的ImageView上设置xml动画资源
- 获取该Imageiew的AnimationDrawable类,并调用它的方法start即可
# 补间动画(tween animation)
补间动画有两种使用方式,静态加载和动态加载,其五个动画标签,与其对应的Java类,如下
java类名 | xml健 | 功能描述 |
---|---|---|
ScaleAnimation | scale | 缩放 |
RotateAnimation | rotate | 旋转 |
TranslateAnimation | translate | 移动 |
AlphaAnimation | alpha | 淡入淡出 |
AnimationSet | set | 组合动画 |
xml静态加载方式会经过系统解析成动态方式,这五个类均继承Animation类,下面表格详细介绍了Animation的方法
xml属性 | java方法 | 说明 |
---|---|---|
android:duration | setDuration(long) | 动画持续时间,单位为ms |
android:detachWallpaper | setDetachWallpaper(boolean) | 是否在壁纸上运行 |
android:fillAfter | setFillAfter(boolean) | 控件结束时候是否保持动画的最后状态 |
android:fillBefore | setFillBefore(boolean) | 控件动画结束时是否还原到开始动画前的状态 |
android:fillEnabled | setFillEnabled(boolean) | 与android:fillBefore效果相同 |
android:interpolator | setInterpolator(Interpolator) | 设定插值器 |
android:repeatCount | setRepeateCount(int) | 重复次数 |
android:repeatMode | setRepeatMode(int) | 重复类型,2个值,reverse表示倒序回放,restart表示顺序播放 |
android:startOffset | setStartOffset(long) | 调用start函数之后等待开始运行的时间,单位ms |
android:zAdjustment | setZAdjustment(int) | 表示被设置动画的内容运行在Z轴上的位置(3个值,top/bottom/normal,默认为normal) |
# Interpolator
Interpolator 动画渲染器
在这些xml里有个东西:Interpolator,这个是用来控制动画的变化速度,我们可以自己实现Iinterpolator接口,自行来控制动画的变化速度,
而Android系统已经为我们提供了5个可供选择的实现类:
- LinearInterpolator 动画以均匀的速度改变
- AccelerateInterpolator 在动画开始的地方改变速度较慢,然后开始加速
- AccelerateDecelerateInterpolator 在动画开始、结束的地方改变速度较慢,中间时加速
- CycleInterpolator 动画循环播放特定次数,变化速度按正弦曲线改变: Math.sin(2 * mCycles * Math.PI * input)
- DecelerateInterpolator 在动画开始的地方改变速度较快,然后开始减速
- AnticipateInterpolator 反向,先向相反方向改变一段再加速播放
- AnticipateOversshootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
- BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
- OvershottInterpolator 回弹,最后超出目的值然后缓慢改变到目的值
我们一般是在写动画xml文件时会用到,属性是:android:interpolator, 而上面对应的值是:@android:anim/linear_interpolator,其实就是驼峰命名法变下划线而已 AccelerateDecelerateInterpolator对应:@android:anim/accelerate_decelerate_interpolator!
# 静态加载
# 属性解释
- scale
- duration 动画持续时间,单位ms
- fromXScale 沿着X轴缩放的起始比例
- fromYScale 沿着Y轴缩放的起始比例
- pivotX 缩放的中轴点的x坐标
- pivotY 缩放的中轴点的y坐标
- toXScale 沿着X轴缩放的结束比例
- toYScale 沿着Y轴缩放的结束比例
- rotate
- fromDegrees 旋转的起始角度
- toDegrees 旋转的结束角度
- duration 动画持续时间,单位ms
- interpolator 动画渲染器
- repeatCount 旋转的次数,如果值是n,则旋转n+1次,若n=-1或者infinite,表示动画永不停止
- translate
- duration 动画持续时间,单位ms
- fromXDelta 动画起始位置的x坐标
- fromYDelta 动画起始位置的y坐标
- toXDelta 动画结束位置的x坐标
- toYDelta 动画结束位置的y坐标
- alpha
- duration 动画持续时间,单位ms
- fromAlpha 起始透明度
- toAlpha 结束透明度,透明度范围:0-1,完全透明-完全不透明
- interpolator 动画渲染器
- set
- duration 动画持续时间,单位ms
- interpolator
- shareInterpolator 布尔值,true: 共享一个指定的Interpolator,flase,不共享,动画效果需要单独指定Interpolator
# 使用方法
静态加载方式是采用xml方式来实现补间动画
// 获取要设置补间动画的控件
ImageView mImageView = findViewById(R.id.iv_alpha);
//加载补间动画--alpha动画
Animation animation = AnimationUtils.loadAnimation(mImageView,R.anim.anim_alpha);
// Animation animation = AnimationUtils.loadAnimation(mImageView,R.anim.anim_scale);
// Animation animation = AnimationUtils.loadAnimation(mImageView,R.anim.anim_translate);
// Animation animation = AnimationUtils.loadAnimation(mImageView,R.anim.anim_rotate);
// Animation animation = AnimationUtils.loadAnimation(mImageView,R.anim.anim_set);
animation.setInterpolator(new LinearInterpolator());
//开始动画
mImageView.startAnimation(animation);
//设置动画状态监听
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复
}
});
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
# 动态加载
# 属性解释
- ScaleAnimation
- RotateAnimation
- TranslateAnimation
- AlphaAnimation
- AnimationSet
# 使用方法
动态加载是采用Java的方式
// 获取要设置补间动画的控件
ImageView mImageView = findViewById(R.id.iv_alpha);
//动态创建补间动画
AlphaAnimation mAlphaAnimation = new AlphaAnimation(0, 1);
mAlphaAnimation.setDuration(300);
//开始动画
mImageView.startAnimation(mAlphaAnimation);
//设置动画状态监听
mAlphaAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复
}
});
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
# animator(属性动画)
animator文件夹下存放属性动画(Property Animation),属性动画可以做到View动画做不到的情况,比如3D旋转动画;
属性动画实现原理就算改变控件的属性值实现的动画
Android 3.0, API 11之后才有属性动画。默认帧率10ms/帧,动画默认时间间隔300ms。
xml文件里有三个标签
- animator
- objectAnimator
- valueFrom
- valueTo
- propertyName
- startOffset
- duration
- interpolator
- set
# transition
# drawable & mipmap
Android 有多种存放图片资源的方式,最常用的就是drawable和mipmap两种方式,两者都可以添加图片,不过官方建议mipmap存放App应用图标,可见Android官方建议 (opens new window),两者有以下区别:
- mipmap不能放9patch图片
- mipmap支持多尺度缩放效果更好,更多用来存放应用图标
- png、jpeg、gif、.9图、xml均放在drawable
- drawable里图片需要准备多种密度的图片,以应对Android的碎片化问题
# 图片资源分类
图片资源最常用的是drawable资源,格式有png(推荐)、jpg(可接受)、gif(不建议),使用图片资源需要根据不同屏幕密度提供多张不同尺寸的图片,如下表:
密度分类 | 密度值范围 | 代表分辨率 | 图标尺寸 | 图片比例 |
---|---|---|---|---|
mdpi | 120~160dpi | 320x480px | 48✖48px | 1 |
hdpi | 160~240dpi | 480x480px | 72x72px | 1.5 |
xhdpi | 240~320dpi | 720x1280px | 96x96px | 2 |
xxhdpi | 320~480dpi | 1080x1920px | 144x144 | 3 |
xxxhdpi | 480~640dpi | 1440x2560px | 192x192px | 4 |
# 应用图标规范
Android官方建议将应用图标存放在mipmap目录中,而不是drawable目录中,与drawable不同,所有mipmap目录都会保留在APK中,即使基于构建特定密度的APK
也是如此,这样,起动器应用便可选取要显示在主屏幕上的最佳分辨率图标。
res/
mipmap-xxxhdpi/
launcher.png
mipmap-xxhdpi/
launcher.png
mipmap-xhdpi/
launcher.png
mipmap-hdpi/
launcher.png
mipmap-mdpi/
launcher.png
2
3
4
5
6
7
8
9
10
11
12
13
# xml资源
# selector
# shape
- rectangle
- oval
- line
- ring
属性 | 描述 |
---|---|
android:color | 填充的颜色 |
# layout
该目录主要存放UI布局,由于Android的碎片化问题,布局设计要十分灵活,主要有以下几种技巧
- 使用允许布局调整大小的视图尺寸
- 根据屏幕配置创建备用布局界面
- 使用最小宽度限定符
-sw600dp: 希望在屏幕宽度至少为 600dp 时使用该布局
下面是最小宽度值与典型屏幕尺寸的对应关系
- 320dp:典型手机屏幕(240x320 ldpi、320x480 mdpi、480x800 hdpi等等)
- 480dp:约5英寸的大手机屏幕(480x800 mdpi)
- 600dp:7英寸平板电脑(600x1024 mdpi)
- 720dp:10英寸平板电脑(720x1280 mdpi、800x1280 mdpi)
- 使用可用宽度限定符
-w600dp: 希望在屏幕宽度至少为 600dp 时使用该布局
- 使用可用高度限定符
-h600dp: 希望在屏幕高度至少为 600dp 时使用该布局
- 使用屏幕方向限定符
-land: 横向布局、-port:纵向布局
-sw600dp-land: 希望在屏幕宽度至少为 600dp 且为横向布局时使用该布局
- 使用Fragment将界面组件模块化
- 提供可以随试图一起拉伸的位图
- .9.png 图片
# menu
菜单是Android应用中非常重要的组成部分,主要分为以下三类:
- 选项菜单
- 上下文菜单
- 上下文操作模式以及弹出菜单
menu 也有两种方式设置,即xml静态方式和java动态方式
Java类名 | xml关键字 | 功能描述 |
---|---|---|
menu | menu | 菜单项的容器 |
group | group | item的不可见容器 |
MenuItem | item | 菜单项 |
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group>
<item
android:id="@+id/nav_one"
android:enabled="true"
android:icon="@drawable/icon_elab_select"
android:title="@string/e_lab"
app:showAsAction="ifRoom" />
</group>
<item
android:id="@+id/nav_two"
android:enabled="true"
android:icon="@drawable/icon_mail_select"
android:title="@string/maillist"
app:showAsAction="ifRoom" />
</menu>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19