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
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:
- Supporting Multiple Screens
- Difference between px, dp, dip and sp in Android?
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)
<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