笔记
new View()
,它的layoutParam
默认是wrap_content
wrap_content看的是 子view 的大小,match_parent看的是 父view 的大小。
父view 是wrap_content,子view1 有个是具体值 则父view 大小就是子view1的大小(其他子view 是match_parent最大也是 子view1 的大小)(子view1的位置也可以不在第一个位置)【即具体值优先】
SurfaceView
SurfaceView使用步骤
- 继承SurfaceView实现 SurfaceHolder.Callback 重写三方法
- 在构造方法中获得SurfaceHolder对象:getHolder
- 在构造方法中SurfaceHolder对象通过调用addCallback获得回调函数
- 在surfaceCreated中进行SurfaceHolder对象通过调用lockCanvas锁定画布,获得Canvas对象
- Canvas进行绘制操作
- SurfaceHolder对象通过调用unlockCanvasAndPost解锁画布
SurfaceView双缓冲应用
双缓冲是为了防止动画闪烁而实现的一种多线程应用,基于SurfaceView的双缓冲实现很简单,开一条线程并在其中绘图即可。本文介绍基于SurfaceView的双缓冲实现,以及介绍类似的更高效的实现方法。
SurfaceView每次绘图都会锁定Canvas,也就是说同一片区域这次没画完下次就不能画,因此要提高双缓冲的效率,就得开一条线程专门画图,开另外一条线程做预处理的工作。
1 |
|
1 | package com.testSurfaceView; |
安卓自带的几个颜色
colorPrimaryDark
:状态栏颜色colorPrimary
:appbar颜色textColorPrimary
:appbar左侧字体颜色windowBackground
:屏幕颜色navigationBarColor
:导航栏颜色
让整个App变灰色
方法一:
1 | public View onCreateView({ View parent, String name, Context context, AttributeSet attrs) |
方法二:
1 | setContentView(R.layout.activity_scrolling) |
布局
LinearLayout线性布局
有权重layout_weight来设置各自布局大小比例
百分比布局
PercentRelativeLayout百分比布局
PercentFrameLayout百分比布局
是新增的布局
具体使用:
在
app/build.gradle
的dependences闭包中添加1
2
3
4dependencies{
compile 'com.android.support:percent:24.2.1'
...
}在布局中使用
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<android.support.percent.PercentFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:text="Button 1"
android:layout_gravity="left|top"
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"/>
<Button
android:id="@+id/button2"
android:text="Button 2"
android:layout_gravity="right|top"
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"/>
<Button
android:id="@+id/button3"
android:text="Button 3"
android:layout_gravity="left|bottom"
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"/>
<Button
android:id="@+id/button4"
android:text="Button 4"
android:layout_gravity="right|bottom"
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"/>
</android.support.percent.PercentFrameLayout>PercentFrameLayout还有FrameLayout的属性,所以加了layout_gravity属性使得上面的布局就是左上、右上、左下、右下四个按钮均分的。
动画
补间动画
1 |
|
1 |
|
Bitmap
配置信息与压缩方式
Bitmap中有两个内部枚举类:
- Config是用来设置颜色配置信息
- CompressFormat是用来设置压缩方式
Config | 单位像素所占字节数 | 解析 |
---|---|---|
Bitmap.Config.ALPHA_8 | 1 | 颜色信息只由透明度组成,占8位 |
Bitmap.Config.ARGB_4444 | 2 | 颜色信息由rgba四部分组成,每个部分都占4位,总共占16位 |
Bitmap.Config.ARGB_8888 | 4 | 颜色信息由rgba四部分组成,每个部分都占8位,总共占32位。是Bitmap默认的颜色配置信息,也是最占空间的一种配置 |
Bitmap.Config.RGB_565 | 2 | 颜色信息由rgb三部分组成,R占5位,G占6位,B占5位,总共占16位 |
RGBA_F16 | 8 | Android 8.0 新增(更丰富的色彩表现HDR) |
HARDWARE | Special | Android 8.0 新增 (Bitmap直接存储在graphic memory) |
通常我们优化Bitmap时,当需要做性能优化或者防止OOM,我们通常会使用Bitmap.Config.RGB_565这个配置,因为Bitmap.Config.ALPHA_8只有透明度,显示一般图片没有意义,Bitmap.Config.ARGB_4444显示图片不清楚,Bitmap.Config.ARGB_8888占用内存最多。
CompressFormat | 解析 |
---|---|
Bitmap.CompressFormat.JPEG | 表示以JPEG压缩算法进行图像压缩,压缩后的格式可以是”.jpg”或者”.jpeg”,是一种有损压缩 |
Bitmap.CompressFormat.PNG | 颜色信息由rgba四部分组成,每个部分都占4位,总共占16位 |
Bitmap.Config.ARGB_8888 | 颜色信息由rgba四部分组成,每个部分都占8位,总共占32位。是Bitmap默认的颜色配置信息,也是最占空间的一种配置 |
Bitmap.Config.RGB_565 | 颜色信息由rgb三部分组成,R占5位,G占6位,B占5位,总共占16位 |
常用操作
裁剪、缩放、旋转、移动
1 | Matrix matrix = new Matrix(); |
虽然Matrix还可以调用postSkew方法进行倾斜操作,但是却不可以在此时创建Bitmap时使用。
Bitmap与Drawable转换
1 | // Drawable -> Bitmap |
保存与释放
1 | Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test); |
图片压缩
1 | public static Bitmap compressImage(Bitmap image) { |
BitmapFactory
Bitmap创建流程
Option类
常用方法 | 说明 |
---|---|
boolean inJustDecodeBounds | 如果设置为true,不获取图片,不分配内存,但会返回图片的高度宽度信息 |
int inSampleSize | 图片缩放的倍数 |
int outWidth | 获取图片的宽度值 |
int outHeight | 获取图片的高度值 |
int inDensity | 用于位图的像素压缩比 |
int inTargetDensity | 用于目标位图的像素压缩比(要生成的位图) |
byte[] inTempStorage | 创建临时文件,将图片存储 |
boolean inScaled | 设置为true时进行图片压缩,从inDensity到inTargetDensity |
boolean inDither | 如果为true,解码器尝试抖动解码 |
Bitmap.Config inPreferredConfig | 设置解码器这个值是设置色彩模式,默认值是ARGB_8888,在这个模式下,一个像素点占用4bytes空间,一般对透明度不做要求的话,一般采用RGB_565模式,这个模式下一个像素点占用2bytes |
String outMimeType | 设置解码图像 |
boolean inPurgeable | 当存储Pixel的内存空间在系统内存不足时是否可以被回收 |
boolean inInputShareable | inPurgeable为true情况下才生效,是否可以共享一个InputStream |
boolean inPreferQualityOverSpeed | 为true则优先保证Bitmap质量其次是解码速度 |
boolean inMutable | 配置Bitmap是否可以更改,比如:在Bitmap上隔几个像素加一条线段 |
int inScreenDensity | 当前屏幕的像素密度 |
基本使用
1 | try { |
内存回收
1 | if(bitmap != null && !bitmap.isRecycled()){ |
Bitmap类的构造方法都是私有的,所以开发者不能直接new出一个Bitmap对象,只能通过BitmapFactory类的各种静态方法来实例化一个Bitmap。仔细查看BitmapFactory的源代码可以看到,生成Bitmap对象最终都是通过JNI调用方式实现的。所以,加载Bitmap到内存里以后,是包含两部分内存区域的。简单的说,一部分是Java部分的,一部分是C部分的。这个Bitmap对象是由Java部分分配的,不用的时候系统就会自动回收了,但是那个对应的C可用的内存区域,虚拟机是不能直接回收的,这个只能调用底层的功能释放。所以需要调用recycle()方法来释放C部分的内存。从Bitmap类的源代码也可以看到,recycle()方法里也的确是调用了JNI方法了的。
相关链接
防重复点击
法1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public class FastClickAvoider {
private long lastClickTime;
private long timeSpace = 500;
public FastClickAvoider(){
super();
}
public FastClickAvoider(long timeSpace){
this.timeSpace = timeSpace;
}
public synchronized boolean isFastClick() {
long time = System.currentTimeMillis();
if (time - lastClickTime < timeSpace) {
return true;
}
lastClickTime = time;
return false;
}
}使用
1
2
3
4
5
6
7
8
9
10
11protected FastClickAvoider fastClickAvoider;
//自定义控件的构造函数或者BaseActivity的onCreate中实例化
if (fastClickAvoider == null) {
fastClickAvoider = new FastClickAvoider();
}
//在点击事件中调用
if (fastClickAvoider != null && !fastClickAvoider.isFastClick()) {
//do Something
}
制作vector
- 下载软件Vector Magic 。如破解版
- 解压它,然后根据步骤进行破解
- 使用:
- 用上面的软件保存“svg”类型的文件
- 打开 http://inloop.github.io/svg2android/ 把上一步生成好的一个或多个svg文件拖入,然后下载下来
- 将下载好的xml文件放入安卓项目的
res/drawable
里
inflate
Android inflate的三种用法
inflate是用来把XML定义好的布局找出来,inflate之后并没有直接显示,需要再加入到其他布局当中才能显示,以下是inflate的三种使用方式:
- 使用
LayoutInflater.inflate
方法 - 使用
context.getSystemService
方法 - 使用
View.inflate
方法
1 | //方法3:使用View.inflate方法 |
LayoutInflater.inflate()详解
结论:推荐使用
inflater.inflate(R.layout.item, parent, false);
构造方法可转成四个方法
1 | inflater.inflate(R.layout.item, null, true); |
第一个参数:想要添加的布局
第二个参数:想要添加到哪个布局上面
为null则第三个参数无效,第一个参数中最外层的布局大小无效
第三个参数:是否直接添加到第二个参数布局上面
为true:layout文件会默认调addView添加到parent中;
为false:以其他方式添加进parent中。
例子:
Activity布局(parent)
1 |
|
要添加的布局layout.xml
1 |
|
使用:
1 |
|
其中的inflater.inflate(R.layout.layout, rl, false);
改成四种情况是:
inflater.inflate(R.layout.layout, null, true);
inflater.inflate(R.layout.layout, null, false);
inflater.inflate(R.layout.layout, rl, true);
这种情况不能再调用 addView 会报错(
java.lang.IllegalStateException:The specified child already has a parent.Yout must call removeView() on the child's parent first.
)inflater.inflate(R.layout.layout, rl, false);
tablayout
它有默认宽高:如果想要这个默认宽高不起效,加:
1 | app:tabMaxWidth="0dp" |
performClick 与 onCallClick
API等级
performClick是在API 1中加入
callOnClick是在API 15 中加入代码实现层面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/**
* Directly call any attached OnClickListener. Unlike {@link #performClick()},
* this only calls the listener, and does not do any associated clicking
* actions like reporting an accessibility event.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
public boolean callOnClick() {
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
li.mOnClickListener.onClick(this);
return true;
}
return false;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
* a sound, etc.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
return result;
}
从代码中可以看出,callOnClick是performClick的简化版,不包含点击播放声音,不具有辅助功能,那么什么是辅助功能,给出官方介绍如下:
许多Android用户有不同的能力(限制),这要求他们以不同的方式使用他们的Android设备。这些限制包括视力,肢体或与年龄有关,这些限制阻碍了他们看到或充分使用触摸屏,而用户的听力丧失,让他们可能无法感知声音信息和警报。
Android提供了辅助功能的特性和服务帮助这些用户更容易的使用他们的设备,这些功能包括语音合成、触觉反馈、手势导航、轨迹球和方向键导航。Android应用程序开发人员可以利用这些服务,使他们的应用程序更贴近用户。