I am trying to create a circle drawable with a dash. I am able to achieve circle with dash but am not able to apply gradient color. Is there any way to do it? thanks in advance.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="@dimen/size60"
android:height="@dimen/size60" />
<stroke
android:width="1dp"
android:color="@color/white"
android:dashWidth="3dp"
android:dashGap="1dp" />
</shape>
View achieved:
View Required:
CodePudding user response:
There is not a way to create a gradient ring using just XML AFAIK. You'll have better luck using a custom drawable. The following combine a sweep gradient shader with a Paint object to create a ring that has a gradient from start to end.
class DashedRingDrawable : Drawable() {
private val mPaint = Paint().apply {
style = Paint.Style.STROKE
strokeWidth = STROKE_WIDTH
}
private val mColorArray = intArrayOf(Color.WHITE, Color.BLACK)
private var mRingOuterDiameter = 0f
private var mRingOuterRadius = 0f
private var mRingInnerRadius = 0f
override fun onBoundsChange(bounds: Rect) {
super.onBoundsChange(bounds)
check(bounds.width() == bounds.height()) {
"Width must be equal to height. (It's a circle.)"
}
mRingOuterDiameter = bounds.width().toFloat()
mRingOuterRadius = mRingOuterDiameter / 2
mRingInnerRadius = (mRingOuterDiameter - STROKE_WIDTH) / 2
val dashLength = getNewDashLength()
mPaint.pathEffect = DashPathEffect(floatArrayOf(dashLength, GAP_LENGTH), 0f)
mPaint.shader = SweepGradient(mRingOuterRadius, mRingOuterRadius, mColorArray, null)
}
override fun draw(canvas: Canvas) {
// The following statement is here to show the boundaries and can be removed/commented out.
// canvas.drawColor(Color.RED)
canvas.drawCircle(mRingOuterRadius, mRingOuterRadius, mRingInnerRadius, mPaint)
}
override fun setAlpha(alpha: Int) {
}
override fun setColorFilter(colorFilter: ColorFilter?) {
}
override fun getOpacity(): Int {
return PixelFormat.OPAQUE
}
// Adjust the dash length so that we end on a gap and not in the middle of a dash.
private fun getNewDashLength(): Float {
val circumference = Math.PI.toFloat() * mRingInnerRadius
val dashCount = (circumference / (DASH_LENGTH GAP_LENGTH)).toInt()
val newDashLength = (circumference - dashCount * GAP_LENGTH) / dashCount
return newDashLength
}
companion object {
const val STROKE_WIDTH = 15f
const val DASH_LENGTH = 50f
const val GAP_LENGTH = 15f
}
}
For API 24 and higher, you can place this drawable into an XML file and use it like any other XML drawable.
<drawable xmlns:android="http://schemas.android.com/apk/res/android"
/>
For APIs before API 24, you will need to work with this custom drawable programmatically.