Android Graphics之PathEffect

#本文基於android sdk 22android


在android graphics模塊中有一類特效類叫作「path effect」,他們有一個共同的基類「PathEffect」。這些path effect的惟一目的就是給path增長特效,換句話話說只有當paint的style爲「STROKE」或者「FILL_AND_STROKE」時,path effect纔會生效。添加path effect的方式很簡單,只須要調用Paint.setPathEffect()便可。git


截止到android sdk 22,共有6中內置的PathEffect。下面表格列出這六種path effect,並給出基本說明。github



CornerPathEffect 處理path的各個鏈接點,能夠產生圓角效果,能夠控制圓角半徑
DashPathEffect 生成虛線效果,能夠分別控制實點和虛點長度,能夠控制偏移量
PathDashPathEffect 相似於DashPathEffect, 只不過增長了控制實點形狀的能力
DiscretePathEffect 沿着path產生毛邊的效果,能夠控制毛邊顆粒間距,以及毛邊顆粒偏移距離
ComposePathEffect 能夠將任意兩種path effect的效果,好比CornerPathEffect和DashPathEffect。不過要注意的是它與SumPathEffect的不一樣,ComposePathEffect的疊加效果至關於,先生效效果A,而後以A爲基礎生效效果B。
SumPathEffect 能夠疊加任意兩種path effect的效果,與Compose不一樣的是,它至關於同時生效A和B,而後在視圖上將兩種效果生硬的上下疊加起來。


下面是各類path effect的實例代碼和運行結果。canvas


CornerPathEffectide


核心代碼:this

package com.zlsam.learngraphics.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by zhanglong on 16/8/18.
 */
public class CornerPathEffectView extends View {

    private int mCornerRadius 5;
    private Path mPath;
    private Paint mPaint;

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

    public CornerPathEffectView(Context contextAttributeSet attrs) {
        this(contextattrs0);
    }

    public CornerPathEffectView(Context contextAttributeSet attrs, int defStyleAttr) {
        super(contextattrsdefStyleAttr);

        if (isInEditMode()) {
            // Init path
            mPath new Path();
            mPath.moveTo(10100);
            mPath.lineTo(6010);
            mPath.lineTo(120190);
            mPath.lineTo(18040);
            mPath.lineTo(240160);
            mPath.lineTo(30010);
            mPath.lineTo(360190);
            mPath.lineTo(42040);
            mPath.lineTo(480160);

            // Init paint
            mPaint new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(2);
            mPaint.setColor(Color.CYAN);
            mPaint.setPathEffect(new CornerPathEffect(mCornerRadius));
            return;
        }

        // Init path
        mPath new Path();
        mPath.moveTo(10100);
        mPath.lineTo(6010);
        mPath.lineTo(120190);
        mPath.lineTo(18040);
        mPath.lineTo(240160);
        mPath.lineTo(30010);
        mPath.lineTo(360190);
        mPath.lineTo(42040);
        mPath.lineTo(480160);

        // Init paint
        mPaint new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.CYAN);
        mPaint.setPathEffect(new CornerPathEffect(mCornerRadius));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPathmPaint);
    }

    public void setCornerRadius(int radius) {
        mCornerRadius = radius;
        mPaint.setPathEffect(new CornerPathEffect(mCornerRadius));
        invalidate();
    }

    public int getCornerRadius() {
        return mCornerRadius;
    }
}
























url


運行效果:spa

wKiom1e2dvWzM88ZAABVXOeP8Bk161.png-wh_50



DashPathEffect.net


核心代碼:3d


package com.zlsam.learngraphics.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by zhanglong on 16/8/18.
 */
public class DashPathEffectView extends View {

    private float mSolidLength 1F;
    private float mVirtualLength 1F;
    private float mPhase 0;
    private Path mPath;
    private Paint mPaint;


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

    public DashPathEffectView(Context contextAttributeSet attrs) {
        this(contextattrs0);
    }

    public DashPathEffectView(Context contextAttributeSet attrs, int defStyleAttr) {
        super(contextattrsdefStyleAttr);
        if (isInEditMode()) {
            // Init path
            mPath new Path();
            mPath.moveTo(10100);
            mPath.lineTo(6010);
            mPath.lineTo(120190);
            mPath.lineTo(18040);
            mPath.lineTo(240160);
            mPath.lineTo(30010);
            mPath.lineTo(360190);
            mPath.lineTo(42040);
            mPath.lineTo(480160);

            // Init paint
            mPaint new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(2);
            mPaint.setColor(Color.CYAN);
            mPaint.setPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase));
            return;
        }

        // Init path
        mPath new Path();
        mPath.moveTo(10100);
        mPath.lineTo(6010);
        mPath.lineTo(120190);
        mPath.lineTo(18040);
        mPath.lineTo(240160);
        mPath.lineTo(30010);
        mPath.lineTo(360190);
        mPath.lineTo(42040);
        mPath.lineTo(480160);

        // Init paint
        mPaint new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.CYAN);
        mPaint.setPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPathmPaint);
    }

    public void setSolidLength(float length) {
        mSolidLength = length;
        mPaint.setPathEffect(new DashPathEffect(new float[]{mSolidLengthmVirtualLength}mPhase));
        invalidate();
    }

    public float getSolidLength() {
        return mSolidLength;
    }

    public void setVirtualLength(float length) {
        mVirtualLength = length;
        mPaint.setPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase));
        invalidate();
    }

    public float getVirtualLength() {
        return mVirtualLength;
    }

    public void setPhase(float phase) {
        mPhase = phase;
        mPaint.setPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase));
        invalidate();
    }

    public float getPhase() {
        return mPhase;
    }

}






































運行效果:

wKiom1e2d36yXne3AACIsK_C_9U390.png-wh_50


PathDashPathEffect


核心代碼:


package com.zlsam.learngraphics.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by zhanglong on 16/8/18.
 */
public class PathDashPathEffectView extends View {

    private Path mPath;
    private Paint mPaint;

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

    public PathDashPathEffectView(Context contextAttributeSet attrs) {
        this(contextattrs0);
    }

    public PathDashPathEffectView(Context contextAttributeSet attrs, int defStyleAttr) {
        super(contextattrsdefStyleAttr);
        if (isInEditMode()) {
            // Init path
            mPath new Path();
            mPath.moveTo(10100);
            mPath.lineTo(6010);
            mPath.lineTo(120190);
            mPath.lineTo(18040);
            mPath.lineTo(240160);
            mPath.lineTo(30010);
            mPath.lineTo(360190);
            mPath.lineTo(42040);
            mPath.lineTo(480160);

            // Init paint
            mPaint new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(2);
            mPaint.setColor(Color.CYAN);

            Path path = new Path();
            path.addOval(new RectF(001020)Path.Direction.CCW);
            mPaint.setPathEffect(new PathDashPathEffect(path200PathDashPathEffect.Style.ROTATE));
            return;
        }

        // Init path
        mPath new Path();
        mPath.moveTo(10100);
        mPath.lineTo(6010);
        mPath.lineTo(120190);
        mPath.lineTo(18040);
        mPath.lineTo(240160);
        mPath.lineTo(30010);
        mPath.lineTo(360190);
        mPath.lineTo(42040);
        mPath.lineTo(480160);

        // Init paint
        mPaint new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.CYAN);
        Path path = new Path();
        path.addOval(new RectF(001020)Path.Direction.CCW);
        mPaint.setPathEffect(new PathDashPathEffect(path200PathDashPathEffect.Style.ROTATE));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPathmPaint);
    }
}



















運行結果:

wKiom1e2d9PSUTM9AABPwNPbObc547.png-wh_50


DiscretePathEffect


核心代碼:


package com.zlsam.learngraphics.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DiscretePathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by zhanglong on 16/8/18.
 */
public class DiscretePathEffectView extends View {

    private float mSegmentLength 1.0F;
    private float mDeviation 1.0F;
    private Path mPath;
    private Paint mPaint;

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

    public DiscretePathEffectView(Context contextAttributeSet attrs) {
        this(contextattrs0);
    }

    public DiscretePathEffectView(Context contextAttributeSet attrs, int defStyleAttr) {
        super(contextattrsdefStyleAttr);
        if (isInEditMode()) {
            // Init path
            mPath new Path();
            mPath.moveTo(10100);
            mPath.lineTo(6010);
            mPath.lineTo(120190);
            mPath.lineTo(18040);
            mPath.lineTo(240160);
            mPath.lineTo(30010);
            mPath.lineTo(360190);
            mPath.lineTo(42040);
            mPath.lineTo(480160);

            // Init paint
            mPaint new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(2);
            mPaint.setColor(Color.CYAN);
            mPaint.setPathEffect(new DiscretePathEffect(mSegmentLengthmDeviation));
            return;
        }

        // Init path
        mPath new Path();
        mPath.moveTo(10100);
        mPath.lineTo(6010);
        mPath.lineTo(120190);
        mPath.lineTo(18040);
        mPath.lineTo(240160);
        mPath.lineTo(30010);
        mPath.lineTo(360190);
        mPath.lineTo(42040);
        mPath.lineTo(480160);

        // Init paint
        mPaint new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.CYAN);
        mPaint.setPathEffect(new DiscretePathEffect(mSegmentLengthmDeviation));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPathmPaint);
    }

    public void setSegmentLength(float length) {
        mSegmentLength = length;
        mPaint.setPathEffect(new DiscretePathEffect(mSegmentLengthmDeviation));
        invalidate();
    }

    public float getSegmentLength() {
        return mSegmentLength;
    }

    public void setDeviation(float deviation) {
        mDeviation = deviation;
        mPaint.setPathEffect(new DiscretePathEffect(mSegmentLengthmDeviation));
        invalidate();
    }

    public float getDeviation() {
        return mDeviation;
    }
}































運行結果:

wKiom1e2eBmhokp1AACLD9g6s4A811.png-wh_50


ComposePathEffect


核心代碼:


package com.zlsam.learngraphics.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposePathEffect;
import android.graphics.CornerPathEffect;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by zhanglong on 16/8/18.
 */
public class ComposePathEffectView extends View {

    private int mCornerRadius 0;
    private float mSolidLength 1F;
    private float mVirtualLength 1F;
    private float mPhase 0;
    private Path mPath;
    private Paint mPaint;

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

    public ComposePathEffectView(Context contextAttributeSet attrs) {
        this(contextattrs0);
    }

    public ComposePathEffectView(Context contextAttributeSet attrs, int defStyleAttr) {
        super(contextattrsdefStyleAttr);
        if (isInEditMode()) {
            // Init path
            mPath new Path();
            mPath.moveTo(10100);
            mPath.lineTo(6010);
            mPath.lineTo(120190);
            mPath.lineTo(18040);
            mPath.lineTo(240160);
            mPath.lineTo(30010);
            mPath.lineTo(360190);
            mPath.lineTo(42040);
            mPath.lineTo(480160);

            // Init paint
            mPaint new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(2);
            mPaint.setColor(Color.CYAN);
           mPaint.setPathEffect(new ComposePathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
            return;
        }

        // Init path
        mPath new Path();
        mPath.moveTo(10100);
        mPath.lineTo(6010);
        mPath.lineTo(120190);
        mPath.lineTo(18040);
        mPath.lineTo(240160);
        mPath.lineTo(30010);
        mPath.lineTo(360190);
        mPath.lineTo(42040);
        mPath.lineTo(480160);

        // Init paint
        mPaint new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.CYAN);
       mPaint.setPathEffect(new ComposePathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPathmPaint);
    }

    public void setCornerRadius(int radius) {
        mCornerRadius = radius;
        mPaint.setPathEffect(new ComposePathEffect(new DashPathEffect(new float[]{mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public int getCornerRadius() {
        return mCornerRadius;
    }

    public void setSolidLength(float length) {
        mSolidLength = length;
       mPaint.setPathEffect(new ComposePathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public float getSolidLength() {
        return mSolidLength;
    }

    public void setVirtualLength(float length) {
        mVirtualLength = length;
       mPaint.setPathEffect(new ComposePathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public float getVirtualLength() {
        return mVirtualLength;
    }

    public void setPhase(float phase) {
        mPhase = phase;
       mPaint.setPathEffect(new ComposePathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public float getPhase() {
        return mPhase;
    }

}












































運行結果:

wKioL1e2eGyx-FCOAACjDl32eWo019.png-wh_50


SumPathEffect


核心代碼:


package com.zlsam.learngraphics.patheffect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.SumPathEffect;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by zhanglong on 16/8/18.
 */
public class SumPathEffectView extends View {

    private int mCornerRadius 0;
    private float mSolidLength 1F;
    private float mVirtualLength 1F;
    private float mPhase 0;
    private Path mPath;
    private Paint mPaint;

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

    public SumPathEffectView(Context contextAttributeSet attrs) {
        this(contextattrs0);
    }

    public SumPathEffectView(Context contextAttributeSet attrs, int defStyleAttr) {
        super(contextattrsdefStyleAttr);

        if (isInEditMode()) {
            // Init path
            mPath new Path();
            mPath.moveTo(10100);
            mPath.lineTo(6010);
            mPath.lineTo(120190);
            mPath.lineTo(18040);
            mPath.lineTo(240160);
            mPath.lineTo(30010);
            mPath.lineTo(360190);
            mPath.lineTo(42040);
            mPath.lineTo(480160);

            // Init paint
            mPaint new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(2);
            mPaint.setColor(Color.CYAN);
           mPaint.setPathEffect(new SumPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
            return;
        }

        // Init path
        mPath new Path();
        mPath.moveTo(10100);
        mPath.lineTo(6010);
        mPath.lineTo(120190);
        mPath.lineTo(18040);
        mPath.lineTo(240160);
        mPath.lineTo(30010);
        mPath.lineTo(360190);
        mPath.lineTo(42040);
        mPath.lineTo(480160);

        // Init paint
        mPaint new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.CYAN);
       mPaint.setPathEffect(new SumPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPath(mPathmPaint);
    }

    public void setCornerRadius(int radius) {
        mCornerRadius = radius;
        mPaint.setPathEffect(new SumPathEffect(new DashPathEffect(new float[]{mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public int getCornerRadius() {
        return mCornerRadius;
    }

    public void setSolidLength(float length) {
        mSolidLength = length;
       mPaint.setPathEffect(new SumPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public float getSolidLength() {
        return mSolidLength;
    }

    public void setVirtualLength(float length) {
        mVirtualLength = length;
       mPaint.setPathEffect(new SumPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public float getVirtualLength() {
        return mVirtualLength;
    }

    public void setPhase(float phase) {
        mPhase = phase;
       mPaint.setPathEffect(new SumPathEffect(new DashPathEffect(new float[] {mSolidLengthmVirtualLength}mPhase), new CornerPathEffect(mCornerRadius)));
        invalidate();
    }

    public float getPhase() {
        return mPhase;
    }
}











































運行結果:

wKiom1e2eJjDWl38AACqVrCdg5o514.png-wh_50


本文的示例×××地址:https://github.com/zhanglong1/AndroidGraphicsDemo

相關文章
相關標籤/搜索