編輯:關於Android編程
前幾天突然需要做兩種圖表——柱形圖、折線圖,於是第一反應是先看看網上有沒有現成的,結果有是有,但都不是我想要的,而且大多數不是用純android代碼完成,HTML5似乎完成這類工作要容易得多,但是我本人並不會HTML5,只能黯然神傷,掩面流淚,最終只能自己敲代碼了。
**知識點:**android自定義view、圖形圖像、Fragment、MVC模式。
折線圖:
代碼,注釋很詳細,直接看代碼就行了:
public class LineChartView extends View {
private int width;
private int height;
private float maxValue;//傳入數據的最大值
private int dataNum;//數據總數
private Paint mPaintBg;//報表背景畫筆
private Paint mPaintCoveredBg;//用於畫數據覆蓋部分
private Paint mPaintChartLine;//用於畫報表的網格
private Paint mPaintDataLine;//用於畫數據連線
private Paint mPaintTextDate;//用於畫日期文本
private Paint mPaintCircle;//用於畫空心圓
private Paint mPaintFilledCircle;//用於畫實心圓
private Paint mPaintTextValue;//用於畫數據訪問量值
private Path path;
private HashMap dataTotal;//用於得存儲傳入的總數據
//用一個setPaints()方法,設定所有畫筆的屬性,增加代碼靈活性
public void setPaints(int bgColor, int coveredBgColor, int chartLineColor
, int dataLineColor, int textDateColor, int filledCircleColor, int circleColor, int textValueColor) {
mPaintBg.setColor(bgColor);
mPaintBg.setStyle(Paint.Style.FILL);
mPaintCoveredBg.setColor(coveredBgColor);
mPaintCoveredBg.setStyle(Paint.Style.FILL);
mPaintCircle.setColor(circleColor);
mPaintCircle.setStyle(Paint.Style.STROKE);
mPaintCircle.setStrokeWidth(5);
mPaintCircle.setAntiAlias(true);
mPaintFilledCircle.setColor(filledCircleColor);
mPaintFilledCircle.setStyle(Paint.Style.FILL);
mPaintFilledCircle.setAntiAlias(true);
mPaintChartLine.setColor(chartLineColor);
mPaintChartLine.setStyle(Paint.Style.STROKE);
mPaintChartLine.setAntiAlias(true);
mPaintDataLine.setColor(dataLineColor);
mPaintDataLine.setStyle(Paint.Style.STROKE);
mPaintDataLine.setStrokeWidth(SizeConvert.dip2px(getContext(), 5));
mPaintDataLine.setAntiAlias(true);
mPaintTextDate.setColor(textDateColor);
mPaintTextDate.setTextSize(SizeConvert.dip2px(getContext(), 10));
mPaintTextDate.setTextAlign(Paint.Align.CENTER);
mPaintTextDate.setAntiAlias(true);
mPaintTextValue.setColor(textValueColor);
mPaintTextValue.setTextSize(SizeConvert.dip2px(getContext(), 12));
mPaintTextValue.setTextAlign(Paint.Align.CENTER);
mPaintTextValue.setAntiAlias(true);
//重繪
invalidate();
}
//用於設定傳入的總數據
public void setDataTotal(HashMap dataTotal) {
this.dataTotal = dataTotal;
invalidate();
}
public LineChartView(Context context) {
super(context);
}
public LineChartView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintBg = new Paint();
mPaintCoveredBg = new Paint();
mPaintCircle = new Paint();
mPaintChartLine = new Paint();
mPaintDataLine = new Paint();
mPaintTextDate = new Paint();
mPaintTextValue = new Paint();
mPaintFilledCircle = new Paint();
path = new Path();
dataTotal = new HashMap<>();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//當總數據已經傳入,即不為空時,根據總數據中數據個數設定view的總寬
if (dataTotal != null) {
width = (dataTotal.size() - 1) * xAddedNum + chartMarginHorizontal * 2;
getMaxValue(dataTotal);
}
height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
}
/**
* 用於得到總數據中最大數據
* @param dataTotal 總數據
*/
private void getMaxValue(HashMap dataTotal) {
maxValue = 0;
dataNum = 0;
for (int key : dataTotal.keySet()) {
if (dataTotal.get(key).getPageViewValue() > maxValue) {
maxValue = dataTotal.get(key).getPageViewValue();
}
dataNum++;
}
}
private int mChartHeight;//折線圖的高
private int mChartWidth;//折線圖的
private int startX = SizeConvert.dip2px(getContext(), 10);//開始繪制的x坐標
private int startY = SizeConvert.dip2px(getContext(), 5);//開始繪制的y坐標
private int chartMarginBottom = SizeConvert.dip2px(getContext(), 30);//折線圖距離父控件底部距離
private int chartMarginHorizontal = SizeConvert.dip2px(getContext(), 12);//折線圖距離父控件左右的距離
private int valueAlignLeft = SizeConvert.dip2px(getContext(), 0);//value參數文本距離左邊距離
private int dateAlignLeft = SizeConvert.dip2px(getContext(), 0);//date參數文本距離左邊距離
private int valueAlignBottom = SizeConvert.dip2px(getContext(), 5);//value參數文本距離底部距離
private int dateAlignBottom = SizeConvert.dip2px(getContext(), 10);//date參數文本距離底部距離
private int xAddedNum = SizeConvert.dip2px(getContext(), 60);//繪制折線圖時每次移動的x軸距離
private int yAddedNum;//繪制折線圖時每次移動的y軸距離
private boolean isDrawFirst;//是否是第一次繪制
private float circleFilledRadius = SizeConvert.dip2px(getContext(), 5);//外圓半徑
private float circleRadius = SizeConvert.dip2px(getContext(), 3);//內圓半徑
private float firstX;//第一個點的x軸坐標
private float firstY;//第一個點的y軸坐標
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
isDrawFirst = true;
mChartHeight = height - chartMarginBottom;
yAddedNum = mChartHeight / 4;
mChartWidth = width - chartMarginHorizontal * 2;
canvas.drawRect(startX, startY, startX + mChartWidth, startY + mChartHeight, mPaintBg);
for (int key : dataTotal.keySet()) {
float value = dataTotal.get(key).getPageViewValue();
if (isDrawFirst) {
//當第一次繪制時得到第一個點的橫縱坐標
firstX = startX;
firstY = startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight;
path.moveTo(firstX, firstY);
isDrawFirst = false;
}
//每循環一次,將path線性相位一次
path.lineTo(startX, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight);
startX += xAddedNum;
}
//重新給startX賦值
startX = SizeConvert.dip2px(getContext(), 10);
//畫出折線
canvas.drawPath(path, mPaintDataLine);
//畫出折線以下部分的顏色
path.lineTo(startX + mChartWidth, startY + mChartHeight);
path.lineTo(startX, startY + mChartHeight);
path.lineTo(firstX, firstY);
canvas.drawPath(path, mPaintCoveredBg);
//畫出每個點的圓圈,和對應的文本
for (int key : dataTotal.keySet()) {
int date = dataTotal.get(key).getDate();
float value = dataTotal.get(key).getPageViewValue();
canvas.drawCircle(startX, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight, circleFilledRadius, mPaintFilledCircle);
canvas.drawCircle(startX, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight, circleRadius, mPaintCircle);
canvas.drawText(date + , startX + dateAlignLeft, height - dateAlignBottom, mPaintTextDate);
canvas.drawText(value + , startX + valueAlignLeft, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight - valueAlignBottom, mPaintTextValue);
startX += xAddedNum;
}
//在次使startX回到初始值
startX = SizeConvert.dip2px(getContext(), 10);
/**
* 畫出網格
*/
//豎線
for (int i = 0; i < dataNum; i++) {
canvas.drawLine(startX + i * xAddedNum, startY, startX + i * xAddedNum, startY + mChartHeight, mPaintChartLine);
}
//橫線
for (int i = 0; i < 5; i++) {
canvas.drawLine(startX, startY + i * yAddedNum, startX + mChartWidth, startY + i * yAddedNum, mPaintChartLine);
}
path.reset();
}
}
柱形圖:
代碼:<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
Fragment 主活動: activity_main: content_chart:/**
* 柱形圖
*/
public class HistogramView extends View {
private int width;
private int height;
private Paint mBgPaint;
private Paint mHistogramBgPaint;
private Paint mHistogramPaint;
private Paint mTextPaint;
private HashMap
public class FragmentChart extends Fragment implements View.OnClickListener{
private RelativeLayout mItemFirst;
private RelativeLayout mItemSecond;
private RelativeLayout mItemThird;
private RelativeLayout mItemForth;
private HistogramView mHistogramView;
private HashMap
public class MainActivity extends FragmentActivity {
private FragmentChart mFragmentChart;
private RadioGroup mRadioGroup;
private FragmentTransaction transaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFragmentChart = new FragmentChart();
mFragmentManager = getSupportFragmentManager();
transaction = mFragmentManager.beginTransaction();
transaction.add(R.id.frame_layout, mFragmentChart);
transaction.commit();
mRadioGroup = (RadioGroup) findViewById(R.id.radiogroup);
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.button1:
transaction = mFragmentManager.beginTransaction();
transaction.hide(mFragmentChat);
transaction.hide(mFragmentSetting);
transaction.hide(mFragmentWork);
transaction.show(mFragmentChart);
transaction.commit();
break;
}
}
});
}
}
前沿:在全新的Camera API2架構下,常常會有人疑問再也看不到熟悉的SetParameter/Paramters等相關的身影,取而代之的是一
本文講述了Android模擬器中安裝apk的方法。分享給大家供大家參考,具體如下:第一步:在Eclipse中啟動模擬器。第二步:打開doc命名窗口,轉到你android
繪制曲線類:public class BaseFundChartView extends View { Paint linePaint; Paint text
項目開啟的Activity越多,占的內存越多,我們是不是有時候想當我打開很多界面的時候,我們到底打開多少個Activity,OK現在你的難題解決了,只有把這個Activi