Dynamically change drawable colors - java

In my application I have a lot of drawables defined with xml files. For example I have a button defined like that:
button.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Bottom 3dp Shadow -->
<item android:top="3dp">
<shape android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#color/black_30" />
</shape>
</item>
<!-- green top color -->
<item android:top="3dp" android:bottom="3dp" android:id="#+id/background">
<shape android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#color/green1" />
</shape>
</item>
</layer-list>
and then I display a button like that:
layout.xml
<Button
android:id="#+id/button"
android:layout_gravity="center"
android:layout_height="60dp"
android:layout_width="fill_parent"
android:textSize="17sp"
android:gravity="center"
android:background="#drawable/button" />
When I navigate in the app, I want to "theme" some views (some colors are changing in function of the context) and to do that I would like to be able to change dynamically the color of the button (green1) at runtime.
1) One first nice approach would be to change the color definition in button.xml with an ?attr/my_color. And then define the different color values I need in the theme file style.xml. Then at runtime, I can switch to the desired theme and that will work. The complete steps are here:
How to reference colour attribute in drawable?
The issue is that it works on Android 5 but not on Android 4 ( and I need to support this version) (we get an android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>)
2) The second approach is to load the drawable in the code and then use setColorto change the color of the drawable: (written in Xamarin.Android but I am sure that you will understand the corresponding Java version)
LayerDrawable button = (LayerDrawable)Resources.GetDrawable(Resource.Drawable.normal_question_button);
GradientDrawable background = (GradientDrawable)button.FindDrawableByLayerId(Resource.Id.background);
background.SetColor(Android.Graphics.Color.Red.ToArgb());
The good things is that it's works... but randomly... Sometimes when I am displaying the button again, it's still the original green that is displayed. Sometimes, it's the new color... And once I have one of the both behaviour, the same color can stay many time and suddenly it changes again to the correct one.
Someone could explain this? Is there some caching on drawables that can gives that kind of issue?
3) I was thinking about a third solution: dynamically change the color defined in colors.xml (where green1 is defined) but it doesn't seem possible

In fact for 2) one really simple solution is:
instead of trying to customize the drawable coming from the xml file:
LayerDrawable button = (LayerDrawable)Resources.GetDrawable(Resource.Drawable.normal_question_button);
GradientDrawable background = (GradientDrawable)button.FindDrawableByLayerId(Resource.Id.background);
background.SetColor(Android.Graphics.Color.Red.ToArgb());
We can change directly the color on each button once we have an instance for them:
LayerDrawable buttonDrawable = _button.Background;
GradientDrawable background = (GradientDrawable)buttonDrawable.FindDrawableByLayerId(Resource.Id.background);
background.SetColor(Android.Graphics.Color.Red.ToArgb());

Related

How to make color gradient overlay in android

I was wondering how can we create a gradient overlay which colours are extracted from a image.
Like Resso home track player does.
It's really going to be interesting
I assume you wanted to have a background gradient effect, to make this do these steps:
Go to res -> drawable -> Right click on the folder and then select New -> Drawable Resource File
Make a file name "gradient_background" and then press OK
Add <item>, <shape> and then <gradient>, example:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#4e54c8"
android:endColor="#8f94fb"
android:type="linear" />
</shape>
</item>
</selector>
Adjust what type of the gradient effect you want to make, it can be a linear, radial, sweep and so on.
Full documentation: https://learntodroid.com/how-to-add-a-gradient-background-to-an-android-app/
To make a gradient that you will use as background, you can follow these simple steps
Go to res -> drawable, right click and select New -> Drawable Resource file.
Name the file anything you want example "background_gradient"
On Root element: type shape and create the file.
Add gradient element inside the shape element. You will have something like this below
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><gradient android:startColor="#color/your_start_color" android:endColor="#color/your_end_color" android:angle="0" android:type="linear"/></shape>
The gradient element comes with attribute that will define what you want. Like
android:type = "linear|radial|sweep" android:gradientRadius for radial type.
centerX and centerY etc.. you can play with them.
To use the the created gradient, goTo the layout you want to use it and use it as background. for example
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#drawable/background_gradient"><!-- other content of your xml --></RelativeLayout>

Inner shadow have incorrect Color in Android 6-7

Greetings to all
I need assistance to solve the problem with shape, gradient. I use theme with parent ↓
<style name="Theme.MaterialComponents.DayNight.NoActionBar.Bridge" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge" />
<style name="Theme.Movie42" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
and i have a shape with gradient inside ↓
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient
android:angle="90"
android:centerColor="#color/center_of_shape"
android:centerX="0.6"
android:endColor="#color/end_of_shape"
android:startColor="#color/start_of_shape"
android:type="linear" />
</shape>
</item>
I use it for make inner shadow on imageView↓
imageView.background =
ContextCompat.getDrawable(application.applicationContext, itemMovieData.drawable)
imageView.setImageDrawable(
ContextCompat.getDrawable(
application.applicationContext,
R.drawable.shape
)
)
When i run app on Android 11 (emulator) everyfing looks good
but when it runs on real device with Android 6 or 7 (maybe else versions)
"inner shadow" have a white color which is i don't actually need↓
How to fix this issue? Make shadow "great again", i mean make it dark on api 23/24↑
Here is the answer. Color 00FFFFFF and 00000000 are not the same colors. Yes they both 100% transparent and on screen looks the same. In android 6-7 it matters which of these colors do you chose.
So I chose the wrong color and make my shadow white. I am ashamed

Create circular looking drawable in android

I want to create a circular color filled drawable with a letter inside it in android java. I want to set the letter and color dynamically. Any ideas how to create it?
Try this.https://github.com/amulyakhare/TextDrawable
in this repository you can put text in a drawable
Create your TextView like this (this one centers the text):
<TextView
android:id="#+id/mTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_centerVertical="true"
android:background="#drawable/shape_circle">
</TextView>
Your shape like this:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#color/circleColor">
</solid>
<size
android:width="#dimen/circleSize"
android:height="#dimen/circleSize"
/>
</shape>
Then you can set the text in the TextView dynamically as usual with mTextView.setText().
To change the color dynamically, take a look here.

Simple gradient in Android

I'm kinda new to Android, and I'm looking to create a really simple gradient of 2 colors, from top to bottom, display it on the view, and maybe save it as an image. I really didn't find an answer that suits my needs, I'm really looking for the simplest and most straight-forward way.
Thanks!
I think the easiest way is to create a simple Shape template in XML, and then use it in any view you want, like this:
shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:type= "linear"
android:startColor="#474946"
android:endColor="#181818"
android:angle="270"/>
</shape>
then in your view tag just add:
android:background="#drawable/shape"
I will answer in two parts creating gradient and the displaying it.
To create gradient Create a new xml file in your drawable folder and name it whatever you want. In this case i will call it myGradient.xml.
Open myGradient.xml file and paste the code below which will help create two color gradient. You can change the values of color to what you need.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:bottom="6px" android:right="4dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#d7009482"
android:endColor="#ad1c4e9b"
android:centerX="100%"
android:centerY="150%"
android:type="linear"
android:angle="135"/>
</shape>
</item>
</layer-list>
This will give you output below.
Gradient with two colors
The second part will be to display this gradient in view.
Open your view and set background to be the gradient.
android:background="#drawable/myGradient
Hope that will help you

Dynamically creating drawables

I am trying the create a button that has a ring around it (it is for a clicker-counter app). Currently I am creating this ring a drawable then setting the background of the button to the drawable. The code in the drawable is as follows:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="#dimen/large_inner_radius"
android:thickness="#dimen/large_thickness"
android:useLevel="false">
<solid android:color="#color/large_circle" />
</shape>
The Dimentions are in another dimens file, here they are
<dimen name="large_inner_radius">200dp</dimen>
<dimen name="large_thickness">10dp</dimen>
The problem is, I need the be able to scale these drawables for different size android screens and I would like to be able to do this dynamically from code. I can not just scale the drawable because the thickness of the ring would be wrong.
Can anyone help please?

Categories

Resources