android系统新特性——用户界面以及系统界面改进

用户界面改进

Android用户界面改进最明显的就是MD了。MD是Google于2014年推出的设计语言,它是一套完整的设计系统,包含了动画、样式、布局、组件等一系列与设计有关的元素。通过对这些行为的描述,让开发者设计出更符合目标的软件,同时对这些软件的功能也更易于用户的理解。除此之外,还有另外两个用户界面方面的改进,包括:

  • 多窗口功能
  • App Shortcuts

多窗口功能

在Android7之前的版本上,所有activity都是全屏的,如果不设置透明效果,一次只能看到一个activity的界面。但是从Android7开始,系统支持了多窗口的功能。在有了多窗口支持之后,用户可以同时打开和看到多个应用的界面。这对于用户来说,是非常方便的。

Android上的多窗口功能有下面3种模式。

  • 二分屏模式

    这种模式主要在手机上使用。该模式将屏幕一分为二,同时显示两个应用的界面。屏幕中间是一条可以移动调整窗口大小的分隔线。

  • 画中画模式

    这种模式主要在TV上使用,在该模式下,某个应用的界面(通常是视频播放类应用)以一个小的浮动窗口形式在屏幕上显示。在Android8上,系统支持在tv之外的设备上使用这一功能。例如,手机上的视频聊天软件可以利用这一功能。

  • Freeform模式

    这种模式类似于常见的桌面操作系统,窗口可以自由拖动和修改大小。但这一功能,在手机设备上,使用起来不是很方便,因此系统上没有提供直接打开这一功能的入口。Android7上,想要打开这一功能,需要借助命令行。

    将设备连上pc之后,执行以下两条adb命令即可打开freeform模式:

    (1)adb shell settings put global enable_freeform_support 1。

    (2)然后重启手机:adb reboot。

    重启之后,在近期任务界面会出现一个按钮,这个按钮可以将窗口切换到freeform模式。可能在有些手机上会报权限错误,这个大家可以Google下如何解决。

开发者相关

生命周期

多窗口不影响和改变原先activity的生命周期。

在多窗口模式下,多个activity可以同时可见,但只有一个activity是resumed状态。所有其他activity都会处于paused状态(尽管它们是可见的)。

在以下三种场景下,系统会通知应用有状态变化,应用可以进行处理:

  • 当用户以多窗口的模式启动的应用
  • 当用户改变了activity的窗口大小
  • 当用户将应用窗口从多窗口模式改为全屏模式

Manifest新增属性

AndroidManifest.xml中新增了下面两个属性来进行多窗口的控制。

  • android:resizeableActivity=["true"|"false"]

    这个属性可以用在activity或者application中。如果该属性设置为true,activity将能以分屏和自由形状模式启动。如果此属性设置为false,activity将不支持多窗口模式。如果该值为false,且用户尝试在多窗口模式下启动activity,该activity将全屏显示。对于api目标level为24或更高级别的应用来说,这个值默认是true。

  • android:supportsPictureInPicture=["true"|"false"]

    这个属性用在activity上,表示该activity是否支持画中画模式。如果android:resizeableActivity=false,这个属性值将被忽略。

Layout新增属性

除了AndroidManifest.xml,在layout文件中,也新增了一些属性来进行相应的控制。

  • android:defaultWidth、android:defaultHeight指定了freeform模式下的默认宽度和高度
  • android:gravity指定了freeform模式下的初始gravity
  • android:minWidth、android:minHeight指定了分屏和freeform模式下的最小高度和宽度。如果用户在分屏模式中移动分界线,使activity尺寸低于指定的最小值,系统会将activity剪裁为用户请求的尺寸。
css 复制代码
 <activity
            android:supportsPictureInPicture="true"
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <layout android:defaultHeight="500dp"
                android:gravity="top|end"
                android:minHeight="450dp"
                android:minWidth="300dp"
                android:defaultWidth="600dp">

            </layout>
        </activity>
css 复制代码
package com.mvp.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import com.mvp.myapplication.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'myapplication' library on application startup.
    static {
        System.loadLibrary("myapplication");
    }

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());
        
//        Android7上还增加了下面这些api:
//        this.isInMultiWindowMode()//查询是否处于多窗口模式
//        this.isInPictureInPictureMode()//查询是否处于画中画模式
//        this.onMultiWindowModeChanged();//多窗口模式变化时进行通知(进入或退出多窗口)
//        this.onPictureInPictureModeChanged();//画中画模式变化时进行通知(进入或退出画中画模式)
        this.enterPictureInPictureMode();//进入画中画模式,如果系统不支持,这个调用无效
    }


    /**
     * A native method that is implemented by the 'myapplication' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

至于多窗口功能的实现主要依赖于ams和wms这两个系统服务,它们都位于system_server进程中。前者负责所有activity的管理,后者负责所有窗口的管理(不仅activity具有窗口,其他模块也会有窗口,例如,输入法)。ams和wms需要配合一起工作,因为无论是创建还是销毁activity都涉及activity对象和窗口对象的创建和销毁。

App Shortcuts

App Shortcuts是Android7.1上推出的新功能。借助于这项功能,应用程序可以在launcher中放置一些常用的应用入口以方便用户使用。

每个shortcut可以对应一个或者多个intent,它们各自会通过特定的intent来启动应用程序,例如:

  • 对于一个地图应用,可以提供一个shortcut导航用户至某个特定的地点
  • 对于一个通信应用,可以提供一个shortcut来发送消息给好友
  • 对于一个视频应用,可以提供一个shortcut来播放某个电视剧

当一个shortcut包括了多个intent时,用户的一次点击会触发所有这些intent,其中的最后一个intent决定了用户所看到的结果。

开发者API

使用shortcuts有两种方式。

  • 动态形式:在运行时,通过ShortcutManager API来进行注册。通过这种方式,可以在运行时,动态地发布、更新和删除shortcut。
  • 静态形式:在apk中包含一个资源文件来描述shortcut。这种注册方法将导致:如果要更新shortcut,必须更新整个应用程序。
    目前,每个应用程序最多可以注册4个shortcuts,无论是动态形式还是静态形式。

具体用户,读者可以参考下面这篇博客:https://www.jianshu.com/p/6b6f79096256

系统界面改进

系统界面属于系统的一部分。系统上方的status bar,以及下方的navigation bar都属于系统界面。除此之外,近期任务界面、锁屏也都是属于系统界面。可见,系统界面是用户交互最多的ui元素。

systemUI整体介绍

AOSP源码中,包含了两类Android应用程序:

  • 一类是系统的内置应用,这些应用提供了手机的基本功能。包括launcher、系统设置、电话、相机等。它们位于/packages/apps/目录下。理论上,这些应用都是可以被第三方应用所替代的,例如:我们完全可以安装一个第三方的电话、相机,而不使用系统的,这也是Android系统最为灵活的地方(注意:系统设置通常无法被第三方应用替代,因为它使用了一些拥有非常高权限的内部api。为了保证系统安装,这些api很多不会对外开放)。
  • 另外一类应用,则是属于framework的一部分,这些应用是无法被第三方应用所替代的。它们位于/frameworks/base/packages目录下,包括了systemUI、VpnDialogs等。

整个systemUI 由一个application的子类systemUIApplication进行初始化,application对应了整个应用程序的全局状态。系统会保证,application对象一定是应用程序中第一个实例化的对象。并且,application的oncreate方法一定早于应用中所有的activity、service、broadcastreceiver(但是不包含contentProvider)创建之前被调用。

systemUIApplication负责了所有systemUI组件的初始化,这其中就包含了最常见的system Bar(status Bar和navigation Bar合称为system Bar)。

system Bar虽然是系统的一部分,但是为了让应用能够提供更好的用户体验,系统提供了接口来进行控制。开发者可以根据需要来显示或隐藏status bar和navigation bar(它们中两者之一或者全部)。

三种模式

对于system bar的控制,Android系统定义了三种场景模式:

  • Lights Out模式
    这是Android4.4之前版本上的模式,这种模式的行为是:当用户几秒钟内没有操作的情况下,action bar和status bar会被淡化成不可用状态。但是navigation bar是正常可用的,虽然它会被dim。如果在4.4之后的版本上开发,考虑下面这两种模式。
  • Lean Back模式
    在这种模式下,system bar虽然是隐藏的,每当用户轻触屏幕时,它们会重新显示出来变成可用。因此,这种模式适合于用户无须频繁交互的应用,例如播放视频。
  • Immersive模式
    在这种模式下,只有当用户从屏幕边缘滑向屏幕中间时,system bar才会显示出来。因此这种模式适用于需要频繁交互但用户不太需要system bar的应用。例如,全屏游戏或者画图软件。

api与使用场景
https://www.jianshu.com/p/7de7bcf604b0

沉浸式全屏

Android4.4引用了一个新的flag:SYSTEM_UI_FLAG_IMMERSIVE。使用这个flag可以使你的应用获得真正的全屏。当这个flag与SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN组合起来使用时,会隐藏整个system bar使得应用获取整个屏幕的触摸事件。

由于应用接受了全部的触摸事件,只有当用户从屏幕边缘往内部滑动时,system bar才会显示出来。这样会清除SYSTEM_UI_FLAG_HIDE_NAVIGATION(如果设置了SYSTEM_UI_FLAG_FULLSCREEN也会被清除)。如果希望system bar在这之后再次自动隐藏起来,可同时设置SYSTEM_UI_FLAG_IMMERSIVE_STICKY。

提醒气泡:

当应用程序中首次进入沉浸式模式时,系统会显示提醒气泡。提醒气泡用于提醒用户如何显示系统栏。

非沉浸式模式:

这是应用程序在进入沉浸式模式之前出现的状态。除此之外,如果使用了SYSTEM_UI_FLAG_IMMERSIVE标志,并且当用户从屏幕边缘往内部滑动时,此时会清除SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN标志。清除这些标志后,system bar将重新出现并保持可见,此时也会是这样。请注意,最好的做法是将所有UI控件与系统栏保持同步,以最大限度地减少屏幕地状态数量,从而提供更加无缝地用户体验。所以这里所有的UI控件都与状态栏一起显示。一旦应用程序进入沉浸式模式,UI控件将于系统栏一起隐藏。为了确保UI可视性与系统栏可见性保持同步,可通过View.OnSystemUiVisibilityChangeListener来响应UI改变事件。

沉浸式模式:

系统栏和其他UI控件被隐藏。可以使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY或SYSTEM_UI_FLAG_IMMERSIVE标志来实现此状态。

响应System UI的改变事件

在system bar隐藏或显示之后,应用自身的UI也可能需要做一些改变。并且,保持这两者的状态同步时一个很好的做法。

如果应用想要关心system ui的变更事件,只需要设置一个监听即可。例如,可以在activity的oncreate方法完成这个监听

java 复制代码
  View decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                //只有在LOW_PROFILE、HIDE_NAVIGATION和FULLSCREEN都没有设置的时候,system bar才是可见的
                if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN)==0){
                    //system bar可见时,例如显示action bar或者导航相关的控件
                }else{
                    //system bar不可见时 例如隐藏action bar或者导航相关的控件
                }
            }
        });
相关推荐
拓端研究室4 分钟前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
zhangphil1 小时前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_512744641 小时前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.1 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao1 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee2 小时前
PHP伪协议总结
android·开发语言·php
mmsx8 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人11 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌12 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
_Shirley13 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙