关于android:为任意屏幕尺寸构建-Android-界面

49次阅读

共计 15009 个字符,预计需要花费 38 分钟才能阅读完成。

在过来的 12 个月内,有约 1 亿台新平板设施被激活,Chrome OS 的激活量增长了 92%,是增长速度最快的桌面平台。这意味着在平板电脑、可折叠设施和 Chrome OS 设施上,有超过 2.5 亿台大屏幕设施运行着 Android 零碎,而对于可折叠设施的应用数量也在一直增长,同比增长超过 250%,因而,” 大屏 ” 正在成为 Android 设施中一个重要且增长势头最快的细分市场。这也让设施制造厂商们意识到,针对大屏做优化是让设施在高端手机细分市场中怀才不遇的机会。

随着平板和可折叠设施的迅速倒退,是时候进行将手机和平板离开去思考了,而更应该提供面向一整个生态系统的利用,来进步其在市场中的影响力。本文咱们将介绍开发者如何通过咱们提供的新 API 和工具疾速拥抱并进入这一细分市场。

如果您更喜爱通过视频理解此内容,请在此处查看:

https://www.bilibili.com/vide…

△ 为任意屏幕尺寸构建 Android 界面

用户参与度

在 Android 开发者峰会举办后的几个月,Play 商店推出新的激励措施,包含会依照设施类型对利用进行评级等动作,激励开发者将更多眼光放到大屏下来。所以目前正是迎接这些变动的绝佳机会,不仅可能投合之后的市场变动,还能就此解决因为没有适配大屏而造成用户的应用体验欠缺的难堪。

△ 针对大屏优化的 Microsoft Outlook 利用界面

咱们还察看到那些针对所有屏幕尺寸进行优化的利用,在围绕用户互动度、留存率等指标上,都获得了不错的问题。比方其中的一个胜利案例 Candy Camera,它通过优化可折叠设施和大屏幕的布局,使得应用这些设施的用户在利用上破费的工夫减少了 10%,7 天用户留存率更是增长了 14%,而这并不是个例。另一个案例是 Microsoft Outlook,它最近的更新通过应用双窗口布局充分发挥了大屏劣势,能够同时查看收件箱和电子邮件内容,并可能在领有多个显示屏的某个独自窗口中独立撰写电子邮件。这些例子充沛表明: 是时候开始解脱手机这一繁多界面限度的解放,从而自在地进行设计和开发了。

然而也别太放心,咱们为此曾经做了很多的工作,旨在让您在整个开发周期中尽可能更轻松一些,接下来看看咱们提供了哪些帮忙您更好进行大屏适配的工具吧。

窗口大小类和 Reference Devices

在多元化的设施生态中,各种 Android 设施的形态各异且尺寸不一,这就使得利用的布局须要非常灵便。在不同的设施上运行同一利用,都应该可能灵便适应不同设施的屏幕尺寸。为此,咱们深入研究了 Android 设施市场,并从 Web 的自适应和响应式开发的最佳实际中吸取了一些灵感,构建出可动静调整尺寸的新 Android 界面根底,咱们将其称为窗口大小类。

窗口大小类是一组主观的视口断点,您能够依据它们来设计、开发和测试可调整大小的利用布局。这些断点将帮忙您理解要进行优化的要害尺寸,以便将利用适配于整个生态系统。窗口大小类分为三类,别离是较小型、中等型和开展型,它们旨在均衡布局的简略和灵活性,以针对非凡状况优化您的利用。咱们举荐您应用窗口大小断点来做出高级利用布局决策,对于布局网格列的变动,它们还能映射到 Material Design 布局断点。

新的 WindowSizeClass API 会在 Jetpack WindowManager 1.1 中提供,它将让您解脱易出错的 isTable 逻辑。这些新 API 还将打消设施在横竖屏切换时须要自定义逻辑的需要,在大多数状况下只需针对不同的窗口大小类断点进行设计,利用就会适应正确的布局和各种利用状态。

class WindowMetrics {class WindowSizeClass(val name: String) {
        companion object {val COMPACT = WindowSizeClass(“COMPACT”)
            val MEDIUM = WindowSizeClass(“MEDIUM”)
            val EXPANDED = WindowSizeClass(“EXPANDED”)
        }
    }

    val widthClass: WindowSizeClass
        get() {...}
    val heightClass: WindowSizeClass
        get() {...}
}

有一点比拟重要的是,从 Android 12 开始,将容许利用任意调整尺寸,且容许所有利用都以多窗口模式运行。以 Samsung Galaxy Fold 系列来看,其提供的分屏模式使得屏幕利用率进步了 7 倍,而分屏容许用户依据本人的偏好对尺寸进行调整,这也进一步突出了构建可动静调整尺寸界面的重要性。

从设施和配置的角度来对布局进行考量,咱们让每个窗口大小类都代表了一些典型设施的配置 (如下图所示),当您思考基于断点对布局进行设计时,这将会是一个很有用的参考。其中,较小型代表了竖屏模式下手机的典型模式,中等型代表了大部分平板电脑和更大的可折叠设施的尺寸,开展型则代表了平板电脑或更大的可折叠设施,或是桌面设施在横屏模式下的显示状况。

△ 基于宽度的窗口大小类的示意

除了以上三种基于宽度的断点外,咱们还引入了具备雷同类别名称的基于高度的断点,以便实用于更高级别的布局场景,并赋予更多的灵活性。假如咱们须要应用较小的高度断点来对横屏手机界面进行布局优化,尽管这听起来很简单,然而别放心,依据咱们同许多 Android 开发者进行深谈后,大部分状况下只须要依据宽度进行布局适配就能够了。

△ 基于高度的窗口大小类的示意

总而言之,窗口大小类的呈现,代表了 Android 在自适应和响应式布局开发中的一大提高,包含更新和优化的指南、Jetpack WindowManager 中的新 API 以及 Android Studio 中的新工具。

谈到 Android Studio,咱们将在 Android Studio Bumblebee 中引入一种新的工具类别,咱们将其称为 Reference Devices,它的引入是为了让 Android 利用的构建可能响应和适应所有设施类别。咱们在对市场数据进行充沛钻研之后,提供了四种 Reference Devices,别离代表了手机、可折叠设施、平板电脑和桌面设施。它们既能够笼罩目前市场上的支流设施,又涵盖到了快速增长的细分市场,还能够确保利用在大部分窗口大小类中都可能失常运行。

△ 四种 Reference Devices

在本文对大屏幕适配的介绍中,若您只想疾速通晓要留神的点,那请记住以下几点:

  1. 为了确保利用在不同设施尺寸上都可能正确展现,请优先针对较小和开展型宽度大小类来优化布局;
  2. 在所有的 Reference Devices 上都测试一遍您的利用,优先采纳在中等型下的最佳布局;
  3. 为了提供更好的用户体验,请增加对利用有意义的性能,如反对可折叠设施的折叠状态或针对键盘、鼠标和触控笔输出反对进行优化;

如需理解更多无关窗口大小类的详细信息,请查阅 窗口大小类。

如需查看对于窗口大小类的理论利用示例,请参阅 JetNews Compose 示例。

适配大屏

设计好看且响应迅速的界面是开发利用的第一步,但如何实现和保护这种设计相对是个挑战,为了简化您的工作,咱们会致力于提供高效的工具。当初便会介绍如何通过新的 Jetpack API 和 Android Studio 性能,来对现有利用进行更新,以针对所有屏幕尺寸进行优化。

咱们将会应用 Trackr 作为示例,这是一个开源的工作治理利用,咱们最近对该利用进行了更新,使其更好地反对更大屏幕的设施。Trackr 的开发曾是为了展现如何在 Android 中反对无障碍性能体验的最佳实际,随着最近针对大屏幕的更新,它无疑是一个很好的示例。

△ 更改之前的 Trackr 款式

上图是咱们进行更改之前的 Trackr 款式,您会发现不论在什么设施或屏幕下,都会有一个单窗口工作列表以及用于导航到归档或设置页面的底部利用栏。Trackr 有几个次要界页,包含工作列表、工作详情、工作创立或编辑页面。接下来,就让咱们对 Trackr 进行大屏优化。

NavigationRailView

咱们正在 Android Studio Chipmunk 中开发一个新的工具 Visual Linting。能够通过它在 Layout Validation 中对界面进行查看,并显示一些正告和相干倡议。咱们应用 Visual Linting 对 Trackr 的布局进行查看,来通过工具找出一些潜在的大屏幕显示的相干问题。咱们能够关上 main_activity 布局,而后关上 Layout Validation 工具 (还能够通过 View – Tools Window 门路找到该选项)。

△ Layout Validation 中对界面进行查看

在 Layout Validation 界面,您会发现有一个新的 Reference Devices 的类别,通过它您能够在 Android Studio 中应用新的 Reference Devices 性能。在 Layout Validation 右上角能够发现一个正告图标,单击此图标能够关上正告窗口,点击每个正告会显示哪些设施会受到影响。如上图所示,咱们会发现两个跟大屏显示相干的正告: 底部利用栏只举荐用于较小屏幕以及 MaterialTextView 的局部行蕴含超过 120 个字符。

△ 正告窗口

开展正告能够查看到 Android Studio 是否提供了批改倡议,这里对于底部利用栏正告的批改倡议就是应用 Navigation Rail、抽屉式导航栏,或应用顶部利用栏代替。对于 Trackr,我认为应用导航路由更有建设性。而针对 MaterialTextView 的批改倡议是要么缩小 TextView 的宽度,要么思考应用多列布局,这里应用多列布局更适宜咱们的利用。对于 Trackr,咱们将会应用典型的列表加详情窗口的款式来解决这些正告,针对有着中等或较大宽度的设施,咱们将应用 NavRail,而非底部利用栏,对于开展型宽度的设施咱们将应用双窗口布局来展现工作和相干详情。

咱们先来进行第一项优化,应用 NavRail 而非底部利用栏,首先咱们要思考的是导航模型,所幸咱们不会更改很多具体的视图,仅仅只会更改导航形式,因为 NavRail 会始终存在于整个视图体系中,能够通过它导航到任何其余视图。为了实现这一模式,咱们能够将 Navigation Rail View 增加到 main_activity 布局中,如下代码所示:

// main_activity.xml
<androidX.coordinatorlayout.widget.CorrdinatorLayout
…>
<com.google.android.material.navigationrail.NavigationRailView
    android:id="@+id/navigation_rail"
    android :layout_width="wrap_content"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app: layout_constraintTop_toTopOf="parent"
    app:headerLayout="@layout/navigation_rail_header"
    app:labelVisibilityMode="unlabeled"
    app:menu="@menu/navigation_rail" />
</androidX.coordinatorlayout.widget.CorrdinatorLayout>

在此之前,main_activity 仅由 FragmentContainerView 和 CoordinatorLayout 组成,并通过 NavHostFragment 来托管其余 Fragment。而将 NavigationRailView 搁置在 main_activity 布局级别后,它将在所有视图中长久存在。尽管如此,我只想要 NavigationRail 用于宽度为 600dp 或者更大的屏幕尺寸,要实现这一点,一个简略的办法是增加资源限定 (resource-qualified) 的 main_activity 布局,并在蕴含 NavHostFragment 的 FragmentContainerView 的同一级别上增加 NavigationRailView:

// w600dp/tasks_fragment.xml
<layout...>
   <data.../>
   <androidx.coordinatorlayout.widget.CoordinatorLayout...>
   <com.google.android.material.appbar.AppBarLayout.../>
   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/tasks_list"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:clipToPadding="false"
       android:paddingLeft="@dimen/pane_margin"
       android:paddingRight="@dimen/pane_margin"
       tools:ignore="SpeakableTextPresentCheck"
       tools:listitem="@layout/task_summary"/>
       <com.google.android.material.bottomappbar.BottomAppBar.../>
       <com.google.android.material.floatingactionbutton.FloatingActionButton.../>
   </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

咱们还须要更新 tasks_fragments.xml,从宽度为 600dp 或更大的显示屏中移除底部利用栏。与实现 NavRail 的形式相似,能够为 tasks_fragments 增加资源限定 (resource-qualified) 的布局,而后就能够移除底部利用栏和相干的悬浮操作按钮,其余所有放弃不变从而让工作列表持续依照预期工作。最初,在设置 NavRail 菜单栏的 ID 来匹配现有导航目标视图的 ID,再在 MainActivity 中为 NavRail 设置 NavController:

<!=-NavRail Menu -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        android:id="@+id/nav_tasks"
        android:icon="@drawable/ic_task" .../>
    <item
        android:id="@+id/nav_archives"
        android:icon="@drawable/ic_archive" .../>
</menu>
// MainActivity NavController
class MainActivity: AppCompatActivity() {
...
    override func onCreate(saveInstanceState: Bundle?) {
    ...
        binding.navigationRail?.apply{setupWithNavController(navController)
            setOnItemReselectedListener()
            headerView?.setOnClickListener {navController.navigate(R.id.nav_task_edit_graph)
            }
        }
    }
}

这样就实现了,能够在 Android Studio 查看显示是否一切正常,通过在各种 Reference Devices 中来回切换查看布局是否依照咱们的预期进行。当查看 Phone Reference Device 时,仍然可能看到底部利用栏,而切换到更大的屏幕后,咱们发现它开始应用 NavRail 了,所有依照咱们的预期进行。

△ Phone Reference Device 下的成果

△ Tablet Reference Device 下的成果

SlidingPanelLayout

接下来让咱们持续基于开展型宽度设施来实现双窗口视图布局。反对这一布局形式的一个简略办法是应用 SlidingPaneLayout,它的劣势在于能够轻松复用现有的布局代码,以下是目前更新后的导航图:

△ 更新后的导航图

咱们能够通过 NavigationRailView 导航到利用任意一个顶层布局,但依然能够通过抉择界面中某个单项工作而导航到详情页面的 Fragment。这种模式在实现 SlidingPanelLayout 时会产生一些变动,咱们将增加一个新布局 TwoPaneTasks 来蕴含 SlidingPaneLayout,此布局将同时蕴含工作列表和详情的 Fragment。通过这种形式更新利用导航,无论屏幕尺寸如何都可能领有雷同的导航图,这意味着调整屏幕尺寸不会产生导航的变动,从而让用户感到困惑。

因为工作和详情都出现在 SlidingPaneLayout 中的同一个新的 Fragment 中,因而咱们为该 Fragment 的导航交互专门增加一个新的子导航层次结构。这样,当我抉择一项工作并且利用从双窗口变成单窗口时,该我的项目将位于导航栈的顶部,并是可见的状态。

简略说,咱们将应用 SlidingPaneLayout 和 FragmentContainerView 来增加一个新 Fragment 来托管工作和详情窗格,这样不用对现有代码进行大的重构。

// tasks_two_pane_fragment.xml
<layout...>
   <androidx.slidingpanelayout.widget.SlidingPaneLayout
       android:id="@+id/sliding_pane_layout"...>
       <androidx.fragment.app.FragmentContainerView
           android:id="@+id/list_pane"
           android:name="com.example.android.trackr.ui.tasks.TasksFragment"
           android:layout_width="@dimen/list_pane_width"
           android:layout_height="match_parent"
           android:layout_weight="@dimen/list_pane_weight"
           tools:layout="@layout/tasks_fragment" />
   <androidx.fragment.app.FragmentContainerView
           android:id="@+id/detail_pane"
           android:name="androidx.navigation.fragment.NavHostFragment"
           android:layout_width="@dimen/detail_pane_width"
           android:layout_height="match_parent"
           android:layout_weight="@dimen/detail_pane_weight"
           app:navGraph="@navigation/task_detail"
           tools:layout="@layout/task_detail_fragment" />
   </androidx.slidingpanelayout.widget.SlidingPaneLayout>
</layout>

而后,持续更新利用的顶层导航层次结构,使新的双窗口 Fragment 成为利用的起始目标页面,并从利用的导航图中移除详情目标页面。

<!-- 顶层导航图 -->
<navigation app: startDestination="@+id/nav_tasks"...>
   <fragment
       android:id="@+id/nav_tasks"
       android:name="..trackr.ui.tasks.TasksTwoPaneFragment" ...>
       <action
           android:id="@+id/to_task_edit"
           app: destination="@id/nav_task_edit_graph' />
   </fragment>
<!--Remove the 'details' destination-->
...
</navigation>

<!-SlidingPaneLayout 导航图 -->
<navigation...
       app:startDestination="@id/nav_task_detail_placeholder">
       <action
           android:id="@+id/to_task_detail"
           app:destination="@id/nav_task_detail"
           app:popUpTo="@id/nav_task_detail"
           app :popUpToInclusive="true"
       <fragment
           android:id="@+id/nav_task_detail"
           android:name="..trackr.ui..TaskDetailFragment"...>
       <argument
           android:name="taskId"
           app:argType="long" />
   </fragment>
<!-- 为其实目标页面应用一个 placeholder-->
   <fragment
       android:id="@+id/nav_task_detail_placeholder"
       android:name="..trackr.ui.PlaceholderFragment"
       tools:layout="@layout/placeholder_fragment"/>
</navigation>

最初,再为 SlidingPaneLayout 专门增加一个新导航图,并在 TasksTwoPaneFragment Kotlin 代码中解决 SlidingPaneLayoutNavController 配置逻辑。通过这两项更改利用在不同设施不同形状下的布局会更加正当。实现这些后,咱们再次通过在 Android Studio 中的 Reference Devices 工具,就能看到新的布局在所有的设施屏幕中都可能完满布局了。而为了在利用运行时进行测试,Android Studio Chipmunk 提供了可反对尺寸调整的模拟器,通过它能够在雷同的 Reference Devices 之间切换,来疾速验证利用布局是否正确。

另外,SlidingPaneLayout 提供了另一个重要个性是它不仅实用于大屏幕设施,而且实用于多屏幕设施。Microsoft 最近为 SlidingPaneLayout 提供了一个反对铰链检测的性能,让其主动可能反对跨屏幕拆分窗口,而无需更改任何代码。这意味着利用的新列表 / 详情布局将实用于所有设施,包含多屏幕设施。

尽管上述提到的办法对于优化大屏显示十分有用,然而许多开发者的利用都基于多个 Activity,对于这些利用,12L 中公布的新 Activity Embedding API 将使反对双窗口视图等新界面范式变得容易,敬请期待。

Jetpack Compose

Jetpack Compose 在 2021 年 7 月公布了 1.0 版本后,在 Android 开发者社区产生了微小反应,成千上万的利用曾经在生产环境中应用了 Compose,包含 Play 商店利用自身。Jetpack Compose 自身是一种申明式的界面工具包,通过它您能够依据页面状态进行形容,Compose 会自行进行所有必要的更新。所有的界面都是通过在代码中形容而成,这样也就很容易在运行时做出对于界面款式的决策,而在传统的视图零碎中,咱们通过对不同屏幕配置进行编译,从而实现对视图的配置,这两者有着微小的不同。这也让 Compose 能够轻松解决不同屏幕尺寸而带来的界面更改。

接下来,让咱们通过 JetNews 来向您展现如何通过 Compose 来进行不同屏幕尺寸的适配。JetNews 的主界面展现了一长串滚动的文章,在针对大屏幕进行优化之前,它的界面如下图所示,能够发现,并没有很好地利用额定的屏幕空间。

△ JetNews 的主界面展现

前文中曾经介绍了 WindowManager API,目前咱们正在将其集成到 Compose 中去,以便更轻松地从 Compose 中拜访这些信息。在此期间,咱们能够创立一个 composable 函数来解决与 WindowManager 的集成,而后轻松将以后 Activity 的窗口信息转换为最终的窗口大小类,代码如下所示:

@Composable
fun Activity.rememberWindowSizeClass(): WindowSize {
   val configuration = LocalConfiguration.current
   val windowMetrics = remember (configuration) {WindowMetricsCalculator.getOrCreate()
           .computeCurrentWindowMetrics(this)
   }
   val windowDpSize = with (LocalDensity.current) {windowMetrics.bounds.toComposeRect().size.toDpSize()}
   when {
       windowDpSize.width < 600.dp -> WindowSize.Compact
       windowDpSize.width < 840.dp
       else -> WindowSize.Expanded
   }
}

WindowManager 库很快就会推出间接应用这些类的 API,Compose 也会很快反对更不便的性能来实现此项工作,敬请期待。目前,您可临时借用这一代码来实现这一性能上的须要。

△ JetNews 侧边抽屉导航栏展现

回到 JetNews,咱们能够看到在大屏状态下,侧边的抽屉导航栏会以模态的形式呈现,但它会延长到整个屏幕而呈现大量空白区域。依据前文中提到的批改倡议,是应用 Navigation Rail,而 Compose 则间接反对,咱们仅须要对其进行设置并将内容传入即可。

NavigationRail(
    header = {JetnewsIcon()
    }
) {Column(verticalArrangement = Arrangement.Center) {
        Icon(
            icon = Icons.Filled.Home,
            action = navigateToHome
        )
        Icon(
            icon = Icons.Filled.ListAlt,
            action = navigateToInterests
        )
    }
}

题目图标和两个导航项图标,一个用于主页面,一个用于 Interests 页面,并增加它们对应的导航操作。为了将 Navigation Rail 集成到利用中,咱们对顶层利用组件做了一些更改。首先,咱们获取以后的窗口大小类,以及显示较小尺寸上的 ModalDrawer,而后确保设置了 ModalDrawer 让其只响应该尺寸中的手势。再将 Navigation Rail 与蕴含利用中所有屏幕的主导航图并排搁置:

@Composable
fun JetnewsApp() {val windowSize = rememberWindowSizeState()
    val isDrawerActive = windowSize == WindowSize.Compact
    ModalDrawer(
        gesturesEnabled = isDrawerActive
        drawerContent = {...}
    ) {
        val showNavRail = isDrawerActive
        Row() {if (showNavRail) {AppNavRail()
            }
            JetnewsNavGraph()}
    }
}

而后咱们发现因为文章列表仍然在大屏下没有充分利用空间,因而咱们决定在大屏下构建列表 / 详情布局,这一布局形式是 Material Design 中举荐的大屏幕标准布局之一,让咱们将文章列表与关上的文章并排显示。JetNews 利用有两个咱们能够复用的组件: PostList 和 PostContent,这种在一开始就将界面拆分为组件的做法,不仅能让测试更加容易,还能让咱们轻松对布局进行改良。

为了并排显示 Feed 和 Post,JetNews 简略地应用 Row 包裹两个组件,第一个组件具备固定宽度,第二个组件填充屏幕的其余部分。详情组件包裹在穿插突变动画中,这让用户点击列表关上文章时看到带有动画过渡的转换成果。

要正确构建列表 / 详情构造,除了理论布局之外咱们还须要解决几个问题。其中比拟乏味的一点是思考利用如何在不同尺寸布局之间转换,例如对于可折叠手机,利用可能会从较大的屏幕变为较小的屏幕。

△ 可折叠手机上布局转换

为了正确处理如何将列表和详情窗口折叠成单窗口层次结构,当在较小的屏幕上时,咱们须要晓得用户最初与哪个窗口交互,为此,咱们实现了一个简略的自定义修饰符来记录最初一次交互,并以此决定,在不同的折叠状态下应该显示什么内容,从而进一步晋升层次结构。

@Composable
fun HomeFeedWithArticleDetailsScreen(...) {Row() {
        PostList(
            modifier
                .width(334.dp)
                .notifyInput(onInteractWithList))
        Crossfade(...) {
            PostContent(
                modifier
                    .fillMaxSize()
                    .notifyInput {onInteractWithDetail(detailPost.id)
                    }
            )
        }
    )}
}

咱们还须要晓得,咱们是从多大尺寸的屏幕将一次只显示其中一个窗口转变为显示列表 / 详情布局的。在 JetNews 中咱们首先获取窗口大小类的信息,在较小和中等型宽度显示单窗口,而在开展型宽度显示列表 / 详情布局。

val windowSize = rememberWindowSizeState()

val homeScreenType = when (windowSize) {
    WindowSize.Compact,
    WindowSize.Medium -> HomeScreenType.Feed
    WIndowSize.Expanded -> HomeScreenType.FeeWithArticleDetails
}

而后,开始针对 JetNews 的导航进行更改。JetNews 最后以主页面和文章页面构建而成,每个页面都有本人的 ViewModel,导航和 ViewModel 之间的集成意味着两个页面始终在不同的导航门路上。然而,为了将页面重组成列表 / 详情布局,咱们须要将这两个屏幕并排显示,此处咱们有两种可选计划。一是在详情页面嵌套 NavHost,另外一种计划是对立 ViewModel,因为详情页面内并没有下一级别的导航入口而只会显示一篇关上的文章,咱们决定采纳第二种形式,将两个 ViewModel 合二为一来简化构造。

咱们创立了三个主界面入口点,一个是 HomeFeedScreen,它只负责展现 PostList;一个是 ArticleScreen 负责展现 PostContent;以及新的 HomeFeedWithArticleDetailsScreen 负责显示蕴含 PostList 和 PostContent 的列表 / 详情布局。

△ 图左: 主界面入口点 HomeFeedScreen 图右: 主界面入口点 ArticleScreen

△ 主界面入口点 HomeFeedWithArticleDetailsScreen

上图是咱们适配之前和适配之后的页面款式,能够发现对屏幕空间的利用有了十分大的改善。但这次更改是针对屏幕尺寸做的决策,咱们是不是能够让单个组件本身依据页面而领有不同尺寸呢?例如咱们有一张卡片,当在列表中因为空间的限度只展现题目和副标题,而有更多空间时,则调整为显示图像。对于此类情况咱们能够应用 Box With Constraints,它相似于框布局,可能依据范畴内的测量信息来用于决策。

获取更好的用户体验

在前文中,咱们提到为了提供更好的用户体验,请增加对利用有意义的性能,如反对可折叠设施。同 WindowManager API 相似,咱们能够轻松地将 Compose 与针对可折叠设施的 API 进行集成。通过这些 API,可能获取到该设施是否且何时触发了铰链或折叠等性能,以及以后设施处于何种姿势。Compose 能够轻松察看这些 API 赋予的状态,从而轻松对界面进行转换。同样,对于此性能的 API 行将在 Compose 中提供,敬请期待。

除了目前提到的 API 之外,咱们始终致力开发 Compose 的外部构件,以加强包含键盘和鼠标反对在内的输出设施,这对于在 Chrome OS 上运行的利用尤其有用。如需理解 Chrome OS 和输出详细信息,敬请关注咱们近期的文章公布。

如需理解更多 Compose 示例详情,请查阅 Compose 示例代码。

新的 Compose 和大屏幕指南——构建自适应布局,心愿可能对您的开发有所帮忙。

测试和保护

当初您已理解如何轻松更新利用,来构建可调整尺寸的新界面。如何测试和保护我的项目也是一个十分重要的课题。保护并反对所有不同尺寸的界面会大大引入测试复杂性,咱们始终致力在不进步工作量的状况下,通过新的自动化测试工具和 API,让您可能配置更多设施来减少测试覆盖率。咱们将会通过 Gradle 托管设施,从而实现在各种屏幕尺寸和 API 级别上运行虚构设施来运行现有的 instrumentation 测试。您只需形容要在其上运行测试的设施的配置,其余均由 Gradle 负责,包含设施事后配置和测试工作的运行。

只需在构建脚本过程中定义设施,并将其增加到设备组:

testOptions
    devices {pixel2api29 (com.android.build.api.dsl.ManagedVirtualDevice) {nexus9api30 (com.android.build.api.dsl.ManagedVirtualDevice) {
            device = "Nexus 9"
            apiLevel = 30
            systemImageSource = "google"
            abi = "×86"
        }
    }
    deviceGroups {
        mediumAndExpandedWidth{targetDevices.addAll(devices.pixel2api29)
            targetDevices.addAll(devices.nexus9api30)
    }
}

而后应用 Gradle 托管设备组来运行测试:

$ gradlew -Pandroid.experimental.androidTest.useUnifiedTestPlatform=true mediumAndExpandedWidthGroupDebugAndroidTest

因为 Gradle 同时治理设施配置和测试作业,Gradle 托管设施还反对测试分片,让您可能跨指定数量的雷同设施来宰割测试从而缩小总体测试作业工夫。只须要指定以下参数即可指定要分片的数量:

$ gradlew -Pandroid.experimental.androidTest.numManagedDeviceShards=2 deviceDebugAndroidTest

但咱们晓得运行大量虚构设施会占用 CPU 和内存,这可能会限度 Gradle 托管设施和测试分片的用途。为了解决此问题,Gradle 托管设施引入了一种针对 instrumentation 测试而优化的新型虚构设施,称为自动化测试设施,这些设施以 headless 模式运行,禁用了自动化测试通常不须要的后盾过程和服务,从而升高了每台设施的总体 CPU 和内存使用率,这将让您可能同时针对代表不同屏幕尺寸的多台设施运行测试。以后,这一性能可在 Android 10 上应用,随着工夫的推移将反对更高的 API 级别,以确保现有的屏幕截图测试可能持续与自动化测试设施配合运行。

咱们还在开发一组全新 AndroidX Testing API,让您可能将设施置于不同的状态进行测试。例如,您能够测试利用从平折变为半开状态,或在纵向或横向模式之间旋转时的反馈。

总结

明天咱们探讨了很多内容,从新的设计指南和窗口大小类,到用于更新现有利用的特定 API。大屏幕和可折叠设施代表 Android 的一个宏大且一直增长的细分市场,为了抓住这一增长机会,当初是时候为这些设施构建和设计界面,以便为应用最高级设施的用户取得杰出的体验。

欢迎您 点击这里 向咱们提交反馈,或分享您喜爱的内容、发现的问题。您的反馈对咱们十分重要,感谢您的反对!

正文完
 0