Reputation: 3621
Following code will set gradient on textview (not background, but text itself). But I need to change angle of this gradient, how to do it?
Shader textShader = new LinearGradient(0, 0, 0, textView.getPaint().getTextSize(),
new int[]{context.getResources().getColor(R.color.color1), context.getResources().getColor(R.color.color2)},
new float[]{0, 1}, Shader.TileMode.CLAMP);
textView.getPaint().setShader(textShader);
Thank you in advance.
Upvotes: 6
Views: 3647
Reputation: 2857
According to this answer, I modified your code. Try this:
double angleInRadians = Math.toRadians(45);
double length = textView.getPaint().getTextSize();
double endX = Math.sin(angleInRadians) * length;
double endY = Math.cos(angleInRadians) * length;
Shader textShader = new LinearGradient(0, 0, endX, endY,
new int[]{context.getResources().getColor(R.color.color1), context.getResources().getColor(R.color.color2)},
new float[]{0, 1}, Shader.TileMode.CLAMP);
textView.getPaint().setShader(textShader);
Update:
I'm ashamed to say that my above answer is not correct. These answers (mayank1513 answer and Chaudhari Sachin answer) are the same and they are good but they have few bugs:
1. They don't work correctly for agnles more than 90 degrees. For exmaple if you test them with 180 degrees, then you won't see any gradient, because these solutions are using (0,0) point as rotation center.
2. If you have a TextView with width or height more or less than its text width or height, then gradient doesn't render correctly. For example you can test it by a TextView with match_parent
width and height and centered Hello
text or with an enabled scrolling small TextView and long text.
I developed new soltuion. It calcuates text bound first and then rotates gradient line around center of this bound.
textView.post(new Runnable() {
@Override
public void run() {
final Rect textBound = new Rect(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
final Layout layout = textView.getLayout();
for(int i = 0; i < textView.getLineCount(); i++) {
float left = layout.getLineLeft(i);
float right = layout.getLineRight(i);
if(left < textBound.left) textBound.left = (int)left;
if(right > textBound.right) textBound.right = (int)right;
}
textBound.top = layout.getLineTop(0);
textBound.bottom = layout.getLineBottom(textView.getLineCount() - 1);
if(textView.getIncludeFontPadding()) {
Paint.FontMetrics fontMetrics = textView.getPaint().getFontMetrics();
textBound.top += (fontMetrics.ascent - fontMetrics.top);
textBound.bottom -= (fontMetrics.bottom - fontMetrics.descent);
}
double angleInRadians = Math.toRadians(45);
double r = Math.sqrt(Math.pow(textBound.bottom - textBound.top, 2) +
Math.pow(textBound.right - textBound.left, 2)) / 2;
float centerX = textBound.left + (textBound.right - textBound.left) / 2;
float centerY = textBound.top + (textBound.bottom - textBound.top) / 2;
float startX = (float)Math.max(textBound.left, Math.min(textBound.right, centerX - r * Math.cos(angleInRadians)));
float startY = (float)Math.min(textBound.bottom, Math.max(textBound.top, centerY - r * Math.sin(angleInRadians)));
float endX = (float)Math.max(textBound.left, Math.min(textBound.right, centerX + r * Math.cos(angleInRadians)));
float endY = (float)Math.min(textBound.bottom, Math.max(textBound.top, centerY + r * Math.sin(angleInRadians)));
Shader textShader = new LinearGradient(startX, startY, endX, endY,
new int[]{context.getResources().getColor(R.color.color1),
context.getResources().getColor(R.color.color2)},
new float[]{0, 1}, Shader.TileMode.CLAMP);
textView.setTextColor(Color.WHITE);
textView.getPaint().setShader(textShader);
}
});
Upvotes: 2
Reputation: 71
final TextView myTextView = findViewById(R.id.my_text_view);
myTextView.post(new Runnable()
{
@Override
public void run() {
int length = textView.getMeasuredWidth();
float angle = 45; // specify angle in degrees here
Shader textShader = new LinearGradient(0, 0, (int) (Math.sin(Math.PI * angle / 180) * length),
(int) (Math.cos(Math.PI * angle / 180) * length),
new int[]{Color.BLUE, Color.GREEN, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE, Color.RED},
null,
Shader.TileMode.CLAMP);
myTextView.getPaint().setShader(textShader);
textView.invalidate();
}
});
Upvotes: 2
Reputation: 18538
Working code
final double angleInRadians = Math.toRadians(45);
final TextView textView = findViewById(R.id.app_name);
textView.post(new Runnable() {
@Override
public void run() {
double length = textView.getMeasuredWidth();
double endX = Math.sin(angleInRadians) * length;
double endY = Math.cos(angleInRadians) * length;
Shader textShader = new LinearGradient(0, 0, (int) endX, (int) endY,
new int[]{Color.BLUE, Color.GREEN, Color.GREEN, Color.BLUE, Color.RED, Color.GREEN, Color.BLUE, Color.RED},
null, Shader.TileMode.CLAMP);
textView.getPaint().setShader(textShader);
textView.invalidate();
}
});
This sets gradient with specified angle.
Upvotes: 1