自定义View之一(垂直柱状图)
第一次写博客,想想心里还有点小激动呢...
代码注释很少,但实现很简单,大家看看就明白了
自己项目里抠出来的代码,希望能起到抛砖引玉的效果,如果有更好的实现,请不吝赐教
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
首先在attrs.xml中声明自定义view的属性:
<declare-styleable name="ChartBaseView"> <attr name="icon" format="reference" /> <attr name="background" format="reference|color" /> </declare-styleable>
定义自定义图表基类(因为我定义的不止这一种图表,所以才定义了一个基类):
public class ChartBaseView extends View { private static final String TAG = "ChartBaseView"; protected Bitmap mIcon; private Paint mPaint; private int mBackgroundColor; protected int mViewHeight; protected int mViewWidth; protected static final float PERCENT_TO_DRAW_TEXT = 0.45f;//view中画文本的区域大小占的百分比 protected String mDataValue;//数据值 protected String mDataUnit;//数据的单位 protected String mDataType;//是哪种类型的图表 private static final int TEXT_SIZE_VALUE = 22; private static final int TEXT_SIZE_UNIT = 18; private static final int TEXT_SIZE_TYPE = 14; private static final int TEXT_SPACE_VERTICAL = 5; private Rect mTextRect; public void setDataProperty(String value, String unit, String type){ if(value == null || unit == null || type == null){ Log.e(TAG, "propery null"); return; } mDataValue = value; mDataUnit = unit; mDataType = type; } public void setDataValue(String value){ mDataValue = value; } public void setDataUnit(String unit){ mDataUnit = unit; } public void setDataType(String type){ mDataType = type; } public ChartBaseView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } public ChartBaseView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } protected void init(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ChartBaseView); int drawableId = typedArray.getResourceId(R.styleable.ChartBaseView_icon, R.drawable.ic_launcher); Log.e(TAG, "drawableId=" + drawableId + ", defaultId=" + R.drawable.ic_launcher); mIcon = BitmapFactory.decodeResource(getResources(), drawableId); mBackgroundColor = typedArray.getColor(R.styleable.ChartBaseView_background, android.R.color.white); typedArray.recycle(); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextRect = new Rect(); } public ChartBaseView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(mBackgroundColor); canvas.drawBitmap(mIcon, 20, 20, mPaint); mViewHeight = getMeasuredHeight(); mViewWidth = getMeasuredWidth(); //画文本 float textWidth = 0; float textHeight = 0; mPaint.setTextSize(TEXT_SIZE_TYPE); float textBase = mViewHeight * PERCENT_TO_DRAW_TEXT - TEXT_SPACE_VERTICAL; if(mDataType != null){ mPaint.getTextBounds(mDataType, 0, mDataType.length(), mTextRect); textWidth = mTextRect.width(); textHeight = mTextRect.height(); canvas.drawText(mDataType, mViewWidth - textWidth, textBase , mPaint); textBase -= TEXT_SPACE_VERTICAL + textHeight; } if(mDataUnit != null){ mPaint.setTextSize(TEXT_SIZE_UNIT); textWidth = mPaint.measureText(mDataUnit); canvas.drawText(mDataUnit, mViewWidth - textWidth, textBase , mPaint); } if(mDataValue != null){ mPaint.setTextSize(TEXT_SIZE_VALUE); canvas.drawText(mDataValue, mViewWidth - textWidth - mPaint.measureText(mDataValue), textBase, mPaint); } } }
垂直柱状图实现:
public class SimpleVerticalBarChart extends ChartBaseView { public SimpleVerticalBarChart(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public SimpleVerticalBarChart(Context context, AttributeSet attrs) { super(context, attrs); } public SimpleVerticalBarChart(Context context) { super(context); } private ArrayList<Integer> mLevels; private ArrayList<Integer> mLevelColors; private static final int LEVEL_COUNT = 4; private Paint mLinePaint; private Paint mRectPaint; private int mColumnCount = 18; @Override protected void init(Context context, AttributeSet attrs) { super.init(context, attrs); mLinePaint = new Paint(); mLinePaint.setColor(getResources().getColor(R.color.horizontal_bar_chart_dot_line_color)); mRectPaint = new Paint(); mRectPaint.setColor(getResources().getColor(R.color.horizontal_bar_chart_top_color)); } //几行,几列,颜色 public void setLevelData(ArrayList<Integer> levels){ mLevels = levels; mColumnCount = levels.size(); invalidate(); } public void setLevelColors(ArrayList<Integer> levelColors){ mLevelColors = levelColors; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float lineHeight = mViewHeight * (1 - PERCENT_TO_DRAW_TEXT)/LEVEL_COUNT; float columnWidth = mViewWidth*1.0f/mColumnCount; //画矩形 int level; if(mLevels.size() > 0){ float left = 0, top , right = columnWidth, bottom = mViewHeight; for(int pos = 0;pos<mColumnCount;pos++){ level = mLevels.get(pos); top = bottom - level * lineHeight; canvas.drawRect(left, top, right, bottom, mRectPaint); left+= columnWidth; right += columnWidth; } } //画行 float startY = mViewHeight * PERCENT_TO_DRAW_TEXT; for(int i = 0;i<LEVEL_COUNT;i++){ canvas.drawLine(0, startY, mViewWidth, startY, mLinePaint); startY += lineHeight; } //画列 float startX = 0; for(int i = 0;i<mColumnCount;i++){ canvas.drawLine(startX, mViewHeight*PERCENT_TO_DRAW_TEXT, startX, mViewHeight, mLinePaint); startX += columnWidth; } } }
使用:
布局中使用:
<com.app.shecare.ui.view.SimpleVerticalBarChart android:id="@+id/shi_zhi_analyse" android:layout_width="match_parent" android:layout_height="200dp" shecare:background="@color/tab_text_selected" shecare:icon="@drawable/wechat" />
代码中设置参数(测试):
SimpleVerticalBarChart shiZhiAnalyseChart = (SimpleVerticalBarChart) view.findViewById(R.id.shi_zhi_analyse); ArrayList<Integer> levels = new ArrayList<Integer>(); for(int i = 0;i<15;i++){ int level = Math.abs(random.nextInt() % 4)+1; levels.add(level); } shiZhiAnalyseChart.setLevelData(levels); shiZhiAnalyseChart.setDataProperty("89", "分", "月经分析");
效果截图: