简体   繁体   中英

how to draw nested circle programmatically

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM