Android 上自定義的複式折線圖(二)

騷劍客發表於2016-06-02

轉發請註明出處:http://blog.csdn.net/qq_30552993/article/details/51564048

Android 上自定義的複式折線圖(二)

Android 上自定義的複式折線圖(三)

寫這篇文章主要是對Android 上自定義的複式折線圖(一)進行了一些修改.因為在()中出現瞭如下問題:

1.沒有自適應螢幕大小,使得有時候LineView這個控制元件右邊會有多餘的

2.如果沒有資料的時候LineView就不會顯示Y軸的標籤;

修復後的功能:

1.表格中X軸預設有10個單位,如果沒有資料沒有10也是會顯示錶格(這裡的預設10是可以進行設定的)

2.表格中資料超過10個就會進行水平滾動

3.因為預設10個單位的表格的話這樣才可以實現自適應螢幕問題,不過這裡要傳一個這個控制元件的所佔寬度大小

4.同時也去掉之前(一)中的一些方法,就沒有說可以設計表格單位的大小等等一些方法

這裡就先不多說,先附上效果圖:

LineView.java

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import java.util.ArrayList;

@SuppressLint("DrawAllocation")
public class LineView extends View {

    private static final String TAG = "LineView";
    // 預設邊距
    private int Margin = 20;
    // 原點座標
    private int Xpoint;
    private int Ypoint;

    // X,Y軸的單位長度,即表格中的正方形的寬高
    private int Yscale;
    private int Xscale;

    //是否顯示錶格
    private boolean isShowGrid = false;
    //是否展示表格為虛線
    private boolean isDottedLine = false;

    // X最左邊跟Y左下面的線的顏色
    private int XYColor = Color.WHITE;
    // X軸字型的顏色
    private int XTextColor = Color.WHITE;
    // Y軸字型的顏色
    private int YTextColor = Color.WHITE;
    // 表格字型的顏色
    private int GridColor = Color.WHITE;
    // 資料字型的顏色
    private int DataColor = Color.WHITE;

    private int XTextSize = 8;
    private int YTextSize = 8;

    private int marginLeft = 0;
    private int marginBottom = 0;

    private Resources r = Resources.getSystem();

    // X軸上面的顯示文字
    private ArrayList<String> XLabel;
    // Y軸上面的顯示文字
    private ArrayList<String> YLabel;

    // 曲線資料
    private ArrayList<ArrayList<Integer>> dataLists;
    private ArrayList<Integer> dataColorList;

    // 單前資料
    private ArrayList<Integer> dataList;
    private int color;

    private int viewWidth;
    private int defXCount = 10;
    private int dataCount;

    public LineView(Context context) {
        super(context);
        initSize();
    }

    public LineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSize();
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (dataLists.size() > 0 && viewWidth > 0) {
            Xscale = (viewWidth - this.Margin * 2) / defXCount;
            Yscale = Xscale / 2;
            if (dataLists.get(0).size() <= defXCount) {
                dataCount = defXCount;
            } else {
                dataCount = dataLists.get(0).size();
            }
        }
        Log.e(TAG, "Xscale:" + Xscale + " ;Yscale:" + Yscale);
        setMeasuredDimension(Xscale * dataCount + this.Margin * 2 + marginLeft,
                Yscale * YLabel.size() + this.Margin + marginBottom);
    }

    private void initSize() {
        setXTextSize(XTextSize);
        setYTextSize(YTextSize);
        setMarginLeft(marginLeft);
        setMarginBottom(marginBottom);
        this.Margin = setDimensionDIP(Margin);
    }


    // 初始化資料值
    public void init() {
        Xpoint = this.Margin + marginLeft;
        Ypoint = this.getHeight() - this.Margin - marginBottom;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Paint p1 = new Paint();
        p1.setStyle(Paint.Style.STROKE);
        p1.setAntiAlias(true);
        p1.setColor(XYColor);
        p1.setStrokeWidth(2);
        init();
        if (isShowGrid) {
            this.drawTable(canvas);
        } else {
            this.drawXLine(canvas, p1);
            this.drawYLine(canvas, p1);
        }
        if (dataLists != null) {
            for (int i = 0; i < dataLists.size(); i++) {
                this.drawData(canvas, i);
            }
        }
    }

    // 畫表格
    private void drawTable(Canvas canvas) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(GridColor);
        Path path = new Path();
        if (isDottedLine) {
            PathEffect effects = new DashPathEffect(new float[]{5, 5, 5, 5}, 1);//畫虛線
            paint.setPathEffect(effects);
        }
        int startX = 0;
        int startY = 0;
        int stopX = 0;
        int stopY = 0;
        // 縱向線
        for (int i = 0; i <= dataCount; i++) {
            startX = Xpoint + i * Xscale;
            startY = Ypoint;
            stopY = Ypoint - (this.YLabel.size() - 1) * Yscale;
            if (i != 0) {
                path.moveTo(startX - Xscale / 2, startY);
                path.lineTo(startX - Xscale / 2, stopY);
                canvas.drawPath(path, paint);
            }
            path.moveTo(startX, startY);
            path.lineTo(startX, stopY);
            canvas.drawPath(path, paint);
        }

        // 橫向線
        for (int i = 0; i < YLabel.size(); i++) {
            startX = Xpoint;
            startY = Ypoint - i * Yscale;
            stopX = Xpoint + (dataCount) * Xscale;
            path.moveTo(startX, startY);
            path.lineTo(stopX, startY);
            paint.setColor(GridColor);
            canvas.drawPath(path, paint);
        }
        Log.e(TAG, "defXCount :" + defXCount);
    }

    //畫縱軸
    private void drawXLine(Canvas canvas, Paint p) {
        p.setColor(XYColor);
        float stopX = Xpoint;
        float stopY = Ypoint - Yscale * (YLabel.size() - 1);
        canvas.drawLine(Xpoint, Ypoint, stopX, stopY, p);
        // Y軸最後是否有箭頭
        canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY + Yscale / 3, p);
        canvas.drawLine(stopX, stopY, stopX + Xscale / 6, stopY + Yscale / 3, p);
    }

    // 畫橫軸
    private void drawYLine(Canvas canvas, Paint p) {
        p.setColor(XYColor);
        float stopX = Xpoint + Xscale * dataCount;
        float stopY = Ypoint;
        canvas.drawLine(Xpoint, Ypoint, stopX, stopY, p);
        // X軸最後是否有箭頭
        canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY - Yscale / 3, p);
        canvas.drawLine(stopX, stopY, stopX - Xscale / 6, stopY + Yscale / 3, p);
    }

    // 畫資料
    private void drawData(Canvas canvas, int pos) {
        dataList = dataLists.get(pos);
        color = dataColorList.get(pos);
        Paint p = new Paint();
        p.setAntiAlias(true);

        // 縱軸資料
        for (int i = 0; i < YLabel.size(); i++) {
            int startY = Ypoint - i * Yscale;
            p.setColor(YTextColor);
            p.setTextSize(XTextSize);
            p.setTextAlign(Paint.Align.RIGHT);
            canvas.drawText(this.YLabel.get(i), this.Margin / 4 * 3 + marginLeft,
                    startY + this.Margin / 4, p);
        }

        //橫軸資料
        for (int i = 0; i < dataCount; i++) {
            int startX = Xpoint + i * Xscale;
            p.setColor(XTextColor);
            p.setTextSize(YTextSize);
            p.setTextAlign(Paint.Align.CENTER);
            String text = "";
            if (i < XLabel.size()) {
                text = this.XLabel.get(i);
            }
            canvas.drawText(text, startX + Xscale / 2,
                    this.getHeight() - this.Margin / 2 - marginBottom, p);
            p.setColor(dataColorList.size() > 0 ? color : DataColor);
            if (i < XLabel.size()) {
                canvas.drawCircle(startX + Xscale / 2, calY(dataList.get(i)), 4, p);
            }
            if (i < XLabel.size() - 1) {
                canvas.drawLine(startX + Xscale / 2, calY(dataList.get(i)),
                        Xpoint + (i + 1) * Xscale + Xscale / 2, 
                        calY(dataList.get(i + 1)), p);
            }
        }
    }

    /**
     * @param y
     * @return
     */
    private int calY(int y) {
        int y0 = 0;
        int y1 = 0;
        //	Log.i("zzzz", "y:"+y);
        try {
            y0 = Integer.parseInt(YLabel.get(0));
            //		Log.i("zzzz", "y0"+y0);
            y1 = Integer.parseInt(YLabel.get(1));
            //		Log.i("zzzz","y1"+y1);
        } catch (Exception e) {
            //		Log.i("zzzz", "string changed is err");
            return 0;
        }
        try {
            //		Log.i("zzzz", "返回資料"+(Ypoint-(y-y0)*Yscale/(y1-y0)) );
            return Ypoint - ((y - y0) * Yscale / (y1 - y0));
        } catch (Exception e) {
            //	Log.i("zzzz", "return is err");
            return 0;
        }
    }

    public void setXYColor(int XYColor) {
        this.XYColor = XYColor;
    }

    public void setXTextColor(int XTextColor) {
        this.XTextColor = XTextColor;
    }

    public void setYTextColor(int YTextColor) {
        this.YTextColor = YTextColor;
    }

    public void setGridColor(int gridColor) {
        this.GridColor = gridColor;
    }

    public void setDataColor(int dataColor) {
        this.DataColor = dataColor;
    }

    public void setDataColorList(ArrayList<Integer> dataColorList) {
        this.dataColorList = dataColorList;
    }

    public void setXTextSize(int XTextSize) {
        this.XTextSize = setDimensionSP(XTextSize);
    }

    public void setYTextSize(int YTextSize) {
        this.YTextSize = setDimensionSP(YTextSize);
    }

    public void setMarginLeft(int marginLeft) {
        this.marginLeft = setDimensionDIP(marginLeft);
    }

    public void setMarginBottom(int marginBottom) {
        this.marginBottom = setDimensionDIP(marginBottom);
    }

    public void setDefXCount(int defXCount) {
        this.defXCount = defXCount;
    }

    public void setShowGrid(boolean isShowGrid) {
        this.isShowGrid = isShowGrid;
    }

    public void setDottedLine(boolean isDottedLine) {
        this.isDottedLine = isDottedLine;
    }

    public void setXYLabel(ArrayList<String> xlabel, ArrayList<String> ylabel, 
                           int viewWidth) {
        this.XLabel = xlabel;
        this.YLabel = ylabel;
        this.viewWidth = viewWidth;
    }

    public void setDataList(ArrayList<ArrayList<Integer>> dataLists) {
        this.dataLists = dataLists;
        postInvalidate();
    }

    private int setDimensionDIP(int size) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, 
                                                 r.getDisplayMetrics());
    }

    private int setDimensionSP(int size) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, 
                                                 r.getDisplayMetrics());
    }
}

這裡先來一個列子,說明怎麼使用LineView

MainActivity.java

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import java.util.ArrayList;


public class MainActivity extends Activity {

    private LinearLayout mLineLL;
    private LineView mSkinLineView;

    private ArrayList<Integer> colorList = new ArrayList<>();//折線的顏色列表
    private ArrayList<String> XLabel = new ArrayList<>(); //X軸上的標籤資料列表
    private ArrayList<String> YLabel = new ArrayList<>(); //Y軸上的標籤資料列表
    private ArrayList<ArrayList<Integer>> dataLists;//折線上的資料列表
    private int width;
    private int height;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        colorList.add(getResources().getColor(R.color.using_before));
        colorList.add(getResources().getColor(R.color.using_after));
        for (int i = 0; i < 0; i++) {
            XLabel.add(String.valueOf(i));
        }
        for (int i = 0; i < 11; i++) {
            YLabel.add(String.valueOf(i * 10));
        }

        mLineLL = (LinearLayout) findViewById(R.id.LineLL);
        mSkinLineView = (LineView) findViewById(R.id.skinLineView);
        mSkinLineView.setDataColorList(colorList);
        mSkinLineView.setXYLabel(XLabel, YLabel, getLineViewWidth());
        mSkinLineView.setShowGrid(true);
        mSkinLineView.setDottedLine(true);
        mSkinLineView.setGridColor(Color.LTGRAY);
        randSet(mSkinLineView);

        findViewById(R.id.resetBtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                randSet(mSkinLineView);
            }
        });
    }

    private void randSet(LineView lineView) {
        ArrayList<ArrayList<Integer>> dataLists = new ArrayList<>();

        ArrayList<Integer> dataList1 = new ArrayList<Integer>();
        int random1 = (int) (Math.random() * 99 + 1);
        for (int i = 0; i < XLabel.size(); i++) {
            dataList1.add((int) (Math.random() * random1));
        }

        ArrayList<Integer> dataList2 = new ArrayList<Integer>();
        int random2 = (int) (Math.random() * 99 + 1);
        for (int i = 0; i < XLabel.size(); i++) {
            dataList2.add((int) (Math.random() * random2));
        }
        dataLists.add(dataList1);
        dataLists.add(dataList2);
        lineView.setDataList(dataLists);
    }

    private int getLineViewWidth() {
        width = getWindowManager().getDefaultDisplay().getWidth();
        height = getWindowManager().getDefaultDisplay().getHeight();
        FrameLayout.LayoutParams params 
                          = (FrameLayout.LayoutParams) mLineLL.getLayoutParams();
        int LineViewWidth = width - params.leftMargin - params.rightMargin;
        return LineViewWidth;
    }
}

佈局檔案activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0099FF"
    android:id="@+id/LineLL"
    android:orientation="vertical">

    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <sl.myapplication.LineView
                android:id="@+id/skinLineView"
                android:layout_width="match_parent"
                android:layout_height="200dip" />
        </LinearLayout>
    </HorizontalScrollView>

    <Button
        android:id="@+id/resetBtn"
        android:text="重新整理"
        android:textColor="@color/white"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

相關文章