Reputation: 779
Task:
Want to accomplish gradient BORDER...
Start color starts from blue circle edge and end color ends on red ring edge.
I tried with shape oval, and ring and radial gradient. I need gradient that starts from edge of the circle (not from the centre) and expand to the end color. I am interested is it even possible to do that with radial gradient. What am I missing?
So far I made it like this:
<!-- Added shadow -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="85dp"
android:height="85dp">
<shape
android:shape="ring"
android:thickness="10dp"
android:useLevel="false">
<gradient
android:endColor="@android:color/transparent"
android:gradientRadius="37.5dp"
android:startColor="@color/colorBlack"
android:type="radial"></gradient>
</shape>
</item>
<item
android:width="64dp"
android:height="64dp"
android:left="11dp"
android:top="11dp">
<shape android:shape="oval">
<solid android:color="@color/colorPrimaryBlue" />
</shape>
</item>
</layer-list>
OUTPUT:
Original problem is not solved. The main problem is that radial gradient starts from the centre of the circle and not from the edge.
Any more ideas?
Upvotes: 1
Views: 2413
Reputation: 62841
I understand that you want what can be described as a corona around the disk with the disk a solid color and the corona starting with the color black at the disk's edge and transitioning to transparency radially.
I think you will need to implement a drawable for the corona with a RadialGradient using the constructors that allows the specification of colors and color stops from the center of the disk.
Mark Allison has a blog post entitled RadialGradient – Gradients that discusses the use of RadialGradients and their implementation.
You can look at a similar implementation that is transparent in the center and starts with black at the edge of the disk and transitions to a separate color. You would have to compute the starting position of the black as a fraction of the overall size of the image.
The following is a custom drawable that produces the desired effect:
class CoronaDrawable : Drawable() {
private val mPaint = Paint()
private var mRadius = 0f
private val mColors =
intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.BLACK, Color.BLACK and 0xFFFFFF)
private val mStops = floatArrayOf(0f, 0.85f, 0.85f, 1.0f)
override fun onBoundsChange(bounds: Rect) {
super.onBoundsChange(bounds)
mRadius = min(bounds.width(), bounds.height()) / 2f
mPaint.shader = shaderFactory(mRadius, mRadius, mColors, mStops)
}
override fun draw(c: Canvas) {
c.drawCircle(mRadius, mRadius, mRadius, mPaint)
}
override fun setAlpha(alpha: Int) {
}
override fun setColorFilter(filter: ColorFilter?) {
}
override fun getOpacity(): Int {
return PixelFormat.OPAQUE
}
private fun shaderFactory(centerX: Float, centerY: Float, colors: IntArray, stops: FloatArray) =
RadialGradient(
centerX, centerY, min(centerX, centerY), colors, stops, Shader.TileMode.CLAMP
)
}
which looks like this in the Android Studio layout designer as the background to a simple View:
The key take-away here is that the blank area in the center is set to transition from transparent to transparent or, otherwise, no change. This gives the empty center. At 85% of the radius the color abruptly changes to black and transitions to a transparent black.
For API 24+, you can place this drawable into a drawable resource file as follows and use it like a regular drawable.
corona.xml
<drawable class="com.example.radialgradientwithstops.CoronaDrawable"/>
You will have to determine how best to incorporate this drawable into your layer list or other means of presentation in your app.
Upvotes: 1
Reputation: 548
Try this
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow -->
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#00CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#10CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#20CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#30CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<solid android:color="#50CCCCCC" />
<corners android:radius="3dp" />
</shape>
</item>
<!-- Background Color (white) -->
<item>
<shape android:shape="oval">
<solid android:color="@android:color/holo_blue_dark" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
But I recommend using a drawable with Oval Shape and elevation.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@android:color/white"/>
</shape>
</item>
</layer-list>
android:elevation="@dimen/elevation_fab"
Otherwise, FAB is also an Ideal recommendation.
Upvotes: 1
Reputation: 2487
Try this, using gradient type "sweep":
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="85dp"
android:height="85dp">
<shape
android:shape="oval">
<gradient
android:endColor="@android:color/transparent"
android:startColor="@color/black"
android:type="sweep" />
</shape>
</item>
<item
android:width="64dp"
android:height="64dp"
android:left="11dp"
android:top="11dp">
<shape android:shape="oval">
<solid android:color="@color/blue" />
</shape>
</item>
</layer-list>
Upvotes: 1