自定義view-手?jǐn)]一個餅圖

1捌治、餅圖可以應(yīng)用在多方面,比如 財務(wù)類資金用途占比統(tǒng)計纽窟、生活類個人喜好占比肖油、等等,待產(chǎn)品提出這樣得效果臂港,我們可以隨意的繪制出來森枪。下面我來一步步剖析餅圖的繪制過程。如下圖先看效果


image.png

2审孽、第一步先分析一下這個餅圖的思路县袱,首先這個餅圖是由多個扇形以及折線以及文字組成∮恿Γ可以分為三塊來分別繪制式散。首先需要用到的知識點(diǎn)先大概說一下。

· 畫扇形用到canvas.drawArc()或者用Path類下的path.arcTo() 都可以實(shí)現(xiàn)
· 畫折線用drawLine()即可
· 畫文字用drawText()即可
· 計算弧長上的坐標(biāo)需要用到三角函數(shù) cos 余弦打颤、 sin正弦

3暴拄、我們直接來分析代碼

/**
 * 餅圖的顏色
 */
private int[] mColors = {Color.YELLOW, Color.RED, Color.GREEN, Color.BLUE, Color.GRAY, Color.LTGRAY};
/**
 * 初始化各個扇形的角度
 */
private float[] mPieAngles = {123, 73, 63, 53, 23, 13};
/**
 * 初始化文字
 */
private String[] texts = {"feng", "fang", "wei", "ran", "hello world", "some a bitch"};

/**
 * 扇形最大的間隔度數(shù)
 */
private int angleDash = 2;

/**
 * 扇形的半徑
 */
private int mRadius = 200;

以上是該餅圖所需要的一些初始化數(shù)據(jù)

4、先計算出view可用的寬和高方便平移坐標(biāo)系编饺,以及初始化扇形的外框矩形坐標(biāo)

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    //view 的可用高度
    mViewHeight = h - getPaddingTop() - getPaddingBottom();
    //view 的可用寬度
    mViewWidth = w - getPaddingLeft() - getPaddingRight();
    //畫扇形的矩形坐標(biāo)
    mRectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
}

5揍移、之后我們需要初始化扇形、折線反肋、文字的畫筆那伐,以及坐標(biāo)系原點(diǎn)

  private void init() {
    //扇形的畫筆
    mPiePaint = new Paint();
    mPiePaint.setAntiAlias(true);
    mPiepath = new Path();
    //折線的畫筆
    mLinePaint = new Paint();
    mLinePaint.setStrokeWidth(2);
    mLinePaint.setColor(Color.WHITE);
    mLinePaint.setAntiAlias(true);
    //文字的畫筆
    mTextPaint = new Paint();
    mTextPaint.setAntiAlias(true);
    mTextPaint.setColor(Color.WHITE);
    mTextPaint.setTextSize(25);
    //標(biāo)題的畫筆
    mTitlePaint = new Paint();
    mTitlePaint.setTextSize(40);
    mTitlePaint.setAntiAlias(true);
    mTitlePaint.setTextAlign(Paint.Align.CENTER);
    mTitlePaint.setColor(Color.WHITE);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //將坐標(biāo)原點(diǎn)平移到(mViewWidth / 2, mViewHeight / 2)位置處
    canvas.translate(mViewWidth / 2, mViewHeight / 2);
    //畫文字和折線以及扇形
    drawPieAndLineAndText(canvas);
    //畫標(biāo)題
    drawTitle(canvas);
}

說明:將坐標(biāo)系平移到view中心 便于之后的弧長的中點(diǎn)坐標(biāo)的計算,下面正式進(jìn)入核心代碼

6石蔗、畫扇形

private void drawPie(Canvas canvas, int i) {
    //畫扇形
    if (i == 0) {
        mPiepath.moveTo(10, 10);
        mPiepath.arcTo(new RectF(mRectF.left + 10, mRectF.top + 10,
                mRectF.right + 10, mRectF.bottom + 10), startAngle, mPieAngles[i]);
    } else {
        mPiepath.moveTo(0, 0);
        mPiepath.arcTo(mRectF, startAngle, mPieAngles[i]);
    }
    mPiePaint.setColor(mColors[i]);
    canvas.drawPath(mPiepath, mPiePaint);
    mPiepath.reset();
    startAngle = (int) (startAngle + mPieAngles[i] + angleDash);
}

這里我需要解釋一下罕邀,圖示效果,有一個弧度最大的扇形有一個偏移效果养距,我這邊是將path的起點(diǎn)坐標(biāo)從原來的(0诉探,0)變?yōu)椋?0,10)棍厌,將該扇形的矩形輪廓坐標(biāo)也對應(yīng)的偏移了10個像素肾胯,即可達(dá)到偏移效果
這里的startAngle是每個扇形的起始繪制的角度,每繪制一個扇形耘纱,下一個扇形的起始繪制角度就是 上一個扇形的角度與上一個扇形的起始的角度以及扇形之間的間隔角度和敬肚。

7、畫折線和文字 這里只貼出核心代碼解釋

        float xStart = (float) (mRadius * Math.cos(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
        float yStart = (float) (mRadius * Math.sin(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
        float xStop = (float) ((mRadius + lineFirstLength) * Math.cos(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
        float yStop = (float) ((mRadius + lineFirstLength) * Math.sin(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
        canvas.drawLine(xStart, yStart, xStop, yStop, mLinePaint);
        if (xStop > xStart) {
            canvas.drawLine(xStop, yStop, xStop + lineSecondLength, yStop, mLinePaint);
            mTextPaint.setTextAlign(Paint.Align.LEFT);
            canvas.drawText(texts[i], xStop + lineSecondLength + 10, yStop, mTextPaint);
        } else {
            canvas.drawLine(xStop, yStop, xStop - lineSecondLength, yStop, mLinePaint);
            mTextPaint.setTextAlign(Paint.Align.RIGHT);
            canvas.drawText(texts[i], xStop - lineSecondLength - 10, yStop, mTextPaint);
        }

根據(jù)三角函數(shù)很容易計算出束析,每個扇形的弧長中點(diǎn)坐標(biāo) 即上面的xStart,yStart 然后根據(jù)同樣的算法艳馒,將半徑延長即可計算出第一段線段的終點(diǎn)坐標(biāo) 即 xStop,yStop,根據(jù)這兩個點(diǎn)即可畫出第一段線段。

第二段線段就需要做一些判斷了 根據(jù)第一段線段的走向弄慰,判斷出第二段線段的走勢第美,如何第一段是趨于向右的,那么第二段線段水平向右陆爽,反之向左什往。

畫完兩段線段之后再末尾 繪制對應(yīng)的文字 (這里根據(jù)畫筆paint的一個屬性即可確定文字是從左向右還是從右向左)
mTextPaint.setTextAlign(Paint.Align.LEFT);

到此,簡單的餅圖就繪制完成了慌闭,其中主要弧長中點(diǎn)坐標(biāo)的計算恶守,以及三角函數(shù)和android的drawXXX()方法的結(jié)合使用

源碼github地址:https://github.com/weiranqiaobo/pieDemo/tree/master

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贡必,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庸毫,老刑警劉巖仔拟,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異飒赃,居然都是意外死亡利花,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門载佳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炒事,“玉大人,你說我怎么就攤上這事蔫慧∧尤椋” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵姑躲,是天一觀的道長睡扬。 經(jīng)常有香客問我,道長黍析,這世上最難降的妖魔是什么卖怜? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮阐枣,結(jié)果婚禮上马靠,老公的妹妹穿的比我還像新娘。我一直安慰自己蔼两,他們只是感情好甩鳄,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著额划,像睡著了一般娩贷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锁孟,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天彬祖,我揣著相機(jī)與錄音茁瘦,去河邊找鬼。 笑死储笑,一個胖子當(dāng)著我的面吹牛甜熔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播突倍,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼腔稀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了羽历?” 一聲冷哼從身側(cè)響起焊虏,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秕磷,沒想到半個月后诵闭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澎嚣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年疏尿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片易桃。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡褥琐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晤郑,到底是詐尸還是另有隱情敌呈,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布造寝,位于F島的核電站驱富,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏匹舞。R本人自食惡果不足惜褐鸥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赐稽。 院中可真熱鬧叫榕,春花似錦、人聲如沸姊舵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽括丁。三九已至荞下,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尖昏。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工仰税, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抽诉。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓陨簇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親迹淌。 傳聞我的和親對象是個殘疾皇子河绽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件唉窃、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,029評論 4 62
  • Nikki Haley Nimrata"Nikki"Haley(néeRandhawa, born January...
    RED_cc33閱讀 422評論 0 0
  • AQTime AQTime簡介 AQTime針對運(yùn)行時分析:性能瓶頸耙饰、內(nèi)存泄露、代碼覆蓋率纹份、故障模擬苟跪,在影響產(chǎn)品質(zhì)...
    龍翱天際閱讀 596評論 0 0
  • 世間的人,有各種各樣浩如煙海變化多端的牍疏,人的需要 有需要蠢笋,就有交易,就有了生意 我滿足你的需要鳞陨,你給我錢昨寞,天經(jīng)地義...
    傅李葉_aiden閱讀 167評論 0 0
  • 事情的開始應(yīng)該這樣講起援岩,昨晚和大一時參加學(xué)生會而成為了摯友的男人女人們出去聚了餐,說說笑笑間談起了最近的改變掏导。大家...
    MH木子閱讀 220評論 0 0