How to add ImageView instead Labels on Axis in AChartEngine? - android

I want to add Image instead of Labels on XAxis, so does anyone know how to do that ?
Thanks in advance.
Update
I want to do something like the below image.

For this you have to edit source code of Achartengine because there is not any direct method for this.
Draw circles instead of small lines . For different colors of the circles , you may have to change few other things .
Change drawXLabels() method in XYChart.java .
protected void drawXLabels(List<Double> xLabels, Double[] xTextLabelLocations, Canvas canvas,
Paint paint, int left, int top, int bottom, double xPixelsPerUnit, double minX, double maxX) {
int length = xLabels.size();
boolean showLabels = mRenderer.isShowLabels();
boolean showGridY = mRenderer.isShowGridY();
boolean showTickMarks = mRenderer.isShowTickMarks();
for (int i = 0; i < length; i++) {
double label = xLabels.get(i);
float xLabel = (float) (left + xPixelsPerUnit * (label - minX));
if (showLabels) {
paint.setColor(mRenderer.getXLabelsColor());
if (showTickMarks) {
// canvas.drawLine(xLabel, bottom, xLabel, bottom + mRenderer.getLabelsTextSize() / 3, paint);
canvas.drawCircle(xLabel, bottom + mRenderer.getLabelsTextSize() / 3,3, paint);
}
drawText(canvas, getLabel(mRenderer.getLabelFormat(), label), xLabel,
bottom + mRenderer.getLabelsTextSize() * 4 / 3 + mRenderer.getXLabelsPadding(), paint,
mRenderer.getXLabelsAngle());
}
if (showGridY) {
paint.setColor(mRenderer.getGridColor(0));
// canvas.drawLine(xLabel, bottom, xLabel, top, paint);
canvas.drawCircle(xLabel, top,3, paint);
}
}
drawXTextLabels(xTextLabelLocations, canvas, paint, showLabels, left, top, bottom,
xPixelsPerUnit, minX, maxX);
}

Related

How can I draw a zigzag underline on a specific text of an EditText, similar to a spell-check underline?

Description: I want to be able to draw a zigzag line span on a text with a given start and end position of an EditText in Android. I have tried using a custom ReplacementSpan class to draw the zigzag line, but when I try to modify the underlined text (such as deleting one character), the whole underlined text is deleted and the cursor cannot be placed inside the underlined text.
Demo:
Code: Here's a code snippet of the ZigzagUnderlineSpan class I'm using.
public class ZigzagUnderlineSpan extends ReplacementSpan {
private final int mColor;
public ZigzagUnderlineSpan(int color) {
this.mColor = color;
}
#Override
public int getSize(#NonNull Paint paint, CharSequence text, int start, int end, #Nullable Paint.FontMetricsInt fm) {
return Math.round(paint.measureText(text, start, end));
}
#Override
public void draw(#NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, #NonNull Paint paint) {
float endX = x + paint.measureText(text, start, end);
//Create zigzag path
Path path = createZigzagLine(x, endX, bottom, 5);
//Save state of paint
final int originalColor = paint.getColor();
Paint.Style originalStyle = paint.getStyle();
//Set color and stock
paint.setColor(mColor);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);
// Restore original state of paint
paint.setColor(originalColor);
paint.setStyle(originalStyle);
// Draw the text
canvas.drawText(text, start, end, x, y, paint);
}
/**
* create zigzag path: /\/\/\/\/\/\
* #param startX the start x
* #param endX the end x
* #param bottomY bottom y position
* #param step half period of the zigzag line
* #return path
*/
private Path createZigzagLine(float startX, float endX, float bottomY, float step) {
float topY = bottomY - step;
Path path = new Path();
path.moveTo(startX, bottomY);
for (float x = startX; x< endX; x += step) {
int i = (int) ((x - startX)/step);
path.lineTo(x, i % 2 == 0 ? bottomY : topY);
}
return path;
}
}
Here is how I use it:
SpannableStringBuilder spannable = new SpannableStringBuilder(editText.getText());
spannable.setSpan(new ZigzagUnderlineSpan(Color.RED), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spannable);
Question: Can you help me fix this issue so that I can modify the underlined text and put the cursor inside it? or even using another approach to achieve what i want.

Move a ball on Grid path randomly in Canvas Android

Requirement is to keep a ball moving on the Grid path generated in Canvas. I have generated a Grid in canvas but not able to understand how to move the ball randomly means starting point show be different on the path. I am sharing what I have done. I have also plotted the ball in the screen but not getting the point how to put the ball exactly on the grid line randomly and start moving it
public class PixelGridView extends View {
//number of row and column
int horizontalGridCount = 11;
private Drawable horiz;
private Drawable vert;
private final float width;
long mInterpolateTime;
PointF mImageSource = new PointF();
public PixelGridView(#NonNull Context context) {
this(context, null);
}
public PixelGridView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
horiz = new ColorDrawable(Color.WHITE);
horiz.setAlpha(160);
vert = new ColorDrawable(Color.WHITE);
vert.setAlpha(160);
width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, .9f, context.getResources().getDisplayMetrics());
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
horiz.setBounds(left, 0, right, (int) width);
vert.setBounds(0, top, (int) width, bottom);
}
private float getLinePosition(int lineNumber) {
int lineCount = horizontalGridCount;
return (1f / (lineCount + 1)) * (lineNumber + 1f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//drawTask.start();
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
canvas.drawCircle(120, 110, 10, paint);
int count = horizontalGridCount;
for (int n = 0; n < count; n++) {
float pos = getLinePosition(n);
// Draw horizontal line
canvas.translate(0, pos * getHeight());
Log.e("Position1", "" + pos * getHeight());
horiz.draw(canvas);
canvas.translate(0, -pos * getHeight());
// Draw vertical line
canvas.translate(pos * getHeight(), 0);
Log.e("Position2", "" + pos * getHeight());
vert.draw(canvas);
canvas.translate(-pos * getHeight(), 0);
}
}
}[![Canvas Image][1]][1]
//MainActivity
public class PathAnimationActivity extends AppCompatActivity {
LinearLayout rlLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_path);
rlLayout=findViewById(R.id.rlLayout);
PixelGridView pixelGrid = new PixelGridView(this);
rlLayout.addView(pixelGrid);
}
}
First thing i have noticed it that you haven't used invalidate (); at the end because thats critical in order to animate the canvas ( redraw the frames ) so please include that .
there may be several ways to achieve what you want follows is my idea
this canvas need to be divided into multiple x , y divided planes as follows and save them in array of points which you can randomize and give those points to ball to move ,
Step 1, get the canvas size
step 2, divide is in x and y coordinate depending on size of each device varies so you need to control that factor via Screen size
step 3, save the coordinates in matrix or array
step 4, set position of balls from those arrays values ( randomly can you define the random limits as per the max and min values of x and y from the coordinates division .
example , function move will take ball object and x, y are the positions move (ball, x, y ); and you can randomize the x and y based on max and min limits of your coordinates division example total y lines and total x lines values
in order to get an idea about how to move the ball on canvas you can see this code here : https://github.com/pintspin/ball_animation

Trying to draw grid ends up in drawing long rectangle

I'd like to draw a grid. Therefore I've got
private int GRID_WIDTH = 6; <----Amount of columns
private int GRID_HEIGHT = 6; <----Amount of rows
private int GRID_SIZE; = 50 <----Width and height of a cell
Now I am trying to draw them:
for(int i = 0; i < GRID_WIDTH; i++) {
for(int j = 0; j < GRID_HEIGHT; j++) {
canvas.drawRect(new Rect(i*GRID_SIZE + 5, j*GRID_SIZE + 5, GRID_SIZE, GRID_SIZE), paint);
}
}
The "5" after each coordinate should make a gap between two rectangles.
This should end up in some nice grid, but as result I see multiple rectangles pushed together, without these 5px padding between them. No matter what I choose as padding, It resuls in following image: (Here the padding is set to 20 instead of 5...)
What am i doing wrong?
Thanks in advance!
Consider that the Rect constructor signature is:
Rect(int left, int top, int right, int bottom)
and you're doing like:
Rect(int left, int top, int width, int height)
Notice the difference in the last two arguments. You must do like this:
int left = i * (GRID_SIZE + 5);
int top = j * (GRID_SIZE + 5);
int right = left + GRID_SIZE;
int bottom = top + GRID_SIZE;
canvas.drawRect(new Rect(left, top, right, bottom), paint);

Use special date format for x axis in achartengine

I'm using achartengine to visualize some data in time. The use of a TimeChart and TimeSeries is perfect but I would like following result which doesn't seem possible at the moment.
Currently I'm using this:
GraphicalView view = ChartFactory.getTimeChartView(this, dataset, renderer, "MMM");
This results in following output on x axis:
nov. apr. aug.
But I would like a marker for each month and only the first character of each month, like this:
N D J F M A M J J A S O
Ideas on how to accomplish this? Thanks!
I've found the solution myself where I override the drawXLabels method in a custom TimeChart class.
private class CustomTimeChart extends TimeChart {
public CustomTimeChart(XYMultipleSeriesDataset dataset,
XYMultipleSeriesRenderer renderer) {
super(dataset, renderer);
}
#Override
protected void drawXLabels(List<Double> xLabels,
Double[] xTextLabelLocations, Canvas canvas, Paint paint,
int left, int top, int bottom, double xPixelsPerUnit,
double minX, double maxX) {
int length = xLabels.size();
if (length > 0) {
boolean showLabels = mRenderer.isShowLabels();
boolean showGridY = mRenderer.isShowGridY();
DateFormat format = new SimpleDateFormat("MMMM");
for (int i = 0; i < length; i++) {
long label = Math.round(xLabels.get(i));
float xLabel = (float) (left + xPixelsPerUnit
* (label - minX));
if (showLabels) {
paint.setColor(mRenderer.getXLabelsColor());
canvas.drawLine(xLabel, bottom, xLabel, bottom
+ mRenderer.getLabelsTextSize() / 3, paint);
drawText(canvas, format.format(new Date(label)).substring(0, 1).toUpperCase(Locale.getDefault()),
xLabel, bottom + mRenderer.getLabelsTextSize()
* 4 / 3, paint,
mRenderer.getXLabelsAngle());
}
if (showGridY) {
paint.setColor(mRenderer.getGridColor());
canvas.drawLine(xLabel, bottom, xLabel, top, paint);
}
}
}
drawXTextLabels(xTextLabelLocations, canvas, paint, true, left,
top, bottom, xPixelsPerUnit, minX, maxX);
}
Also make sure to use the setXLabels(int i) on the XYMultipleSeriesRenderer instance to set how many months you want to show on x axis.

Android - Why doesn't my axis draw?

The following is supposed to draw an axis in the middle of the screen. However, nothing appears. I am positive that is has to do with my Paths.
#Override
protected void onDraw(Canvas canvas) {
//Variables declared here temporarily for testing purposes
int canterX = getWidth() /2;
int centerY = getHeight() /2;
int radius = 150;
Path verticalAxis = new Path();
Path horizontalAxis = new Path();
drawAxis();
}
private void drawAxis(Canvas canvas) {
int axisLineThickness = 1;
int verticalEndX;
int verticalEndY;
int horizontalEndX;
int horizontalEndY;
Paint axisPaint = new Paint();
axisPaint.setColor(Color.WHITE);
axisPaint.setStrokeWidth(axisLineThickness);
double theta;
for(int i = 90; i < 360; i += 180) {
theta = toRadians(i);
verticalEndX = centerX + (int) ((cos(theta)) * radius);
verticalEndY = centerY + (int) ((sin(theta)) * radius);
verticalAxis.moveTo(centerX, centerY);
verticalAxis.lineTo(verticalEndX, verticalEndY);
}
canvas.drawPath(verticalAxis, axisColor);
for(int i = 90; i < 360; i += 180) {
theta = toRadians(i);
horizontalEndX = centerX + (int) ((cos(theta)) * radius);
horizontalEndY = centerY + (int) ((sin(theta)) * radius);
horizontalAxis.moveTo(centerX, centerY);
horizontalAxis.lineTo(verticalEndX, verticalEndY);
}
canvas.drawPath(horizontalAxis, axisColor);
}
I know I can make the axis draw if I add the following to the vertical and horizontal for loops respectively:
Vertical For Loop:
canvas.drawLine(centerX, centerY, verticalEndX, verticalEndY, paint);
Horizontal For Loop:
canvas.drawLine(centerX, centerY, horizontalEndX, horizontalEndY, paint);
But I don't want to solve the issue this way, I want to correct what is wrong with my paths. Can anyone tell me why the points aren't adding to my path correctly? The loop should only go through twice which creates a line for each side of the axis. Ie. One loop creates the top of the vertical axis and the second loop creates the bottom part.
How do I get my paths create that full line and then draw it outside of the loop?
Paint's default style appears to be FILL, so maybe just having a line in your path is confusing things. Try setting it to STROKE:
axisPaint.setStyle(Paint.Style.STROKE);
See Paint.Style

Categories

Resources