Android Gradient drawable programmatically - android

I have a gradient drawable defined in xml that I use it as a background, like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:bottom="4dp">
<shape>
<gradient
android:startColor="#color/blue"
android:endColor="#color/dark_blue"
android:angle="270" />
</shape>
</item>
<item android:top="98dp">
<shape>
<gradient
android:startColor="#color/black"
android:endColor="#color/transparent_black"
android:angle="270" />
</shape>
</item>
</layer-list>
I need to implement this programmatically. I have tried to use a GradientDrawable as follows (this method is implemented on a custom view):
int[] colors1 = {getResources().getColor(R.color.black), getResources().getColor(R.color.trasparent_black)};
GradientDrawable shadow = new GradientDrawable(Orientation.TOP_BOTTOM, colors1);
shadow.setBounds(0,98, 0, 0);
int[] colors = new int[2];
colors[0] = getResources().getColor(R.color.blue);
colors[1] = getResources().getColor(R.color.dark_blue);
GradientDrawable backColor = new GradientDrawable(Orientation.TOP_BOTTOM, colors);
backColor.setBounds(0, 0,0, 4);
//finally create a layer list and set them as background.
Drawable[] layers = new Drawable[2];
layers[0] = backColor;
layers[1] = shadow;
LayerDrawable layerList = new LayerDrawable(layers);
setBackgroundDrawable(layerList);
The problem is that it seems that setting the bounds is useless or doesn't work the same way as (android:top, android:bottom xml parameters). The resulting background is each layer painted from top to bottom, one above the other.
I want to generate something like this:

Found the answer!. Possible duplicate Multi-gradient shapes.
Replaced:
backColor.setBounds(0, 0,0, 4);
shadow.setBounds(0,98, 0, 0);
for
layerList.setLayerInset(0, 0, 0, 0, 4);
layerList.setLayerInset(1, 0, 98, 0, 0);

Related

How to create Gradient with more than three colors using XML

I need to create a linear Gradient with 5 different colors.
I tried the following:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item>
<shape>
<gradient
android:startColor="#color/diagramBlueColor"
android:endColor="#color/diagramGreenColor"
android:type="linear"
android:angle="0" />
</shape>
</item>
<item>
<shape>
<gradient
android:startColor="#color/diagramGreenColor"
android:endColor="#color/diagramYellowColor"
android:type="linear"
android:angle="0" />
</shape>
</item>
<item>
<shape>
<gradient
android:startColor="#color/diagramYellowColor"
android:endColor="#color/diagramOrangeColor"
android:type="linear"
android:angle="0" />
</shape>
</item>
<item>
<shape>
<gradient
android:startColor="#color/diagramOrangeColor"
android:endColor="#color/diagramRedColor"
android:type="linear"
android:angle="0" />
</shape>
</item>
</layer-list>
</item>
</selector>
But every shape is overriding the shape before. I need to create the gradient using xml. How can i do that?
If it is not possible with pure xml then how can i do it in java code?
I tried this:
/**
*
* #return
*/
public static PaintDrawable getColorScala() {
ShapeDrawable.ShaderFactory shaderFactory = new ShapeDrawable.ShaderFactory() {
#Override
public Shader resize(int width, int height) {
LinearGradient linearGradient = new LinearGradient(0, 0, width, height,
new int[] {
0xFF1e5799,
0xFF207cca,
0xFF2989d8,
0xFF207cca }, //substitute the correct colors for these
new float[] {
0, 0.40f, 0.60f, 1 },
Shader.TileMode.REPEAT);
return linearGradient;
}
};
PaintDrawable paint = new PaintDrawable();
paint.setShape(new RectShape());
paint.setShaderFactory(shaderFactory);
return paint;
}
But when i set the background of my view:
view.setBackground(Colors.getColorScala());
The background of my view is white. I want it to look like that:
You can't as you already found. Lookup you colors to make it more flexible in code i think is the best way to do so
getColor(R.color.rainbow_1);
getColor(R.color.rainbow_2);
getColor(R.color.rainbow_3);
getColor(R.color.rainbow_4);
getColor(R.color.rainbow_5);
and create your array
you can get your colors via getColor from colors.xml or parse it..
int[] gradientColors = new int[] {
Color.parseColor("#80E1F1"),
Color.parseColor("#5257F6"),
Color.parseColor("#8222FC")
};
float[] gradientColorPos = new float[] {
0, 0.5f, 1f
};
use it like so..
paint.setShader(new LinearGradient(0, 0, width, height, gradientColors, gradientColorPos, Shader.TileMode.MIRROR));

Change xml drawables colors dynamically [duplicate]

What I'm trying to achieve is to use a Drawable with a couple of layers inside it, but control some values at runtime such as the startColor for the gradient. Here's what I have in my_layered_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#FF000000" />
<solid android:color="#FFFFFFFF" />
</shape>
</item>
<item android:top="1dp" android:bottom="1dp">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#FF000000" />
<gradient
android:startColor="#FFFFFFFF"
android:centerColor="#FFFFFF88"
android:endColor="#FFFFFFFF"
android:gradientRadius="250"
android:centerX="1"
android:centerY="0"
android:angle="315"
/>
</shape>
</item>
</layer-list>
And if I use mMyImageView.setBackgroundResource(R.drawable.my_layered_shape) it works.
I don't mind splitting the xml if I have to, or doing the whole thing programatically as long as there's a way to get at the various color values. The concept I'm going for programmatically (i.e. my best shot at doing the same in code as this xml) is:
Drawable[] layers = new Drawable[2];
ShapeDrawable sd1 = new ShapeDrawable(new RectShape());
sd1.getPaint().setColor(0xFFFFFFFF);
sd1.getPaint().setStyle(Style.STROKE);
sd1.getPaint().setStrokeWidth(1);
// sd1.getPaint().somehow_set_stroke_color?
ShapeDrawable sd2 = new ShapeDrawable(new RectShape());
sd2.getPaint().setColor(0xFF000000);
sd2.getPaint().setStyle(Style.STROKE);
// sd2.getPaint().somehow_set_stroke_color?
// sd2.getPaint().somehow_set_gradient_params?
layers[0] = sd1;
layers[1] = sd2;
LayerDrawable composite = new LayerDrawable(layers);
mMyImageView.setBackgroundDrawable(composite);
Thanks.
It seems that is does not work with ShapeDrawable, but take a look at my GradientDrawable example:
GradientDrawable gd = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]{Color.RED, Color.GREEN});
gd.setStroke(10, Color.BLUE);
You may also need following method:
gd.setGradientCenter(float x, float y);
gd.setGradientRadius(float gradientRadius);
Just gonna leave this here... Not tested yet
/**
* Created by Nedo on 09.04.2015.
*/
public class ShapeBuilder {
public static Drawable generateSelectorFromDrawables(Drawable pressed, Drawable normal) {
StateListDrawable states = new StateListDrawable();
states.addState(new int[]{ -android.R.attr.state_focused, -android.R.attr.state_pressed, -android.R.attr.state_selected}, normal);
states.addState(new int[]{ android.R.attr.state_pressed}, pressed);
states.addState(new int[]{ android.R.attr.state_focused}, pressed);
states.addState(new int[]{ android.R.attr.state_selected}, pressed);
return states;
}
public static Drawable generateShape(String colorTop, String colorBot, String colorStroke, int stokeSize, float strokeRadius) {
int top, bot, stroke;
top = Color.parseColor(colorTop);
bot = Color.parseColor(colorBot);
stroke = Color.parseColor(colorStroke);
GradientDrawable drawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, new int[]{top, bot});
drawable.setStroke(stokeSize, stroke);
drawable.setCornerRadius(strokeRadius);
return drawable;
}
public static Drawable buildSelectorShapeFromColors(String colorNormalStroke, String colorNormalBackTop, String colorNormalBackBot,
String colorPressedStroke, String colorPressedBackTop, String colorPressedBackBot,
int strokeSize, float strokeRadius) {
Drawable pressed = generateShape(colorPressedBackTop, colorPressedBackBot, colorPressedStroke, strokeSize, strokeRadius);
Drawable normal = generateShape(colorNormalBackTop, colorNormalBackBot, colorNormalStroke, strokeSize, strokeRadius);
return generateSelectorFromDrawables(pressed, normal);
}
}
Edit: tested Now, had one mistake.
You actually have to describe every single state. If you group states they will only be triggered if all of them accure at once...

LayerDrawable programmatically

Since my application's color theme is dynamic i can only create background drawables using colors and shapedrawables,
i want to build a edittext background drawable with colors and shapes as shown below.
But i want to do this programatically
How to build this same drawable programatically?
<item>
<shape>
<solid android:color="#android:color/yellow" />
</shape>
</item>
<!-- main color -->
<item
android:bottom="1dp"
android:left="1dp"
android:right="1dp">
<shape>
<solid android:color="#android:color/white" />
</shape>
</item>
<!-- draw another block to cut-off the left and right bars -->
<item android:bottom="10dp">
<shape>
<solid android:color="#android:color/white" />
</shape>
</item>
this is what i tried....
GradientDrawable border = new GradientDrawable();
border.setShape(GradientDrawable.RECTANGLE);
border.setColor(Color.WHITE);
GradientDrawable background = new GradientDrawable();
background.setShape(GradientDrawable.RECTANGLE);
background.setColor(Color.YELLOW);
GradientDrawable clip = new GradientDrawable();
clip.setShape(GradientDrawable.RECTANGLE);
border.setColor(Color.WHITE);
Drawable[] layers = {background, border, clip};
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerInset(0, 0, 0, 0, 0);
layerDrawable.setLayerInset(1, 1, 0, 1, 1);
layerDrawable.setLayerInset(2, 0, 0, 0, 10);
but the result is different....please help....!
I finally got it working. Instead of using GradientDrawable I used ShapeDrawable.
By setting this LayerDrawable as an EditText background you can regenerate default EditText
styles with custom colors.
ShapeDrawable border = new ShapeDrawable();
border.getPaint().setColor(Color.WHITE);
ShapeDrawable background = new ShapeDrawable();
background.getPaint().setColor(Color.BLACK);
ShapeDrawable clip = new ShapeDrawable();
clip.getPaint().setColor(Color.WHITE);
Drawable[] layers = {background, border, clip};
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerInset(0, 0, 0, 0, 0);
layerDrawable.setLayerInset(1, 1, 0, 1, 1);
layerDrawable.setLayerInset(2, 0, 0, 0, 10);
This also works with Gradient Drawables:
GradientDrawable border = new GradientDrawable();
border.setColor(Color.White);
GradientDrawable background = new GradientDrawable();
background.setColor(Color.Black);
GradientDrawable clip = new GradientDrawable();
clip.setColor(Color.White);
GradientDrawable[] layers = {background, border, clip};
LayerDrawable layerDrawable = new LayerDrawable(layers);
layerDrawable.setLayerInset(0, 0, 0, 0, 0);
layerDrawable.setLayerInset(1, 1, 0, 1, 1);
layerDrawable.setLayerInset(2, 0, 0, 0, 10);

Drawing LinearGradient in a layout

i try to draw LinearGradient in a layout but the gradient is not fit into my view.
Instead of gradient i see only one color.
I think its because im not giving the right dimension of the view
Here is my code:
backGroundColorView = (LinearLayout) findViewById(R.id.backGroundColorView);
int[] tempColors = data.getAppBackgroundColor();
LinearGradient test = new LinearGradient(0.f, 0.f, backGroundColorView.getWidth(), backGroundColorView.getHeight(), tempColors, null, TileMode.CLAMP);
ShapeDrawable shape = new ShapeDrawable(new RectShape());
shape.getPaint().setShader(test);
backGroundColorView.setBackgroundDrawable(shape);
Thank for helping
just use GradientDrawable as a background http://developer.android.com/reference/android/graphics/drawable/GradientDrawable.html
You can use this site do create the gradient you want and then add a file in your res/drawable and put the code inside.
After that all you have to do is set the background of your layout to be the drawable file you just created.
If you have any questions just ask ;)
EDIT:
Change your code to this:
GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM,tempColors);
gd.setCornerRadius(0f);
backGroundColorView.setBackgroundDrawable(gd);
Try this
backGroundColorView = (LinearLayout) findViewById(R.id.backGroundColorView);
int[] tempColors = data.getAppBackgroundColor();
GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,tempColors);
gd.setCornerRadius(0f);
backGroundColorView .setBackgroundDrawable(gd);
Instead of
backGroundColorView = (LinearLayout) findViewById(R.id.backGroundColorView);
int[] tempColors = data.getAppBackgroundColor();
LinearGradient test = new LinearGradient(0.f, 0.f, backGroundColorView.getWidth(), backGroundColorView.getHeight(), tempColors, null, TileMode.CLAMP);
ShapeDrawable shape = new ShapeDrawable(new RectShape());
shape.getPaint().setShader(test);
backGroundColorView.setBackgroundDrawable(shape);
GradientDrawable
you can create linear gradiant like this:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
android:type="linear"
android:centerX="50%"
android:startColor="#FF003333"
android:centerColor="#FF05C1FF"
android:endColor="#FF003333"
android:angle="270"/>
<!-- <gradient
android:centerColor="#FF05C1FF"
android:centerX="50%"
android:centerY="50%"
android:endColor="#FF003333"
android:gradientRadius="50"
android:startColor="#FF003333"
android:type="radial" /> -->
<corners
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp"
android:topLeftRadius="15dp"
android:topRightRadius="15dp" />
</shape>
and use it as background of linear layout.
ihope it solves your problem.
see i have used this in my post: customToast
you can use this also:
GradientDrawable grad = new GradientDrawable(Orientation.LEFT_RIGHT,
new int[]{0xffffffff, 0xffff00ff, 0xffffff00,
0xff0000ff, 0xf0f0f0f0, 0xfefefefe});
grad.setBounds(0, 0, 320, 480);

Android - how to define ShapeDrawables programmatically?

What I'm trying to achieve is to use a Drawable with a couple of layers inside it, but control some values at runtime such as the startColor for the gradient. Here's what I have in my_layered_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#FF000000" />
<solid android:color="#FFFFFFFF" />
</shape>
</item>
<item android:top="1dp" android:bottom="1dp">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#FF000000" />
<gradient
android:startColor="#FFFFFFFF"
android:centerColor="#FFFFFF88"
android:endColor="#FFFFFFFF"
android:gradientRadius="250"
android:centerX="1"
android:centerY="0"
android:angle="315"
/>
</shape>
</item>
</layer-list>
And if I use mMyImageView.setBackgroundResource(R.drawable.my_layered_shape) it works.
I don't mind splitting the xml if I have to, or doing the whole thing programatically as long as there's a way to get at the various color values. The concept I'm going for programmatically (i.e. my best shot at doing the same in code as this xml) is:
Drawable[] layers = new Drawable[2];
ShapeDrawable sd1 = new ShapeDrawable(new RectShape());
sd1.getPaint().setColor(0xFFFFFFFF);
sd1.getPaint().setStyle(Style.STROKE);
sd1.getPaint().setStrokeWidth(1);
// sd1.getPaint().somehow_set_stroke_color?
ShapeDrawable sd2 = new ShapeDrawable(new RectShape());
sd2.getPaint().setColor(0xFF000000);
sd2.getPaint().setStyle(Style.STROKE);
// sd2.getPaint().somehow_set_stroke_color?
// sd2.getPaint().somehow_set_gradient_params?
layers[0] = sd1;
layers[1] = sd2;
LayerDrawable composite = new LayerDrawable(layers);
mMyImageView.setBackgroundDrawable(composite);
Thanks.
It seems that is does not work with ShapeDrawable, but take a look at my GradientDrawable example:
GradientDrawable gd = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]{Color.RED, Color.GREEN});
gd.setStroke(10, Color.BLUE);
You may also need following method:
gd.setGradientCenter(float x, float y);
gd.setGradientRadius(float gradientRadius);
Just gonna leave this here... Not tested yet
/**
* Created by Nedo on 09.04.2015.
*/
public class ShapeBuilder {
public static Drawable generateSelectorFromDrawables(Drawable pressed, Drawable normal) {
StateListDrawable states = new StateListDrawable();
states.addState(new int[]{ -android.R.attr.state_focused, -android.R.attr.state_pressed, -android.R.attr.state_selected}, normal);
states.addState(new int[]{ android.R.attr.state_pressed}, pressed);
states.addState(new int[]{ android.R.attr.state_focused}, pressed);
states.addState(new int[]{ android.R.attr.state_selected}, pressed);
return states;
}
public static Drawable generateShape(String colorTop, String colorBot, String colorStroke, int stokeSize, float strokeRadius) {
int top, bot, stroke;
top = Color.parseColor(colorTop);
bot = Color.parseColor(colorBot);
stroke = Color.parseColor(colorStroke);
GradientDrawable drawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, new int[]{top, bot});
drawable.setStroke(stokeSize, stroke);
drawable.setCornerRadius(strokeRadius);
return drawable;
}
public static Drawable buildSelectorShapeFromColors(String colorNormalStroke, String colorNormalBackTop, String colorNormalBackBot,
String colorPressedStroke, String colorPressedBackTop, String colorPressedBackBot,
int strokeSize, float strokeRadius) {
Drawable pressed = generateShape(colorPressedBackTop, colorPressedBackBot, colorPressedStroke, strokeSize, strokeRadius);
Drawable normal = generateShape(colorNormalBackTop, colorNormalBackBot, colorNormalStroke, strokeSize, strokeRadius);
return generateSelectorFromDrawables(pressed, normal);
}
}
Edit: tested Now, had one mistake.
You actually have to describe every single state. If you group states they will only be triggered if all of them accure at once...

Categories

Resources