android drawpath大小,Android Path和PathMeasure
本文繼續介紹自定義控件的相關內容,Path在一些高級特效中使用相當廣泛,如一些加載特效、刮刮卡和前段時間的比較火的撕衣應用。
Path一般結合xfermode或者貝塞爾曲線做一些很炫的交互效果,有關貝塞爾曲線的內容這里暫不涉及,本文主要介紹Path的一些簡單基礎用法,相關的類還包括PathMeasure,需要掌握PathMeasure的兩個方法:getLength()、getSegment。
Path封裝了由直線和曲線(二階,三階貝塞爾曲線)構成的幾何路徑。你能用Canvas中的drawPath來把這條路徑畫出來(同樣支持Paint的不同繪制模式),也可以用于剪裁畫布和根據路徑繪制文字。我們有時會用Path來描述一個圖像的輪廓,所以也會稱為輪廓線(輪廓線僅是Path的一種使用方法,兩者并不等價)。
PathMeasure
PathMeasure是用來測量Path路徑長度的類,可以通過getLength()獲取Path的長度,但是該值的大小與forceClosed強相關,forceClosed可以通過如下方法傳入:
public PathMeasure(Path path, boolean forceClosed)
public void setPath(Path path, boolean forceClosed)
forceClosed就是Path最終是否需要閉合,如果為true的話,則不管關聯的Path是否是閉合的,都會被閉合,forceClosed對綁定的Path不會產生任何影響。
可以通過如下一個簡單的代碼測試一下影響:
path.moveTo(100,100);
path.lineTo(100,300);
path.lineTo(300,300);
path.lineTo(300,100);
pathMeasure=new PathMeasure(path,true);
float length=pathMeasure.getLength();
Log.d(TAG, "MyPathView: length="+length);
上述代碼Path路徑就是繪制一個不閉合的正方形,如果將PathMeasure的第二個參數forceClosed傳入true,這是length為800,如果forceClosed為false,那么這時length為600。
一定要注意這里PathMeasure的forceClosed參數與Path類的close()方法的差異,PathMeasure的forceClosed參數并不會影響視覺上的繪制,就是說如果繪制Path不是閉合圖像,這時候視覺上仍然是不閉合的。
但是Path的close()方法會影響圖像,close()方法的意思是將當前點與初始點連接在一起,如果當前點與初始點不在一個點,這時候會將兩個點連接在一起,而且在視覺上可以看到效果。如果連接了最后一個點和初始點仍然無法形成封閉圖形,則close()方法什么也不做。
Direction
在使用Path繪制圖形時有一個Direction類型的參數,該參數有兩個值CW和CCW,其中CW是順時針的繪制,CCW是逆時針繪制。
public void addCircle(float x, float y, float radius, Direction dir)
public void addOval(RectF oval, Direction dir)
public void addRect(RectF rect, Direction dir)
public void addRoundRect(RectF rect, float rx, float ry, Direction dir)
Direction在繪制時一般沒有太大的差異,但是如果涉及到某些特效時,需要特別注意。
下面通過示例代碼運行截圖對比一下:
// 順時針
path.addCircle(500, 400, 300, Path.Direction.CW);
canvas.drawPath(path, paint);
canvas.drawTextOnPath(str, path, 0, 0, paint);
path.reset();
// 逆時針
path.addCircle(500, 1100, 300, Path.Direction.CCW);
canvas.drawPath(path, paint);
canvas.drawTextOnPath(str, path, 0, 0, paint);
PathMeasure的getSegment方法
public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)
該方法是一個boolean類型的方法,主要用于截取指定Path的片段到dst中,通過參數startD和stopD來控制截取的長度,最后一個參數startWithMoveTo表示起始點是否使用moveTo方法,通常為True,保證每次截取的Path片段都是正常的、完整的。
如果startWithMoveTo設置為false,通常是和dst一起使用,因為dst中保存的Path是被不斷添加的,而不是每次被覆蓋,設置為false,則新增的片段會從上一次Path終點開始計算,這樣可以保存截取的Path片段數組連續起來。
在Android kitkat版本及之前的版本,該方法所獲取到的path可能由于硬件加速問題導致無法被繪制顯示出來的。要解決該問題的簡單方法就是在所要獲取的path上執行lineTo(0, 0) 或執行rLineTo(0, 0)。
public MyPathView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
dstPath = new Path();
path = new Path();
path.addCircle(500, 500, 200, Path.Direction.CW);
pathMeasure = new PathMeasure(path, false);
length = pathMeasure.getLength();
final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
animatorValue = (float) valueAnimator.getAnimatedValue();
invalidate();
}
});
valueAnimator.setDuration(1300);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
dstPath.reset();
dstPath.lineTo(0, 0);
float stop = length * animatorValue;
float start = (float) (stop - ((0.5 - Math.abs(animatorValue - 0.5)) * length));
pathMeasure.getSegment(start, stop, dstPath, true);
canvas.drawPath(dstPath, paint);
}
Path與xfermode示例
Path也經常與xfermode組合使用,如下是一個簡單刮刮卡示例,如果有興趣可以參看Bitmap學習筆記。
public MyPathView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(30);
//paint.setAlpha(0);
//paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
path = new Path();
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
//雙緩沖機制創建前景灰色圖層
foreground = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
myCanvas = new Canvas(foreground);
myCanvas.drawColor(Color.GRAY);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.drawBitmap(foreground, 0, 0, null);
myCanvas.drawPath(path, paint);
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = (int) event.getX();
startY = (int) event.getY();
path.moveTo(startX, startY);
break;
case MotionEvent.ACTION_MOVE:
int stopX = (int) event.getX();
int stopY = (int) event.getY();
path.lineTo(stopX, stopY);
startX = stopX;
startY = stopY;
break;
}
invalidate();
return true;
}
小結
本文介紹的內容不多,都是一些Path的簡單基礎的用法,包括如何獲取繪制Path的長度,如何截取繪制Path的部分片段,通過Path和xfermode實現一個刮刮卡效果。將Path簡單的用法使用熟練后,然后再結合其它相關類就可以實現一些很炫很酷的交互效果。
下一篇文章中會介紹貝塞爾曲線相關的內容,貝塞爾曲線實現的交互確實要比正余弦函數實現的交互要平滑許多,比如加入購物車或者加載的波紋效果都會使用貝塞爾曲線。
總結
以上是生活随笔為你收集整理的android drawpath大小,Android Path和PathMeasure的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 零购商城官网(零购官网商家入驻)
- 下一篇: android studio socke