I have just begin to create some custom views in Android but I am facing problem while drawing bitmap (arrows) outside the circle.
Here is my code:
Canvas osCanvas = new Canvas(windowFrame); // Create a canvas to draw onto the new image
RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Anti alias allows for smooth corners
paint.setColor(Color.parseColor("#FAFAFA")); // This is the color of your activity background
osCanvas.drawRect(outerRectangle, paint);
final Paint stroke = new Paint();
//paint.setColor(Color.TRANSPARENT); // An obvious color to help debugging
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // A out B http://en.wikipedia.org/wiki/File:Alpha_compositing.svg
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
double rad = Math.min(getWidth(), getHeight()) / 2.5 - menuInnerPadding;
float radius = (float) rad;
stroke.setColor(Color.parseColor("#999999"));
stroke.setStyle(Paint.Style.STROKE);
stroke.setAntiAlias(true);
stroke.setStrokeWidth(5f);
osCanvas.drawCircle(centerX ,
centerY , radius - stroke.getStrokeWidth() +5f, stroke);
for(int i=0;i<elements.size();i++){
double angle =0;
if(i==0){
angle = startAngle;
}else{
angle = startAngle+(i * ((2 * Math.PI) / elements.size()));
}
elements.get(i).x = (int) (centerX + Math.cos(angle)*(radius));
elements.get(i).y = (int) (centerY + Math.sin(angle)*(radius));
float ang = (float) Math.cos(angle)*(radius);
Path path = new Path();
path.addCircle(elements.get(i).x,elements.get(i).y, radius, Path.Direction.CW);
if(BLINKER_ID == i){
if(blinkerPain != null){
osCanvas.drawBitmap(elements.get(i).bitmap,elements.get(i).x,elements.get(i).y,blinkerPain);
blinkerPain = null;
}
}else{
// here i am drawing the red arrows (bitmap images) But it's not fitting outside the circle.
osCanvas.drawBitmap(elements.get(i).bitmap,elements.get(i).x ,elements.get(i).y ,textPaint);
}
}
Here is my output
I think issue is with the padding.
I did code new write.
You should check this code.
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth( 2 );
paint.setStyle(Paint.Style.STROKE );
canvas.drawColor(Color.WHITE);
float x = 400;
float y = 400;
float r = 200;
canvas.drawCircle( x , y , r , paint );
Bitmap icon = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.ic_launcher);
int length = 8;
float radian = (float)(Math.PI * 2f) / length;
for( int i = 0; i<length; i++ ) {
drawBitmap( canvas , icon , x , y , r, radian * i);
}
}
private void drawBitmap( Canvas canvas, Bitmap bitmap, float pivotX, float pivotY, float radius, float radian ) {
Matrix m = new Matrix();
m.postTranslate( -bitmap.getWidth()/2 , -bitmap.getHeight()/2 );
m.postRotate( (float)(radian * 180 / Math.PI) + 90 );
float drawHeight = radius + (bitmap.getHeight()/2);
m.postTranslate( ((float)Math.cos( radian ) * drawHeight) + pivotX
, ((float)Math.sin( radian ) * drawHeight) + pivotY );
canvas.drawBitmap( bitmap , m , null );
}
Related
So I am nearly at the end.
I have been researching the whole day on how to do this.
Draw a path which grows(animation) from one point to another.
I have tried it with Matrix, but that just ended with turning my whole paths.
Here is a image of my project:
my project
My goal is to draw a animated path from one circle to the other.
Code:
public void init(#Nullable AttributeSet attr) {
circle = new Paint();
circle.setColor(Color.GREEN);
circle.setStyle(Paint.Style.FILL);
circle.setAntiAlias(true);
line = new Paint();
line.setColor(Color.GREEN);
line.setStyle(Paint.Style.STROKE);
line.setStrokeWidth(10);
line.setAntiAlias(true);
Collections.addAll(height, 100, 20, 50, 40, 70, 10, 50); // in percent
System.out.println(height.size() + " this is the size");
}
#Override
protected void onDraw(Canvas canvas) {
float y = getHeight() / 20 * 14;
float x = getWidth() / 8;
float radius = (canvas.getWidth() * canvas.getHeight()) / 40940;
for (int c = 1; c < 8; c++) {
System.out.println("at " + c);
canvas.drawCircle(x * c, y - ((getHeight() / 20) * (height.get(c - 1) / 10)), radius, circle);
points.add(new PointF(x * c, (y - ((getHeight() / 20) * (height.get(c - 1) / 10)))));
}
}
Please Help,
Thanks
you just need animate the path using ValueAnimator
create one path object
Path path = new Path();
and create animator
ValueAnimator animator = new ValueAnimator();
float startX = // starting circle x co-ordinate
float startY = // starting circle y co-ordinate
float endX = // end circle x co-ordinate
float endY = // end circle y co-ordinate
PropertyValuesHolder propertyX = PropertyValuesHolder.ofFloat("x",startX,endX);
PropertyValuesHolder propertyY = PropertyValuesHolder.ofFloat("y",startY,endY);
valueAnimator.setValues(propertyX,propertyY);
valueAnimator.setDuration(1000); // animation time
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float x = (float) animation.getAnimatedValue("x");
float y = (float) animation.getAnimatedValue("y");
path.lineTo(x,y);
invalidate();
}
});
valueAnimator.start();
and in onDraw() draw the path
canvas.drawPath(path,paint);
I'm trying to implement a way to sample a texture in Java. I want this to work the same way it would by using GLSL's "texture" function. I want the neighboring pixels to be taken into account when the color is calcuated.
For example, say I use a float to get the image color at a certain pixel, and the number falls between two pixels. How can I calculate a mix of the neighboring pixels? Here's an image showing my goal.
Is there an easy way to do this using java's BufferedImage class?
Here's the code I have so far, it only works for the x position at the moment.
public static final java.awt.Color getColor(final BufferedImage image, final float x, final int y) {
final float imageX = x * image.getWidth();
final float decimal = imageX % 1f;
final java.awt.Color left = new java.awt.Color(image.getRGB(Maths.clamp((int) imageX - 1, 0, image.getWidth() - 1), y));
final java.awt.Color center = new java.awt.Color(image.getRGB(Maths.clamp((int) imageX, 0, image.getWidth() - 1), y));
final java.awt.Color right = new java.awt.Color(image.getRGB(Maths.clamp((int) imageX + 1, 0, image.getWidth() - 1), y));
if (decimal == 0.5f) return center;
if (decimal < 0.5f) {
final float distanceFromCenter = 0.5f - decimal;
final float distanceFromLeft = decimal + 0.5f;
final Vector3f leftColor = new Vector3f(left.getRed() / 255f, left.getGreen() / 255f, left.getBlue() / 255f);
final Vector3f centerColor = new Vector3f(center.getRed() / 255f, center.getGreen() / 255f, center.getBlue() / 255f);
leftColor.scale(1f - distanceFromLeft);
centerColor.scale(1f - distanceFromCenter);
final Vector3f color = Vector3f.add(leftColor, centerColor, null);
return new java.awt.Color(color.getX(), color.getY(), color.getZ());
} else {
final float distanceFromCenter = decimal - 0.5f;
final float distanceFromRight = 1f - decimal + 0.5f;
final Vector3f rightColor = new Vector3f(right.getRed() / 255f, right.getGreen() / 255f, right.getBlue() / 255f);
final Vector3f centerColor = new Vector3f(center.getRed() / 255f, center.getGreen() / 255f, center.getBlue() / 255f);
rightColor.scale(1f - distanceFromRight);
centerColor.scale(1f - distanceFromCenter);
final Vector3f color = Vector3f.add(rightColor, centerColor, null);
return new java.awt.Color(color.getX(), color.getY(), color.getZ());
}
}
hope this code help, if you use this appropriately. This function extract pixels from buffered image and we can replace it what ever we want:
private BufferedImage changeColor(BufferedImage image, int srcColor, int replaceColor)
{
BufferedImage destImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = destImage.createGraphics();
g.drawImage(image, null, 0, 0);
g.dispose();
for (int width = 0; width < image.getWidth(); width++)
{
for (int height = 0; height < image.getHeight(); height++)
{
if (destImage.getRGB(width, height) == srcColor)
{
destImage.setRGB(width, height, replaceColor);
}
}
}
return destImage;
}
I am trying to create a 10x10 grid in android studio that will display in the center of the screen, i am trying to use a for loop to do this but cant get it right. Does anyone know how to do this, ive been looking on google and there are no examples or guides on how to do it. my code is below.
public class Draw extends View {
Paint red = new Paint();
Paint green = new Paint();
float startX;
float stopX;
float startY;
float stopY;
int rectSide = 1000;
public Draw(Context context) {
super(context);
red.setColor(Color.RED);
green.setColor(Color.GREEN);
red.setStrokeWidth(8);
green.setStrokeWidth(8);
}
#Override
public void onDraw(Canvas canvas) {
int width = canvas.getWidth();
int height = canvas.getHeight();
for (int i = 2; i < 10; i++) {
startX = width / 2 - rectSide / 2;
startY = i*100;
stopX = width / 2 + rectSide / 2;
stopY = i*100;
canvas.drawLine(startX, startY, stopX, stopY, red);
}
for (int i = 2; i < 10; i++) {
startX = i*100;
startY = height / 2 - rectSide / 2;
stopX = i*100;
stopY = height / 2 + rectSide / 2;
canvas.drawLine(startX, startY, stopX, stopY, red);
}
}
}
I made a little loading circle with Canvas and Paint.
This is my first attempt to use these classes so it could be something I used wrong.
My problem is, that the resolution of painting are too low. I can clearly see the pixels.
How could I improve on this?
By the way this is my class:
public class LoadingCircle extends LinearLayout {
public LoadingCircle(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
}
// time
int countDownTime = 180;
Paint paint = new Paint();
RectF oval = new RectF();
Path path = new Path();
// value
int value = 360 / countDownTime;
// starting progress
int progress = -360 - value;
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
float width = (float) getWidth();
float height = (float) getHeight();
float center_x = width / 2, center_y = height / 2;
float loadingRadius = (float) ((width / 2)*0.85);
float whiteRadius = (float) (loadingRadius * 1.06);
float greenRadius = (float) (loadingRadius * 1.14);
// **background green circle**/
oval.set(center_x - greenRadius, center_y - greenRadius, center_x + greenRadius, center_y + greenRadius);
paint.setColor(Color.parseColor("#a3d47b"));
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawArc(oval, 270, 360, true, paint);
// ****//
// **background green circle**/
oval.set(center_x - whiteRadius, center_y - whiteRadius, center_x + whiteRadius, center_y + whiteRadius);
paint.setColor(Color.parseColor("#ffffff"));
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawArc(oval, 270, 360, true, paint);
// **Loading circle**//
path.addCircle(center_x, center_y, loadingRadius, Path.Direction.CW);
paint.setColor(Color.parseColor("#71b23c"));
paint.setStyle(Paint.Style.FILL_AND_STROKE);
oval.set(center_x - loadingRadius, center_y - loadingRadius, center_x + loadingRadius, center_y + loadingRadius);
progress = progress + value;
Log.i("proges: ", progress + "");
canvas.drawArc(oval, 270, progress, true, paint);
// /**//
}
public void setCountDownTime(int time) {
this.countDownTime = time;
this.value = 360 / countDownTime;
this.progress = -360 - value;
}
// reseting loading circle
public void reset() {
this.progress = -360 - value;
this.invalidate();
}
}
Declare paint like this:
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
This will enable the antialiasing and you'll get rid of that ugly pixellation.
Or, you can do it in your function:
paint.setAntiAlias(true);
Is there a simple library that can parse a True Type font file and give me a list of vectors/points for me to render it myself? I'm talking about something similar to freetype, but for Java.
Java can do that out of the box. Some time ago, I explored this field.
I used Processing for easy/fast graphic rendering, but the code to access font information is pure Java. So maybe my little program can be of interest for you. I just pasted it in Pastebin
/**
Get a font and display glyphs with additional information
(bounding boxes, anchor & control points...)
by Philippe Lhoste <PhiLho(a)GMX.net> http://Phi.Lho.free.fr & http://PhiLho.deviantART.com
*/
/* File/Project history:
1.01.000 -- 2008/08/28 (PL) -- Some improvements.
1.00.000 -- 2008/08/28 (PL) -- Creation.
*/
/* Copyright notice: For details, see the following file:
http://Phi.Lho.free.fr/softwares/PhiLhoSoft/PhiLhoSoftLicence.txt
This program is distributed under the zlib/libpng license.
Copyright (c) 2008 Philippe Lhoste / PhiLhoSoft
*/
import java.awt.font.*;
import java.awt.geom.*;
final static int DEMO_ID = 2;
final static String FONT_NAME = "Times New Roman";
final static String STRING = "p#";
int FONT_SIZE, SCALE;
Graphics2D g2;
AffineTransform transform;
HashMap colorList = new HashMap();
void setup()
{
size(1000, 700);
smooth();
noLoop();
background(150);
noFill();
g2 = ((PGraphicsJava2D) g).g2;
// Move drawing to a convenient place
transform = new AffineTransform();
if (DEMO_ID == 1)
{
FONT_SIZE = 1;
SCALE = 300;
transform.translate(40, 320);
transform.scale(SCALE, SCALE);
}
else if (DEMO_ID == 2)
{
FONT_SIZE = 2;
SCALE = 300;
transform.translate(50, 500);
transform.scale(SCALE, SCALE);
}
else if (DEMO_ID == 3)
{
FONT_SIZE = 2;
SCALE = 300;
transform.translate(50, 500);
transform.scale(SCALE, SCALE);
}
// g2.setTransform(transform);
// And show the origin (and scale) of drawing
SetColor(#FF0000); // Update g2
strokeWeight(5);
Line2D.Double line = new Line2D.Double(-0.1, -0.1, 0.1, 0.1);
g2.draw(transform.createTransformedShape(line));
line = new Line2D.Double(-0.1, 0.1, 0.1, -0.1);
g2.draw(transform.createTransformedShape(line));
strokeWeight(2);
// Now, we get the font
Font font = new Font(FONT_NAME, Font.PLAIN, FONT_SIZE);
g2.setFont(font);
FontRenderContext frc = g2.getFontRenderContext();
if (DEMO_ID == 1)
{
//~ String str = "%&#";
GlyphVector glyphVector = font.createGlyphVector(frc, STRING);
for (int i = 0; i < STRING.length(); i++)
{
strokeWeight(2);
SetColor(#00FF00);
Shape vbs = glyphVector.getGlyphVisualBounds(i);
g2.draw(transform.createTransformedShape(vbs));
SetColor(#005000);
Rectangle r = glyphVector.getGlyphPixelBounds(i, null, 0.0f, 0.0f);
g2.draw(transform.createTransformedShape(r));
SetColor(#A0A000);
Shape lbs = glyphVector.getGlyphLogicalBounds(i);
g2.draw(transform.createTransformedShape(lbs));
SetColor(#0050F0);
strokeWeight(5);
Shape shape = glyphVector.getGlyphOutline(i);
g2.draw(transform.createTransformedShape(shape));
}
// Draw the whole string at once
SetColor(#F0A000);
strokeWeight(1);
Shape shape = glyphVector.getOutline();
g2.draw(transform.createTransformedShape(shape));
}
else if (DEMO_ID == 2)
{
GlyphVector glyphVector = font.createGlyphVector(frc, STRING);
for (int i = 0; i < STRING.length(); i++)
{
SetColor(#0050F0);
strokeWeight(5);
Shape shape = glyphVector.getGlyphOutline(i);
g2.draw(transform.createTransformedShape(shape));
HighlightPoints(shape);
}
}
else if (DEMO_ID == 3) // To test the SEG_CUBICTO case!
{
SetColor(#0050F0);
strokeWeight(5);
GeneralPath shape = new GeneralPath();
shape.moveTo(1.5, 0.0);
shape.lineTo(1.8, 0.0);
shape.quadTo(2.0, 0.3, 1.5, 0.3);
shape.lineTo(1.1, 0.3);
shape.curveTo(0.7, 0.3, 0.5, -0.5, 1.2, -0.2);
shape.lineTo(1.5, -0.3);
shape.closePath();
g2.draw(transform.createTransformedShape(shape));
HighlightPoints(shape);
}
}
void HighlightPoints(Shape shape)
{
strokeWeight(1);
PathIterator iterator = shape.getPathIterator(null);
float[] coords = new float[6];
float px = 0, py = 0;
while (!iterator.isDone())
{
int type = iterator.currentSegment(coords);
switch (type)
{
case PathIterator.SEG_MOVETO: // One point
print("Move ");
px = coords[0];
py = coords[1];
DrawMovePoint(px, py);
break;
case PathIterator.SEG_LINETO:
print("Line ");
px = coords[0];
py = coords[1];
DrawLinePoint(px, py);
break;
case PathIterator.SEG_QUADTO: // Two points
print("Quad ");
DrawControlLine(coords[0], coords[1], px, py);
px = coords[2];
py = coords[3];
DrawControlLine(coords[0], coords[1], px, py);
DrawControlPoint(coords[0], coords[1]);
DrawQuadPoint(px, py);
break;
case PathIterator.SEG_CUBICTO: // Three points
print("Cubic "); // Not seen yet...
DrawControlLine(coords[0], coords[1], px, py); // Connect to last point
px = coords[4];
py = coords[5];
DrawControlLine(coords[2], coords[3], px, py);
DrawControlPoint(coords[0], coords[1]);
DrawControlPoint(coords[2], coords[3]);
DrawCubicPoint(px, py);
break;
case PathIterator.SEG_CLOSE: // No points
}
iterator.next();
}
}
void DrawMovePoint(float x, float y)
{
float radius = 2.5 / SCALE;
Ellipse2D.Float e = new Ellipse2D.Float(x - radius, y - radius, 2 * radius, 2 * radius);
SetColor(#FF00A0);
g2.fill(transform.createTransformedShape(e));
SetColor(#FF00FF);
g2.draw(transform.createTransformedShape(e));
}
void DrawLinePoint(float x, float y)
{
float radius = 4.5 / SCALE;
Ellipse2D.Float e = new Ellipse2D.Float(x - radius, y - radius, 2 * radius, 2 * radius);
SetColor(#FF00FF);
g2.draw(transform.createTransformedShape(e));
}
void DrawQuadPoint(float x, float y)
{
SetColor(#80FF00);
float radius = 3.0 / SCALE;
Rectangle2D.Float r = new Rectangle2D.Float(x - radius, y - radius, 2 * radius, 2 * radius);
g2.draw(transform.createTransformedShape(r));
}
void DrawCubicPoint(float x, float y)
{
SetColor(#FF8000);
float radius = 5.0 / SCALE;
Rectangle2D.Float r = new Rectangle2D.Float(x - radius, y - radius, 2 * radius, 2 * radius);
g2.draw(transform.createTransformedShape(r));
}
void DrawControlPoint(float x, float y)
{
SetColor(#D0E000);
float radius = 3.0 / SCALE;
Ellipse2D.Float e = new Ellipse2D.Float(x - radius, y - radius, 2 * radius, 2 * radius);
g2.draw(transform.createTransformedShape(e));
}
void DrawControlLine(float x1, float y1, float x2, float y2)
{
SetColor(#FFA000);
Line2D.Float l = new Line2D.Float(x1, y1, x2, y2);
g2.draw(transform.createTransformedShape(l));
}
Color GetColor(color c)
{
Integer ic = Integer.valueOf(c); // New to 1.5! Cache values
Color k = (Color) colorList.get(ic);
if (k == null)
{
k = new Color(ic);
colorList.put(ic, k);
}
return k;
}
void SetColor(color c)
{
Color k = GetColor(c);
g2.setPaint(k);
}
You can use Batik to parse a TrueType Font and generate an SVG file (SVGFont). So I bet that you could use the libraries to get your vectors out.