最近做比特币相关的行情展示,涉及到这个大量的double类型数据的处理。为了显示整齐好看,同时针对位数什么的进行限制,以及精度控制。顺带说下,这个曲线图用的是PhilJay/MPAndroidChart ,蛮强大的。如果是简单的其实自己也可以开发的,小白打算后面就自己搞一个demo学习下。
误区:一开始小萌新以为是控制精度(小数点后几位),然后进度控制完后如果位数不足就末尾补0. 然后就发现如果是0.0000233这些,如果你进行了进度过滤,那么将会得到0,很尴尬。 哈哈。。。
实际上只需要:
1. substring截取从0开始的几位数(比如七位)
2. 然后进行位数不足, 末尾补0的操作
3. 如果获取的double类型发现是0.232323233-E6这样色的,那么就不能直接做字符串截取,会得到0.23232 - 实际上是0.000000232....。 所以这种情况需要BigDecimal进行一个转换才行,然后再做截取
所以粘贴下下相关代码处理: formatNum方法小萌新做了改动。
import android.content.Context;
import java.math.BigDecimal;
import java.util.regex.Pattern;
/*
*@Description: 数字处理工具
*@Author: hl
*@Time: 2018/12/25 17:35
*/
public class NumberFormateTool {
/**
* <pre>
* 数字格式化显示
* 小于万默认显示 大于万以1.7万方式显示最大是9999.9万
* 大于亿以1.1亿方式显示最大没有限制都是亿单位
* </pre>
*
* @param num 格式化的数字
* @param kBool 是否格式化千,为true,并且num大于999就显示999+,小于等于999就正常显示
* @return
*/
public static String formatNum(Context context, String num, Boolean kBool) {
StringBuffer sb = new StringBuffer();
// if (!StringUtils.isNumeric(num))
// return "0";
if (kBool == null)
kBool = false;
BigDecimal b0 = new BigDecimal("1000");
BigDecimal b1 = new BigDecimal("10000");
BigDecimal b2 = new BigDecimal("100000000");
BigDecimal b3 = new BigDecimal(num);
String formatNumStr = "";
String nuit = "";
// 以千为单位处理
if (kBool) {
if (b3.compareTo(b0) == 0 || b3.compareTo(b0) == 1) {
return "999+";
}
return num;
}
// 以万为单位处理
if (b3.compareTo(b1) == -1) {
sb.append(b3.toString());
} else if ((b3.compareTo(b1) == 0 && b3.compareTo(b1) == 1)
|| b3.compareTo(b2) == -1) {
formatNumStr = b3.divide(b1).toString();
nuit = "万";
} else if (b3.compareTo(b2) == 0 || b3.compareTo(b2) == 1) {
formatNumStr = b3.divide(b2).toString();
nuit = "亿";
}
if (!"".equals(formatNumStr)) {
// int i = formatNumStr.indexOf(".");
// if (i == -1) {
// sb.append(formatNumStr).append(nuit);
// } else {
// i = i + 1;
// String v = formatNumStr.substring(i, i + 1);
// if (!v.equals("0")) {
// sb.append(formatNumStr.substring(0, i + 2)).append(nuit);
// } else {
// sb.append(formatNumStr.substring(0, i + 2)).append(nuit);
// }
// }
if (!formatNumStr.contains(".")) {
sb.append(formatNumStr).append(nuit);
} else {
sb.append(String.format("%.2f", Double.parseDouble(formatNumStr))).append(nuit);
}
}
if (sb.length() == 0)
return "0";
return sb.toString();
}
/**
* 数字流水号长度不够补0方法
* @param liuShuiHao
* @return
*/
public static String numLengthFomate(String liuShuiHao, int length) {
String zeroS = liuShuiHao;
for(int i = liuShuiHao.length(); i < length; ++i){
zeroS += "0";
}
return zeroS;
}
/**
* 截取7位显示
* @param liuShuiHao
* @return
*/
public static String numLengthFomate7(String liuShuiHao) {
String zeroS = liuShuiHao.substring(0, liuShuiHao.length() > 7 ? 7 : liuShuiHao.length());
return zeroS;
}
/*
* 是否为浮点数?double或float类型。
* @param str 传入的字符串。
* @return 是浮点数返回true,否则返回false。
*/
public static boolean isDoubleOrFloat(String str) {
Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
return pattern.matcher(str).matches();
}
}
处理部分Big处理->截取七位->末尾不足补0:
补充1 :关于这个万,亿的显示,主要是没考虑千的问题,所以小萌新做了修改,因为我不需要这个"999+”的做法,看你想怎么改了咯。如果是万以下的单位会直接返回该值,然后了, 我会进行这个截取处理:
**补充2 : **关于MPAndroidChart,我把我效果的部分代码配置贴以下:
init部分:
///< k线
//chart.setViewPortOffsets(0, 0, 0, 0);
chart.setBackgroundColor(Color.rgb(255, 255, 255));
// no description text
chart.getDescription().setEnabled(false);
//是否显示边界
chart.setDrawBorders(true);
chart.setBorderColor(Color.rgb(227, 227, 227));
//是否展示网格线
//chart.setDrawGridBackground(true);
// enable touch gestures
chart.setTouchEnabled(true);
// enable scaling and dragging
chart.setDragEnabled(true);
chart.setScaleEnabled(false);
// if disabled, scaling can be done on x- and y-axis separately
chart.setPinchZoom(false);
//chart.setDrawGridBackground(true);
//chart.setMaxHighlightDistance(300);
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
//xAxis.setDrawGridLines(false);
//xAxis.setDrawLabels(true);
// xAxis.setGranularity(1f);
//xAxis.setCenterAxisLabels(true);//设置标签居中
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return TimeUtils.longToDate((long) value * 1000, "HH:mm");
}
});
// YAxis y = chart.getAxisLeft();
// //y.setTypeface(tfLight);
// //y.setLabelCount(6, false);
// y.setTextColor(R.color.text_gray);
// y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
// y.setDrawGridLines(true);
// y.setAxisLineColor(Color.RED);
YAxis yAxis = chart.getAxisLeft();
yAxis.setAxisLineColor(Color.rgb(227, 227, 227));
yAxis.setZeroLineColor(Color.rgb(227, 227, 227));
yAxis.setGridColor(Color.rgb(227, 227, 227));
//yAxis.setDrawGridLines(true);
// yAxis.setValueFormatter(new IAxisValueFormatter() {
// @Override
// public String getFormattedValue(float value, AxisBase axis) {
// return "20%";
// }
// });
chart.getAxisRight().setEnabled(false);
chart.getLegend().setEnabled(false);
//setData(45, 100);
chart.animateXY(2000, 2000);
MyMarkerView mv = new MyMarkerView(context, R.layout.custom_marker_view);
mv.setChartView(chart);
chart.setMarker(mv);
///< 控制是否显示markerview
chart.setDrawMarkers(true);
// don't forget to refresh the drawing
//chart.invalidate();
数据填充更新部分:
setData(...)
/**
* 曲线图绘制边框和填充颜色
*/
private int edgeColor = Color.parseColor("#1b77f7");
private int fillColor = Color.parseColor("#428EFF");
/**
* 填充K线数据
*
* @param coincapPriceBeanList
*/
private void setData(List<MarketKValueDetailBean.CoincapPriceBean> coincapPriceBeanList) {
ArrayList<Entry> values = new ArrayList<>();
for (int i = 0; i < coincapPriceBeanList.size(); i++) {
Entry entry = new Entry((float) coincapPriceBeanList.get(i).getDate(), (float) coincapPriceBeanList.get(i).getPrice());
entry.setData(TimeUtils.longToDateBy1970(coincapPriceBeanList.get(i).getDate(), "yyyy-MM-dd HH:mm:ss"));
values.add(entry);
}
LineDataSet set1;
if (chart.getData() != null &&
chart.getData().getDataSetCount() > 0) {
set1 = (LineDataSet) chart.getData().getDataSetByIndex(0);
///< 控制高亮线颜色
set1.setHighLightColor(edgeColor);
///< 沿边颜色以
set1.setColor(edgeColor);
///< 填充颜色
set1.setFillColor(fillColor);
set1.setValues(values);
chart.getData().notifyDataChanged();
chart.notifyDataSetChanged();
chart.invalidate();
} else {
// create a dataset and give it a type
set1 = new LineDataSet(values, "DataSet all");
set1.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set1.setCubicIntensity(0.2f);
set1.setDrawFilled(true);
set1.setDrawCircles(false);
set1.setLineWidth(1.8f);
set1.setCircleRadius(4f);
set1.setCircleColor(Color.WHITE);
set1.setHighLightColor(edgeColor);
///< 控制高亮线显示
set1.setHighlightEnabled(true);
///< 沿边颜色以
set1.setColor(edgeColor);
///< 填充颜色
set1.setFillColor(fillColor);
set1.setFillAlpha(100);
set1.setDrawHorizontalHighlightIndicator(false);
// set1.setFillFormatter(new IFillFormatter() {
// @Override
// public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) {
// return chart.getAxisLeft().getAxisMinimum();
// }
// });
// create a data object with the data sets
LineData data = new LineData(set1);
//data.setValueTypeface(tfLight);
data.setValueTextSize(9f);
///< 拐点值是否显示
data.setDrawValues(false);
// set data
chart.setData(data);
chart.invalidate();
}
}
对应实体类粘贴下吧:
import java.util.List;
public class MarketKValueDetailBean {
/**
* intervalType : 4
* error_code : 0
* error_message : succ
* coincap_price : [{"volume_usd":0,"price_btc":1,"coin_label":"bitcoin","available_supply":1500517590,"date":1367174841,"price":135.3,"coin_name":"BTC","volume_coin":0}]
*/
private String intervalType;
private int error_code;
private String error_message;
private List<CoincapPriceBean> coincap_price;
private MarketKValueDetailBean(){}
public String getIntervalType() {
return intervalType;
}
public void setIntervalType(String intervalType) {
this.intervalType = intervalType;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
public String getError_message() {
return error_message;
}
public void setError_message(String error_message) {
this.error_message = error_message;
}
public List<CoincapPriceBean> getCoincap_price() {
return coincap_price;
}
public void setCoincap_price(List<CoincapPriceBean> coincap_price) {
this.coincap_price = coincap_price;
}
@NotProguard
public static class CoincapPriceBean {
/**
* volume_usd : 0
* price_btc : 1
* coin_label : bitcoin
* available_supply : 1500517590
* date : 1367174841
* price : 135.3
* coin_name : BTC
* volume_coin : 0
*/
private int volume_usd;
private int price_btc;
private String coin_label;
private long available_supply;
private long date;
private double price;
private String coin_name;
private int volume_coin;
private CoincapPriceBean(){}
public int getVolume_usd() {
return volume_usd;
}
public void setVolume_usd(int volume_usd) {
this.volume_usd = volume_usd;
}
public int getPrice_btc() {
return price_btc;
}
public void setPrice_btc(int price_btc) {
this.price_btc = price_btc;
}
public String getCoin_label() {
return coin_label;
}
public void setCoin_label(String coin_label) {
this.coin_label = coin_label;
}
public long getAvailable_supply() {
return available_supply;
}
public void setAvailable_supply(long available_supply) {
this.available_supply = available_supply;
}
public long getDate() {
return date;
}
public void setDate(int date) {
this.date = date;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getCoin_name() {
return coin_name;
}
public void setCoin_name(String coin_name) {
this.coin_name = coin_name;
}
public int getVolume_coin() {
return volume_coin;
}
public void setVolume_coin(int volume_coin) {
this.volume_coin = volume_coin;
}
}
}
还有个时间转换的工具
/**
* long时间转字符串
* @param lo
* @param pattern "yyyy-MM-dd HH:mm:ss"
* @return
*/
public static String longToDate(long lo, String pattern){
Date date = new Date(lo);
SimpleDateFormat sd = new SimpleDateFormat(pattern);
return sd.format(date);
}
/**
* long时间转字符串 - 从1970算起
* @param lo
* @param pattern "yyyy-MM-dd HH:mm:ss"
* @return
*/
public static String longToDateBy1970(long lo, String pattern){
Date date = new Date(lo * 1000L);
SimpleDateFormat sd = new SimpleDateFormat(pattern);
return sd.format(date);
}
基本上就可以了呀。过程中还是遇到很多问题,目前算是基本解决了都。。加油。。每次的不同接触总会有收获的....