How to draw a nested circle programmatically

Here I am using a layer list to draw a nested circle 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>

      

Not. I want the same nested circle to be used programmatically because I want to dynamically change the color or there is a way to dynamically change the color in the xml 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);

}
}

      

thank

+2


source to share


3 answers


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

Depending on the device announced, the 1dp screen density 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

to compute real pixels 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:

+2


source


If you want to change the drawing color while still using xml, you can add an id to the element you want to change:

<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 a list of layers to use, and find the corresponding 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 am passing in the GradientDrawable because the tag <shape>

is a pointer to ( form tag documentation )

+1


source


<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 have provided the XML and set their ids and also programmatically changing the color How to change the color of XML elements

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 everyone, its works for me and please close it

0


source







All Articles