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);
}
}
Related
I know how to use CircularReveal to reveal a view, so I'm looking for a way to do something like "CircularHide". In other words, I want to invisible a view by a circular animation (increasing radius) after making it visible. How can I do that?
I've written this to reveal:
private void startCircularReveal() {
RelativeLayout changeableLayout = findViewById(R.id.layoutChangeable);
int centerX = (likeButton.getRight() + likeButton.getLeft()) / 2;
int centerY = (likeButton.getBottom() + likeButton.getTop()) / 2;
float endRadius = (float) Math.hypot(changeableLayout.getWidth(), changeableLayout.getHeight());
changeableLayout.setVisibility(View.VISIBLE);
Animator revealAnimator = ViewAnimationUtils.createCircularReveal(changeableLayout,
centerX, centerY, 0, endRadius);
revealAnimator.setDuration(200).start();
}
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();
}
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);
}
}
}
It's no secret. My math skills aren't that impressive.
I'm developing my own Wear Watchface. But I want to draw a Drawline to the center of the screen for every 10 minute place on the watch. (See the 500px analog example).
By using the Google example code I can achieve this but only an entire line from the side of the screen to the center. But I want it to be like 5% (or a fixed amount of pixels) in length of that like in the 500px watchface. This is Google's code for drawing the second dial:
float centerX = width / 2f;
float centerY = height / 2f;
float secRot = mTime.second / 30f * (float) Math.PI;
float secLength = centerX - 20;
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint);
By changing the mTime.second I can draw from a specific second.
Found the solution, here's a snippet:
int teller_minuut_stip = 0; //Current minute
float secRot_stip = teller_minuut_stip / 30f * (float) Math.PI;
float secRot_stip_klein = teller_minuut_stip / 30f * (float) Math.PI;
float secLength_stip = centerX - 10;
float secX = (float) Math.sin(secRot_stip) * secLength_stip;
float secY = (float) -Math.cos(secRot_stip) * secLength_stip;
float secLength_stip_klein = centerX - 140;
float secX_klein = (float) Math.sin(secRot_stip_klein) * secLength_stip_klein;
float secY_klein = (float) -Math.cos(secRot_stip_klein) * secLength_stip_klein;
float eindpunt_x = centerX + secX;
float eindpunt_y = centerY + secY;
float lijn_x = eindpunt_x - secX_klein;
float lijn_y = eindpunt_y - secY_klein;
canvas.drawLine(eindpunt_x, eindpunt_y, lijn_x, lijn_y, datePaint_cirkel_kleurtien);
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