Android自定义控件系列四:绘制实用型的柱形图和折线图

概述:

前几天突然需要做两种图表——柱形图、折线图,于是第一反应是先看看网上有没有现成的,结果有是有,但都不是想要的,而且大多数不是用纯android代码完成,不过HTML5似乎完成这类工作要容易得多,单是非我们所擅长。

**知识点:**android自定义view、图形图像、Fragment、MVC模式。

Demo

界面是模仿红圈营销搭建的

折线图: 

代码,注释很详细,直接看代码就行了:

001.public class LineChartView extends View {

002.

003.private int width;

004.private int height;

005.private float maxValue;//传入数据的最大值

006.private int dataNum;//数据总数

007.

008.private Paint mPaintBg;//报表背景画笔

009.private Paint mPaintCoveredBg;//用于画数据覆盖部分

010.private Paint mPaintChartLine;//用于画报表的网格

011.private Paint mPaintDataLine;//用于画数据连线

012.private Paint mPaintTextDate;//用于画日期文本

013.private Paint mPaintCircle;//用于画空心圆

014.private Paint mPaintFilledCircle;//用于画实心圆

015.private Paint mPaintTextValue;//用于画数据访问量值

016.

017.private Path path;

018.

019.private HashMap<Integer, PageViewData> dataTotal;//用于得存储传入的总数据

020.

021.//用一个setPaints()方法,设定所有画笔的属性,增加代码灵活性

022.public void setPaints(int bgColor, int coveredBgColor, int chartLineColor

023.int dataLineColor, int textDateColor, int filledCircleColor, int circleColor, int textValueColor) {

024.

025.mPaintBg.setColor(bgColor);

026.mPaintBg.setStyle(Paint.Style.FILL);

027.

028.mPaintCoveredBg.setColor(coveredBgColor);

029.mPaintCoveredBg.setStyle(Paint.Style.FILL);

030.

031.mPaintCircle.setColor(circleColor);

032.mPaintCircle.setStyle(Paint.Style.STROKE);

033.mPaintCircle.setStrokeWidth(5);

034.mPaintCircle.setAntiAlias(true);

035.

036.mPaintFilledCircle.setColor(filledCircleColor);

037.mPaintFilledCircle.setStyle(Paint.Style.FILL);

038.mPaintFilledCircle.setAntiAlias(true);

039.

040.mPaintChartLine.setColor(chartLineColor);

041.mPaintChartLine.setStyle(Paint.Style.STROKE);

042.mPaintChartLine.setAntiAlias(true);

043.

044.mPaintDataLine.setColor(dataLineColor);

045.mPaintDataLine.setStyle(Paint.Style.STROKE);

046.mPaintDataLine.setStrokeWidth(SizeConvert.dip2px(getContext(), 5));

047.mPaintDataLine.setAntiAlias(true);

048.

049.mPaintTextDate.setColor(textDateColor);

050.mPaintTextDate.setTextSize(SizeConvert.dip2px(getContext(), 10));

051.mPaintTextDate.setTextAlign(Paint.Align.CENTER);

052.mPaintTextDate.setAntiAlias(true);

053.

054.mPaintTextValue.setColor(textValueColor);

055.mPaintTextValue.setTextSize(SizeConvert.dip2px(getContext(), 12));

056.mPaintTextValue.setTextAlign(Paint.Align.CENTER);

057.mPaintTextValue.setAntiAlias(true);

058.

059.//重绘

060.invalidate();

061.}

062.

063.

064.//用于设定传入的总数据

065.public void setDataTotal(HashMap<Integer, PageViewData> dataTotal) {

066.this.dataTotal = dataTotal;

067.invalidate();

068.}

069.

070.public LineChartView(Context context) {

071.super(context);

072.}

073.

074.public LineChartView(Context context, AttributeSet attrs) {

075.super(context, attrs);

076.mPaintBg = new Paint();

077.mPaintCoveredBg = new Paint();

078.mPaintCircle = new Paint();

079.mPaintChartLine = new Paint();

080.mPaintDataLine = new Paint();

081.mPaintTextDate = new Paint();

082.mPaintTextValue = new Paint();

083.mPaintFilledCircle = new Paint();

084.path = new Path();

085.

086.dataTotal = new HashMap<>();

087.}

088.

089.@Override

090.protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

091.super.onMeasure(widthMeasureSpec, heightMeasureSpec);

092.//当总数据已经传入,即不为空时,根据总数据中数据个数设定view的总宽

093.if (dataTotal != null) {

094.width = (dataTotal.size() - 1) * xAddedNum + chartMarginHorizontal * 2;

095.getMaxValue(dataTotal);

096.}

097.height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

098.setMeasuredDimension(width, height);

099.}

100.

101./**

102.* 用于得到总数据中最大数据

103.* @param dataTotal 总数据

104.*/

105.private void getMaxValue(HashMap<Integer, PageViewData> dataTotal) {

106.maxValue = 0;

107.dataNum = 0;

108.for (int key : dataTotal.keySet()) {

109.if (dataTotal.get(key).getPageViewValue() > maxValue) {

110.maxValue = dataTotal.get(key).getPageViewValue();

111.}

112.dataNum++;

113.}

114.}

115.

116.private int mChartHeight;//折线图的高

117.private int mChartWidth;//折线图的

118.private int startX = SizeConvert.dip2px(getContext(), 10);//开始绘制的x坐标

119.private int startY = SizeConvert.dip2px(getContext(), 5);//开始绘制的y坐标

120.private int chartMarginBottom = SizeConvert.dip2px(getContext(), 30);//折线图距离父控件底部距离

121.private int chartMarginHorizontal = SizeConvert.dip2px(getContext(), 12);//折线图距离父控件左右的距离

122.private int valueAlignLeft = SizeConvert.dip2px(getContext(), 0);//value参数文本距离左边距离

123.private int dateAlignLeft = SizeConvert.dip2px(getContext(), 0);//date参数文本距离左边距离

124.private int valueAlignBottom = SizeConvert.dip2px(getContext(), 5);//value参数文本距离底部距离

125.private int dateAlignBottom = SizeConvert.dip2px(getContext(), 10);//date参数文本距离底部距离

126.private int xAddedNum = SizeConvert.dip2px(getContext(), 60);//绘制折线图时每次移动的x轴距离

127.private int yAddedNum;//绘制折线图时每次移动的y轴距离

128.private boolean isDrawFirst;//是否是第一次绘制

129.private float circleFilledRadius = SizeConvert.dip2px(getContext(), 5);//外圆半径

130.private float circleRadius = SizeConvert.dip2px(getContext(), 3);//内圆半径

131.

132.private float firstX;//第一个点的x轴坐标

133.private float firstY;//第一个点的y轴坐标

134.

135.@Override

136.protected void onDraw(Canvas canvas) {

137.super.onDraw(canvas);

138.isDrawFirst = true;

139.mChartHeight = height - chartMarginBottom;

140.yAddedNum = mChartHeight / 4;

141.mChartWidth = width - chartMarginHorizontal * 2;

142.

143.canvas.drawRect(startX, startY, startX + mChartWidth, startY + mChartHeight, mPaintBg);

144.for (int key : dataTotal.keySet()) {

145.float value = dataTotal.get(key).getPageViewValue();

146.if (isDrawFirst) {

147.//当第一次绘制时得到第一个点的横纵坐标

148.firstX = startX;

149.firstY = startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight;

150.path.moveTo(firstX, firstY);

151.isDrawFirst = false;

152.}

153.//每循环一次,将path线性相位一次

154.path.lineTo(startX, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight);

155.startX += xAddedNum;

156.}

157.//重新给startX赋值

158.startX = SizeConvert.dip2px(getContext(), 10);

159.//画出折线

160.canvas.drawPath(path, mPaintDataLine);

161.//画出折线以下部分的颜色

162.path.lineTo(startX + mChartWidth, startY + mChartHeight);

163.path.lineTo(startX, startY + mChartHeight);

164.path.lineTo(firstX, firstY);

165.canvas.drawPath(path, mPaintCoveredBg);

166.

167.//画出每个点的圆圈,和对应的文本

168.for (int key : dataTotal.keySet()) {

169.int date = dataTotal.get(key).getDate();

170.float value = dataTotal.get(key).getPageViewValue();

171.canvas.drawCircle(startX, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight, circleFilledRadius, mPaintFilledCircle);

172.canvas.drawCircle(startX, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight, circleRadius, mPaintCircle);

173.canvas.drawText(date + "", startX + dateAlignLeft, height - dateAlignBottom, mPaintTextDate);

174.canvas.drawText(value + "", startX + valueAlignLeft, startY + (1f - value / ((int) maxValue * 1.5f)) * mChartHeight - valueAlignBottom, mPaintTextValue);

175.

176.startX += xAddedNum;

177.}

178.

179.//在次使startX回到初始值

180.startX = SizeConvert.dip2px(getContext(), 10);

181./**

182.* 画出网格

183.*/

184.//竖线

185.for (int i = 0; i < dataNum; i++) {

186.canvas.drawLine(startX + i * xAddedNum, startY, startX + i * xAddedNum, startY + mChartHeight, mPaintChartLine);

187.}

188.

189.//横线

190.for (int i = 0; i < 5; i++) {

191.canvas.drawLine(startX, startY + i * yAddedNum, startX + mChartWidth, startY + i * yAddedNum, mPaintChartLine);

192.}

193.

194.path.reset();

195.

196.}

197.}

柱形图: 

代码:

01./**

02.* 柱形图

03.*/

04.public class HistogramView extends View {

05.

06.private int width;

07.private int height;

08.

09.private Paint mBgPaint;

10.private Paint mHistogramBgPaint;

11.private Paint mHistogramPaint;

12.private Paint mTextPaint;

13.

14.private HashMap<Integer,HistogramData> dataTotal;

15.

16.public void setPaints(int bgColor,int histogramBgColor,int histogramColor,int textColor){

17.

18.mBgPaint.setColor(bgColor);

19.mBgPaint.setStyle(Paint.Style.FILL);

20.

21.mHistogramBgPaint.setColor(histogramBgColor);

22.mHistogramBgPaint.setStyle(Paint.Style.FILL);

23.

24.mHistogramPaint.setColor(histogramColor);

25.mHistogramPaint.setStyle(Paint.Style.FILL);

26.

27.mTextPaint.setColor(textColor);

28.mTextPaint.setTextSize(SizeConvert.dip2px(getContext(), 9));

29.mTextPaint.setTextAlign(Paint.Align.CENTER);

30.

31.invalidate();

32.};

33.

34.public void setDataTotal(HashMap<Integer, HistogramData> dataTotal) {

35.this.dataTotal = dataTotal;

36.invalidate();

37.}

38.

39.public HistogramView(Context context) {

40.super(context);

41.}

42.

43.public HistogramView(Context context, AttributeSet attrs) {

44.super(context, attrs);

45.mHistogramBgPaint = new Paint();

46.mHistogramPaint = new Paint();

47.mTextPaint = new Paint();

48.mBgPaint = new Paint();

49.

50.dataTotal = new HashMap<>();

51.}

52.

53.@Override

54.protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

55.super.onMeasure(widthMeasureSpec, heightMeasureSpec);

56.if(dataTotal!=null){

57.width = dataTotal.size()*SizeConvert.dip2px(getContext(), 40);

58.}

59.height = getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);

60.setMeasuredDimension(width, height);

61.}

62.

63.private int mHistogramHeight;

64.int startX = SizeConvert.dip2px(getContext(), 20);

65.int startY = SizeConvert.dip2px(getContext(),20);

66.int radius = 45;

67.int greyValueAlignLeft = SizeConvert.dip2px(getContext(), 5);

68.int nameAlignLeft = SizeConvert.dip2px(getContext(), 15);

69.int greyValueAlignBottom = SizeConvert.dip2px(getContext(), 5);

70.int nameAlignBottom = SizeConvert.dip2px(getContext(), 15);

71.int histogramWidth = SizeConvert.dip2px(getContext(), 8);

72.int xAddedNum = SizeConvert.dip2px(getContext(), 40);

73.int histogramAlignTop = SizeConvert.dip2px(getContext(), 2);

74.

75.@Override

76.protected void onDraw(Canvas canvas) {

77.super.onDraw(canvas);

78.mHistogramHeight = height-SizeConvert.dip2px(getContext(),40);

79.canvas.drawRect(0,startY,width,mHistogramHeight,mBgPaint);

80.for(int key:dataTotal.keySet()){

81.String name = dataTotal.get(key).getName();

82.int greyValue = dataTotal.get(key).getGreyValue();

83.

84.canvas.drawText(greyValue + "%", startX + greyValueAlignLeft, startY-greyValueAlignBottom , mTextPaint);

85.canvas.drawRect(startX, startY+histogramAlignTop, startX + histogramWidth, mHistogramHeight, mHistogramBgPaint);

86.canvas.drawRect(startX, startY+(1f - greyValue / 100f) * (mHistogramHeight - startY-histogramAlignTop)+histogramAlignTop, startX + histogramWidth, mHistogramHeight, mHistogramPaint);

87.

88.canvas.save();

89.canvas.rotate(-radius, startX,height);

90.canvas.drawText(name, startX + nameAlignLeft, height-nameAlignBottom, mTextPaint);

91.canvas.restore();

92.startX+=xAddedNum;

93.}

94.startX = SizeConvert.dip2px(getContext(), 20);

95.}

96.

97.}

Fragment

001.public class FragmentChart extends Fragment implements View.OnClickListener{

002.

003.private RelativeLayout mItemFirst;

004.private RelativeLayout mItemSecond;

005.private RelativeLayout mItemThird;

006.private RelativeLayout mItemForth;

007.

008.private HistogramView mHistogramView;

009.private HashMap<Integer,HistogramData> mDataHistogramTotal;

010.private boolean isShowHistogram = false;

011.

012.private LineChartView mLineChartView;

013.private HashMap<Integer,PageViewData> mDataPageView;

014.private boolean isShowSecondItem = false;

015.@Nullable

016.@Override

017.public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

018.View view = inflater.inflate(R.layout.content_chart,null);

019.mItemFirst = (RelativeLayout) view.findViewById(R.id.first_page_item_1);

020.mItemSecond = (RelativeLayout) view.findViewById(R.id.first_page_item_2);

021.mItemThird = (RelativeLayout) view.findViewById(R.id.first_page_item_3);

022.mItemForth = (RelativeLayout) view.findViewById(R.id.first_page_item_4);

023.

024.mHistogramView = (HistogramView) view.findViewById(R.id.histogram_view_item_1);

025.mLineChartView = (LineChartView) view.findViewById(R.id.line_chart_view_item_2);

026.

027.mItemFirst.setOnClickListener(this);

028.mItemSecond.setOnClickListener(this);

029.mItemThird.setOnClickListener(this);

030.mItemForth.setOnClickListener(this);

031.

032.initDataHistogram();

033.initDataPageView();

034.

035.return view;

036.}

037.

038.private void initDataPageView() {

039.mDataPageView = new HashMap<>();

040.mDataPageView.put(1,new PageViewData(1,9,16));

041.mDataPageView.put(2,new PageViewData(2,10,18));

042.mDataPageView.put(3,new PageViewData(3,11,33));

043.mDataPageView.put(4,new PageViewData(4,12,97));

044.mDataPageView.put(5,new PageViewData(5,13,46));

045.mDataPageView.put(6,new PageViewData(6,14,55));

046.mDataPageView.put(7,new PageViewData(7,15,11));

047.mDataPageView.put(8,new PageViewData(8,16,22));

048.mDataPageView.put(9,new PageViewData(9,17,8));

049.mDataPageView.put(10,new PageViewData(10,18,19));

050.mDataPageView.put(11,new PageViewData(11,16,22));

051.

052.mLineChartView.setDataTotal(mDataPageView);

053.mLineChartView.setPaints(Color.argb(255,225250250),

054.Color.argb(255,234234250), Color.argb(255,74,208204),

055.Color.argb(255,105210249),Color.argb(255,203203203)

056.,Color.argb(255,255255255),Color.argb(255,105210249),Color.argb(255,105210249));

057.}

058.

059.private void initDataHistogram(){

060.mDataHistogramTotal = new HashMap<>();

061.mDataHistogramTotal.put(1,new HistogramData(1,"海萌",100));

062.mDataHistogramTotal.put(2,new HistogramData(2,"涛涛",18));

063.mDataHistogramTotal.put(3,new HistogramData(3,"火风",17));

064.mDataHistogramTotal.put(4,new HistogramData(4,"周杰伦",16));

065.mDataHistogramTotal.put(5,new HistogramData(5,"王宝强",15));

066.mDataHistogramTotal.put(6,new HistogramData(6,"林俊杰",14));

067.mDataHistogramTotal.put(7,new HistogramData(7,"孙悟空",11));

068.mDataHistogramTotal.put(8,new HistogramData(8,"钟航",10));

069.mDataHistogramTotal.put(9,new HistogramData(9,"小明",8));

070.mDataHistogramTotal.put(10new HistogramData(10"小红"5));

071.

072.mHistogramView.setDataTotal(mDataHistogramTotal);

073.mHistogramView.setPaints(Color.argb(255,250250250),

074.Color.argb(255,238238238), Color.argb(255,240,14177),

075.Color.argb(255,168168168));

076.}

077.

078.@Override

079.public void onClick(View v) {

080.switch (v.getId()){

081.case R.id.first_page_item_1:

082.isShowHistogram = !isShowHistogram;

083.if(isShowHistogram) {

084.mHistogramView.setVisibility(View.VISIBLE);

085.}else{

086.mHistogramView.setVisibility(View.GONE);

087.}

088.break;

089.case R.id.first_page_item_2:

090.isShowSecondItem= !isShowSecondItem;

091.if(isShowSecondItem) {

092.mLineChartView.setVisibility(View.VISIBLE);

093.}else{

094.mLineChartView.setVisibility(View.GONE);

095.}

096.break;

097.case R.id.first_page_item_3:

098.break;

099.case R.id.first_page_item_4:

100.break;

101.}

102.}

103.}

主活动:

01.public class MainActivity extends FragmentActivity {

02.

03.private FragmentChart mFragmentChart;

04.private RadioGroup mRadioGroup;

05.private FragmentTransaction transaction;

06.

07.@Override

08.protected void onCreate(Bundle savedInstanceState) {

09.super.onCreate(savedInstanceState);

10.setContentView(R.layout.activity_main);

11.mFragmentChart = new FragmentChart();

12.mFragmentManager = getSupportFragmentManager();

13.transaction = mFragmentManager.beginTransaction();

14.transaction.add(R.id.frame_layout, mFragmentChart);

15.transaction.commit();

16.mRadioGroup = (RadioGroup) findViewById(R.id.radiogroup);

17.

18.mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

19.@Override

20.public void onCheckedChanged(RadioGroup group, int checkedId) {

21.

22.switch (checkedId) {

23.case R.id.button1:

24.transaction = mFragmentManager.beginTransaction();

25.transaction.hide(mFragmentChat);

26.transaction.hide(mFragmentSetting);

27.transaction.hide(mFragmentWork);

28.transaction.show(mFragmentChart);

29.transaction.commit();

30.break;

31.

32.}

33.}

34.});

35.}

36.}

activity_main:

01.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

02.

03.android:layout_width="match_parent"

04.android:layout_height="match_parent"

05.android:orientation="vertical"

06.>

07.

08.<FrameLayout

09.android:id="@+id/frame_layout"

10.android:layout_width="match_parent"

11.android:layout_height="wrap_content"

12.android:layout_weight="1">

13.</FrameLayout>

14.

15.<RadioGroup

16.android:id="@+id/radiogroup"

17.android:layout_width="match_parent"

18.android:layout_height="60dp"

19.android:layout_alignParentBottom="true"

20.android:background="@color/light_gray"

21.android:checkedButton="@+id/button1"

22.android:gravity="center_vertical"

23.android:orientation="horizontal"

24.android:padding="2dp">

25.

26.<RadioButton

27.android:id="@+id/button1"

28.android:layout_width="0dp"

29.android:layout_height="wrap_content"

30.android:layout_weight="1"

31.android:background="@null"

32.android:button="@null"

33.android:drawableTop="@drawable/radio_button_chart"

34.android:gravity="center"

35.android:text="报表"

36.android:textColor="@color/radio_button_text_color"

37./>

38.

39.<RadioButton

40.android:id="@+id/button2"

41.android:layout_width="0dp"

42.android:layout_height="wrap_content"

43.android:layout_weight="1"

44.android:button="@null"

45.android:drawableTop="@drawable/radio_button_chat"

46.android:gravity="center"

47.android:text="沟通"

48.android:textColor="@color/radio_button_text_color"

49./>

50.

51.<RadioButton

52.android:id="@+id/button3"

53.android:layout_width="0dp"

54.android:layout_height="wrap_content"

55.android:layout_weight="1"

56.android:button="@null"

57.android:drawableTop="@drawable/radio_button_work"

58.android:gravity="center"

59.android:text="工作"

60.android:textColor="@color/radio_button_text_color"

61./>

62.

63.<RadioButton

64.android:id="@+id/button4"

65.android:layout_width="0dp"

66.android:layout_height="wrap_content"

67.android:layout_weight="1"

68.android:button="@null"

69.android:drawableTop="@drawable/radio_button_setting"

70.android:gravity="center"

71.android:text="更多"

72.android:textColor="@color/radio_button_text_color"

73./>

74.

75.</RadioGroup>

76.</LinearLayout>

content_chart:

001.<?xml version="1.0" encoding="utf-8"?>

002.<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"

003.android:layout_width="match_parent"

004.android:layout_height="match_parent">

005.

006.<LinearLayout

007.android:layout_width="match_parent"

008.android:layout_height="match_parent"

009.android:background="@color/background"

010.android:orientation="vertical">

011.

012.<RelativeLayout

013.android:layout_width="match_parent"

014.android:layout_height="60dp"

015.android:background="@drawable/item_bg">

016.

017.<TextView

018.android:id="@+id/textview"

019.android:layout_width="wrap_content"

020.android:layout_height="wrap_content"

021.android:layout_centerInParent="true"

022.android:text="报表"

023.android:textSize="20sp"/>

024.

025.<ImageView

026.android:id="@+id/image_button"

027.android:layout_width="wrap_content"

028.android:layout_height="wrap_content"

029.android:layout_alignParentRight="true"

030.android:layout_centerVertical="true"

031.android:layout_margin="20dp"

032.android:src="@mipmap/report_subscribe"/>

033.

034.</RelativeLayout>

035.

036.<LinearLayout

037.android:layout_width="match_parent"

038.android:layout_height="match_parent"

039.android:orientation="vertical">

040.

041.<RelativeLayout

042.android:id="@+id/first_page_item_1"

043.android:layout_width="match_parent"

044.android:layout_height="@dimen/first_page_item_height"

045.android:layout_marginTop="@dimen/first_page_item_margin_top"

046.android:background="@drawable/item_bg"

047.android:gravity="center_vertical">

048.

049.<LinearLayout

050.android:layout_width="wrap_content"

051.android:layout_height="wrap_content"

052.android:orientation="vertical">

053.

054.<TextView

055.android:layout_width="wrap_content"

056.android:layout_height="wrap_content"

057.android:layout_margin="@dimen/first_page_item_left_padding"

058.android:text="随时定位"

059.android:textColor="@color/black"

060.android:textSize="@dimen/first_page_item_left_big_size"/>

061.

062.<LinearLayout

063.android:layout_width="wrap_content"

064.android:layout_height="wrap_content"

065.android:orientation="horizontal">

066.

067.<TextView

068.android:layout_width="wrap_content"

069.android:layout_height="wrap_content"

070.android:drawableTop="@mipmap/red_point_people"

071.android:gravity="center"

072.android:paddingLeft="@dimen/first_page_item_left_padding"

073.android:paddingRight="@dimen/first_page_item_left_padding"

074.android:text="48"

075.android:textSize="@dimen/first_page_item_right_small_size"/>

076.

077.<TextView

078.android:layout_width="wrap_content"

079.android:layout_height="wrap_content"

080.android:drawableTop="@mipmap/blue_point_people"

081.android:gravity="center"

082.android:paddingLeft="@dimen/first_page_item_left_padding"

083.android:paddingRight="@dimen/first_page_item_left_padding"

084.android:text="16"

085.android:textSize="@dimen/first_page_item_right_small_size"/>

086.

087.<TextView

088.android:layout_width="wrap_content"

089.android:layout_height="wrap_content"

090.android:drawableTop="@mipmap/grey_point_people"

091.android:gravity="center"

092.android:paddingLeft="@dimen/first_page_item_left_padding"

093.android:paddingRight="@dimen/first_page_item_left_padding"

094.android:text="16"

095.android:textSize="@dimen/first_page_item_right_small_size"/>

096.</LinearLayout>

097.

098.</LinearLayout>

099.

100.<LinearLayout

101.android:layout_width="wrap_content"

102.android:layout_height="match_parent"

103.android:layout_alignParentRight="true"

104.android:gravity="center|right"

105.android:orientation="vertical"

106.android:paddingRight="@dimen/first_page_item_left_padding">

107.

108.<TextView

109.android:layout_width="wrap_content"

110.android:layout_height="wrap_content"

111.android:text="12%"

112.android:textColor="@color/orange"

113.android:textSize="@dimen/first_page_item_right_big_size"/>

114.

115.<TextView

116.android:layout_width="wrap_content"

117.android:layout_height="wrap_content"

118.android:text="今日人均灰点率"

119.android:textSize="@dimen/first_page_item_right_small_size"/>

120.

121.</LinearLayout>

122.

123.</RelativeLayout>

124.

125.<HorizontalScrollView

126.android:layout_width="match_parent"

127.android:layout_height="wrap_content"

128.android:scrollbars="none">

129.

130.<com.test.shiweiwei.myproject.selfish_view.HistogramView

131.android:id="@+id/histogram_view_item_1"

132.android:layout_width="wrap_content"

133.android:layout_height="160dp"

134.android:background="@drawable/item_bg"

135.android:visibility="gone"/>

136.

137.</HorizontalScrollView>

138.

139.<RelativeLayout

140.android:id="@+id/first_page_item_2"

141.android:layout_width="match_parent"

142.android:layout_height="@dimen/first_page_item_height"

143.android:layout_marginTop="@dimen/first_page_item_margin_top"

144.android:background="@drawable/item_bg"

145.android:gravity="center_vertical">

146.

147.<LinearLayout

148.android:layout_width="wrap_content"

149.android:layout_height="wrap_content"

150.android:gravity="center_vertical"

151.android:orientation="vertical">

152.

153.<TextView

154.android:layout_width="wrap_content"

155.android:layout_height="wrap_content"

156.android:layout_margin="@dimen/first_page_item_left_padding"

157.android:text="客户拜访"

158.android:textColor="@color/black"

159.android:textSize="@dimen/first_page_item_left_big_size"/>

160.

161.<LinearLayout

162.android:layout_width="wrap_content"

163.android:layout_height="wrap_content"

164.android:orientation="vertical">

165.

166.<TextView

167.android:layout_width="wrap_content"

168.android:layout_height="wrap_content"

169.android:gravity="center"

170.android:paddingLeft="@dimen/first_page_item_left_padding"

171.android:paddingRight="@dimen/first_page_item_left_padding"

172.android:text="10月人均拜访:1.7"

173.android:textSize="@dimen/first_page_item_right_small_size"/>

174.

175.<TextView

176.android:layout_width="wrap_content"

177.android:layout_height="wrap_content"

178.android:gravity="center"

179.android:paddingLeft="@dimen/first_page_item_left_padding"

180.android:paddingRight="@dimen/first_page_item_left_padding"

181.android:paddingTop="5dp"

182.android:text="昨日总拜访:9"

183.android:textSize="@dimen/first_page_item_right_small_size"/>

184.</LinearLayout>

185.

186.</LinearLayout>

187.

188.<LinearLayout

189.android:layout_width="wrap_content"

190.android:layout_height="match_parent"

191.android:layout_alignParentRight="true"

192.android:gravity="center|right"

193.android:orientation="vertical"

194.android:paddingRight="@dimen/first_page_item_left_padding">

195.

196.<TextView

197.android:layout_width="wrap_content"

198.android:layout_height="wrap_content"

199.android:text="3.0"

200.android:textColor="@color/light_blue"

201.android:textSize="@dimen/first_page_item_right_big_size"/>

202.

203.<TextView

204.android:layout_width="wrap_content"

205.android:layout_height="wrap_content"

206.android:text="昨日人均拜访"

207.android:textSize="@dimen/first_page_item_right_small_size"/>

208.

209.</LinearLayout>

210.

211.</RelativeLayout>

212.

213.<HorizontalScrollView

214.android:layout_width="match_parent"

215.android:layout_height="wrap_content"

216.android:scrollbars="none">

217.

218.<com.test.shiweiwei.myproject.selfish_view.LineChartView

219.android:id="@+id/line_chart_view_item_2"

220.android:layout_width="wrap_content"

221.android:layout_height="160dp"

222.android:background="@drawable/item_bg"

223.android:visibility="gone"/>

224.

225.</HorizontalScrollView>

226.

227.<RelativeLayout

228.android:id="@+id/first_page_item_3"

229.android:layout_width="match_parent"

230.android:layout_height="@dimen/first_page_item_height"

231.android:layout_marginTop="@dimen/first_page_item_margin_top"

232.android:background="@drawable/item_bg"

233.android:gravity="center_vertical">

234.

235.<LinearLayout

236.android:layout_width="wrap_content"

237.android:layout_height="wrap_content"

238.android:gravity="center_vertical"

239.android:orientation="vertical">

240.

241.<TextView

242.android:layout_width="wrap_content"

243.android:layout_height="wrap_content"

244.android:layout_margin="@dimen/first_page_item_left_padding"

245.android:text="新增客户-全部"

246.android:textColor="@color/black"

247.android:textSize="@dimen/first_page_item_left_big_size"/>

248.

249.<LinearLayout

250.android:layout_width="wrap_content"

251.android:layout_height="wrap_content"

252.android:orientation="vertical">

253.

254.<TextView

255.android:layout_width="wrap_content"

256.android:layout_height="wrap_content"

257.android:gravity="center"

258.android:paddingLeft="@dimen/first_page_item_left_padding"

259.android:paddingRight="@dimen/first_page_item_left_padding"

260.android:text="10月日均增长量:3.0"

261.android:textSize="@dimen/first_page_item_right_small_size"/>

262.

263.<TextView

264.android:layout_width="wrap_content"

265.android:layout_height="wrap_content"

266.android:gravity="center"

267.android:paddingLeft="@dimen/first_page_item_left_padding"

268.android:paddingRight="@dimen/first_page_item_left_padding"

269.android:paddingTop="@dimen/first_page_item_left_padding_top"

270.android:text="十月新增客户:21"

271.android:textSize="@dimen/first_page_item_right_small_size"/>

272.</LinearLayout>

273.

274.</LinearLayout>

275.

276.<LinearLayout

277.android:layout_width="wrap_content"

278.android:layout_height="match_parent"

279.android:layout_alignParentRight="true"

280.android:gravity="center|right"

281.android:orientation="vertical"

282.android:paddingRight="@dimen/first_page_item_left_padding">

283.

284.<TextView

285.android:layout_width="wrap_content"

286.android:layout_height="wrap_content"

287.android:text="3"

288.android:textColor="@color/light_green"

289.android:textSize="@dimen/first_page_item_right_big_size"/>

290.

291.<TextView

292.android:layout_width="wrap_content"

293.android:layout_height="wrap_content"

294.android:text="昨日新增客户"

295.android:textSize="@dimen/first_page_item_right_small_size"/>

296.

297.</LinearLayout>

298.

299.</RelativeLayout>

300.

301.<RelativeLayout

302.android:id="@+id/first_page_item_4"

303.android:layout_width="match_parent"

304.android:layout_height="@dimen/first_page_item_height"

305.android:layout_marginTop="@dimen/first_page_item_margin_top"

306.android:background="@drawable/item_bg"

307.android:gravity="center_vertical">

308.

309.<LinearLayout

310.android:layout_width="wrap_content"

311.android:layout_height="wrap_content"

312.android:gravity="center_vertical"

313.android:orientation="vertical">

314.

315.<TextView

316.android:layout_width="wrap_content"

317.android:layout_height="wrap_content"

318.android:layout_margin="@dimen/first_page_item_left_padding"

319.android:text="客户总量-全部"

320.android:textColor="@color/black"

321.android:textSize="@dimen/first_page_item_left_big_size"/>

322.

323.<LinearLayout

324.android:layout_width="wrap_content"

325.android:layout_height="wrap_content"

326.android:orientation="vertical">

327.

328.<TextView

329.android:layout_width="wrap_content"

330.android:layout_height="wrap_content"

331.android:gravity="center"

332.android:paddingLeft="@dimen/first_page_item_left_padding"

333.android:paddingRight="@dimen/first_page_item_left_padding"

334.android:text="昨日净增客户:3.0"

335.android:textSize="@dimen/first_page_item_right_small_size"/>

336.

337.<TextView

338.android:layout_width="wrap_content"

339.android:layout_height="wrap_content"

340.android:gravity="center"

341.android:paddingLeft="@dimen/first_page_item_left_padding"

342.android:paddingRight="@dimen/first_page_item_left_padding"

343.android:paddingTop="@dimen/first_page_item_left_padding_top"

344.android:text="十月净增客户:-1"

345.android:textSize="@dimen/first_page_item_right_small_size"/>

346.</LinearLayout>

347.

348.</LinearLayout>

349.

350.<LinearLayout

351.android:layout_width="wrap_content"

352.android:layout_height="match_parent"

353.android:layout_alignParentRight="true"

354.android:gravity="center|right"

355.android:orientation="vertical"

356.android:paddingRight="@dimen/first_page_item_left_padding">

357.

358.<TextView

359.android:layout_width="wrap_content"

360.android:layout_height="wrap_content"

361.android:text="21"

362.android:textColor="@color/purple"

363.android:textSize="@dimen/first_page_item_right_big_size"/>

364.

365.<TextView

366.android:layout_width="wrap_content"

367.android:layout_height="wrap_content"

368.android:text="总客户数"

369.android:textSize="@dimen/first_page_item_right_small_size"/>

370.

371.</LinearLayout>

372.

373.</RelativeLayout>

374.</LinearLayout>

375.

376.</LinearLayout>

377.

378.</ScrollView>

==========================================================================================

欢迎加入我们的技术交流群:
Android群: 66756039
JavaEE群:  361579846

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-29 07:26:41

Android自定义控件系列四:绘制实用型的柱形图和折线图的相关文章

Android自定义view之绘制实用型的柱形图和折线图

概述: 前几天突然需要做两种图表--柱形图.折线图,于是第一反应是先看看网上有没有现成的,结果有是有,但都不是我想要的,而且大多数不是用纯android代码完成,HTML5似乎完成这类工作要容易得多,但是我本人并不会HTML5,只能黯然神伤,掩面流泪,最终只能自己敲代码了. **知识点:**android自定义view.图形图像.Fragment.MVC模式. Demo 界面是模仿红圈营销搭建的 折线图: 代码,注释很详细,直接看代码就行了: public class LineChartView

Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一),今天就来真正实践一下,让这两个方法大显神威来帮我们搞定图片的屏幕适配问题. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45038329,非允许请勿用于商业或盈利用途,违者必究. 使用ImageView会遇到

Android自定义控件系列 十:利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件

这个例子是比较有用的,基本上可以说,写完这一次,以后很多情况下,直接拿过来addView一下,然后再addInterceptorView一下,就可以轻轻松松的达到组合界面中特定控件来响应特定方向的触摸事件了. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45198549,非允许请勿用于商业或盈利用途,违者必究. 在写Android应用的过程之中,经常会遇到这样的情况:界面包含了多个控件,我们希望触摸在界面上的不

Android自定义控件_View的绘制流程

每一个View/ViewGroup的显示都会经过三个过程:1.measure过程(测量View显示的大小,位置):2.layout过程(布局view的位置):3.draw过程(上一篇文章说到的通过canvas绘制到界面上显示,形成了各色的View) 下面分析一下各个过程:measure过程: 因为DecorView实际上是派生自FrameLayout的类,也即一个ViewGroup实例,该ViewGroup内部的ContentViews又是一个ViewGroup实例,依次内嵌View或ViewG

[转]Android自定义控件系列五:自定义绚丽水波纹效果

出处:http://www.2cto.com/kf/201411/353169.html 今天我们来利用Android自定义控件实现一个比较有趣的效果:滑动水波纹.先来看看最终效果图: 图一 效果还是很炫的:饭要一口口吃,路要一步步走,这里我们将整个过程分成几步来实现 一.实现单击出现水波纹单圈效果: 图二 照例来说,还是一个自定义控件,这里我们直接让这个控件撑满整个屏幕(对自定义控件不熟悉的可以参看我之前的一篇文章:Android自定义控件系列二:自定义开关按钮(一)).观察这个效果,发现应该

android自定义控件系列教程----视图的测量和布局

前面说点什么 当我们的一个视图界面绘制在android屏幕上面的时候其实都必须经过这几步measure. layout.draw这几个阶段,我们可以在view类里面看到这几个函数,然后里面有几个函数是onmeasure.onlayout.ondraw这几个函数是我们重写控件需要注意的这几个函数,下面我们就来讲讲这几个函数的功能和作用. onMeasure 正如这个函数的名子一样就是测量,所有的图示其实系统在绘制之前都不知道它到底有多大的,所以在很多时候我们在初始化界面oncreate的时候直接去

Android自定义控件系列之应用篇——圆形进度条

一.概述 在上一篇博文中,我们给大家介绍了Android自定义控件系列的基础篇.链接:http://www.cnblogs.com/jerehedu/p/4360066.html 这一篇博文中,我们将在基础篇的基础上,再通过重写ondraw()方法和自定义属性实现圆形进度条,效果如图所示: 二.实现步骤   1.  编写自定义组件MyCircleProgress扩展View public class MyCircleProgress extends View { - } 2.  在MyCircl

Android自定义控件系列五:自定义绚丽水波纹效果

尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自定义控件实现一个比较有趣的效果:滑动水波纹.先来看看最终效果图: 图一 效果还是很炫的:饭要一口口吃,路要一步步走,这里我们将整个过程分成几步来实现 一.实现单击出现水波纹单圈效果: 图二 照例来说,还是一个自定义控件,这里我们直接让这个控件撑满整个屏幕(对自定义控件不熟悉的可以参看我之前的一篇文章:Android自定义控件系列二

Android自定义控件系列二:如何自定义属性

上一篇Android自定义控件系列一:如何测量控件尺寸 我们讲了如何确定控件的属性,这篇接着也是讲个必要的知识-如何自定义属性.对于一个完整的或者说真正有实用价值的控件,自定义属性是必不可少的. 如何为控件定义属性 在res/values/attrs.xml(attrs.xml如果不存在,可以创建个)中使用<declare-styleable>标签定义属性,比如我想定义个显示头像的圆形的图片控件(AvatarImageView): 01.<?xml version="1.0&q