and*_*per 9 android android-custom-view android-layout android-notifications remoteview
我需要制作一个自定义的大型通知,底部有大约3个图像,顶部有图像标题和2个文本视图.
像这样的东西:

上部区域需要看起来与本机通知完全相同,以使它在两者之间有一个很好的过渡.
底部区域是动态的,照片放在那里(使用位图).
一旦我使用自定义视图,它实际上包含整个布局,包括上部区域.
我想到了两个解决方案:
为了创建位图,我可以使用这样的东西:
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;
Run Code Online (Sandbox Code Playgroud)
出于某种原因,它没有很好地显示图像,但你明白了......
我也试图在#2上夸大视图,并绘制到位图.它可以工作,但在某些设备和配置(甚至是风景)上它不能很好地工作.
以下是通知底部区域的示例布局:
<?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>
Run Code Online (Sandbox Code Playgroud)
关于在自定义布局上使用样式的文档非常模糊,只需要小心并在多个Android设备上试用它:
警告:使用自定义通知布局时,请特别注意确保自定义布局使用不同的设备方向和分辨率.虽然此建议适用于所有View布局,但对于通知尤为重要,因为通知抽屉中的空间非常有限.不要使自定义布局过于复杂,并确保以各种配置进行测试.
样式文本也是如此:
始终将样式资源用于自定义通知的文本.通知的背景颜色可能因设备和版本而异,使用样式资源可帮助您解决此问题.从Android 2.3开始,系统为标准通知布局文本定义了一种样式.如果您在面向Android 2.3或更高版本的应用程序中使用相同的样式,则可以确保您的文本在显示背景下可见.
他们不告诉使用什么,哪种款式或颜色或任何东西......
是否可以创建此类通知?我应该怎么处理?
你还有其他想法可以做到这一点吗?
是否也可以使用限定符设置不同的布局(我没有成功)?
此外,也许是最重要的问题:如何在自定义视图上使用默认的通知样式?我不仅谈论标题和副标题textViews(可能使用"android:TextAppearance.StatusBar.EventContent.Title"和"android:TextAppearance.StatusBar.EventContent"样式),但对于通知的任何部分:图标右边的文字,行动,......
编辑:在搜索通知的样式一段时间后,我在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>
Run Code Online (Sandbox Code Playgroud)
有一种名为"TextAppearance.StatusBar.Icon"的样式很奇怪,因为它是一个图标,但它是一个textAppearance.再加上它是空的......
无论如何,在那之后,我找到了下一个布局文件,名为"notification_intruder_content.xml",但我不确定是否可以复制它,因为操作系统之间可能会发生变化(甚至在不同的roms之间):
<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>
Run Code Online (Sandbox Code Playgroud)
我试图使用它(只是更改ID,并设置文本和图像),但它看起来并不好:

不仅如此,但在触摸它时,我看不到触摸正常通知的效果,因此背景也可能是错误的.
编辑:遗憾的是它决定使用自定义视图解决方案(#2),但我找不到有关如何使所有内容看起来都是原生的足够信息,所以我不得不做一些"逆向工程"看着Android的代码以及通知的外观.
如果有人知道如何让它在所有Android版本(和roms)中看起来都很好,请告诉我.
我没有得到Exact输出,试试这个
创建通知:
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());
}
Run Code Online (Sandbox Code Playgroud)
创建视图到位图
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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
