<declare-styleable name="LineChartView"> <attr name="line_title_text" format="string" /> <attr name="line_start_point_x" format="integer" /> <attr name="line_start_point_y" format="integer" /> <attr name="line_delta_x" format="integer" /> <attr name="line_delta_y" format="integer" /> <attr name="line_conut_x" format="integer" /> <attr name="line_conut_y" format="integer" /> <attr name="line_padding_left" format="dimension" /> <attr name="line_padding_right" format="dimension" /> <attr name="line_text_size" format="dimension" /> </declare-styleable> import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.text.TextPaint; import android.util.AttributeSet; import android.view.View; import java.util.ArrayList; import java.util.List; /** * Created by hdz on 2017/1/12. */ public class LineChartView extends View { private String titleText="鍚堝悓璁″垝"; private int startPointX; private int startPointY; private int deltaX; //the delta between two x_value private int deltaY; private int countX; //the count of the x (for example a week is seven and a year is twelve) private int countY; private float paddingLeft; private float paddingRight; private float textSize; private Paint paint; private Paint linePaint; private TextPaint textPaint; private Path path; private List<Integer> dataList; public LineChartView(Context context) { this(context, null); } public LineChartView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LineChartView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs, defStyleAttr); init(); } private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LineChartView, defStyleAttr, 0); titleText = array.getString(R.styleable.LineChartView_line_title_text); startPointX = array.getInteger(R.styleable.LineChartView_line_start_point_x, 0); startPointY = array.getInteger(R.styleable.LineChartView_line_start_point_y, 0); deltaX = array.getInteger(R.styleable.LineChartView_line_delta_x, 0); deltaY = array.getInteger(R.styleable.LineChartView_line_delta_y, 0); countX = array.getInteger(R.styleable.LineChartView_line_conut_x, 0); countY = array.getInteger(R.styleable.LineChartView_line_conut_y, 0); // paddingLeft = array.getDimensionPixelSize(R.styleable.LineChartView_line_padding_left, 0); // paddingRight = array.getDimensionPixelSize(R.styleable.LineChartView_line_padding_right, 0); textSize = array.getDimensionPixelSize(R.styleable.LineChartView_line_text_size, 0); array.recycle(); } private void init() { paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeWidth(5); textPaint = new TextPaint(); textPaint.setAntiAlias(true); path = new Path(); linePaint = new Paint(); linePaint.setColor(0xff2665ac); linePaint.setAntiAlias(true); linePaint.setStyle(Paint.Style.STROKE); linePaint.setStrokeWidth(5); dataList = new ArrayList<Integer>(); dataList.add(56); dataList.add(76); dataList.add(89); dataList.add(36); dataList.add(90); dataList.add(19); dataList.add(80); dataList.add(80); } private void setList(List<Integer> dataList) { this.dataList = dataList; invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //get the padding int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingBottom = getPaddingBottom(); int paddingTop = getPaddingTop(); int height = getHeight(); int width = getWidth(); textPaint.setColor(0xff2665ac); textPaint.setTextSize(textSize); canvas.drawText(titleText, 0.5f * width - textPaint.measureText(titleText) * 0.5f, paddingTop + textPaint.getFontMetrics().bottom * 4, textPaint); //琛ㄦ牸鐨勮捣濮嬬偣 float startY = (textPaint.getFontMetrics().bottom * 4) * 2 + paddingTop; float startX = textSize * 2 + paddingLeft; float endY = height - textSize * 3 - paddingBottom; float endX = width - (textSize + paddingRight); //textSize * 2 杩欐绌洪棿鏄敤鏉ュ啓妯潗鏍囩殑 //height - startY - textSize * 3 - paddingBottom 鐢ㄤ簬鐢诲浘鐨勯珮搴? float chartHeight = endY - startY; float chartWidth = endX - startX; float deltaDistanceY = chartHeight / countY; float deltaDistanceX = chartWidth / countX; //鐢绘í绾? for (int i = 0; i <= countY; i++) { if (i == countY) { paint.setColor(0xff000000); } else { paint.setColor(0xffdddddd); } String numberY = ((countY - i) * deltaY) + ""; canvas.drawText(numberY, startX - (0.5f * textSize + textPaint.measureText(numberY)), startY + deltaDistanceY * i + textPaint.getFontMetrics().bottom * 2, textPaint); canvas.drawLine(startX, startY + i * deltaDistanceY, endX, startY + i * deltaDistanceY, paint); } //鐢荤珫绾? for (int i = 0; i <= countX; i++) { if (i == 0) { paint.setColor(0xff000000); } else { paint.setColor(0xffdddddd); } String numberX = "" + (startPointX + i * deltaX); canvas.drawLine(startX + i * deltaDistanceX, startY, startX + i * deltaDistanceX, endY, paint); canvas.drawText(numberX, startX + i * deltaDistanceX - textPaint.measureText(numberX) * 0.5f, endY + textPaint.getFontMetrics().bottom * 4 + 5, textPaint); } //鐢绘姌绾? path.moveTo(startX, endY - dataList.get(0) * 1.0f / deltaY * deltaDistanceY); for (int i = 0; i < dataList.size(); i++) { float cx = startX + i * deltaDistanceX; float cy = endY - dataList.get(i) * 1.0f / deltaY * deltaDistanceY; canvas.drawText(dataList.get(i) + "", cx - textPaint.measureText(dataList.get(i) + "") * 0.5f, cy - textPaint.getFontMetrics().bottom * 3, textPaint); paint.setColor(Color.RED); canvas.drawCircle(cx, cy, 15, paint); paint.setColor(Color.WHITE); canvas.drawCircle(cx, cy, 10, paint); paint.setColor(Color.RED); canvas.drawCircle(cx, cy, 5, paint); if (i == 0) { } else { path.lineTo(cx, cy); } } canvas.drawPath(path, linePaint); } } <com.hdz.widget.LineChartView android:layout_width="match_parent" android:padding="10dp" app:line_conut_x="7" app:line_conut_y="5" app:line_delta_x="1" app:line_delta_y="20" app:line_start_point_x="3" app:line_text_size="20sp" app:line_title_text="项目成本" />