Uber 如何在 Android 通知中制作进度条?

问题描述 投票:0回答:1

Uber 有一篇文章 https://www.uber.com/en-DE/blog/live-activity-on-ios/ 他们说他们用进度条发出了通知。我知道这篇文章说的是关于 iOS 的,但也有一部分是关于 android 的。通知看起来像这样:通知,android 在右侧 我理解他们在 xml 中做了什么通知,但我无法理解他们如何从代码中控制它。如果无法获取通知宽度,他们如何计算进度?

我尝试使用屏幕宽度并从中减去通知边缘的一些值(大约 110 dp)。然后将其设置为进度条填充线的左内边距。

val displayMetrics: DisplayMetrics = Resources.getSystem().displayMetrics
val screenWidth = displayMetrics.widthPixels
val edgeDistance = 100dip // take it from values file

val progress = (screenWidth - edgeDistance) * p // 0 <= p <= 1

setViewPadding(filledLineId, progress, 0, 0, 0)

但是通知宽度通常比屏幕宽度小得多。在这种情况下,通知右侧的进度条会被切断。 我的进度条 xml:

<LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:id="@id/notification_progress" android:layout_width="fill_parent" android:layout_height="wrap_content"
  xmlns:android="http://schemas.android.com/apk/res/android">
    <FrameLayout 
      android:id="@id/filled" 
      android:background="@color/color2" 
      android:layout_width="wrap_content" 
      android:layout_height="@dimen/height" 
      android:layout_weight="1.0" 
      android:layout_marginEnd="2dp" />
    <ImageView 
      android:id="@id/progress_indicator" 
      android:layout_width="wrap_content" 
      android:layout_height="@dimen/indicator_height" 
      android:src="@drawable/ic_progress_indicator" 
      android:scaleType="fitCenter" android:adjustViewBounds="true"/>
    <FrameLayout 
      android:id="@id/not_filled" 
      android:background="@color/color2" 
      android:layout_width="wrap_content"
      android:layout_height="@dimen/height" 
      android:layout_weight="100" />
</LinearLayout>
android kotlin android-layout android-remoteview
1个回答
0
投票

要使用进度条正确控制自定义通知布局的进度,重要的是要考虑到通知的实际宽度不能总是根据屏幕宽度来估计,特别是因为通知可能由于内容差异而具有可变的大小(例如, 、文本、图标)或系统 UI 元素。

使用基于百分比的方法

由于您的目标是将进度表示为百分比,因此您可以调整方法,而无需通知的确切宽度。您可以根据百分比为填充和未填充的视图使用预定义的宽度(以重量计)。

这是实现进度逻辑的更好方法:

  1. 使用权重:我们不计算通知的像素宽度,而是直接使用布局权重。您可以根据进度设置
    not_filled
    filled
    FrameLayout 的权重。
  2. 根据进度计算权重:如果
    p
    是进度(0到1),则可以确定总重量中有多少已填充,有多少未填充。 例如,如果总重量为 100,则可以将已填充的重量指定为
    p * 100
    ,将未填充的重量指定为
    (1 - p) * 100

更新了 XML 布局

<LinearLayout
    android:id="@+id/notification_progress"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <FrameLayout
        android:id="@+id/filled"
        android:background="@color/color2"
        android:layout_width="0dp"
        android:layout_height="@dimen/height"
        android:layout_weight="0" /> <!-- Initially set to 0 -->

    <ImageView
        android:id="@+id/progress_indicator"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/indicator_height"
        android:src="@drawable/ic_progress_indicator"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true" />

    <FrameLayout
        android:id="@+id/not_filled"
        android:background="@color/color2"
        android:layout_width="0dp"
        android:layout_height="@dimen/height"
        android:layout_weight="100" /> <!-- Initially set to full weight -->
</LinearLayout>

用于设置进度的 Kotlin 代码

// Example function to update the progress
fun updateProgress(p: Float) {
    // Ensure p is between 0 and 1
    val progress = p.coerceIn(0f, 1f)

    // Calculate filled and not filled weights
    val filledWeight = (progress * 100).toFloat()
    val notFilledWeight = (1 - progress) * 100

    // Update weights dynamically
    val filledLayout = remoteViews.getViewId(R.id.filled)
    val notFilledLayout = remoteViews.getViewId(R.id.not_filled)

    // Set the layout weights of the filled and not filled layouts
    remoteViews.setViewLayoutWidth(filledLayout, 0) // width will be set because of weight
    remoteViews.setViewLayoutWidth(notFilledLayout, 0) // width will be set because of weight
    remoteViews.setViewLayoutWeight(filledLayout, filledWeight)
    remoteViews.setViewLayoutWeight(notFilledLayout, notFilledWeight)

    // Notify the change to the system
    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    notificationManager.notify(notificationId, notificationBuilder.build())
}
© www.soinside.com 2019 - 2024. All rights reserved.