《Android进阶之光》读书笔记(一)

Posted by alonealice on 2017-07-14

最近买了一本《Android进阶之光》,看了之后确实有很多之前不了解或是不熟悉的知识,所以记个笔记,以便之后更好的巩固和复习。

Android5.0新特性

RecyclerView分割线

RecyclerView在设置分割线的时候需要自定义(我之前在使用时一般都是直接在布局文件中放根线)。自定义RecyclerView的分割线时,需要创建一个class并且继承RecyclerView.ItemDecoration。继承该类之后需要重写onDraw方法。在该方法中,可以根据recyclerView排列情况,使用canvas绘制分割线。

折叠式和悬浮式Notification

可以通过创建RemoteViews,在设置notification.bigContentView=remoteView;设置可折叠的通知。这类通知在外表看起来与普通的通知完全一样,滑动时,可将折叠部分展示出来。

如果直接将折叠的view设置到普通的content中:notification.contentView=remoteView;,那通知会显示一个被裁剪掉的view。
可以通过设置PendingIntent pendingIntent=PendingIntent.getActivity (this,0,intent,PendingIntent.FLAG_CANCEL_CURRENT); builder.setFullScreenIntent (pendingIntent,true)显示悬浮式的notification。

Notification显示等级

Notification有3个显示等级:
VISIBILITY_PUBLIC:在任何情况下都能显示
VISIBILITY_PRIVATE:只有在没有锁屏时显示通知
VISIBILITY_SECRET:在pin和password等安全锁和没有锁屏的情况下才能够显示的通知。

palette取色器

可以使用Palette来获取bitmap的色调,从而是界面色调一致。
要使用Palette之前,要先引入包:compile 'com.android.support:palette-v7:25.0.0'
使用方法:

1
2
3
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.image);
Palette palette=Palette.from(bitmap).generate();
imageView.setImageDrawable(new ColorDrawable(palette.getVibrantSwatch().getRgb()));

其中generate方法有两个,一个同步,一个异步。

Android6.0新特性

应用权限管理

在之前的Android版本中,应用的权限会在应用安装时授予,而6.0以后,系统不会在安装时授予应用权限,所以应用不得不在需要使用这些权限时,逐个向用户请求。
对于targetSdkVersion<23的应用,系统依旧会授予所申请的权限,这也就保证了之前开发的应用不会在运行时因为权限问题崩溃(想偷懒的话可以这么干)。

Normal Permission与Danger Permission

Android6.0以后的版本中,权限分两钟,一种是Normal Permission,这类权限一般不涉及到用户隐私,比如网络权限、震动权限,系统会直接授予;另一种是Danger Permission,这种权限一般涉及到用户隐私。这类权限是以分组的形式给出,有如下分组:
android.permission.group.CALENDAR (日历权限,包含读取日历和改写日历)
android.permission.group.CAMERA (相机权限)
android.permission.group.CONTACTS (联系人权限 包含读、写联系人)
android.permission.group.LOCATION (位置权限 包含精确、粗略位置)
android.permission.group.MICROPHONE (话筒权限)
android.permission.group.PHONE (电话权限)
android.permission.group.SENSORS (传感器权限)
android.permission.group.SMS (短信权限)
android.permission.group.STORAGE (存储权限 包含读、写sd卡)
这些权限组中,只要一个被授予了,那么整组都会被授予。

我们可以通过ActivityCompat.checkSelfPermissionContextCompat.checkSelfPermission来检查权限:

1
2
3
4
5
6
7
8
if(ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED){
//do
}else{
//申请权限
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}

同时在Activity中重写onRequestPermissionsResult方法,当requestCode返回为1时,说明权限申请成功。

Android7.0新特性

多窗口模式

当长按菜单键时,应用进入多窗口模式。activity的生命周期如下:onPause->onStop->onDestory->onCreate->onStart->onPause,当我们点击该窗口时,会进入onResume,这里可以看到,开启多窗口时,activity会先销毁,在创建。当我们推出多窗口模式时也一样,一用会先销毁,再创建,但是会直接进入到onResume中。

我们可以在Application中设置android:resizeableActivity="false"禁止多窗口模式。但是当targetSdkVersion<24时,该设置会无效,在这种情况下,我们可以这只activity android:screenOrientation="portrait"禁止屏幕旋转,来达到禁止多窗口模式的效果。

Material Design

Material Design相关控件

SnakeBar可以通过setAction来添加操作,同时,make方法中的view参数是Snake的父控件,可以确保其显示在正确的位置(不过我试了发现不管传什么view其都显示在最下面)。

TextInputLayout里面有且只有一个edittext,它可以使edittext在点击后依旧在输入框上面显示hint内容。除此之外,更加友好的提示错误信息:

1
2
textInputLayout.setErrorEnable(true);
textInputLayout.setError(“错误信息”);

这样可以在输入框下面显示错误提示
hint的颜色可以通过修改colorAccent修改。

TabLayout可以设置app:tabMode="scrollable"来使其可以滑动,当不设置或者设置为app:tabMode="fixed时,所有的item都会挤在一个页面宽度中。

NaviationView实现侧滑菜单功能,它主要是与DrawerLayout同用。它可以通过设置app:headerLayout=""引入头文件,app:menu=""引入菜单文件,菜单文件中可以通过设置group来设置分组,group可以设置”android:checkableBehavior="single"来设置只能选一个。

Coordinatorlayout可以是toolbar随着滑动消失,toolbar需要设置app:layout_scrollFlags="scroll|enterAlways"(toolbar要包含在AppBarLayout中)。
Coordinatorlayout配合CollapsingToolbarLayout可以使Toolbar折叠,代码如下:

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
31
32
33
34
35
36
37
38
39
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="#f24242"
android:minHeight="100dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">

<LinearLayout
...
</LinearLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v7.widget.RecyclerView>

解释几个CollapsingToolbarLayout关键的参数:
app:contentScrim="#f24242"设置收缩后的顶部颜色
app:expandedTitleGravity="center"表示展开后文字的位置,默认是left|bottom
app:layout_scrollFlags= "scroll|exitUntilCollapsed"表示既随着滑动收缩,又保留在顶部,如果设置为app:layout_scrollFlags= "scroll|enterAlwaysCollapsed"
app:layout_scrollFlags= "scroll|enterAlways",则表示既收缩,但是不保留,最终会划走。

自定义Behavior

自定义Behavior需要继承CollapsingToolbarLayout.Behavior<View类,实现方法主要分两种,一种是view监听CollapsingToolbarLayout状态,这种情况时我们需要重写onStartNestedScroll、和onNestedPreScroll方法;另一种是监听另一个view的变化,这种情况时需要重写layoutDependsOn方法和onDependentViewChange方法。

1
2
3
4
5
6
7
8
9
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
View child, View directTargetChild, View target, int nestedScrollAxes) {
return false;
}

public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target,
int dx, int dy, int[] consumed) {
// Do nothing
}

onStartNestedScroll方法的返回值表示这次滑动我们是否关心,而onNestedScrollAccepted表示滑动时的变化。

onNestedScrollAccepted方法的child表示设置了当前Behavior的view,dx,dy表示滑动的距离。

1
2
3
4
5
6
7
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return false;
}

public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
return false;
}

layoutDependsOn返回我们是否需要对本次滑动关心,而onDependentViewChanged表示滑动时的变化。layoutDependsOnonDependentViewChanged方法中的child表示设置Behavior的view,dependency表示我们关心的view
``