I have a graph built using androidplot. I need to see each value horizontally (rotate 90 degrees). In the screenshot I showed what I mean. How to do it?
There is not a configuration option built in to do this, but it'd relatively easy to do in a custom renderer. Here's the quickstart example modified to do it:
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.androidplot.ui.SeriesRenderer;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.LineAndPointRenderer;
import com.androidplot.xy.PointLabelFormatter;
import com.androidplot.xy.PointLabeler;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.List;
/**
* A simple XYPlot
*/
public class SimpleXYPlotActivity extends Activity {
private XYPlot plot;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_xy_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 2, 3, 6, 7, 8, 9, 10, 13, 14};
Number[] series1Numbers = {1, 4, 2, 8, 4, 16, 8, 32, 16, 64};
Number[] series2Numbers = {5, 2, 10, 5, 20, 10, 40, 20, 80, 40};
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series1");
XYSeries series2 = new SimpleXYSeries(
Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format =
new MyLineAndPointFormatter(this, R.xml.line_point_formatter_with_labels);
LineAndPointFormatter series2Format =
new MyLineAndPointFormatter(this, R.xml.line_point_formatter_with_labels_2);
// add an "dash" effect to the series2 line:
series2Format.getLinePaint().setPathEffect(new DashPathEffect(new float[] {
// always use DP when specifying pixel sizes, to keep things consistent across devices:
PixelUtils.dpToPix(20),
PixelUtils.dpToPix(15)}, 0));
// (optional) add some smoothing to the lines:
// see: http://androidplot.com/smooth-curves-and-androidplot/
series1Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
series2Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
plot.addSeries(series2, series2Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
#Override
public StringBuffer format(Object obj, #NonNull StringBuffer toAppendTo, #NonNull FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
#Override
public Object parseObject(String source, #NonNull ParsePosition pos) {
return null;
}
});
}
/**
* A LineAndPointRenderer that rotates it's point labels -90 degrees.
*/
static class MyLineAndPointRenderer extends LineAndPointRenderer<MyLineAndPointFormatter> {
public MyLineAndPointRenderer(XYPlot plot) {
super(plot);
}
// Basically just copy the entire renderPoints implementation and add a rotation as shown below
#Override
protected void renderPoints(Canvas canvas, RectF plotArea, XYSeries series, int iStart, int iEnd, List<PointF> points,
LineAndPointFormatter formatter) {
if (formatter.hasVertexPaint() || formatter.hasPointLabelFormatter()) {
final Paint vertexPaint = formatter.hasVertexPaint() ? formatter.getVertexPaint() : null;
final boolean hasPointLabelFormatter = formatter.hasPointLabelFormatter();
final PointLabelFormatter plf = hasPointLabelFormatter ? formatter.getPointLabelFormatter() : null;
final PointLabeler pointLabeler = hasPointLabelFormatter ? formatter.getPointLabeler() : null;
for(int i = iStart; i < iEnd; i++) {
PointF p = points.get(i);
if(p != null) {
if (vertexPaint != null) {
canvas.drawPoint(p.x, p.y, vertexPaint);
}
if (pointLabeler != null) {
// this is where we rotate the text:
final int canvasState = canvas.save();
try {
canvas.rotate(-90, p.x, p.y);
canvas.drawText(pointLabeler.getLabel(series, i),
p.x + plf.hOffset, p.y + plf.vOffset, plf.getTextPaint());
} finally {
canvas.restoreToCount(canvasState);
}
}
}
}
}
}
}
static class MyLineAndPointFormatter extends LineAndPointFormatter {
// if you dont use configurator you can omit this constructor. this example uses it
// tho so here it is.
public MyLineAndPointFormatter(Context context, int xmlCfgId) {
super(context, xmlCfgId);
}
#Override
public Class<? extends SeriesRenderer> getRendererClass() {
return MyLineAndPointRenderer.class;
}
#Override
public SeriesRenderer doGetRendererInstance(XYPlot plot) {
return new MyLineAndPointRenderer(plot);
}
}
}
The important stuff is at the bottom in MyLineAndPointRenderer. Basically you're just extending LineAndPointRenderer and overriding renderPoints(...) to rotate the canvas -90 degrees before drawing the text labels, and then restore the canvas immediately after.
Related
I have a spinner in my layout. I would like to change the shape drawn as a path when a different item is selected. Currently my code is adding my second path to the first one, instead of just replacing it. Here is my code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private MyView myView;
private boolean firstTimeThru = true;
private LinearLayout root;
private Spinner mySpinner;
private Paint myPaint;
private Path path = new Path();
float[] finalXCoord, finalYCoord;
float[] xCoord1 = {0,30, 50};
float[] yCoord1 = {0, 100, 40};
float[] xCoord2 = {52,300, 100, 60};
float[] yCoord2 = {100, 200, 40, 80};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finalXCoord = xCoord1;
finalYCoord = yCoord1;
// Hide the Title Bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Hide the Status Bar
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
// Create the spinner, add contents, add events, add to Layout
mySpinner = new Spinner(this);
List<String> list = new ArrayList<String>();
list.add("1st Path");
list.add("2nd Path");
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, list);
mySpinner.setAdapter(spinnerArrayAdapter);
myPaint = new Paint();
myPaint.setColor(Color.GREEN);
mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
System.out.println(mySpinner.getSelectedItemId());
if (mySpinner.getSelectedItemId()==0) {
myPaint.setColor(Color.GREEN);
finalXCoord = xCoord1;
finalYCoord = yCoord1;
}
if (mySpinner.getSelectedItemId()==1) {
myPaint.setColor(Color.RED);
finalXCoord = xCoord2;
finalYCoord = yCoord2;
}
if (!firstTimeThru) {
System.out.println("Not First Time");
//demoview.changeToRed();
}
System.out.println(myPaint.getColor());
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
root.addView(mySpinner);
// Add view with canvas
myView = new MyView(this);
root.addView(myView);
setContentView(root);
}
public class MyView extends View {
public Canvas mCanvas;
public MyView(Context context) {
super(context);
}
public void drawPath(float[] xCoord, float[] yCoord) {
path.moveTo(xCoord[0], yCoord[0]);
for(int i=1; i<xCoord.length; i++) {
path.lineTo(xCoord[i], yCoord[i]);
}
path.close();
mCanvas.drawPath(path, myPaint);
invalidate();
}
protected void onDraw(Canvas canvas) {
mCanvas = canvas;
//myPaint.setStyle(Paint.Style.FILL_AND_STROKE);
myPaint.setStrokeWidth(10);
myPaint.setPathEffect(null);
//paint.setColor(Color.BLACK);
myPaint.setStyle(Paint.Style.STROKE);
drawPath(finalXCoord, finalYCoord);
//invalidate();
}
}
}
You probably need to reset your path:
public void drawPath(float[] xCoord, float[] yCoord) {
path.reset();
path.moveTo(xCoord[0], yCoord[0]);
for(int i=1; i<xCoord.length; i++) {
path.lineTo(xCoord[i], yCoord[i]);
}
path.close();
mCanvas.drawPath(path, myPaint);
invalidate();
}
I am developing line chart using achartengine 1.1.0.jar.
I am facing one issue when my final line chart is drawn.
The y axis labels drawn without vertical space between labels and all labels drawn together.
I have attached screen shot of my line chart drawn.
Here i am also attaching snippet code with it.
package com.example.simplelinecharexample;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;
import org.achartengine.renderer.XYSeriesRenderer;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.widget.LinearLayout;
public class main extends Activity {
private GraphicalView mChart;
private String[] mMonth = new String[] { "Jan", "Feb", "Mar", "Apr", "May",
"Jun",
"Jul", "Aug" };
private String[] mweek = new String[] { "Mon", "Tue", "Wed", "Thu", "Fri",
"Sat",
"Sun" };
private String[] steps = new String[31];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i <= 15; i++)
if (i == 0)
steps[i] = String.valueOf(0);
else
steps[i] = String.valueOf(Integer.parseInt(steps[i - 1]) + 2000);
OpenChart();
}
private void OpenChart() {
int z[] = { 0, 1, 2, 3, 4, 5, 6, 7};
// int x[] = { 10, 18, 32, 21, 48, 60, 53, 80 };
int[] income = { 2000, 2500, 2700, 3000, 2800, 3500,5000 , 15000};
XYSeries xSeries = new XYSeries("X Series");
for (int i = 0; i < z.length; i++) {
xSeries.add(z[i], income[i]);
}
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(xSeries);
XYSeriesRenderer Xrenderer = new XYSeriesRenderer();
Xrenderer.setColor(Color.RED);
Xrenderer.setPointStyle(PointStyle.DIAMOND);
Xrenderer.setDisplayChartValues(true);
Xrenderer.setLineWidth(5);
Xrenderer.setFillPoints(true);
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
mRenderer.setChartTitle("X Vs Y Chart");`enter code here`
mRenderer.setXTitle("X Values");
mRenderer.setYTitle("Y Values");
mRenderer.setXLabels(0);![enter image description here][2]
mRenderer.setShowGrid(true);
mRenderer.setYLabels(49);
for (int i = 0; i < mweek.length; i++) {
mRenderer.addXTextLabel(i, mweek[i]);
}
mRenderer.addSeriesRenderer(Xrenderer);
mRenderer.setXLabelsAlign(Align.LEFT);
mRenderer.setYLabelsAlign(Align.RIGHT);
mRenderer.setLabelsTextSize(20);
mRenderer.setYAxisMin(0);
mRenderer.setXAxisMin(-1);
mRenderer.setYAxisMax(98000);
mRenderer.setPanEnabled(false, true);
mRenderer.setPanLimits(new double[]{0.0,Double.MAX_VALUE,0.0,98000});
mRenderer.setZoomEnabled(true, false);
mRenderer.setAntialiasing(true);
mRenderer.setMargins(new int[] { 60, 120, 60, 60 });
LinearLayout chart_container = (LinearLayout) findViewById(R.id.Chart_layout);
mChart = (GraphicalView) ChartFactory.getLineChartView(
getBaseContext(), dataset, mRenderer);
chart_container.addView(mChart);
}
}
I want add vertical space between y axis labels and it should auto scrollable.
Just replace your line
mRenderer.setYLabels(49);
to
mRenderer.setYLabels(10);
When you decrease the size of SetYlabels it will increase the space between Y labels.
Enjoy...
Every time I call this method it return nullpointerexception:
java.lang.NullPointerException at org.achartengine.chart.XYChart.toScreenPoint(XYChart.java:867)
I see mScreenR of chart is null
Without using this method toScreenPoint(double) the charts works well this is the code:
package com.insights.insights.gui;
import java.util.ArrayList;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import com.insights.insights.R;
import com.insights.insights.local.ApplicationsController;
import com.insights.insights.model.AppMetrics;
import com.insights.insights.model.Application;
import com.insights.insights.model.Applications;
import com.insights.insights.model.Day;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout;
import android.widget.LinearLayout;
import android.widget.Toast;
public class ChartFragment extends Fragment {
private XYMultipleSeriesRenderer renderer;
private XYMultipleSeriesDataset dataset;
private GraphicalView graphicalView;
private XYSeries firstSeries;
private XYChart chart=null;
private String apiKey;
private ArrayList<Day> days;
private View view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apiKey = getArguments().getString(getString(R.string.tabs_activity_api_key));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.chart_fragment, container, false);
v.findViewById(R.idChartFragment.container).requestFocus();
this.view = v;
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Obtaining data to plot
Applications applications = ApplicationsController.getInstance(getActivity()).getApplications();
ArrayList<Application> applicationArray = applications.getApplication();
if (applicationArray != null && !applicationArray.isEmpty()) {
for (int i = 0; i < applicationArray.size(); i++) {
if (applicationArray.get(i).getApiKey().equals(apiKey)) {
ArrayList<AppMetrics> appMetrics = applicationArray.get(i).getAppMetrics();
for (int j = 0; j < appMetrics.size(); j++) {
if (appMetrics.get(j).getMetric().equals("Sessions")) {
days = appMetrics.get(j).getDay();
break;
}
}
}
}
}
// If there isn't any item to plot and show a toast
if (days == null) {
Toast toast = Toast.makeText(getActivity(), R.string.chart_fragment_no_items, Toast.LENGTH_LONG);
toast.show();
return;
}
// Ploting the items
dataset = getDataset(days);
renderer = getRenderer();
setRendererStyling(renderer);
// add plot to the layout
if (graphicalView == null) {
LinearLayout layout = (LinearLayout) view.findViewById(R.idChartFragment.Chart);
chart= new LineChart(dataset, renderer);
graphicalView = new GraphicalView(getActivity(), chart);
renderer.setSelectableBuffer(11);
layout.addView(graphicalView);
} else{
graphicalView.repaint();
}
if(chart!=null&&firstSeries!=null){
for(int i=0;i<firstSeries.getItemCount();i++){
double x = firstSeries.getX(i);
double y = firstSeries.getY(i);
double[] screenPoint = chart.toScreenPoint(new double[] { x, y },0);
Log.i("puntos", x + "," + y + " = "+" ("+screenPoint[0]+", "+screenPoint[1]+")");
}
}
}
/**
* Method for set the style of the plotter window and the string at the x
* axis
*
* #param mRenderer
* render to put style in
*
* #param dataSetX
* string to set at x axis
*/
private void setRendererStyling(XYMultipleSeriesRenderer mRenderer) {
mRenderer.setApplyBackgroundColor(false);
mRenderer.setMarginsColor(R.drawable.transperent_color);
mRenderer.setMargins(new int[] { 0, 0, 0, 0 });
mRenderer.setShowAxes(false);
mRenderer.setZoomButtonsVisible(false);
mRenderer.setExternalZoomEnabled(false);
mRenderer.setPointSize(20);
mRenderer.setClickEnabled(false);
mRenderer.setDisplayValues(false);
mRenderer.setXLabels(0);
mRenderer.setYLabels(0);
mRenderer.setPanEnabled(false);
mRenderer.setZoomEnabled(false);
mRenderer.setShowLegend(false);
}
/**
* Method to introduce the values of the y axis
*
* #param dataSetY
* data to set at axis y
* #return the data to set
*/
private XYMultipleSeriesDataset getDataset(ArrayList<Day> days) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
firstSeries = new XYSeries("");
for (int i = 0; i < 12; i++) {
int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
firstSeries.add(i, value);
}
dataset.addSeries(firstSeries);
return dataset;
}
/**
* Method for set the style of the line you want to plot and create a new
* renderer
*
* #return the renderer
*/
private XYMultipleSeriesRenderer getRenderer() {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
XYSeriesRenderer r = new XYSeriesRenderer();
r.setColor(getResources().getColor(R.color.grey_number_label_background));
r.setLineWidth(getResources().getInteger(R.integer.chart_fragment_line_width));
// r.setDisplayChartValues(true);
r.setPointStyle(PointStyle.POINT);
r.setFillPoints(true);
renderer.addSeriesRenderer(r);
return renderer;
}
}
And this is the layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+idChartFragment/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<LinearLayout
android:id="#+idChartFragment/Chart"
android:layout_width="300dp"
android:layout_height="300dp"
android:orientation="horizontal"/>
<AbsoluteLayout
android:id="#+idChartFragment/absolute"
android:layout_width="300dp"
android:layout_height="300dp"/>
</RelativeLayout>
Second Edit:
I want to do something like this:
With my code I do this:
This is my code:
package com.insights.insights.gui;
import java.util.ArrayList;
import java.util.List;
import org.achartengine.GraphicalView;
import org.achartengine.chart.ClickableArea;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.SeriesSelection;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Layout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.maps.ItemizedOverlay.OnFocusChangeListener;
import com.insights.insights.R;
import com.insights.insights.local.ApplicationsController;
import com.insights.insights.model.AppMetrics;
import com.insights.insights.model.Application;
import com.insights.insights.model.Applications;
import com.insights.insights.model.Day;
/**
*
* #author Manuel Plazas Palacio
*
*/
public class ChartFragment extends Fragment {
private XYMultipleSeriesRenderer renderer;
private XYMultipleSeriesDataset dataset;
private GraphicalView graphicalView;
private XYSeries firstSeries;
private XYChart chart = null;
private AbsoluteLayout absoluteLayout;
private ImageView point;
private LinearLayout pointInfoConatiner;
private TextView pointNumberText;
private TextView pointNameText;
private TextView pointDateText;
private Typeface avenirHeavy;
private Typeface avenirLight;
private String apiKey;
private String metricName;
private ArrayList<Day> days;
// The max and the min values displayed
private double max = 0;
private double min = 0;
private View view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apiKey = getArguments().getString(getString(R.string.tabs_activity_api_key));
metricName = "Sessions";
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.chart_fragment, container, false);
v.findViewById(R.idChartFragment.container).requestFocus();
this.view = v;
absoluteLayout = (AbsoluteLayout) v.findViewById(R.idChartFragment.absolute);
// pointInfoConatiner = (LinearLayout) v.findViewById(R.idChartFragment.pointInfoContainer);
// pointNumberText = (TextView) v.findViewById(R.idChartFragment.pointNumberText);
// pointNameText = (TextView) v.findViewById(R.idChartFragment.pointNameText);
// pointDateText = (TextView) v.findViewById(R.idChartFragment.pointDateText);
//
// pointNameText.setText(metricName);
// Obtaining data to plot
Applications applications = ApplicationsController.getInstance(getActivity()).getApplications();
ArrayList<Application> applicationArray = applications.getApplication();
if (applicationArray != null && !applicationArray.isEmpty()) {
for (int i = 0; i < applicationArray.size(); i++) {
if (applicationArray.get(i).getApiKey().equals(apiKey)) {
ArrayList<AppMetrics> appMetrics = applicationArray.get(i).getAppMetrics();
for (int j = 0; j < appMetrics.size(); j++) {
if (appMetrics.get(j).getMetric().equals(metricName)) {
days = appMetrics.get(j).getDay();
break;
}
}
}
}
}
// If there isn't any item to plot and show a toast
if (days == null) {
Toast toast = Toast.makeText(getActivity(), R.string.chart_fragment_no_items, Toast.LENGTH_LONG);
toast.show();
}
// Ploting the items
dataset = getDataset(days);
renderer = getRenderer();
setRendererStyling(renderer);
// add plot to the layout
if (graphicalView == null) {
LinearLayout layout = (LinearLayout) view.findViewById(R.idChartFragment.Chart);
chart = new LineChart(dataset, renderer);
graphicalView = new GraphicalView(getActivity(), chart);
renderer.setSelectableBuffer(11);
layout.addView(graphicalView);
} else {
graphicalView.repaint();
}
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
avenirHeavy = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Avenir Heavy.ttf");
avenirLight = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Avenir Light.ttf");
graphicalView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SeriesSelection seriesSelection = graphicalView.getCurrentSeriesAndPoint();
double[] xy = graphicalView.toRealPoint(0);
//creating the views
createOnClickPointsView();
if (seriesSelection != null) {
// debug
Log.d("Punto", seriesSelection.getXValue() + ", " + seriesSelection.getValue());
double x = firstSeries.getX(seriesSelection.getPointIndex() + 1);
double y = firstSeries.getY(seriesSelection.getPointIndex() + 1);
double[] screenPoint = chart.toScreenPoint(new double[] { x, y });
// debug
Log.d("Chart point", "Chart element in series index " + seriesSelection.getSeriesIndex() + " data point index "
+ seriesSelection.getPointIndex() + " was clicked" + " closest point value X=" + seriesSelection.getXValue()
+ ", Y=" + seriesSelection.getValue() + " clicked point value X=" + (float) xy[0] + ", Y=" + (float) xy[1]);
Log.d("Punto pantalla", " (" + screenPoint[0] + ", " + screenPoint[1] + ")");
int value = Integer.parseInt(days.get((int) (days.size() - (13 - x))).getValue());
String date = days.get((int) (days.size() - (13 - x))).getDate();
pointNumberText.setText(value + "");
pointDateText.setText(date);
// drawing point info
absoluteLayout.addView(pointInfoConatiner, new LayoutParams(getResources().getDrawable(R.drawable.graficapin)
.getIntrinsicWidth(), getResources().getDrawable(R.drawable.graficapin).getIntrinsicHeight(),
(int) (screenPoint[0] - (getResources().getDrawable(R.drawable.graficapin).getIntrinsicWidth() / 2)),
(int) (screenPoint[1] - (getResources().getDrawable(R.drawable.graficapin).getIntrinsicHeight()))));
// drawing point clicked
absoluteLayout.addView(point, new LayoutParams(getResources().getDrawable(R.drawable.puntoon).getIntrinsicWidth(),
getResources().getDrawable(R.drawable.puntoon).getIntrinsicHeight(), (int) (screenPoint[0] - (getResources()
.getDrawable(R.drawable.puntoon).getIntrinsicWidth() / 2)), (int) (screenPoint[1] - ((getResources()
.getDrawable(R.drawable.puntoon).getIntrinsicHeight()) / 4))));
}
}
});
}
/**
* Method for set the style of the plotter window and the string at the x
* axis
*
* #param mRenderer
* render to put style in
*
* #param dataSetX
* string to set at x axis
*/
private void setRendererStyling(XYMultipleSeriesRenderer mRenderer) {
mRenderer.setApplyBackgroundColor(false);
mRenderer.setMarginsColor(R.drawable.transperent_color);
mRenderer.setMargins(new int[] { 0, 0, 0, 0 });
mRenderer.setShowAxes(false);
mRenderer.setZoomButtonsVisible(false);
mRenderer.setExternalZoomEnabled(false);
mRenderer.setPointSize(getResources().getInteger(R.integer.chart_fragment_point_size));
mRenderer.setClickEnabled(true);
mRenderer.setDisplayValues(false);
mRenderer.setXLabels(0);
mRenderer.setYLabels(0);
mRenderer.setPanEnabled(true);
mRenderer.setZoomEnabled(false);
mRenderer.setShowLegend(false);
mRenderer.setYAxisMax(max + 10);
mRenderer.setYAxisMin(min - 10);
}
/**
* Method to introduce the values of the y axis
*
* #param dataSetY
* data to set at axis y
* #return the data to set
*/
private XYMultipleSeriesDataset getDataset(ArrayList<Day> days) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
firstSeries = new XYSeries("");
for (int i = 0; i < 12; i++) {
int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
firstSeries.add(i, value);
}
dataset.addSeries(firstSeries);
XYSeries secondSeries = new XYSeries("");
for (int i = 1; i < 11; i++) {
int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
if (i == 1) {
max = value;
min = value;
}
if (value > max)
max = value;
if (value < min)
min = value;
secondSeries.add(i, value);
}
dataset.addSeries(secondSeries);
return dataset;
}
/**
* Method for set the style of the line you want to plot and create a new
* renderer
*
* #return the renderer
*/
private XYMultipleSeriesRenderer getRenderer() {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
//First chart with the line
XYSeriesRenderer r = new XYSeriesRenderer();
r.setColor(getResources().getColor(R.color.grey_number_label_background));
r.setLineWidth(getResources().getInteger(R.integer.chart_fragment_line_width));
// r.setDisplayChartValues(true);
r.setPointStyle(PointStyle.POINT);
r.setFillPoints(true);
renderer.addSeriesRenderer(r);
// Second chart with the points
XYSeriesRenderer r1 = new XYSeriesRenderer();
r1.setColor(getResources().getColor(R.color.purple_chart_points));
r1.setLineWidth(0);
r1.setFillPoints(true);
r1.setPointStyle(PointStyle.CIRCLE);
renderer.addSeriesRenderer(r1);
return renderer;
}
public XYSeries getFirstSeries() {
return firstSeries;
}
public void setFirstSeries(XYSeries firstSeries) {
this.firstSeries = firstSeries;
}
public XYChart getChart() {
return chart;
}
public void setChart(XYChart chart) {
this.chart = chart;
}
/**
* Method for create the views when clicking on a point of the chart
*/
private void createOnClickPointsView() {
//If the info is already visible
if (pointInfoConatiner != null)
absoluteLayout.removeView(pointInfoConatiner);
// If the point is drawn
if (point != null)
absoluteLayout.removeView(point);
pointInfoConatiner = new LinearLayout(getActivity());
pointInfoConatiner.setBackgroundDrawable(getResources().getDrawable(R.drawable.graficapin));
pointInfoConatiner.setOrientation(LinearLayout.VERTICAL);
pointInfoConatiner.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(0, 8, 0, 0);
pointNumberText = new TextView(getActivity());
pointNumberText.setTextSize(18);
pointNumberText.setTextColor(getResources().getColor(R.color.purple_chart_points));
pointNumberText.setTypeface(avenirHeavy);
pointNumberText.setGravity(Gravity.CENTER);
pointNameText = new TextView(getActivity());
pointNameText.setTextSize(18);
pointNameText.setTextColor(getResources().getColor(R.color.grey_users_label));
pointNameText.setTypeface(avenirLight);
pointNameText.setText(metricName);
pointNameText.setGravity(Gravity.CENTER);
pointDateText = new TextView(getActivity());
pointDateText.setTextSize(11);
pointDateText.setTextColor(getResources().getColor(R.color.grey_users_label));
pointDateText.setTypeface(avenirHeavy);
pointDateText.setGravity(Gravity.CENTER);
pointInfoConatiner.addView(pointNumberText, 0, layoutParams);
layoutParams.setMargins(0, 2, 0, 0);
pointInfoConatiner.addView(pointNameText, 1, layoutParams);
pointInfoConatiner.addView(pointDateText, 2, layoutParams);
point = new ImageView(getActivity());
point.setImageDrawable(getResources().getDrawable(R.drawable.puntoon));
}
}
Anyone know how can I:
1-Quit the bottom border
2-Quit the line of the pink chart
3-The chart don't move when I touch the points
4- When I ask for the screen point why to many times the y value returns infinite
There used to be this bug in an older version of AChartEngine. I suggest you update to 1.1.0.
Also, please note that the chart must have been already displayed when calling the method. If the chart didn't display on screen then there is no way to calculate that.
I'm using the last version of the AndEngine, branch GLES2, with two devices: HTC Desire and a Galaxy Nexus.
I have a problem when using a SpriteGroup with Sprites scrolling down on the screen. New sprites are attached to a SpriteGroup on the top of the screen and detached when they go off the bottom. And I use a pool to avoid using to much memory.
As soon as there are some sprites detached, some newly attached sprites begin to blink randomly for a few frames. This is very annoying and I have no idea why...
I tried to setVisible(false) the sprites when recycling them, I also tried without the pool but it doesn't change a thing.
I think that SpriteGroup may have a bug, but not sure where. I tried to attach the children in SpriteGroup in the begin() method to be sure it didn't happen during the loop of onUpdateSpriteBatch(), without luck.
Here is an example based on the AndEngineExamples project. You can directly replace the SpriteBatchExample class, launch the project and go to Simple/Drawing a SpriteBatch, to see the problem.
Thanks in advance for any idea !
package org.andengine.examples;
import java.util.Iterator;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.sprite.batch.SpriteGroup;
import org.andengine.entity.util.FPSLogger;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.adt.list.SmartList;
import org.andengine.util.adt.pool.GenericPool;
public class SpriteBatchExample extends SimpleBaseGameActivity {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
// ===========================================================
// Fields
// ===========================================================
private BitmapTextureAtlas mBitmapTextureAtlas;
private ITextureRegion mFaceTextureRegion;
private float mSecondsElapsedSinceLastGeneration = 0;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
#Override
public void onCreateResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 32, 32, TextureOptions.BILINEAR);
this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "face_box.png", 0, 0);
this.mBitmapTextureAtlas.load();
}
#Override
public Scene onCreateScene() {
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
final SpriteGroup spriteGroup = new SpriteGroup(this.mBitmapTextureAtlas, 500, this.getVertexBufferObjectManager());
spriteGroup.setPosition(0, 0);
scene.attachChild(spriteGroup);
final SpritePool lPool = new SpritePool(mFaceTextureRegion, getVertexBufferObjectManager());
final SmartList<Sprite> lSpriteList = new SmartList<Sprite>();
final float lCharactersPeriod = 0.4f;
scene.registerUpdateHandler(new TimerHandler(0.05f, true, new ITimerCallback() {
#Override
public void onTimePassed(final TimerHandler pTimerHandler) {
final float lSecondsElapsedSinceLastUpdate = 0.1f;
final Iterator<Sprite> li = lSpriteList.iterator();
while (li.hasNext()) {
final Sprite lChar = li.next();
boolean lRemoveChar = false;
// Character destruction OR movement
final float lY = lChar.getY();
if (lY > CAMERA_HEIGHT) {
lRemoveChar = true;
} else {
lChar.setPosition(lChar.getX(), lY + 60 * lSecondsElapsedSinceLastUpdate);
}
if (lRemoveChar) {
// Remove character from scene
lChar.detachSelf();
lPool.recyclePoolItem(lChar);
li.remove();
}
}
// Character generation
mSecondsElapsedSinceLastGeneration += lSecondsElapsedSinceLastUpdate;
if (mSecondsElapsedSinceLastGeneration > lCharactersPeriod) {
// generate sprite
final Sprite lSprite = lPool.obtainPoolItem();
lSprite.setPosition((float) Math.random() * CAMERA_WIDTH, 0);
spriteGroup.attachChild(lSprite);
lSpriteList.add(lSprite);
mSecondsElapsedSinceLastGeneration -= lCharactersPeriod;
}
}
}));
return scene;
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
static class SpritePool extends GenericPool<Sprite> {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final VertexBufferObjectManager mVertexBufferObjectManager;
private ITextureRegion mFaceTextureRegion;
// ===========================================================
// Constructors
// ===========================================================
public SpritePool(final ITextureRegion pFaceTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) {
mFaceTextureRegion = pFaceTextureRegion;
mVertexBufferObjectManager = pVertexBufferObjectManager;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
protected Sprite onAllocatePoolItem() {
final Sprite lSprite = new Sprite(50, 0, mFaceTextureRegion, mVertexBufferObjectManager);
lSprite.setIgnoreUpdate(true);
return lSprite;
}
#Override
protected void onHandleRecycleItem(final Sprite pSprite) {
}
#Override
protected void onHandleObtainItem(final Sprite pSprite) {
}
}
}
i had the same issue (last added visible sprite(s) in the group started blinking whenever i set any sprite to invisible), and solved it by overwriting those 2 methods in SpriteGroup:
SpriteGroup result = new SpriteGroup(atlas, capacity, vertexBufferObjectManager) {
#Override
protected boolean onUpdateSpriteBatch() {
return false;
}
#Override
protected void onManagedUpdate(float pSecondsElapsed) {
super.onManagedUpdate(pSecondsElapsed);
final SmartList<IEntity> children = this.mChildren;
if(children != null) {
final int childCount = children.size();
for(int i = 0; i < childCount; i++) {
this.drawWithoutChecks((Sprite)children.get(i));
}
submit();
}
};
source:
http://www.andengine.org/forums/gles2/blinking-last-sprite-in-spritegroup-t7617.html
I have a small test app on Android that is meant to test tracking multitouch input, but I am only ever getting two touches at the same time on my Evo. Does anyone know if this is a limitation to Android or the hardware?
By the way, here's my test class so you can try it out yourself.
import java.util.HashMap;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.MotionEvent;
import android.view.View;
public class PressureView extends View
{
private HashMap<Integer, Spot> mSpots = new HashMap<Integer, Spot>();
private final int[] mColors;
private final Paint mPaint;
public PressureView(Context context)
{
super(context);
mPaint = new Paint();
mPaint.setStyle(Style.FILL);
mColors = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA};
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
for(int id : mSpots.keySet())
{
Spot spot = mSpots.get(id);
mPaint.setColor(spot.Color);
canvas.drawCircle(spot.X, spot.Y, spot.Pressure*500, mPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
System.out.println("************************** " + event.getPointerCount() + " Pointers");
for(int i = 0; i < event.getPointerCount(); i++)
{
int id = event.getPointerId(i);
Spot spot = null;
if(mSpots.containsKey(id))
{
spot = mSpots.get(id);
}
else
{
spot = new Spot();
spot.Color = mColors[mSpots.size()];
}
if(event.getAction() == MotionEvent.ACTION_UP) spot.Pressure = 0;
else spot.Pressure = event.getPressure(id);
spot.X = event.getX(id);
spot.Y = event.getY(id);
mSpots.put(id, spot);
}
invalidate();
return true;
}
private class Spot
{
public float X, Y, Pressure;
public int Color;
}
}
It seems that currently all HTC devices only can 2 finger multi-touch, but the Android SDK supports more fingers. E.g. the Galaxy S i9000 has support for more http://www.youtube.com/watch?v=KRCDRXYJBCY .