Text with Gradient in Android

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)

Image

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.Sample Image

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:

result image

@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



Leave a reply



Submit