I am adding backwards compatibility for an app and setTint is used on a Drawable retrieved from a LayerDrawable. Code is below.
Drawable background = layerDrawable.getDrawable(0);
background = DrawableCompat.wrap(background);
DrawableCompat.setTint(background.mutate(), color);
This works the first time but if I then try and change it again afterwards, it doesn't change. Please note, this is the case for Android SDK < 21. 21 and above it works.
So after reading the documentation like a good boy for the DrawableCompat.wrap method, I realised I needed to add the "wrapped" drawable back into the LayerDrawable.
int id = layerDrawable.getId(0);
Drawable background = layerDrawable.getDrawable(0);
background = DrawableCompat.wrap(background);
layerDrawable.setDrawableByLayerId(id,background);
DrawableCompat.setTint(background.mutate(), color);
Related
My app is using a custom Notification layout with RemoteViews.
To display text, the layout is using the following system styles:
android:TextAppearance.Material.Notification.Title
android:TextAppearance.Material.Notification
This works fine.
However, the TextAppearance style can't be used to set the value of android:tint, so I had to hardcode the color.
To my best knowledge, there's no special system style for setting notification ImageButton tint.
Hardcoded colors work fine on the current Android 5+ systems, but some users install custom ROMs with custom dark themes, and the notification looks wrong, i.e. black icons on black background.
Is there any way to get the system notification icon / imagebutton color, and apply it from an XML layout?
Or maybe there's another way to achieve this?
Sorry, But as per my knowledge custom ROM's have separate system designs,configurations and that are not official as well.
So,supporting Custom ROM without knowledge about its design is not possible.
And android APIs are for supporting official ROM's.
Hope it Helps!!
Try this example :
Definition for notification :
// Declare variable
public static Bitmap icon;
// Assign value but this line can be different depends on current
// android sdk vesion ...
icon = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.YOUR_IMAGE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setShowWhen(false);
mBuilder.setDefaults(Notification.DEFAULT_ALL);
mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
mBuilder.setSmallIcon(R.drawable.image1); // One way to load img
mBuilder.setContentText("this text not visible");
mBuilder.setLargeIcon(icon);// This is the line
mBuilder.setPriority(Notification.PRIORITY_DEFAULT);
mBuilder.setContent(contentNotifySmall); // ORI
//mBuilder.setAutoCancel(false);
mBuilder.setCustomBigContentView(contentNotify);
I setup small and big variant for any case , this is important.
for background can you try these attributes...
app:backgroundTint="#color/pay"
---------Or-------------
android:tint="#color/white"
You can take textColor from TextAppearance_Compat_Notification_Title and add it as tint to an image programmatically like this
val remoteViews = RemoteViews(service.packageName, R.layout.notification_layout)
val icon = Icon.createWithResource(context, R.drawable.icon)
val attrs = intArrayOf(android.R.attr.textColor)
with(context.obtainStyledAttributes(R.style.TextAppearance_Compat_Notification_Title, attrs)) {
val iconColor = getColor(0, Color.GRAY)
icon.setTint(iconColor)
recycle()
}
remoteViews.setImageViewIcon(R.id.ibPlayPause, icon)
You can use a notificationlistenerservice to get an active notification. This returns a list of StatusBarNotifications, then just:
StatusBarNotifcation sBNotification = activeNotifications[0];
Notification notification = sBNotification.getNotification();
int argbColor = notification.color;
If you change ImageButton to ImageView in your layout you can update it with
RemoteViews remoteView = getRemoteViews(context);
// load base icon from res
Bitmap baseIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.base_icon);
// edit Bitmap baseIcon any way for your choose
Bitmap editedBitmap = ...
// update notification view with edited Bitmap
remoteView.setImageViewBitmap(R.id.button_icon, edited);
P.S. you can edit Bitmap like this:
https://stackoverflow.com/a/5935686/7630175 or any other way
Hope it's help
I'm using following function to enable and disable drawables...
public static void setDrawableState(Drawable d, boolean enabled)
{
if (d == null)
return;
d.mutate(); // so drawables don't share state anymore
if (enabled)
d.setAlpha(255);
else
d.setAlpha(100);
}
This worked on all phones I've tried yet, now I see it does not seem to work on android 4.4.2 (maybe it's not even version specific).
Is there another (better) way to set the alpha of a drawable? Or am I'm missing something?
Because drawables might share the same state, changing the drawable state will not have any effect. You need to mutate the drawable, for example in your code, try something like:
d.mutate().setAlpha(100);
Android developer Blogs has a great blog post explaining more on drawable state and mutations.
in case you wanna be really sure:
Drawable d2 = d.getConstantState().newDrawable().mutate();
d2.setAlpha(100)
I have a bitmap drawable image to be displayed in ImageView, below is my code:
BitmapDrawable bitmapGrass = (BitmapDrawable)
getResources().getDrawable(R.drawable.grass);
bitmapGrass.setTileModeX(TileMode.REPEAT);
I want to set that bitmap as background for ImageView, like this:
ImageView bgGrass = (ImageView) findViewById(R.id.image_grass);
bgGrass.setBackground(bitmapGrass);
Now the problem is, the method setBackground() is added in API level 16, but I want my app to support API level 4. I know I can use this code:
bgGrass.setBackgroundDrawable(bitmapGrass);
But the method setBackgroundDrawable() is deprecated. The other way to set the background is using the method setBackgroundResource(int), but the required parameter is integer (not drawable).
Is there any way to implement that bitmap without using deprecated method, perhaps converting the bitmap drawable into resource?
Thanks!
Actually it's fine to call setBackgroundDrawable though it's deprecated in newer platforms. you can check the sdk level at runtime and call the specific method:
if(Build.VERSION.SDK_INT >= 16) {
//call setBackground()
} else {
//call settBackgroundDrawable()
}
I have a code snippet to show you below and I am trying to change view's(v) background. I'll get color code from a TextView(dragged) and change View(v)'s background by using this code. But I get an error as indicate above. How can I fix it? Where is the problem? Thanks.
ColorDrawable cd = (ColorDrawable)dragged.getBackground();
int colorCode = cd.getColor();
v.setBackgroundColor(colorCode);
If you want to just assign a background of one view to another and not just the color you can use the following code
Drawable drawable = dragged.getBackground();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
v.setBackgroundDrawable(drawable );
}else{
v.setBackground(drawable);
}
However if you want to get only the color then you will have to identify in advance what types of drawable are being assigned to view. Then use instanceof to handle how to get background color for corresponding drawable.
how can I set an xml background file that placed in drawable for a view without using #SuppressLint("NewApi") ?
for example I created a drawable xml file for my textview
when I call TV.setBackground(getResources().getDrawable(R.drawable.tv_pic_back)); eclipse automatically add #SuppressLint("NewApi") at the first of my function.
how can I use that without #SuppressLint("NewApi") ?
I have a class where I put a lot of code to handle the different APIs, so that you use one line of code for one API, and another line of code for another API.
public static void setBackgroundDrawable(View view, Drawable drawable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(drawable);
}
else {
view.setBackgroundDrawable(drawable);
}
}
This will still give you a warning because setBackgroundDrawable is deprecated, but if you instead would use setBackground(drawable) for all versions then your application would crash on API levels lower than Jelly Bean (API 16).
However, in your case all you need to do is actually setBackgroundResource(R.drawable.tv_pic_back); because you don't need to get the drawable from the resource id yourself, Android will do that for you if you give it your resource id when you call the right method.
The Android developer reference will tell you which methods are deprecated and which methods are implemented in which API version.