1. 程式人生 > >折線圖(五)根據實際情況值,繪製在折線圖座標軸對應位置上

折線圖(五)根據實際情況值,繪製在折線圖座標軸對應位置上

實現思路,先計算儲存這些實際值,然實際值對應的座標軸上的真正位置,從而繪製繪製出來。主要程式碼如下

/**
 * 繪製所有實際值座標
 * @param canvas
*/
public void drawPoints(Canvas canvas)
{
    if(pointQueue.isEmpty())
        return;
//首先計算取1xValue多少px
float  unitXValue_px = xUnit / xValue;
Paint paint = new Paint();//畫點的畫筆
paint.setColor(Color.GREEN);//設定點為綠色
paint.setStrokeWidth(30
);//設定畫筆為30粗度 //遍歷每一個點繪製出來,並移除在佇列中位置 while (!pointQueue.isEmpty()) { LineChartPoint point = pointQueue.poll(); //算出這點x, y座標 float x = point.xValue * unitXValue_px+chardPading; float y = getMeasuredHeight() - chardPading - point.yValue * unitXValue_px; canvas.drawPoint(x, y , paint);
//繪製點 } } /** * 新增折線圖座標軸點座標 * @param points */ public void setLineChartPoint(LineChartPoint ...points) { if(null == points || points.length < 1) return; for(LineChartPoint point : points) { pointQueue.add(point); } invalidate();//通知view重新繪製介面,也就是view會重新呼叫onDraw方法 }

全部程式碼:

public class MainActivity extends AppCompatActivity {

    private LineChartView lineChartView;
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lineChartView = (LineChartView) findViewById(R.id.lineChartView);
//甲公司第20天盈利 100萬
LineChartView.LineChartPoint point = new LineChartView.LineChartPoint();
point.setxValue(20);
point.setyValue(100);
//乙公司第60天盈利 20萬
LineChartView.LineChartPoint point1 = new LineChartView.LineChartPoint();
point1.setxValue(60);
point1.setyValue(20);
lineChartView.setLineChartPoint(point, point1);
}



}

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="LineChartView">
<!-- 檢視padding -->
<attr name="chartPadding" format="dimension"></attr>
<!-- x軸單位 長度-->
<attr name="xUnit" format="dimension"></attr>
<!-- x軸單位值-->
<attr name="xValue" format="integer"></attr>
<!-- x軸單位字型大小-->
<attr name="unitTextSize" format="dimension"></attr>
<!-- x軸單位名稱-->
<attr name="xName" format="string"></attr>
<!-- x軸單位 長度-->
<attr name="yUnit" format="dimension"></attr>
<!-- x軸單位值-->
<attr name="yValue" format="integer"></attr>
<!-- x軸單位名稱-->
<attr name="yName" format="string"></attr>
    </declare-styleable>
</resources>

/**
 * 繪製折線圖詳情
 */
public class LineChartView extends View

{


    /**
     * 折線圖padding
     */
private float chardPading;
/**
     * x單位長度
     */
private float xUnit;
/**
     * y單位長度
     */
private float yUnit;
    private float textSize;
/**
     * 單位名字
     */
private String xName;
/**
     * 單位值
     */
private int xValue;
    private String yName;
    private int yValue;
    public LineChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
//獲取提供的chardPading長度, 如果不提供,預設為100px. 注意,拿到的dip單位最終會轉化為px
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LineChartView);
chardPading = typedArray.getDimension(R.styleable.LineChartView_chartPadding, 100);//預設檢視距離邊界的長度
xUnit = typedArray.getDimension(R.styleable.LineChartView_xUnit, 50);//預設單位長度為50px
xName = typedArray.getString(R.styleable.LineChartView_xName);//x 軸 名字
xName = null != xName ? xName : "x";//如果不提供名字,則預設為x
xValue = typedArray.getInt(R.styleable.LineChartView_xValue, 10);//預設單位值為10
textSize = typedArray.getDimension(R.styleable.LineChartView_unitTextSize, 25);//預設25px字型大小
yUnit =  typedArray.getDimension(R.styleable.LineChartView_yUnit, xUnit);//預設單位值為與xUnit一樣
yName = typedArray.getString(R.styleable.LineChartView_yName);//y 軸 名字
yName = null != yName ? yName : "y";//如果不提供名字,則預設為y
yValue = typedArray.getInt(R.styleable.LineChartView_yValue, xValue);//預設單位值與xValue一樣
}


    @Override
protected void onDraw(Canvas canvas) {
        //繪製座標軸
drawAxis(canvas);
//繪製x座標軸詳情
drawX_AxisState(canvas);
drawY_AxisState(canvas);
drawPoints(canvas);
}

    /**
     * 為了不遮住座標軸,給予100padding給它
     */
int arrowPadding = 40;
/**
     * 繪製x軸名稱,按提供的長度來標識長度值
     *
     * @param canvas
*/
private void drawX_AxisState(Canvas canvas) {
        Paint paint = new Paint(); //直線畫筆
paint.setColor(Color.BLACK);//設定畫筆為黑色
paint.setStrokeWidth(2);//設定畫筆尖大小為2px
int height = getMeasuredHeight() - (int) chardPading;
        int drawXlengh = getMeasuredWidth() - (int) chardPading * 2 - arrowPadding;//保留能看到箭頭
int xUnit = (int) this.xUnit;
Rect nRect = new Rect();
Paint xValuePaint = new Paint(); //畫筆
xValuePaint.setColor(Color.BLACK);
xValuePaint.setTextSize(textSize);
xValuePaint.getTextBounds(xName, 0, xName.length(), nRect);
        int nWith = nRect.width();//獲取x軸名字長度
int nHeight = nRect.height();//獲取x軸名字高度
canvas.drawText(xName, getMeasuredWidth() - chardPading - nWith / 2, height + nHeight + 15, xValuePaint);
        for (int i = xUnit, j = 1; i < drawXlengh; i += xUnit, j++) {
            canvas.drawLine(chardPading + i, height, chardPading + i, height - 15, paint);
            int drawvalue = xValue * j;
Rect rect = new Rect();
xValuePaint.getTextBounds(drawvalue + "", 0, (drawvalue + "").length(), rect);
            int txtWith = rect.width();
            int txtHeght = rect.height();
canvas.drawText(drawvalue + "", chardPading + i - txtWith / 2, height + txtHeght + 15, xValuePaint);
}
    }


    /**
     * 繪製y軸名稱,按提供的長度來標識長度值
     *
     * @param canvas
*/
private void drawY_AxisState(Canvas canvas) {
        Paint paint = new Paint(); //直線畫筆
Paint yValuePaint = new Paint(); //畫筆
yValuePaint.setColor(Color.BLACK);
yValuePaint.setTextSize(textSize);
paint.setColor(Color.BLACK);//設定畫筆為黑色
paint.setStrokeWidth(2);//設定畫筆尖大小為2px
int height = getMeasuredHeight() - (int) chardPading;
        int drawYlengh = getMeasuredHeight() - (int) chardPading * 2 - arrowPadding;//保留能看到箭頭
int yUnit = (int) this.yUnit;
Rect nRect = new Rect();
yValuePaint.getTextBounds(yName, 0, yName.length(), nRect);
        int nWith = nRect.width();
        int nHeight = nRect.height();
canvas.drawText(yName, chardPading - nWith - 15, chardPading + nHeight / 2, yValuePaint);
        for (int i = yUnit, j = 1; i < drawYlengh; i += yUnit, j++) {
            int drawvalue = yValue * j;
Rect rect = new Rect();
yValuePaint.getTextBounds(drawvalue + "", 0, (drawvalue + "").length(), rect);
            int txtWith = rect.width();
            int txtHeght = rect.height();
canvas.drawLine(chardPading, height - i, chardPading + 15, height - i, paint);
canvas.drawText(drawvalue + "", chardPading - txtWith - 15, height - i + txtHeght / 2, yValuePaint);
}
    }

    /**
     * 為了浪費資源控制元件,一次性用的東西,我們採取使用佇列來快取這些點
     */
private Queue<LineChartPoint> pointQueue = new LinkedList<LineChartPoint>();
/**
     * 繪製所有實際值座標
     * @param canvas
*/
public void drawPoints(Canvas canvas)
    {
        if(pointQueue.isEmpty())
            return;
//首先計算取1xValue多少px
float  unitXValue_px = xUnit / xValue;
Paint paint = new Paint();//畫點的畫筆
paint.setColor(Color.GREEN);//設定點為綠色
paint.setStrokeWidth(30);//設定畫筆為30粗度
        //遍歷每一個點繪製出來,並移除在佇列中位置
while (!pointQueue.isEmpty())
        {
            LineChartPoint point = pointQueue.poll();
//算出這點x, y座標
float  x = point.xValue * unitXValue_px+chardPading;
            float  y = getMeasuredHeight() - chardPading - point.yValue * unitXValue_px;
canvas.drawPoint(x, y , paint);//繪製點
}
    }

    /**
     * 新增折線圖座標軸點座標
     * @param points
*/
public void setLineChartPoint(LineChartPoint ...points) {
        if (null == points || points.length < 1)
            return;
        for (LineChartPoint point : points) {
            pointQueue.add(point);
}
        invalidate();//通知view重新繪製介面,也就是view會重新呼叫onDraw方法
}

    /**
     * 折線座標點
     */
public static class LineChartPoint
    {
        private float xValue;
       private  float yValue;
        public float getxValue() {
            return xValue;
}

        public void setxValue(float xValue) {
            this.xValue = xValue;
}

        public float getyValue() {
            return yValue;
}

        public void setyValue(float yValue) {
            this.yValue = yValue;
}
    }

    /**
     * 繪製座標軸, 並且設定100padding給LineChartView
     *
     * @param canvas
*/
private void drawAxis(Canvas canvas) {
        int chartViewHeight = getMeasuredHeight(); //獲取LineChartView高度
int charViewWidth = getMeasuredWidth(); //獲取LineChartView寬度
Paint paint = new Paint(); //畫筆
paint.setColor(Color.BLACK);//設定畫筆為黑色
paint.setStrokeWidth(4);//設定畫筆尖大小為4px
        /*
        * 繪製直線.在2點之間連線
        * startX 起點的x座標
        * startY 起點的y座標
        * endX 終點的x座標
        * endY 終點的y座標
        * canvas.drawLine(startX, startY, endX, endY)
        */
        //繪製直線paddingTop 了chardPading的y軸
canvas.drawLine(chardPading, chartViewHeight - chardPading, chardPading, chardPading, paint);
//繪製y軸左邊半邊箭頭
canvas.drawLine(chardPading, chardPading, chardPading - 10, chardPading + 10, paint);
//繪製y軸右邊半邊箭頭
canvas.drawLine(chardPading, chardPading, chardPading + 10, chardPading + 10, paint);
//繪製直線paddingLeft 了chardPading的x軸,
canvas.drawLine(chardPading, chartViewHeight - chardPading, charViewWidth - chardPading, chartViewHeight - chardPading, paint);
//繪製x軸上半部分箭頭
canvas.drawLine(charViewWidth - chardPading, chartViewHeight - chardPading, charViewWidth - chardPading - 10, chartViewHeight - chardPading - 10, paint);
//繪製x軸下半部分箭頭
canvas.drawLine(charViewWidth - chardPading, chartViewHeight - chardPading, charViewWidth - chardPading - 10, chartViewHeight - chardPading + 10, paint);
}


}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
    <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="折線圖(五)各公司N天盈利N元"
android:layout_centerHorizontal="true"
/>
    <sam.android.utils.widget.LineChartView
android:id="@+id/lineChartView"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:chartPadding="30dp"
app:xValue="10"
app:xUnit="30dp"
app:xName="萬元"
app:unitTextSize="12sp"
app:yValue="10"
app:yUnit="30dp"
app:yName="天數"
/>
</RelativeLayout>


未更新完,待更新6...........