android draw transparent gradient on canwas! Wrong work - android

I have a canvas!
1.On canvas i'm draw are graph (see below)!
2.Draw a points and lines between.
3.I'm was calculate are all points on a line, and draw little lines to bottom.
4.And draw gradient with are #e5fafd color!
private void drawGradient(Canvas canvas){
Paint gradientPainter = new Paint();
gradientPainter.setStrokeWidth(5);
gradientPainter.setShader(new LinearGradient(0, 0, 0, getHeight(), getResources().getColor(R.color.graph_gradient_start), Color.TRANSPARENT, Shader.TileMode.CLAMP));
for(int i = 0; i < ourCoords.size(); i++){
if(i != ourCoords.size() - 1){
final float x = ourCoords.get(i+1).getxCoord() - ourCoords.get(i).getxCoord();
final float y = ourCoords.get(i+1).getyCoord() - ourCoords.get(i).getyCoord();
float xT = ourCoords.get(i).getxCoord(), yT = ourCoords.get(i).getyCoord();
final float percentX = (float) (x / 100.0);
final float percentY = (float) (y / 100.0);
for(float j= (float) 0.1; j<100.0; j++){
float startX = (percentX * j) + xT;
float startY = (percentY * j) + yT;
float endX = startX;
float endY = startY + 400;
if(startX < (canvasWidth - marginLeft - 8)){
canvas.drawLine(startX, startY, endX, endY, gradientPainter);
}
}
}
drawPoints(canvas, ourCoords.get(i).getxCoord(), ourCoords.get(i).getyCoord(), 20);
}
}
I ended up getting a black gradient. Please help me and sorry for the mistakes.
See screen http://mepic.ru/view/?id=b1904b5d5b6d156e83206ab0c485d40a

Related

How to create dripping Spray can tool for Graffiti app in Android

I am trying to create a spray can tool in Android for a Graffiti app. I want to achieve something similar done in the below image
Dripping Spray Can Sample image
Requirements: If somebody is spraying the can then it should drip some color downwards while drawing a spray line
I am currently using the following code, but not getting the correct results:
if (bufferPaint == null) {
bufferPaint = new Paint();
bufferPaint.setAntiAlias(true);
bufferPaint.setDither(true);
bufferPaint.setXfermode(null);
if (mPaint == null)
setupColor(0f, 100f);
}
int alpha = Math.round((float) 100 / 100 * 255);
bufferPaint.setAlpha(alpha);
private void paintOneDab(float x, float y) {
float radius = 5 / 2f;
float scatter = 500 / 100f;
x += radius 2 scatter (1 - 2 (float) Math.random());
y += radius 2 scatter (1 - 2 (float) Math.random());
float hardness = 20 / 100f;
positions[0] = 0;
positions[1] = (float) (Math.sqrt(hardness));
positions[2] = 1;
bufferPaint.setShader(new RadialGradient(x, y, radius, colors, positions, Shader.TileMode.CLAMP));
mCanvas.save();
int angle = 180;
mCanvas.rotate(angle, x, y);
int roundness = 100;
mCanvas.scale(1f, 100f / roundness, x, y);
mCanvas.drawCircle(x, y, radius, bufferPaint);
mCanvas.restore();
}

Draw spiral view in android Kotlin

I am trying to draw spiral view as in screenshot attached,
I have array of points to draw based on number on circles.
I am new to android and kotlin .
Can anyone please suggest how to do this?
Today I added spiral drawing to this custom scrolling shapes app I'm building. My implementation makes use of Android import android.graphics.Path;. The spiral drawing is based on the user scrolling, with more segments added as the user scrolls.
The gist of the solution is as follows: I start with an initial arc and draw that. That arc is the initial arc of the spiral. On that arc has been added to the path, then use the bounding Rect of the Path to determine the bounds for the next segment of the arc.
The below is a sample but for full context you'll need to view the project: https://github.com/jdgreene2008/android_custom_views
private void addTopSpiralSegment(Path path, RectF bounds, SpiralSegment spiralSegment) {
float centerX = bounds.centerX();
float centerY = bounds.centerY();
float segmentBoundsLeft;
float segmentBoundsRight;
float segmentBoundsTop;
float segmentBoundsBottom;
if (path.isEmpty()) {
segmentBoundsLeft = centerX - spiralSegment.getWidth() / 2;
segmentBoundsRight = centerX + spiralSegment.getWidth() / 2;
segmentBoundsTop = centerY - spiralSegment.getHeight() / 2;
segmentBoundsBottom = centerY + spiralSegment.getHeight() / 2;
} else {
RectF pathBounds = new RectF();
path.computeBounds(pathBounds, true);
segmentBoundsLeft = pathBounds.left;
segmentBoundsRight = segmentBoundsLeft + spiralSegment.getWidth();
segmentBoundsTop = centerY - spiralSegment.getHeight() / 2;
segmentBoundsBottom = centerY + spiralSegment.getHeight() / 2;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
path.addArc(segmentBoundsLeft, segmentBoundsTop, segmentBoundsRight,
segmentBoundsBottom, 180, 180);
}
}
private void addBottomSpiralSegment(Path path, RectF bounds, SpiralSegment spiralSegment) {
float centerX = bounds.centerX();
float centerY = bounds.centerY();
float segmentBoundsLeft;
float segmentBoundsRight;
float segmentBoundsTop;
float segmentBoundsBottom;
if (path.isEmpty()) {
segmentBoundsLeft = centerX - spiralSegment.getWidth() / 2;
segmentBoundsRight = centerX + spiralSegment.getWidth() / 2;
segmentBoundsTop = centerY - spiralSegment.getHeight() / 2;
segmentBoundsBottom = centerY + spiralSegment.getHeight() / 2;
} else {
RectF pathBounds = new RectF();
path.computeBounds(pathBounds, true);
segmentBoundsLeft = pathBounds.right - spiralSegment.getWidth();
segmentBoundsRight = pathBounds.right;
segmentBoundsTop = centerY - spiralSegment.getHeight() / 2;
segmentBoundsBottom = centerY + spiralSegment.getHeight() / 2;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
path.addArc(segmentBoundsLeft, segmentBoundsTop, segmentBoundsRight,
segmentBoundsBottom, 0, 180);
}
}

How to set gradient on TextView color with angle?

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.
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();
}
});
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);
}
});
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.

How tro draw fading path

How can I draw Path with fading (opacity or thicknes) line? Something like this.
I know there is LinearGradient shader for Paint, but it won't bend along the Path.
One possible solution might be to get points along the Path and just draw it by myself through the segments`. But I coouldn't find any method for that either.
I came up with the following code. The mos important thing is PathMeasure's getPosTan() method.
if (getGesturePath() != null) {
final short steps = 150;
final byte stepDistance = 5;
final byte maxTrailRadius = 15;
pathMeasure.setPath(getGesturePath(), false);
final float pathLength = pathMeasure.getLength();
for (short i = 1; i <= steps; i++) {
final float distance = pathLength - i * stepDistance;
if (distance >= 0) {
final float trailRadius = maxTrailRadius * (1 - (float) i / steps);
pathMeasure.getPosTan(distance, pathPos, null);
final float x = pathPos[0] + RandomUtils.nextFloat(0, 2 * trailRadius) - trailRadius;
final float y = pathPos[1] + RandomUtils.nextFloat(0, 2 * trailRadius) - trailRadius;
paint.setShader(new RadialGradient(
x,
y,
trailRadius > 0 ? trailRadius : Float.MIN_VALUE,
ColorUtils.setAlphaComponent(Color.GREEN, random.nextInt(0xff)),
Color.TRANSPARENT,
Shader.TileMode.CLAMP
));
canvas.drawCircle(x, y, trailRadius, paint);
}
}
}

Alignment issues in view

This question is in continuation to my previous doubt
Now I am trying to make a guage view. I am drawing a scale but the alignment is not proper and I am not able to figure out the problem. Here is my code:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
w= canvas.getWidth();
h=canvas.getHeight();
DrawRange(canvas,innerRadius,outerRadius);
}
here innerRadius =250;
and outer radius = 300;
private void DrawRange(Canvas canvas,int r,int R) {
RectF rect = new RectF(canvas.getWidth()/2- r, canvas.getHeight()/2-r, canvas.getWidth()/2+r, canvas.getHeight()/2+r);
RectF rect1 = new RectF(canvas.getWidth()/2- R, canvas.getHeight()/2-R, canvas.getWidth()/2+R, canvas.getHeight()/2+R);
Paint scalePaint = new Paint();
scalePaint.setStyle(Paint.Style.STROKE);
scalePaint.setColor(0x9f004d0f);
scalePaint.setStrokeWidth(2);
scalePaint.setAntiAlias(true);
scalePaint.setTextSize(35.0f);
scalePaint.setTypeface(Typeface.SANS_SERIF);
scalePaint.setTextScaleX(0.4f);
scalePaint.setTextAlign(Paint.Align.CENTER);
canvas.drawOval(rect1, scalePaint);
canvas.drawOval(rect, scalePaint);
canvas.save(Canvas.CLIP_SAVE_FLAG);
int xc = 0;
for (int i = 0; i < totalNicks; i++) {
float y1 = 330;
float y2 = y1 + 5;
if (i % 5 == 0) {
canvas.drawText(""+xc, r-15, y2 , scalePaint);
xc+=5;
}else{
canvas.drawLine(r, y1, r, y2, scalePaint);
}
canvas.rotate(degreesPerNick, w/2, h/2);
}
canvas.restore();
}
I wonder if you are drawing the text and the dashes in the wrong place. The key reference point is the centre of the circles:
int cX = canvas.getWidth()/2;
int cY = canvas.getHeight()/2;
The other key reference is the difference between the two radii:
int deltaR = R - r;
The dashes and text are always drawn at 12 o'clock, say 20% above the inner circle to 1/3 of the way from the outer circle:
int dashInnerY = cY - r - deltaR/5; // 20% of the way between inner and outer radii
int dashOuterY = cY - R + deltaR/3; // 1/3 of the way between outer and inner radii
Then to render a dash:
canvas.drawLine(cX, dashInnerY, cX, dashOuterY, scalePaint);
And the number:
canvas.drawText(""+xc, cX, dashInnerY, scalePaint);

Categories

Resources