Android PathEffect - DashPathEffect

前言

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

作用

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

構造函數(shù)

DashPathEffect 的構造函數(shù)有兩個參數(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ù)個條目(大于等于2),偶數(shù)索引指定“開”間隔,而奇數(shù)索引指定“關”間隔。相位是間隔數(shù)組的偏移量(所有間隔的總和)。間隔數(shù)組控制了沖線的長度。畫筆寬度寬度控制著沖線的厚度。注意:路徑效果只對畫筆樣式為描邊或填充和描邊有效。如果畫筆樣式為填充則會忽略它。

下面通過一個示例來研究這兩個參數(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);
    }
}
運行結果
DashPathEffect.jpg
參數(shù)分析

1.首先看截圖上半部分的四條虛線段,四條虛線對應的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);

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

修改PathEffectView的onDraw代碼:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 繪制兩個條參考線
    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);
}

運行之后結果如下:


pahse"左移"示意圖.jpg

在圖中繪制了兩條參考線,參考線的交點為Path的起始點,從(60, mheight/4)到(mWidth, mHeight * 3 / 4)繪制一條直線,然后給畫筆設置DashPathEffect,DashPathEffect的第二個參數(shù)的值設為60,上面截圖可以清楚看到“左”移60之后的效果,因為虛線的實線部分寬度剛好也為60,所以最后效果就是第一個實線段消失了。

2.然后看截圖下半部分的四條虛線段,這四條虛線段對應的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ù)組值對應的是實線寬度,奇數(shù)索引處數(shù)組值對應的是實線之后空白線的寬度。前面已經(jīng)提到過數(shù)組必須包含偶數(shù)個條目,所以“on”和“off”值是對應的。在繪制View時系統(tǒng)遍歷當前間隔數(shù)組,依次繪制第一個“on”和第一個“off”值,第二個“on”和第二個“off"值。。。,照此類推直至繪制完所有對應的"on"和"off”值,然后按照此方法循環(huán)遍歷間隔數(shù)組直至View的繪制完成。用代碼概括來說就是:

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

構造函數(shù)

DashPathEffect(float intervals[], float phase)

參數(shù)含義

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

用法

Paint.setPathEffect(DashPathEffect dashPathEffect);
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容