分析實現(xiàn)Android自定義View之遞增直方圖

繼上次分析實現(xiàn)Android自定義View之扇形圖之后颂龙,自己又畫了下面的這個遞增直方圖,本來是想做個靜態(tài)的直方圖就完了,結果想想靜態(tài)的沒啥趣味邮弹,于是就加了遞增

運行圖^_^

1 從分析最終效果

  1. 界面上要展現(xiàn)的東西有:x和y兩個坐標軸
  2. 主角直方圖每列
  3. 直方圖頂部文字

2 再分析舀瓢,要在屏幕上畫這樣的豎直列廷雅,怎樣畫?

在屏幕上畫圖就是給指定的屏幕坐標點上色

于是就想到只要能給出每列起始坐標高度的終點坐標京髓,然后給起點和終點之間的點全部上色航缀,最終就應該能有這樣的效果

接著去看我們的繪畫師(canvas)有哪些工具能給我使用,找到有這兩個工具朵锣,可能可以給我們使用

 drawPoint 畫點
 drawLine 畫直線

再想想剛才想的:把起點和終點之間的點全部上色谬盐,不就是在起點和終點之間畫一條直線嘛,想把線畫成像直方圖诚些,可以直接把畫筆調粗點不就可以了

確定了飞傀,就用drawLine來試試

3 接著把界面上的元素轉換為數(shù)據

看看每列直方圖有哪些屬性:

  1. 最明顯:顏色 color
  2. 頂上的描述:name
  3. 底部的位置應該用x軸坐標來描述吧:x
  4. 每列的高度:y

于是肯定就需要一個bean來存放每列直方圖的數(shù)據

public class HistogramData {
    public int value;       //數(shù)值
    public String name;     //文字描述

    public float persentage;    //占數(shù)據總數(shù)的百分比
    public float y;         //在直方圖上的x軸坐標
    public float x;         //在直方圖上的y軸坐標
    public int color;       //填充顏色

    public HistogramData(int value, String name) {
    this.value = value;
    this.name = name;
    }
}

4 結合Android的屏幕坐標皇型,分析:

  1. Andriod屏幕的坐標系統(tǒng)默認是左上角為原點,正方向x軸向右砸烦,y軸向下
  2. View的畫布(canvas)的坐標系統(tǒng)默認和屏幕的一樣
屏幕和畫布坐標.png

直方圖的坐標系是以左下角為原點弃鸦,所以首先就要獲取直方圖View畫布在屏幕中的尺寸,然后找到左下角的點作為直方圖的原點

獲取View在屏幕中的尺寸幢痘,只需在onSizeChanged中就可以得到

protected void onSizeChanged(int w, int h, int oldw, int oldh){
    super.onSizeChanged(w, h, oldw, oldh);    
    this.w = w - 10;    
    this.h = h - 10;
}

這里減去10唬格,是為了讓直方圖原點距離畫布編輯有一定間隔

由于畫布坐標和直方圖坐標的y軸方向是相反的,所以后面有關坐標的計算需要注意

坐標注意.png

如圖:計算每列直方圖的y軸坐標時颜说,就需要通過( h - 列高度 )來得到购岗,使用drawLine畫線時還是這樣

canvas.drawLine(histogramData.x, h, histogramData.x, histogramData.y,paint);

豎直方向是畫從h到y(tǒng)的直線,而不是從0到y(tǒng)的直線

5 具體實現(xiàn)

通過上面的分析门粪,基本上已經可以開始畫直方圖了

會用到的變量

private int[] mColors = {Color.BLUE, Color.DKGRAY, Color.CYAN, Color.RED, Color.GREEN};
private ArrayList<HistogramData> datas;
private Paint paint;            //畫筆
private int mWidth = 70;    //直方圖寬
private int width2 = 20;    //直方圖間距
private int w;              //畫布寬
private int h;              //畫布高

在onSizeChanged方法里確定了畫布寬高之后喊积,就會走到onDraw里開始畫畫

畫直方圖坐標

paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);
canvas.drawLine(10, h, w, h, paint);      //畫坐標系X軸
canvas.drawLine(10, h, 10, 10, paint);    //畫坐標系Y軸

畫每列直方圖

paint.setStrokeWidth(mWidth);
    paint.setStyle(Paint.Style.STROKE);
    if (null == datas) {
        return;
    }
    for (int i = 0; i < datas.size(); i++) {
        HistogramData histogramData = datas.get(i);
        paint.setColor(histogramData.color);
        canvas.drawLine(histogramData.x, h, histogramData.x, histogramData.y,paint);

        //直方圖頂部文字
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawText(histogramData.name, histogramData.x - mWidth / 4, histogramData.y - 10, paint);
    }

6 實現(xiàn)遞增

遞增的實現(xiàn)主要是在數(shù)據處理的時候加上了線程和handler

public void setData(ArrayList<HistogramData> data) {
    this.datas = data;
    if (null == datas || datas.size() == 0) {
        return;
    }
    myHandler = new MyHandler(this);
    new Thread(new Runnable() {
        @Override
        public void run() {
            //計算數(shù)據總和
            float sum = 0;
            for (int i = 0; i < datas.size(); i++) {
                sum += datas.get(i).value;
            }
            //計算數(shù)據占總數(shù)的百分比
            for (int i = 0; i < datas.size(); i++) {
                HistogramData histogramData = datas.get(i);
                histogramData.persentage = histogramData.value / sum;
            }
            //計算單列數(shù)據高度,并緩慢增加
            float startX, endY;
            for (int i = 0; i < datas.size(); i++) {
                HistogramData histogramData = datas.get(i);
                startX = (i + 1) * mWidth + i * width2;
                endY = HistogramView.this.h - histogramData.persentage * HistogramView.this.h;
                histogramData.color = mColors[i % mColors.length];
                //注意:畫布的坐標是左上角為原點玄妈,所以是
                // 從 畫布高-10 為起點, 數(shù)據高度 為終點
                // 遞減
                for (int j = HistogramView.this.h; j >= endY; j--) {
                    histogramData.x = startX;
                    histogramData.y = j;
                    //通知UI更新
                    myHandler.sendEmptyMessage(0);
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }).start();
}

最終效果就是上面那(cu)張(cao)GIF了_乾吻,自定義View還有很長的路要走

完整代碼請移步

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拟蜻,隨后出現(xiàn)的幾起案子绎签,更是在濱河造成了極大的恐慌,老刑警劉巖酝锅,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诡必,死亡現(xiàn)場離奇詭異,居然都是意外死亡屈张,警方通過查閱死者的電腦和手機擒权,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阁谆,“玉大人碳抄,你說我怎么就攤上這事〕÷蹋” “怎么了剖效?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長焰盗。 經常有香客問我璧尸,道長,這世上最難降的妖魔是什么熬拒? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任爷光,我火速辦了婚禮,結果婚禮上澎粟,老公的妹妹穿的比我還像新娘蛀序。我一直安慰自己欢瞪,他們只是感情好,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布徐裸。 她就那樣靜靜地躺著遣鼓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪重贺。 梳的紋絲不亂的頭發(fā)上骑祟,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機與錄音气笙,去河邊找鬼次企。 笑死,一個胖子當著我的面吹牛潜圃,可吹牛的內容都是我干的抒巢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼秉犹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了稚晚?” 一聲冷哼從身側響起崇堵,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎客燕,沒想到半個月后鸳劳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡也搓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年赏廓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傍妒。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡幔摸,死狀恐怖,靈堂內的尸體忽然破棺而出颤练,到底是詐尸還是另有隱情既忆,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布嗦玖,位于F島的核電站患雇,受9級特大地震影響,放射性物質發(fā)生泄漏宇挫。R本人自食惡果不足惜苛吱,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望器瘪。 院中可真熱鬧翠储,春花似錦绘雁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至任斋,卻和暖如春继阻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背废酷。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工瘟檩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澈蟆。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓墨辛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親趴俘。 傳聞我的和親對象是個殘疾皇子睹簇,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內容

  • 一、Android開發(fā)初體驗 二寥闪、Android與MVC設計模式模型對象存儲著應用的數(shù)據和業(yè)務邏輯太惠。模型類通常用來...
    為夢想戰(zhàn)斗閱讀 889評論 0 3
  • 一、概述 1. 四線格與基線 小時候疲憋,我們在剛開始學習寫字母時凿渊,用的本子是四線格的,我們必須把字母按照規(guī)則寫在四線...
    addapp閱讀 7,669評論 2 17
  • 直方圖主要用在數(shù)據圖表缚柳,作為對比數(shù)據埃脏,用柱體高度的高低,形象直觀地表達出來秋忙,往往與折線圖配合使用彩掐,而折線圖便于從眾...
    理想是試閱讀 948評論 0 0
  • 作者| 夏錦瑟 轉眼又到了一年一度的畢業(yè)季佩谷。 看著朋友圈各種曬畢業(yè)照、同學錄监嗜,不禁回想起自己畢業(yè)時的光景谐檀。 只記得...
    眷爾閱讀 533評論 0 1
  • 不是我無聊,就是看下這個能用不裁奇。
    楊書榮閱讀 117評論 0 0