gpt4 book ai didi

android - 如何使用自定义 View 创建通知,但具有原生外观?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:38:25 24 4
gpt4 key购买 nike

背景

我需要制作一个自定义的大样式通知,底部有大约 3 个图像,顶部有一个图像的标题和 2 个 TextView 。

像这样的东西:

enter image description here

上部区域需要看起来与原生通知完全一样,以使其在两者之间有一个很好的过渡。

底部区域在放置哪些照片方面是动态的(使用位图)。

问题

一旦我使用自定义 View ,它实际上包含整个布局,包括上部区域。

我试过的

我想到了2个解决方案:

  • 创建一个包含 3 个图像的位图,然后使用 BigPictureStyle为了它。问题是它在某些情况下可能会裁剪图像的内容,并且如果您转到横向,图像之间的间距将无法很好地显示(我已经检查过:您不能设置多个布局,例如一个一个用于横向,一个用于纵向)。

  • 为了创建位图,我可以使用这样的东西:
        final int widthScreen = getResources().getDisplayMetrics().widthPixels;
    final int width = Math.min(widthScreen, (int) convertDpToPixels(this, 256));
    final Bitmap outputBitmap = Bitmap.createBitmap(width, width / 3, Config.ARGB_8888);
    final Canvas canvas = new Canvas(outputBitmap);
    final int[] imagesResIds = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3 };
    final Paint paint = new Paint();
    for (int i = 0; i < 3; ++i) {
    final Bitmap b = BitmapFactory.decodeResource(getResources(), imagesResIds[i]);
    canvas.drawBitmap(b, null, new Rect(i * (width / 3), 0, (i + 1) * (width / 3) - 1, width / 3 - 1), paint);
    }
    return outputBitmap;

    出于某种原因,它不能很好地显示图像,但你明白了......

    我还尝试扩大 #2 上的 View ,并绘制位图。它可以工作,但在某些设备和配置(甚至横向)上效果不佳。
  • 使用 RemoteViews,然后在 ImageViews 上设置图像。问题是我需要模仿顶部区域以看起来很原生,但即使我找到它,也不能保证它在所有设备和 Android 版本上看起来都很好(对吧?)。另外,我可能需要获取每个 Android 版本的 native 通知布局。使用水平 listView 也可能很好,但它不存在。

  • 这是通知底部区域的示例布局:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="128dp"
    android:gravity="center_horizontal"
    android:orientation="horizontal" >

    <ImageView
    android:layout_width="0px"
    android:layout_height="wrap_content"
    android:layout_weight="1" />

    <ImageView
    android:layout_width="128dp"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    android:src="@drawable/pic1" />

    <ImageView
    android:layout_width="0px"
    android:layout_height="wrap_content"
    android:layout_weight="1" />

    <ImageView
    android:layout_width="128dp"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    android:src="@drawable/pic2" />

    <ImageView
    android:layout_width="0px"
    android:layout_height="wrap_content"
    android:layout_weight="1" />

    <ImageView
    android:layout_width="128dp"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    android:src="@drawable/pic3" />

    <ImageView
    android:layout_width="0px"
    android:layout_height="wrap_content"
    android:layout_weight="1" />

    </LinearLayout>

    我发现了什么

    The documentation关于在自定义布局上使用样式非常模糊,告诉您要小心并在多个 Android 设备上试用:

    Caution: When you use a custom notification layout, take special care to ensure that your custom layout works with different device orientations and resolutions. While this advice applies to all View layouts, it's especially important for notifications because the space in the notification drawer is very restricted. Don't make your custom layout too complex, and be sure to test it in various configurations.



    样式文本也是如此:

    Always use style resources for the text of a custom notification. The background color of the notification can vary across different devices and versions, and using style resources helps you account for this. Starting in Android 2.3, the system defined a style for the standard notification layout text. If you use the same style in applications that target Android 2.3 or higher, you'll ensure that your text is visible against the display background.



    他们不告诉使用什么,哪种样式或颜色或任何东西......

    问题

    是否可以创建这样的通知?我应该如何处理?

    您对如何做到这一点有任何其他想法吗?

    是否也可以使用限定符设置不同的布局(我没有成功)?

    另外,也许是最重要的问题:如何在自定义 View 上使用默认通知样式?我说的不仅是标题和副标题 textViews(可能使用“android:TextAppearance.StatusBar.EventContent.Title”和“android:TextAppearance.StatusBar.EventContent”样式),还包括通知的任何部分:图标右边的文字, Action ,...

    编辑:在搜索了一段时间关于通知的样式后,我在 Android 源代码中的“styles.xml”中找到了这个:
    <style name="TextAppearance.StatusBar.Icon">
    </style>
    <!-- Notification content styles -->
    <style name="TextAppearance.StatusBar.EventContent">
    <item name="textColor">#999999</item>
    <item name="textSize">@dimen/notification_text_size</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Title">
    <item name="textColor">#ffffff</item>
    <item name="fontFamily">sans-serif-light</item>
    <item name="textSize">@dimen/notification_title_text_size</item>
    <item name="textStyle">bold</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Line2">
    <item name="textSize">@dimen/notification_subtext_size</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Info">
    <item name="textSize">@dimen/notification_subtext_size</item>
    <item name="textColor">#999999</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Time">
    <item name="textSize">@dimen/notification_subtext_size</item>
    <item name="textColor">#999999</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Emphasis">
    <item name="textColor">#CCCCCC</item>
    </style>

    奇怪的是有一个名为“TextAppearance.StatusBar.Icon”的样式,因为它是一个图标,但它是一个 textAppearance。再加上它是空的...

    无论如何,在那之后,我找到了下一个布局文件,名为“notification_intruder_content.xml”,但我不确定是否可以复制它,因为操作系统之间(甚至不同 rom 之间)的情况可能会发生变化:
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="4dp"
    >
    <ImageView android:id="@+id/icon"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:scaleType="center"
    android:padding="4dp"
    />
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:layout_marginStart="40dp"
    android:orientation="vertical"
    >
    <TextView android:id="@+id/title"
    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:fadingEdge="horizontal"
    />
    <TextView android:id="@+id/text"
    android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:layout_marginTop="-4dp"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:fadingEdge="horizontal"
    />
    </LinearLayout>
    <LinearLayout
    android:id="@+id/actions"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="48dp"
    android:orientation="horizontal"
    android:visibility="gone"
    >
    <Button
    style="?android:attr/buttonBarButtonStyle"
    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
    android:id="@+id/action0"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:visibility="gone"
    />
    <Button
    style="?android:attr/buttonBarButtonStyle"
    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
    android:id="@+id/action1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:visibility="gone"
    />
    <Button
    style="?android:attr/buttonBarButtonStyle"
    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
    android:id="@+id/action2"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:visibility="gone"
    />
    </LinearLayout>
    </FrameLayout>

    我尝试过使用它(只是更改 id,并设置文本和图像),但它看起来一点也不好看:

    enter image description here

    不仅如此,触摸它时,我看不到触摸普通通知的效果,所以背景也可能是错误的。

    编辑:遗憾的是,决定使用自定义 View 解决方案(#2),但我找不到足够的信息来说明如何让一切看起来都是原生的,所以我不得不通过查看 Android 来做一些“逆向工程”代码以及通知的外观。

    如果有人有关于如何使它在所有 Android 版本(和 rom)中看起来都很好的完整信息,请告诉我。

    最佳答案

    我没有得到确切的输出,试试这个

    创建通知:

    public void CustomNotification() {
    //dynamic layer
    LinearLayout ll = new LinearLayout(this);
    ll.setOrientation(LinearLayout.HORIZONTAL);

    LayoutParams llLP = new LayoutParams(
    LinearLayout.LayoutParams.FILL_PARENT,
    LinearLayout.LayoutParams.WRAP_CONTENT);
    ll.setLayoutParams(llLP);
    ImageView imageView = new ImageView(this);
    LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
    LayoutParams.WRAP_CONTENT);
    imageView.setLayoutParams(lp);
    imageView.setImageResource(R.drawable.v1);

    ll.addView(imageView);
    ImageView imageView1 = new ImageView(this);

    imageView1.setLayoutParams(lp);
    imageView1.setImageResource(R.drawable.v2);

    ll.addView(imageView1);
    //create a dynamic layout to bitmap
    Bitmap bp = convertViewToDrawable(ll);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(
    this).setSmallIcon(R.drawable.ic_launcher)
    .setTicker("Dummy App ").setAutoCancel(true)
    .setContentIntent(null);
    NotificationCompat.BigPictureStyle bigPicStyle = new NotificationCompat.BigPictureStyle();
    bigPicStyle.bigPicture(bp);
    bigPicStyle.setBigContentTitle("My Title");
    builder.setStyle(bigPicStyle);

    NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notificationmanager.notify(100, builder.build());

    }

    创建位图 View
    public static Bitmap convertViewToDrawable(View view) {
    int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    view.measure(spec, spec);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    Bitmap b = Bitmap.createBitmap(view.getMeasuredWidth(),
    view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.translate(-view.getScrollX(), -view.getScrollY());

    view.draw(c);
    view.setDrawingCacheEnabled(true);
    Bitmap cacheBmp = view.getDrawingCache();
    Bitmap viewBmp = cacheBmp.copy(Bitmap.Config.ARGB_8888, true);
    view.destroyDrawingCache();
    return viewBmp;

    }

    输出:

    output

    关于android - 如何使用自定义 View 创建通知,但具有原生外观?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26699788/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com