Error:(66, 27) error: constructor LineData in class LineData cannot be applied to given types; required: ILineDataSet[] found: String[], - android-studio

I was following the example on youtube, https://www.youtube.com/watch?v=TNeE9DJoOMY&t=614s, Creating a Line Graph with multiple data sets in Android Studio. I believe the code is correct... but still getting error: constuctor LineData error.. Another post on stackoverflow suggested that maybe the MPandroidChart library may have changed requiring a different input? The full error is:
Error:(66, 27) error: constructor LineData in class LineData cannot be applied to given types;
required: ILineDataSet[]
found: String[],LineDataSet
reason: varargs mismatch; String[] cannot be converted to ILineDataSet
Here is my main code:
package com.example.rj.linegraph1;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
LineChart lineChart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lineChart = (LineChart) findViewById(R.id.lineChart);
ArrayList<String> xAXIS = new ArrayList<>();
ArrayList<Entry> yAXISsin = new ArrayList<>();
ArrayList<Entry> yAXIScos = new ArrayList<>();
double x = 0;
int numDataPoints = 1000;
for (int i = 0; i < numDataPoints; i++) {
float sinFunction = Float.parseFloat(String.valueOf(Math.sin(x)));
float cosFunction = Float.parseFloat(String.valueOf(Math.cos(x)));
x = x + 0.1;
yAXISsin.add(new Entry(sinFunction,i));
yAXIScos.add(new Entry(cosFunction,i));
xAXIS.add(i, String.valueOf(x));
}
String[] xaxis = new String[xAXIS.size()];
for(int i = 0; i < xAXIS.size(); i++) {
xaxis[i] = xAXIS.get(i).toString();
}
ArrayList<ILineDataSet> lineDataSets = new ArrayList<>();
LineDataSet lineDataSet1 = new LineDataSet(yAXIScos,"cos");
lineDataSet1.setDrawCircles(false);
lineDataSet1.setColors(Color.BLUE);
LineDataSet lineDataSet2 = new LineDataSet(yAXISsin,"sin");
lineDataSet2.setDrawCircles(false);
lineDataSet2.setColors(Color.RED);
lineDataSets.add(lineDataSet1);
lineDataSets.add(lineDataSet2);
lineChart.setData(new LineData(xaxis,lineDataSets));
lineChart.setVisibleXRangeMaximum(65f);
}
}

I think this is how the library requires you to do it now:
for (int i = 0; i < numDataPoints; i++) {
float sinFunction = Float.parseFloat(String.valueOf(Math.sin(x)));
float cosFunction = Float.parseFloat(String.valueOf(Math.cos(x)));
x = x + 0.1;
yAXISsin.add(new Entry(x, sinFunction));
yAXIScos.add(new Entry(x, cosFunction));
//dont use strings anymore
//xAXIS.add(i, String.valueOf(x));
}
ArrayList<ILineDataSet> lineDataSets = new ArrayList<>();
LineDataSet lineDataSet1 = new LineDataSet(yAXIScos,"cos");
LineDataSet lineDataSet2 = new LineDataSet(yAXISsin,"sin");
lineDataSet1.setDrawCircles(false);
lineDataSet1.setColors(Color.RED);
lineDataSet2.setDrawCircles(false);
lineDataSet2.setColors(Color.BLUE);
lineDataSets.add(lineDataSet1);
lineDataSets.add(lineDataSet2);
lineChart.setData(new LineData(lineDataSets));
lineChart.setVisibleXRangeMaximum(65f);
Pretty sure it's something like that. You no longer add the X-Axis values like before. Now the X-Axis values just get added as Entry's.
Let me know if this works. I didn't try it myself.

It might be because you need 'x' to be a double for the math operations but you need to convert it to a float for each Entry.
I also added some logs in here so you can debug it might easily.
public class MainActivity extends AppCompatActivity {
//added for debugging
private static final String TAG = "MainActivity";
LineChart lineChart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lineChart = (LineChart) findViewById(R.id.lineChart);
ArrayList<Entry> yAXISsin = new ArrayList<>();
ArrayList<Entry> yAXIScos = new ArrayList<>();
double x = 0.0;
int numDataPoints = 1000;
for (int i = 0; i < numDataPoints; i++) {
float sinFunction = Float.parseFloat(String.valueOf(Math.sin(x)));
float cosFunction = Float.parseFloat(String.valueOf(Math.cos(x)));
x = x + 0.1;
float xEntry = Float.parseFloat(String.valueOf(x));
yAXISsin.add(new Entry(xEntry, sinFunction));
yAXIScos.add(new Entry(xEntry, cosFunction));
Log.d(TAG, "Populating Arrays with Data: yAXISsin = " + sinFunction);
Log.d(TAG, "Populating Arrays with Data: yAXIScos = " + cosFunction);
Log.d(TAG, "Populating Arrays with Data: xEntry = " + xEntry);
}
ArrayList<ILineDataSet> lineDataSets = new ArrayList<>();
LineDataSet lineDataSet1 = new LineDataSet(yAXIScos,"cos");
LineDataSet lineDataSet2 = new LineDataSet(yAXISsin,"sin");
lineDataSet1.setDrawCircles(false);
lineDataSet1.setColors(Color.RED);
lineDataSet2.setDrawCircles(false);
lineDataSet2.setColors(Color.BLUE);
lineDataSets.add(lineDataSet1);
lineDataSets.add(lineDataSet2);
lineChart.setData(new LineData(lineDataSets));
lineChart.setVisibleXRangeMaximum(65f);
//can also try calling invalidate() to refresh the graph
lineChart.invalidate();

Related

How to do something in MainActivity after the AsyncTask onPostExecute is done

I am trying to get the LatLngs so I can find the nearest place of the search result, I am trying it this way, but the getLatLngs returns null because it hasn't yet initialized.How do I access stuff from MainActivity after the onPostExecute is done.Thank you in advance.
public class GetNearbyPlaces extends AsyncTask<Object, String, String> {
private ArrayList<LatLng> LatLngs = new ArrayList<>();
private LatLng latLngMain;
private LatLng shortestLatLng;
#Override
protected void onPostExecute(String s) {
List<HashMap<String, String>> nearbyPlacesList = null;
DataParser dataParser = new DataParser();
nearbyPlacesList = dataParser.parse(s);
shortestLatLng = DisplayNearbyPlaces(nearbyPlacesList);
}
private LatLng DisplayNearbyPlaces(List<HashMap<String, String>> nearbyPlacesList)
{
int index = 0;
LatLng shortest;
double shortestDistance = Double.MAX_VALUE;
for(int i = 0;i<nearbyPlacesList.size();i++)
{
MarkerOptions markerOptions = new MarkerOptions();
HashMap<String, String> googleNearbyPlace = nearbyPlacesList.get(i);
String nameOfPlace = googleNearbyPlace.get("place_name");
String vicinity = googleNearbyPlace.get("vicinity");
double lat = Double.parseDouble(googleNearbyPlace.get("lat"));
double lng = Double.parseDouble(googleNearbyPlace.get("lng"));
LatLng latLng = new LatLng(lat,lng);
LatLngs.add(latLng);
markerOptions.position(latLng);
markerOptions.title(nameOfPlace + " : " + vicinity);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
if(mMap!=null)
mMap.addMarker(markerOptions);
}
for(int i = 0;i<LatLngs.size();i++)
{
double deltaLat = latLngMain.latitude - LatLngs.get(i).latitude;
double deltaLng = latLngMain.longitude - LatLngs.get(i).longitude;
double distanceInDegree = Math.sqrt(deltaLat * deltaLat + deltaLng * deltaLng);
double distanceInMeter = distanceInDegree * 4000;
if(distanceInMeter<shortestDistance)
{
shortestDistance=distanceInMeter;
index = i;
}
}
shortest = LatLngs.get(index);
return shortest;
}
public LatLng getShortestLatLng()
{
return shortestLatLng;
}
}
In MainActivity
getNearbyPlaces.execute(transferData).get();
nearestDistance = getNearbyPlaces.getShortestLatLng();
You must initialize your LatLngs field before calling methods on it.
Replace
private ArrayList<LatLng> LatLngs;
to
private ArrayList<LatLng> LatLngs = new ArrayList<>();
In your code, you initialize it only in loop of DisplayNearbyPlaces method, and if, for example,
nearbyPlacesList is empty, then body of this loop does not run and field remains uninitialized.

How to animate a filled triangle (drawn by a path) in Android Studio

I'm trying to build a jigsaw-like app for Android that involves the user moving polygonal pieces around the screen by touch event.
I can draw - for example - a triangle, and fill it. I can also move it smoothly round the screen but it leaves a trace - so that the screen rapidly fills up :-(
So I am wondering how to adjust the onDraw method so that the previous positions of the triangle are not included. Or is there some other technique? The question has been asked once before but did not get a satisfactory answer. I am quite new to Android work so I am sure a kind expert will be able to point me in the right direction!
The view:
public class GameView extends View {
public Triangle T1;
Paint paint = new Paint();
private Path path;
public GameView(Context context) {
super(context);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
initTriangle();
}
public void initTriangle() {
int T1Points[][] = new int[3][2];
T1Points[0][0] = -200;
T1Points[0][1] = -100;
T1Points[1][0] = 200;
T1Points[1][1] = -100;
T1Points[2][0] = 0;
T1Points[2][1] = 100;
float[] position = new float[2];
position[0] = (float) 200.0;
position[1] = (float) 100.0;
T1 = new Triangle("T1", T1Points, position);
path = T1.getPath();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float[] pos = new float[2];
pos[0] = event.getX(); //nextx;
pos[1] = event.getY(); //nexty;
T1.setPosition(pos );
Path path = new Path();
path = T1.getPath();
postInvalidate();
return true;
}
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
}
Triangle class:
public class Triangle {
public int[][] myPoints;
public Path path;
public String myname;
public float[] position;
public Triangle (String name, int[][] newpoints, float[] posn) {
myPoints = new int[4][2];
int i;
for (i = 0; i < 3; i++) {
myPoints[i][0] = newpoints[i][0];
myPoints[i][1] = newpoints[i][1];
}
myPoints[3][0] = newpoints[0][0]; // closed circuit for future needs
myPoints[3][1] = newpoints[0][1];
path = new Path();
position = new float[2];
position[0] = posn[0];
position[1] = posn[1];
myname = name;
updatePath();
}
public void setPosition(float[] newPosition){
position[0] = newPosition[0];
position[1] = newPosition[1];
updatePath();
}
public void updatePath(){
int startx = myPoints[0][0] + Math.round(position[0]);
int starty = myPoints[0][1] + Math.round(position[1]);
path.moveTo(startx,starty);
for (int i = 1; i < myPoints.length; i++)
{
int newx = myPoints[i][0] + Math.round(position[0]);
int newy = myPoints[i][1] + Math.round(position[1]);
path.lineTo(newx,newy);
}
path.close();
}
public Path getPath() {
return path;
}
}
Main Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uk.mydomain.animatedtriangle.GameView gameView = new uk.mydomain.animatedtriangle.GameView(this);
RelativeLayout relativeLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
relativeLayout.setLayoutParams(relativeParams);
setContentView(relativeLayout);
relativeLayout.addView(gameView);
}
Sorted! Just needed to add a path.reset() at the end of onDraw.

Android App Development - Library android-graphview

I am having a problem with visualization of time series data on graph view library in android studio. When I am trying to plot my graph against very small values(in the intervals of 0.00003) on x-axis, there is no graph. However, when I am try to plot against integer values(in the interval of 1), the graph shown is as expected.
My Working code -
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
Intent intent = getIntent();
int sample_freq = 32768;
double [] data = intent.getDoubleArrayExtra(DataActivity.EXTRA_TIME_DATA);
int n = data.length;
GraphView graph = findViewById(R.id.graph);
double sample_time = 1/sample_freq;
DataPoint[] points = new DataPoint[n];
for(int i = 0; i < n ; i++)
{
points[i] = new DataPoint(i, data[i]);
}
LineGraphSeries<DataPoint> series = new LineGraphSeries<>(points);
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().setMinY(-15);
graph.getViewport().setMaxY(15);
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(100);
graph.getViewport().setMaxX(5000);
graph.getViewport().setScalable(true);
graph.getViewport().setScalableY(true);
graph.addSeries(series);
TextView textView = findViewById(R.id.textView);
String message = String.valueOf(n);
textView.setText(message);
}
Code which is not working -
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
Intent intent = getIntent();
int sample_freq = 32768;
double [] data = intent.getDoubleArrayExtra(DataActivity.EXTRA_TIME_DATA);
int n = data.length;
GraphView graph = findViewById(R.id.graph);
double sample_time = 1/sample_freq;
DataPoint[] points = new DataPoint[n];
for(int i = 0; i < n ; i++)
{
points[i] = new DataPoint(i*sample_time, data[i]);
}
LineGraphSeries<DataPoint> series = new LineGraphSeries<>(points);
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().setMinY(-15);
graph.getViewport().setMaxY(15);
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(0.01);
graph.getViewport().setMaxX(1);
graph.getViewport().setScalable(true);
graph.getViewport().setScalableY(true);
graph.addSeries(series);
TextView textView = findViewById(R.id.textView);
String message = String.valueOf(n);
textView.setText(message);
}

Limit width size of Stacked Bar chart

I tried to implement this solution for StackedBar Chart but it turns out that there is no Java method getBarGap() in StackedBar chart. Is there any solution into the latest JavaFX version for this problem?
Basic example:
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MainApp extends Application
{
private StackedBarChart<String, Number> stackedChart;
private List<EventsObj> eventsObj;
#Override
public void start(Stage stage) throws Exception
{
createStackedChart();
List<EventsObj> testData = generateTestData();
addStackedChartData(testData);
HBox hb = new HBox();
hb.getChildren().add(stackedChart);
Scene scene = new Scene(hb);
stage.setTitle("JavaFX and Maven");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
private void createStackedChart()
{
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Days");
NumberAxis yAxis = new NumberAxis();
stackedChart = new StackedBarChart<>(xAxis, yAxis);
stackedChart.setCategoryGap(20);
stackedChart.widthProperty().addListener((obs, b, b1) ->
{
// Chart Bar column is not automatically resized. We need to wait for next JavaFX releases to fix this.
Platform.runLater(() -> setMaxBarWidth(stackedChart, xAxis, 40, 10));
});
}
private List<EventsObj> generateTestData()
{
eventsObj = new ArrayList<>();
for (int i = 0; i < 5; i++)
{
eventsObj.add(new EventsObj(String.valueOf(randomDate()), random(2, 60), random(2, 60), random(2, 60), random(2, 60)));
}
return eventsObj;
}
public static int random(int lowerBound, int upperBound)
{
return (lowerBound + (int) Math.round(Math.random() * (upperBound - lowerBound)));
}
private LocalDate randomDate()
{
Random random = new Random();
int minDay = (int) LocalDate.of(1900, 1, 1).toEpochDay();
int maxDay = (int) LocalDate.of(2015, 1, 1).toEpochDay();
long randomDay = minDay + random.nextInt(maxDay - minDay);
LocalDate randomBirthDate = LocalDate.ofEpochDay(randomDay);
return randomBirthDate;
}
private void addStackedChartData(List<EventsObj> data)
{
List<XYChart.Series<String, Number>> dataSeries = new ArrayList<>(data.size());
for (EventsObj data1 : data)
{
final XYChart.Series<String, Number> series1 = new XYChart.Series<>();
series1.setName(data1.getDate());
series1.getData().setAll(
new XYChart.Data<>("Info", data1.getInfo()));
dataSeries.add(series1);
}
stackedChart.getData().setAll(dataSeries);
}
private void setMaxBarWidth(StackedBarChart<String, Number> bc, CategoryAxis xAxis, double maxBarWidth, double minCategoryGap)
{
double barWidth = 0;
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getCategoryGap());
barWidth = (avilableBarSpace / bc.getData().size()) - bc.getCategoryGap();
if (barWidth > maxBarWidth)
{
avilableBarSpace = (maxBarWidth + bc.getCategoryGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getCategoryGap());
}
}
while (barWidth > maxBarWidth);
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (minCategoryGap + bc.getCategoryGap());
barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getCategoryGap());
avilableBarSpace = (barWidth + bc.getCategoryGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getCategoryGap());
}
while (barWidth < maxBarWidth && bc.getCategoryGap() > minCategoryGap);
}
}
In a BarChart chart, the different series added are plotted in the different columns from the same category with a barGap, some spacing in between.
But in a StackBarChart chart, the different series are plotted stacked in the same column, hence in this case there is no bar gap.
If you take the setMaxBarWidth() method from this answer, all you need to do is set bc.getBarGap() to 0, and take sbc.getData().size() as 1. In this case there is no need for iterations.
This will be the new method, really simplified:
private void setMaxCategoryWidth(double maxCategoryWidth, double minCategoryGap){
double catSpace = xAxis.getCategorySpacing();
sbc.setCategoryGap(catSpace - Math.min(maxCategoryWidth, catSpace - minCategoryGap));
}
Basically, all you have to do is subtract the desired width of your category from the initial width of the category and put this extra space into the categoryGap.
Now, you can create your chart:
StackedBarChart<String, Number> sbc = new StackedBarChart<>(xAxis, yAxis);
And set your desired size for the categories:
setMaxCategoryWidth(40, 10);
sbc.widthProperty().addListener((obs, b, b1) -> {
Platform.runLater(() -> setMaxCategoryWidth(40, 10));
});
This pic is generated based on the sample 7.4 taken from here.

How to draw multiline Edittext in notepad?

I am creating a notepad and I want to have edit text with multiple horizontal lines on it. As I have done with some but It is displaying line when I click on next or enter to the next line. I want that lines already be there. When I am using layour with android:lines="5". It is displaying picture as I have attached.
Please suggest on the same. thanks
EDITED: My EditText is showing like this!!!! A Huge gap on top. Please suggest what to do?
This is the code, based on google's note editorThe output will be shown in the image.When you press the enter,new lines will be added.
public class LinedEditText extends EditText {
private Rect mRect;
private Paint mPaint;
// we need this constructor for LayoutInflater
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(R.color.edit_note_line); //SET YOUR OWN COLOR HERE
}
#Override
protected void onDraw(Canvas canvas) {
//int count = getLineCount();
int height = getHeight();
int line_height = getLineHeight();
int count = height / line_height;
if (getLineCount() > count)
count = getLineCount();//for long text with scrolling
Rect r = mRect;
Paint paint = mPaint;
int baseline = getLineBounds(0, r);//first line
for (int i = 0; i < count; i++) {
canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
baseline += getLineHeight();//next line
}
super.onDraw(canvas);
}
}
For more info,Refer this link.
Simple add this line in your XML
android:gravity="top|left"
Here , my code will draw 15 lines by default and you can get more lines by pressing Enter :-
package com.wysiwyg.main;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.EditText;
public class LineEditText extends EditText {
private Rect mRect;
private Paint mPaint;
// we need this constructor for LayoutInflater
public LineEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(Color.BLUE); //SET YOUR OWN COLOR HERE
setMinLines(15);
}
#Override
protected void onDraw(Canvas canvas) {
int height = getHeight();
int line_height = getLineHeight();
int count = height / line_height;
if(getLineCount() > count){
count = getLineCount();
}
Rect r = mRect;
Paint paint = mPaint;
int baseline = getLineBounds(0, r);
for (int i = 0; i < count; i++) {
canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
baseline += getLineHeight();//next line
}
// Finishes up by calling the parent method
super.onDraw(canvas);
}
}

Resources