Text with gradient in Android
It doesn't appear possible to extend TextView to draw text with a gradient. It is, however, possible to achieve this effect by creating a canvas and drawing on it. First we need to declare our custom UI element. In the initiation we need to create a subclass of Layout. In this case, we will use BoringLayout which only supports text with a single line.
Shader textShader=new LinearGradient(0, 0, 0, 20,
new int[]{bottom,top},
new float[]{0, 1}, TileMode.CLAMP);//Assumes bottom and top are colors defined above
textPaint.setTextSize(textSize);
textPaint.setShader(textShader);
BoringLayout.Metrics boringMetrics=BoringLayout.isBoring(text, textPaint);
boringLayout=new BoringLayout(text, textPaint, 0, Layout.Alignment.ALIGN_CENTER,
0.0f, 0.0f, boringMetrics, false);
We then override onMeasure
and onDraw
:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
setMeasuredDimension((int) textPaint.measureText(text), (int) textPaint.getFontSpacing());
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
boringLayout.draw(canvas);
}
Our implementation of onDraw
is at this point quite lazy (it completely ignores the measurement specs!, but so long as you guarantee that the view is given sufficent space, it should work okay.
Alternatively, it would be possible to inherit from a Canvas
and override the onPaint
method. If this is done, then unfortunately the anchor for text being drawn will always be on the bottom so we have to add -textPaint.getFontMetricsInt().ascent()
to our y coordinate.
Set gradient color for text in Android Studio with Kotlin language
In order to set the gradient as Textview
text color, you have to use textshader
with parsing gradients color. You can customise the colors as of your requirement.
val paint = textView.paint
val width = paint.measureText(textView.text.toString())
val textShader: Shader = LinearGradient(0f, 0f, width, textView.textSize, intArrayOf(
Color.parseColor("#F97C3C"),
Color.parseColor("#FDB54E"),
/*Color.parseColor("#64B678"),
Color.parseColor("#478AEA"),*/
Color.parseColor("#8446CC")
), null, Shader.TileMode.REPEAT)
textView.paint.setShader(textShader)
Gradient text color in a custom view
You should define your colorStart and colorEnd as instance variables of your GradientTextView
class.
Then, define a public method within the class to set the colorStart and the colorEnd programmatically:
public class GradientTextView extends android.support.v7.widget.AppCompatTextView {
private int colorStart = ContextCompat.getColor(getContext(), R.color.colorPrimary);
private int colorEnd = ContextCompat.getColor(getContext(), R.color.colorAccent);
public GradientTextView(Context context) {
super(context);
}
public GradientTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GradientTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//Setting the gradient if layout is changed
if (changed) {
getPaint().setShader(new LinearGradient(0, 0, getWidth(), getHeight(), colorStart, colorEnd,
Shader.TileMode.CLAMP));
}
}
public void setGradientColors(int colorStart, int colorEnd) {
this.colorStart = colorStart;
this.colorEnd = colorEnd;
// this forces view redrawing
invalidate();
}
}
Apply a gradient to text of TextView
Try below code:
TextView txt = (TextView) findViewById(R.id.textView1);
Shader textShader=new LinearGradient(0,0, 60, 20,
new int[]{Color.WHITE,Color.TRANSPARENT},
new float[]{0, 1}, TileMode.CLAMP);
txt.getPaint().setShader(textShader);
I guess all you need to adjust (if required) is those values like 60,20 in above.
I am attaching the screenshot of the result, for reference.
Text Gradient in Android Jetpack Compose
So far jetpack compose doesn't provide text gradient and inner shadow out of the box.
Hence need to paint it by yourself:
@Composable
fun drawGradientText(name: String, modifier: Modifier = Modifier) {
val paint = Paint().asFrameworkPaint()
val gradientShader: Shader = LinearGradientShader(
from = Offset(0f, 0f),
to = Offset(0f, 400f),
listOf(Color.Blue, Color.Cyan)
)
Canvas(modifier.fillMaxSize()) {
paint.apply {
isAntiAlias = true
textSize = 400f
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
style = android.graphics.Paint.Style.FILL
color = android.graphics.Color.parseColor("#cdcdcd")
xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
maskFilter = BlurMaskFilter(30f, Blur.NORMAL)
}
drawIntoCanvas { canvas ->
canvas.save()
canvas.nativeCanvas.translate(2f, 5f)
canvas.nativeCanvas.drawText(name, 0f, 400f, paint)
canvas.restore()
paint.shader = gradientShader
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
paint.maskFilter = null
canvas.nativeCanvas.drawText(name, 0f, 400f, paint)
canvas.nativeCanvas.translate(2f, 5f)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
paint.maskFilter = BlurMaskFilter(30f, Blur.NORMAL)
canvas.nativeCanvas.drawText(name, 0f, 400f, paint)
}
paint.reset()
}
}
You can adjust PorterDuff modes and offsets to meet your requirements.
How to create horizontal gradient for text color of AppCompatButton in android
If you want to do this in XML than "Zephyr" approch is perfect suit this but if want want to do this dynamically you can try some thing like
Button theButton = (Button)findViewById(R.id.thebutton);
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, 0, theButton.getHeight(),
new int[] {
Color.LIGHT_GREEN,
Color.WHITE,
Color.MID_GREEN,
Color.DARK_GREEN }, //substitute the correct colors for these
new float[] {
0, 0.45f, 0.55f, 1 },
Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p = new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
theButton.setBackgroundDrawable((Drawable)p);
Not sure but in my case it show gradient horizontally
How to set gradient as text color as well as add stroke around it in TextView Android?
So after waiting for more than 4 days and lots of research, I am finally able to succeed to achieve the desired output.
The mistake I was making is while drawing a stroke on a paint object, I am setting the stroke color as textcolor
. What I did this time was I created a LinearGradient()
object and gave it to paint.shader
while setting the paintStyle(Paint.Style.Stroke)
.
Paint paint = this.getPaint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5f);
paint.setShader(new LinearGradient(0f, 0f, getTextSize(), getTextSize(), mOutlineColor, mOutlineColor, Shader.TileMode.CLAMP));
And after setting the stroke in onDraw()
method of my CustomTextView
class, I called the super.onDraw(canvas)
Then I create a new LinearGradient()
object for the gradient colors as follow:
Paint paint = this.getPaint();
paint.setStyle(Paint.Style.FILL);
Shader linearShader = new LinearGradient(0f, 0f, getWidth(), getTextSize(), colors, null,
Shader.TileMode.CLAMP);
paint.setShader(linearShader);
Finally calling the super.onDraw(canvas)
again and this gives my textview
a stroke as well as gradient as textColor.
Related Topics
Error Strictmode$Androidblockguardpolicy.Onnetwork
Launching Custom Android Application from Android Browser/Chrome
Android Maps API V2 with Custom Markers
Android Setonclicklistener Method - How Does It Work
What Will Happen to the Sharedpreferences on Update an Android App
How to Add Buttons at Top of Map Fragment API V2 Layout
Setting Drawable Folder to Use for Different Resolutions
Android: How to Get a Radiogroup with Togglebuttons
Restore Logcat Window Within Android Studio
Android App Crashes When Launched in Debug Mode
How to Make Circle Custom Progress Bar in Android
Creating a Directory in /Sdcard Fails
Need an Example About Recyclerview.Adapter.Notifyitemchanged(Int Position, Object Payload)
How to Use a Compound Drawable Instead of a Linearlayout That Contains an Imageview and a Textview
How to Add Window -- Token Android.Os.Binderproxy Is Not Valid; Is Your Activity Running