美文网首页
SystemUI 分析之 ExpandableNotificat

SystemUI 分析之 ExpandableNotificat

作者: 头秃到底 | 来源:发表于2024-03-13 22:22 被阅读0次

ExpandableNotificationRow # onFinishInflate

ExpandableNotificationRow 在方法 onFinishInflate 中提到它的布局。

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    mPublicLayout = findViewById(R.id.expandedPublic);
    mPrivateLayout = findViewById(R.id.expanded);
    mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};

    for (NotificationContentView l : mLayouts) {
        l.setExpandClickListener(mExpandClickListener);
        l.setContainingNotification(this);
    }
    mGutsStub = findViewById(R.id.notification_guts_stub);
    mGutsStub.setOnInflateListener((stub, inflated) -> {
        mGuts = (NotificationGuts) inflated;
        mGuts.setClipTopAmount(getClipTopAmount());
        mGuts.setActualHeight(getActualHeight());
        mGutsStub = null;
    });
    mChildrenContainerStub = findViewById(R.id.child_container_stub);
    mChildrenContainerStub.setOnInflateListener((stub, inflated) -> {
        mChildrenContainer = (NotificationChildrenContainer) inflated;
        mChildrenContainer.setIsLowPriority(mIsLowPriority);
        mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
        mChildrenContainer.onNotificationUpdated();

        mTranslateableViews.add(mChildrenContainer);
    });

    // Add the views that we translate to reveal the menu
    mTranslateableViews = new ArrayList<>();
    for (int i = 0; i < getChildCount(); i++) {
        mTranslateableViews.add(getChildAt(i));
    }
    // Remove views that don't translate
    mTranslateableViews.remove(mChildrenContainerStub);
    mTranslateableViews.remove(mGutsStub);
}

ExpandableNotificationRow 类的 onFinishInflate 方法负责完成视图的填充过程。该方法在 XML 布局被填充成实际的视图对象之后被调用,确保所有必要的视图都被正确设置。

在提供的代码片段中,执行了几个关键步骤:

  1. mPublicLayoutmPrivateLayout 通过查找相应 ID(R.id.expandedPublicR.id.expanded)的视图来初始化。这些是 NotificationContentView 的实例,用于显示通知的公共(为了隐私而编辑过的内容)或私有(完整内容)形式。

  2. mLayouts 中的每个布局,调用 setExpandClickListenersetContainingNotification 来设置点击监听器,并将布局与这个 ExpandableNotificationRow 关联。

  3. mGutsStub 通过其视图 ID 查找,并设置了 OnInflateListener。当 mGutsStub 被填充时,它变成了 mGuts,这是一个用于显示通知附加详情或操作(如延迟或屏蔽选项)的 NotificationGuts 视图。

  4. 类似地,mChildrenContainerStub 被查找并设置了 OnInflateListener。在填充之后,它变成了 mChildrenContainer,这是一个 NotificationChildrenContainer,如果当前通知是分组通知中的摘要,则包含子通知。

  5. mTranslateableViews 被初始化并填充了 ExpandableNotificationRow 的所有子视图。某些视图如 mChildrenContainerStubmGutsStub 被从列表中移除,因为它们不参与某些平移动画(如显示通知菜单时)。

onFinishInflate 方法结束时,ExpandableNotificationRow 已经设置好了所有内部视图,并准备好显示通知内容,如果它是一个摘要通知,还包括任何子通知。Guts 和 children container 视图作为存根开始,并在需要时被填充,这可以通过延迟加载更复杂的视图直到实际需要它们来提高性能。

ExpandableNotificationRow的布局文件是 R.layout.status_bar_notification_row,这个视图用于展示一个可扩展的通知行。ExpandableNotificationRow继承自FrameLayout,因此它可以包含多个子视图。布局中的元素定义了通知行的不同部分,包括背景、内容视图(包括公共和私有内容),以及其他的一些视图和视图存根(ViewStub)。

<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright 2014, The Android Open Source Project

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<!-- extends FrameLayout -->
<com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/expandableNotificationRow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusable="true"
    android:clickable="true"
    >

    <!-- Menu displayed behind notification added here programmatically -->

    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
        android:id="@+id/backgroundNormal"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
        android:id="@+id/backgroundDimmed"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.android.systemui.statusbar.notification.row.NotificationContentView
        android:id="@+id/expanded"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" />

    <com.android.systemui.statusbar.notification.row.NotificationContentView
        android:id="@+id/expandedPublic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/veto"
        android:layout_width="48dp"
        android:layout_height="0dp"
        android:gravity="end"
        android:layout_marginEnd="-80dp"
        android:background="@null"
        android:paddingEnd="8dp"
        android:paddingStart="8dp"
        />

    <ViewStub
        android:layout="@layout/notification_children_container"
        android:id="@+id/child_container_stub"
        android:inflatedId="@+id/notification_children_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <ViewStub
        android:layout="@layout/notification_guts"
        android:id="@+id/notification_guts_stub"
        android:inflatedId="@+id/notification_guts"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <com.android.systemui.statusbar.notification.FakeShadowView
        android:id="@+id/fake_shadow"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</com.android.systemui.statusbar.notification.row.ExpandableNotificationRow>

下面是对这个布局文件中各个主要组件的解释:

  1. ExpandableNotificationRow

    • 这是自定义的根视图,扩展自FrameLayout,表示一个可以扩展的通知单元。
    • android:id:视图的ID,可以在代码中用来引用该视图。
    • android:layout_widthandroid:layout_height:定义视图的宽度和高度。这里宽度是填满父视图(match_parent),高度是包裹内容(wrap_content)。
    • android:focusableandroid:clickable:这两个属性设置视图可以获取焦点和接受点击事件。
  2. NotificationBackgroundView

    • 两个背景视图(backgroundNormalbackgroundDimmed)被用于显示通知的背景,一个用于正常状态,一个用于昏暗状态。
  3. NotificationContentView

    • 两个NotificationContentView分别代表公共和私有的通知内容。
    • android:id="@+id/expanded":私有(完整)内容的视图。
    • android:id="@+id/expandedPublic":公共(简略)内容的视图。
  4. Button (id: @+id/veto)

    • 一个按钮视图,可能用于提供通知的某种快速操作,例如删除通知。
    • 使用负的layout_marginEnd,这可能是为了使按钮在视觉上超出其自然位置,创建一种特殊的布局效果。
  5. ViewStub (id: @+id/child_container_stub)

    • 一个ViewStub用于延迟加载notification_children_container布局。这通常用于节省资源,因为ViewStub只有在需要时才会被填充成真正的视图。
    • 该布局用于显示分组通知的子通知。
  6. ViewStub (id: @+id/notification_guts_stub)

    • 另一个ViewStub用于延迟加载notification_guts布局。这个布局包含了通知的额外操作,例如设置或者是延迟提醒。
  7. FakeShadowView (id: @+id/fake_shadow)

    • 一个用于显示阴影效果的视图,可能用于创建提升效果,使通知看起来像是悬浮在上面。

注意:真实的动态视图(例如通知的内容或操作按钮)通常是在代码中动态添加的,而不是直接在XML中硬编码的。因此,ViewStub和动态添加的视图允许开发者根据需要延迟视图的创建和配置。

ExpandableNotificationRow # isTopLevelChild

ExpandableNotificationRow 类的 isTopLevelChild 方法体现了类NotificationStackScrollLayout 是它的父布局。

public boolean isTopLevelChild() {
    return getParent() instanceof NotificationStackScrollLayout;
}

ExpandableNotificationRow 类是用来展示 Android 系统中的通知,其中包括可以折叠和展开的分组通知。当一个通知是分组通知的头部(即摘要),它可以包含多个子通知。这里有几个关键点说明了 ExpandableNotificationRow 如何管理和展示其子通知:

  1. 子通知容器 (NotificationChildrenContainer)ExpandableNotificationRow 通过 NotificationChildrenContainer 管理其子通知。这个容器是一个自定义视图,负责布局和展示所包含的所有子通知。NotificationChildrenContainer 将在 ViewStub 被实例化(inflate)时创建,并且只有当通知确实有子通知时才会被加载。
  2. 延迟加载 (ViewStub)ExpandableNotificationRow 布局中包含一个 ViewStub(ID为 @+id/child_container_stub),它被用来按需加载包含子通知的容器。ViewStub 是一种轻量级的占位视图,直到需要展示子通知时才会被实例化成 NotificationChildrenContainer
  3. 子通知展示: 当 ExpandableNotificationRow 确定为一个分组通知的头部时,它会将子通知添加到 NotificationChildrenContainer 中。子通知每个都是 ExpandableNotificationRow 的实例,它们会被垂直堆叠显示。
  4. 展开和折叠: 分组通知可以通过用户交互(点击、滑动等)或编程方式(如响应其他事件)来展开或折叠。ExpandableNotificationRow 控制其 NotificationChildrenContainer 的展开状态,当用户展开分组时,子通知将会显示出来;当折叠分组时,这些子通知会被隐藏,只显示摘要。
  5. 用户交互ExpandableNotificationRow 还包含逻辑来处理用户的交互,例如点击通知来展开或折叠分组。这通常通过设置点击监听器来实现,当用户点击时,会切换分组的展开状态。
  6. 通知更新: 当通知行更新时,(例如,当新的子通知到来或现有的子通知被移除时),ExpandableNotificationRow 会更新其 NotificationChildrenContainer,添加或删除子通知元素,并重新布局以反映最新的子通知列表。

ExpandableNotificationRowNotificationChildrenContainer 共同工作,确保分组通知的子通知可以被适当地管理和展示,同时也提供了丰富的用户交互以及对展开和折叠状态的响应。

相关文章

网友评论

      本文标题:SystemUI 分析之 ExpandableNotificat

      本文链接:https://www.haomeiwen.com/subject/hxvizdtx.html