2

Here I am using layer list to draw nested Circle by using XML

<item>
    <shape android:shape="oval" >
        <stroke
            android:width="1dp"
            android:color="@android:color/holo_orange_light" />

        <padding
            android:bottom="7dp"
            android:left="7dp"
            android:right="7dp"
            android:top="7dp" />
    </shape>
</item>
<item>
    <shape android:shape="oval" >
        <solid android:color="@color/welcome_bg" />
    </shape>
</item>

No I want same nested circle by using programmatically because I want to change color dynamically or is there any way to change color dynamically in xml provided above

Here is my custom View

public class MyView extends EditText {

public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

}

public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);

}

public MyView(Context context) {
    super(context);

}

@Override
protected void onDraw(Canvas canvas) {
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(Color.GRAY);

    RectF oval1 = new RectF(50, 50, 300, 300);
    canvas.drawOval(oval1, paint);

    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.RED);
    RectF oval2 = new RectF(55, 55, 295, 295);
    canvas.drawOval(oval2, paint);

}
}

Thanks

kumarharsh
  • 18,961
  • 8
  • 72
  • 100
Munir
  • 219
  • 3
  • 11
  • Create a custom View class and there fill onDraw with stuff. That should get you going! – vilpe89 Jan 07 '15 at 08:37
  • I have created a custom view but in that case nested circle not populate properly, it just looks blur pixel but when I use xml code then everthing ok. – Munir Jan 07 '15 at 08:49
  • try this http://stackoverflow.com/questions/15127351/how-to-change-color-of-drawable-shapes-in-android – Vilas Jan 07 '15 at 11:27

3 Answers3

2

When you use xml, specified dimensions are in dp - density independent pixels. But in your code drawing functions take actual pixels as parameters and you have to take that into account and calculate proper values yourself.

Depending on your device declared screen density 1dp will be translated to:

  • ldpi (120 dpi) - 0.75 pix
  • mdpi (160 dpi) - 1 pix
  • hdpi (240 dpi) - 1.5 pix
  • xhdpi (320 dpi) - 2 pix
  • xxhdpi (480 dpi) - 3 pix
  • xxxhdpi (640 dpi) - 4 pix

formula for calculating real pixels is px = dp * (dpi / 160)

public class MyView extends EditText {

float mDensityScale;    

public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr);
}

public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs, 0);    
}

public MyView(Context context) {
    super(context);
    init(context, null, 0);
}

private void init(Context context, AttributeSet attrs, int defStyle)
{
    final DisplayMetrics dm = context.getResources().getDisplayMetrics();
    mDensityScale = dm.density;
}

private float pix(float dp)
{
    return dp * mDensityScale;
}   

@Override
protected void onDraw(Canvas canvas) {
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(Color.GRAY);

    RectF oval1 = new RectF(pix(50), pix(50), pix(300), pix(300));
    canvas.drawOval(oval1, paint);

    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.RED);
    RectF oval2 = new RectF(pix(55), pix(55), pix(295), pix(295));
    canvas.drawOval(oval2, paint);

}
}

You can read more:

Community
  • 1
  • 1
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • The issue with that example, it's draw circle but the outer line of circle and stroke both not perfect, the line of circle and stroke both showing blur behavior @Dalija Prasnikar – Munir Jan 12 '15 at 05:35
  • @Daljia - In the formula px = dp * (dpi / 160) ...dpi is the dots per inch of the device ?...how can we find the dpi of a device ? how can we categorize a device into ldpi or mdi or xdpi etc..thanks – Rakesh patanga Mar 07 '15 at 12:18
  • 1
    @NagaR dpi is dots per inch of device, you can find it through `DisplayMetrics` (`init` method in above code). `dm.densityDpi` will give you dpi of the device (which category it falls in - ldpi, mdpi..) and `dm.density` will give you premultiplied scale (dpi / 160). To calculate device pixels use `px = dp * dm.density` (`pix` method in above code) Also take a look at http://developer.android.com/reference/android/util/DisplayMetrics.html – Dalija Prasnikar Mar 07 '15 at 13:43
2

If you want to change the drawable color while keeping using the xml, you could add an id to the item you want to modify:

<item>
    <shape android:shape="oval" >
        <stroke
            android:width="1dp"
            android:color="@android:color/holo_orange_light" />

        <padding
            android:bottom="7dp"
            android:left="7dp"
            android:right="7dp"
            android:top="7dp" />
    </shape>
</item>
<item android:id="@+id/circle_inner">
    <shape android:shape="oval" >
        <solid android:color="@color/welcome_bg" />
    </shape>
</item>

And then in your code get the layer list drawable and search for relevant id and change the color:

LayerDrawable layerDrawable = (LayerDrawable) v.getBackground();
GradientDrawable innerCircle = (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.circle_inner);
innerCircle.setColor(0xff00ff00);

Note that I'm casting to GradientDrawable, because that's what <shape> tag is a pointer to (shape tag documentation)

zilinx
  • 1,052
  • 8
  • 18
0

<item android:id="@+id/circle_outer">
    <shape android:shape="oval" >
        <stroke
            android:width="1dp"
            android:color="@android:color/holo_orange_light" />

        <padding
            android:bottom="7dp"
            android:left="7dp"
            android:right="7dp"
            android:top="7dp" />
    </shape>
</item>
<item android:id="@+id/circle_inner">
    <shape android:shape="oval" >
        <solid android:color="@color/welcome_bg" />
    </shape>
</item>

Here I provided XML and set their ids as well and changing color programmatically The way color changing of XML Items

LayerDrawable layerDrawable = (LayerDrawable) ctx.getResources().getDrawable(R.drawable.tv_circle);
    GradientDrawable innerCircle = (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.circle_inner);
    GradientDrawable outerCircle = (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.circle_outer);
    innerCircle.setColor(0xff00ff00);
    outerCircle.setStroke(2, Color.BLUE, 0, 10);

Thanks to all, Its works for me and please close it

Munir
  • 219
  • 3
  • 11