将当前时间(以毫秒为单位)传递给 MPChart 会破坏它
Passing current time in milliseconds to MPChart breaks it
我已经尝试解决这个问题,但没有成功。数据未按应有的方式显示。
首先我生成虚拟数据。这是异步完成的,因为我需要在调用 System.currentTimeMillis
之间留出一些间隔。 (撇开这里糟糕的代码,这只是调试数据,不会出现在发行版中。考虑到 ANR,在主线程上使用 Thread.sleep 是个坏主意)
public class AsyncGeneration extends AsyncTask<String, String, String>{
public AsyncGeneration() {
super();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
@Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected String doInBackground(String... strings) {
while(root == null) {
try {
Thread.sleep(200);
}catch(InterruptedException e){}
}
List<Entry> rdata = new ArrayList<>();
for(int i = 1; i < 30; i++){
try{
Thread.sleep(200);
}catch(Exception e){
//IGNORE
}
float time = System.currentTimeMillis();
Log.e("GChart", "Timex: " + time);
Session s = new Session(r.nextInt(5000), time);//Replace time with the index in the for-loop and it works for some reason
rdata.add(new Entry(s.getXValue(), s.getYValue()));
Log.e("GChart", "Timey: " + s.getXValue());
}
final List<Entry> entries = rdata;
OverviewFragment.this.getActivity().runOnUiThread(() ->{
LineDataSet data = new LineDataSet(entries, "Distance");
data.setCircleColor(Color.parseColor("#FF0000"));
LineData lineData = new LineData(data);
tab1chart.setData(lineData);
tab1chart.invalidate(); // refresh
tab1chart.getXAxis().setValueFormatter(new DateFormatter());
tab1chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
tab1chart.getXAxis().setTextSize(10f);
tab1chart.getXAxis().setTextColor(Color.RED);
tab1chart.getXAxis().setDrawAxisLine(true);
tab1chart.getXAxis().setDrawGridLines(true);
tab1chart.getAxisLeft().setValueFormatter(new DistanceValueFormatter());
tab1chart.getAxisLeft().setDrawGridLines(true);
Log.v("Chart", "Chart data loaded and invalidated");//This prints
});
return null;
}
}
到目前为止一切看起来都很好。数据进入图表,没有异常,没有崩溃。
图表呈现时,单个数据点显示在图表的最左侧。我生成了 30 个数据点,其中一个出现了。
这是问题 #1:只显示一个数据点。
第 2 题稍微难一些。底部的整个 X 轴消失。 X 轴消失了,缩放时,Y 轴及其文本也消失了。这很难解释,所以这里是截图:
值得一提的事实是,如果我在 for 循环中传递 i
作为时间,它会按预期显示:所有轴都已就位,缩放不会破坏任何东西。
(浮点型值可以取与长整型值相同的值,除了它们还有小数点。)
此外,我格式化数据:
public class DateFormatter implements IAxisValueFormatter {
SimpleDateFormat formatter;
public DateFormatter(){
formatter = new SimpleDateFormat("dd/MM/yy, HH:mm");
}
@Override
public String getFormattedValue(float value, AxisBase axis) {
//This method is never called. Nothing is returned
if(axis instanceof XAxis) {
String formatted = formatter.format(new Date((long) value));
Log.d("Formatter", "Formatted \"" + value + "\" to \"" + formatted + "\".");
return formatted;
}
return "Not supported";
}
}
移除格式器并没有改变任何东西,轴仍然没有了。缩放仍然会破坏 Y 轴。
所以我的问题是:我该如何解决这个问题?当我以毫秒为单位传递当前时间时,我不明白为什么图表不起作用(我用调试输出检查了值,浮点数可以处理它)。我之前得到了一些调试输出,最终完全停止显示传递给格式化程序的值 < 2000。不过我不能再重现这个了
图表本身似乎没有损坏,但从触摸事件来看,似乎每个点都被推入相同的 X 坐标,但只有一个点呈现。当我触摸图表时,会出现橙色线条,指示数据点的位置。它会在不可见的点上弹出。
当我将 for 循环索引作为 X 值传递时,它按预期工作,格式化程序工作正常(撇开它显示 1970 年的日期这一事实,但它被计为 1 毫秒进入时代,所以这是期待)
我还查看了 this 关于格式化日期的内容。然后,当我尝试传递自纪元以来的毫秒数时,图表停止工作。
我正在使用 MPChart v 3.0.2,针对 Android 26 进行编译,使用 Java 8 和 运行 Android Studio 3.0 beta 2
布局方面,就是一个LinearLayout,里面有一个LineChart。
这应该可以工作,但是当我出于某种原因将当前时间(以毫秒为单位)传递给它时它会中断。传递任何其他数据(只要数字不是那么大)都可以正常工作。
这两张图片不是图表应有的样子。 X 轴应该是可见的,但由于某些原因它与大量数据不一致。
这是 Android MPChart
(have a read this thread) 的已知问题。 MPChart
中支持的时间序列图表 - 您可以将时间(在 millis
中)设置为每小时图表的 X 值。
但是太多的连续数据(点)将无法在折线图中正确绘制。因为 Entry
由于某些性能限制,对象将只接受浮点值。
所以,保留第一个值作为参考,并从参考值中减去每个即将出现的值,然后除以一些常数(比如 1000
)。所以,你X value
设置为 10,20,30....等等。
在 Axis Value formatter
中执行相反的逻辑以正确呈现 X Axis
标签(参见代码片段)。
lineChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss");
return format2.format(new Date(firstTimeStamp + ((long) value) * 1000L));
}
});
我已经尝试解决这个问题,但没有成功。数据未按应有的方式显示。
首先我生成虚拟数据。这是异步完成的,因为我需要在调用 System.currentTimeMillis
之间留出一些间隔。 (撇开这里糟糕的代码,这只是调试数据,不会出现在发行版中。考虑到 ANR,在主线程上使用 Thread.sleep 是个坏主意)
public class AsyncGeneration extends AsyncTask<String, String, String>{
public AsyncGeneration() {
super();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
@Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected String doInBackground(String... strings) {
while(root == null) {
try {
Thread.sleep(200);
}catch(InterruptedException e){}
}
List<Entry> rdata = new ArrayList<>();
for(int i = 1; i < 30; i++){
try{
Thread.sleep(200);
}catch(Exception e){
//IGNORE
}
float time = System.currentTimeMillis();
Log.e("GChart", "Timex: " + time);
Session s = new Session(r.nextInt(5000), time);//Replace time with the index in the for-loop and it works for some reason
rdata.add(new Entry(s.getXValue(), s.getYValue()));
Log.e("GChart", "Timey: " + s.getXValue());
}
final List<Entry> entries = rdata;
OverviewFragment.this.getActivity().runOnUiThread(() ->{
LineDataSet data = new LineDataSet(entries, "Distance");
data.setCircleColor(Color.parseColor("#FF0000"));
LineData lineData = new LineData(data);
tab1chart.setData(lineData);
tab1chart.invalidate(); // refresh
tab1chart.getXAxis().setValueFormatter(new DateFormatter());
tab1chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
tab1chart.getXAxis().setTextSize(10f);
tab1chart.getXAxis().setTextColor(Color.RED);
tab1chart.getXAxis().setDrawAxisLine(true);
tab1chart.getXAxis().setDrawGridLines(true);
tab1chart.getAxisLeft().setValueFormatter(new DistanceValueFormatter());
tab1chart.getAxisLeft().setDrawGridLines(true);
Log.v("Chart", "Chart data loaded and invalidated");//This prints
});
return null;
}
}
到目前为止一切看起来都很好。数据进入图表,没有异常,没有崩溃。
图表呈现时,单个数据点显示在图表的最左侧。我生成了 30 个数据点,其中一个出现了。
这是问题 #1:只显示一个数据点。
第 2 题稍微难一些。底部的整个 X 轴消失。 X 轴消失了,缩放时,Y 轴及其文本也消失了。这很难解释,所以这里是截图:
值得一提的事实是,如果我在 for 循环中传递 i
作为时间,它会按预期显示:所有轴都已就位,缩放不会破坏任何东西。
(浮点型值可以取与长整型值相同的值,除了它们还有小数点。)
此外,我格式化数据:
public class DateFormatter implements IAxisValueFormatter {
SimpleDateFormat formatter;
public DateFormatter(){
formatter = new SimpleDateFormat("dd/MM/yy, HH:mm");
}
@Override
public String getFormattedValue(float value, AxisBase axis) {
//This method is never called. Nothing is returned
if(axis instanceof XAxis) {
String formatted = formatter.format(new Date((long) value));
Log.d("Formatter", "Formatted \"" + value + "\" to \"" + formatted + "\".");
return formatted;
}
return "Not supported";
}
}
移除格式器并没有改变任何东西,轴仍然没有了。缩放仍然会破坏 Y 轴。
所以我的问题是:我该如何解决这个问题?当我以毫秒为单位传递当前时间时,我不明白为什么图表不起作用(我用调试输出检查了值,浮点数可以处理它)。我之前得到了一些调试输出,最终完全停止显示传递给格式化程序的值 < 2000。不过我不能再重现这个了
图表本身似乎没有损坏,但从触摸事件来看,似乎每个点都被推入相同的 X 坐标,但只有一个点呈现。当我触摸图表时,会出现橙色线条,指示数据点的位置。它会在不可见的点上弹出。
当我将 for 循环索引作为 X 值传递时,它按预期工作,格式化程序工作正常(撇开它显示 1970 年的日期这一事实,但它被计为 1 毫秒进入时代,所以这是期待)
我还查看了 this 关于格式化日期的内容。然后,当我尝试传递自纪元以来的毫秒数时,图表停止工作。
我正在使用 MPChart v 3.0.2,针对 Android 26 进行编译,使用 Java 8 和 运行 Android Studio 3.0 beta 2
布局方面,就是一个LinearLayout,里面有一个LineChart。
这应该可以工作,但是当我出于某种原因将当前时间(以毫秒为单位)传递给它时它会中断。传递任何其他数据(只要数字不是那么大)都可以正常工作。
这两张图片不是图表应有的样子。 X 轴应该是可见的,但由于某些原因它与大量数据不一致。
这是 Android MPChart
(have a read this thread) 的已知问题。 MPChart
中支持的时间序列图表 - 您可以将时间(在 millis
中)设置为每小时图表的 X 值。
但是太多的连续数据(点)将无法在折线图中正确绘制。因为 Entry
由于某些性能限制,对象将只接受浮点值。
所以,保留第一个值作为参考,并从参考值中减去每个即将出现的值,然后除以一些常数(比如 1000
)。所以,你X value
设置为 10,20,30....等等。
在 Axis Value formatter
中执行相反的逻辑以正确呈现 X Axis
标签(参见代码片段)。
lineChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss");
return format2.format(new Date(firstTimeStamp + ((long) value) * 1000L));
}
});