Android PathEffect - DashPathEffect

前言

研究一個(gè)類使用方法的最好途徑是閱讀官方文檔 DashPathEffect

作用

DashPathEffect作用是將Path的線段虛線化然眼。

構(gòu)造函數(shù)

DashPathEffect 的構(gòu)造函數(shù)有兩個(gè)參數(shù):

DashPathEffect (float[] intervals, float phase)

官方文檔解釋如下:

The intervals array must contain an even number of entries (>=2), with the even indices specifying the "on" intervals, and the odd indices specifying the "off" intervals. phase is an offset into the intervals array (mod the sum of all of the intervals). The intervals array controls the length of the dashes. The paint's strokeWidth controls the thickness of the dashes. Note: this path effect only affects drawing with the paint's style is set to STROKE or FILL_AND_STROKE. It is ignored if the drawing is done with style == FILL.

翻譯成中文如下:

間隔數(shù)組必須包含偶數(shù)個(gè)條目(大于等于2)勒魔,偶數(shù)索引指定“開”間隔愈捅,而奇數(shù)索引指定“關(guān)”間隔哎媚。相位是間隔數(shù)組的偏移量(所有間隔的總和)忽你。間隔數(shù)組控制了沖線的長(zhǎng)度宗侦。畫筆寬度寬度控制著沖線的厚度。注意:路徑效果只對(duì)畫筆樣式為描邊或填充和描邊有效嗅剖。如果畫筆樣式為填充則會(huì)忽略它辩越。

下面通過一個(gè)示例來研究這兩個(gè)參數(shù)的作用。

代碼部分
  • MainActivity.java
package ivan.rich.patheffect;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
  • activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="ivan.rich.patheffect.MainActivity">

    <ivan.rich.patheffect.PathEffectView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
  • PathEffectView.java
package ivan.rich.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

public class PathEffectView extends View {

    private int mWidth;
    private int mHeight;

    private Paint mLinePaint;
    private Paint mPaint;
    private Path mPath;

    public PathEffectView(Context context) {
        this(context, null);
    }

    public PathEffectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(20);
        mPaint.setColor(getResources().getColor(R.color.colorPrimary));
        mPaint.setStyle(Paint.Style.STROKE);

        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLinePaint.setStrokeWidth(1);
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setColor(getResources().getColor(R.color.colorAccent));

        mPath = new Path();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 繪制一條參考線
        canvas.drawLine(60, 0, 60, mHeight, mLinePaint);

        // 繪制第一條虛線
        DashPathEffect dashPathEffect1 = new DashPathEffect(new float[]{60, 60}, 0);
        mPaint.setPathEffect(dashPathEffect1);
        mPath.reset();
        mPath.moveTo(0, mHeight / 10);
        mPath.lineTo(mWidth, mHeight / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第二條虛線
        DashPathEffect dashPathEffect2 = new DashPathEffect(new float[]{60, 60}, 20);
        mPaint.setPathEffect(dashPathEffect2);
        mPath.reset();
        mPath.moveTo(0, mHeight * 2 / 10);
        mPath.lineTo(mWidth, mHeight * 2 / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第三條虛線
        DashPathEffect dashPathEffect3 = new DashPathEffect(new float[]{60, 60}, 40);
        mPaint.setPathEffect(dashPathEffect3);
        mPath.reset();
        mPath.moveTo(0, mHeight * 3 / 10);
        mPath.lineTo(mWidth, mHeight * 3 / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第四條虛線
        DashPathEffect dashPathEffect4 = new DashPathEffect(new float[]{60, 60}, 60);
        mPaint.setPathEffect(dashPathEffect4);
        mPath.reset();
        mPath.moveTo(0, mHeight * 4 / 10);
        mPath.lineTo(mWidth, mHeight * 4 / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第五條虛線
        DashPathEffect dashPathEffect5 = new DashPathEffect(new float[]{60, 60, 30, 30}, 0);
        mPaint.setPathEffect(dashPathEffect5);
        mPath.reset();
        mPath.moveTo(0, mHeight * 6 / 10);
        mPath.lineTo(mWidth, mHeight * 6 / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第六條虛線
        DashPathEffect dashPathEffect6 = new DashPathEffect(new float[]{60, 30, 30, 60}, 0);
        mPaint.setPathEffect(dashPathEffect6);
        mPath.reset();
        mPath.moveTo(0, mHeight * 7 / 10);
        mPath.lineTo(mWidth, mHeight * 7 / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第七條虛線
        DashPathEffect dashPathEffect7 = new DashPathEffect(new float[]{30, 60, 60, 30}, 0);
        mPaint.setPathEffect(dashPathEffect7);
        mPath.reset();
        mPath.moveTo(0, mHeight * 8 / 10);
        mPath.lineTo(mWidth, mHeight * 8 / 10);
        canvas.drawPath(mPath, mPaint);

        // 繪制第八條虛線
        DashPathEffect dashPathEffect8 = new DashPathEffect(new float[]{30, 30, 60, 60}, 0);
        mPaint.setPathEffect(dashPathEffect8);
        mPath.reset();
        mPath.moveTo(0, mHeight * 9 / 10);
        mPath.lineTo(mWidth, mHeight * 9 / 10);
        canvas.drawPath(mPath, mPaint);
    }
}
運(yùn)行結(jié)果
DashPathEffect.jpg
參數(shù)分析

1.首先看截圖上半部分的四條虛線段信粮,四條虛線對(duì)應(yīng)的DashPathEffect如下:

DashPathEffect dashPathEffect1 = new DashPathEffect(new float[]{60, 60}, 0);
DashPathEffect dashPathEffect2 = new DashPathEffect(new float[]{60, 60}, 20);
DashPathEffect dashPathEffect3 = new DashPathEffect(new float[]{60, 60}, 40);
DashPathEffect dashPathEffect4 = new DashPathEffect(new float[]{60, 60}, 60);

這四個(gè)DashPathEffect的區(qū)別在于第二個(gè)參數(shù)phase值不同黔攒,以參考線為基準(zhǔn)可以清晰地看到phase參數(shù)的作用是將整個(gè)View向“左”移動(dòng)phase。那么將View向左移動(dòng)phase是什么意思呢强缘?下面通過一個(gè)小示例就知道了督惰。

修改PathEffectView的onDraw代碼:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 繪制兩個(gè)條參考線
    canvas.drawLine(60, 0, 60, mHeight, mLinePaint);
    canvas.drawLine(0, mHeight / 4, mWidth, mHeight / 4, mLinePaint);

    DashPathEffect dashPathEffect = new DashPathEffect(new float[]{60, 60}, 60);
    mPaint.setPathEffect(dashPathEffect);

    mPath.reset();
    mPath.moveTo(60, mHeight / 4);
    mPath.lineTo(mWidth, mHeight * 3 / 4);
    canvas.drawPath(mPath, mPaint);
}

運(yùn)行之后結(jié)果如下:


pahse"左移"示意圖.jpg

在圖中繪制了兩條參考線,參考線的交點(diǎn)為Path的起始點(diǎn)旅掂,從(60, mheight/4)到(mWidth, mHeight * 3 / 4)繪制一條直線赏胚,然后給畫筆設(shè)置DashPathEffect,DashPathEffect的第二個(gè)參數(shù)的值設(shè)為60商虐,上面截圖可以清楚看到“左”移60之后的效果觉阅,因?yàn)樘摼€的實(shí)線部分寬度剛好也為60崖疤,所以最后效果就是第一個(gè)實(shí)線段消失了。

2.然后看截圖下半部分的四條虛線段留拾,這四條虛線段對(duì)應(yīng)的DashPathEffect如下:

DashPathEffect dashPathEffect5 = new DashPathEffect(new float[]{60, 60, 30, 30}, 0);
DashPathEffect dashPathEffect6 = new DashPathEffect(new float[]{60, 30, 30, 60}, 0);
DashPathEffect dashPathEffect7 = new DashPathEffect(new float[]{30, 60, 60, 30}, 0);
DashPathEffect dashPathEffect8 = new DashPathEffect(new float[]{60, 60, 40, 40, 20, 20}, 0);

從效果圖可以看出間隔數(shù)組的偶數(shù)索引處數(shù)組值對(duì)應(yīng)的是實(shí)線寬度戳晌,奇數(shù)索引處數(shù)組值對(duì)應(yīng)的是實(shí)線之后空白線的寬度。前面已經(jīng)提到過數(shù)組必須包含偶數(shù)個(gè)條目痴柔,所以“on”和“off”值是對(duì)應(yīng)的沦偎。在繪制View時(shí)系統(tǒng)遍歷當(dāng)前間隔數(shù)組,依次繪制第一個(gè)“on”和第一個(gè)“off”值咳蔚,第二個(gè)“on”和第二個(gè)“off"值豪嚎。。谈火。侈询,照此類推直至繪制完所有對(duì)應(yīng)的"on"和"off”值,然后按照此方法循環(huán)遍歷間隔數(shù)組直至View的繪制完成糯耍。用代碼概括來說就是:

for (i=0 ; i<intervals.length; i+=2) {
    // 實(shí)線寬度on
    mLineWidth = intervals[i];
    // 實(shí)線之間空白線寬度off
    mBlankSpace = intervals[i+1];
}
總結(jié)

構(gòu)造函數(shù)

DashPathEffect(float intervals[], float phase)

參數(shù)含義

  • intervals: 控制實(shí)線和實(shí)線之后空白線的寬度(數(shù)組長(zhǎng)度必須為偶數(shù))
  • phase: 將View向”左“偏移phase

用法

Paint.setPathEffect(DashPathEffect dashPathEffect);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扔字,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子温技,更是在濱河造成了極大的恐慌革为,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舵鳞,死亡現(xiàn)場(chǎng)離奇詭異震檩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蜓堕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門抛虏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人套才,你說我怎么就攤上這事迂猴。” “怎么了背伴?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵错忱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我挂据,道長(zhǎng),這世上最難降的妖魔是什么儿普? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任崎逃,我火速辦了婚禮,結(jié)果婚禮上眉孩,老公的妹妹穿的比我還像新娘个绍。我一直安慰自己勒葱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布巴柿。 她就那樣靜靜地躺著凛虽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪广恢。 梳的紋絲不亂的頭發(fā)上凯旋,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音钉迷,去河邊找鬼至非。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糠聪,可吹牛的內(nèi)容都是我干的荒椭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼舰蟆,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼趣惠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起身害,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤味悄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后题造,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傍菇,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年界赔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丢习。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淮悼,死狀恐怖咐低,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袜腥,我是刑警寧澤见擦,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站羹令,受9級(jí)特大地震影響鲤屡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜福侈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一酒来、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肪凛,春花似錦堰汉、人聲如沸辽社。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滴铅。三九已至,卻和暖如春就乓,著一層夾襖步出監(jiān)牢的瞬間汉匙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工档址, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盹兢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓守伸,卻偏偏與公主長(zhǎng)得像绎秒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子尼摹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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