Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - how to define ShapeDrawables programmatically?

Tags:

android

shape

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.

like image 872
Carl Whalley Avatar asked Aug 22 '11 16:08

Carl Whalley


People also ask

How to define a Drawable?

drawable (comparative more drawable, superlative most drawable) Capable of being drawn (represented graphically). Capable of being drawn (pulled or extracted). Capable of being drawn (deduced or inferred).

How to set image in Drawable XML Android?

To use an image resource, add your file to the res/drawable/ directory of your project. Once in your project, you can reference the image resource from your code or your XML layout. Either way, it's referred to using a resource ID, which is the file name without the file type extension. For example, refer to my_image.

How to add image Drawable Android?

Drag and drop your images directly onto the Resource Manager window in Android Studio. Alternatively, you can click the plus icon (+), choose Import Drawables, as shown in figure 3, and then select the files and folders that you want to import. Figure 3: Select Import Drawables from the dropdown menu.


2 Answers

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); 
like image 200
marnaish Avatar answered Sep 22 '22 20:09

marnaish


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...

like image 27
BooNonMooN Avatar answered Sep 20 '22 20:09

BooNonMooN