編輯:關於Android編程
用過電腦版印象筆記演示功能的應該知道這個效果,現在想在手機上實現一下,當然這個是最終的目標,這篇只是介紹實現過程中的一步 —— 繪制一條寬度逐漸變大的路徑
把一條路徑分成很多段,每段path首尾相連,然後依次設置每一段path的寬度,把這些path存儲在一個集合中,最後依次繪制出來。
這種方法實現的問題主要是如果截取的段太少,在拐角處顯示不圓滑,鋸齒嚴重,所以定義了DEFAULT_SEGMENT_LENGTH來控制截取長度,長度越小,鋸齒度越小,拐角處越圓滑。對於這個問題,如有更好的思路,請告訴我。
這裡要使用到PathMeasure,PathMeasure的getSegment方法就是獲取一段path,
public boolean getSegment (float startD, float stopD, Path dst, boolean startWithMoveTo)
startD 表示從path某個長度位置開始
stopD 表示某個長度位置結束
dst 表示截取後的path
startWithMoveTo 表示這個截取的path開始位置是否移動到截取的開始位置,false的話,path開始點位置是(0,0),這裡需要設置為true,不然達不到首尾相連的效果
對於path長度的獲取,PathMeasure有相應的方法getLength();
/** * 截取path * @param path */ private void getPaths(Path path){ PathMeasure pm = new PathMeasure(path, false); float length = pm.getLength(); int segmentSize = (int) Math.ceil(length / DEFAULT_SEGMENT_LENGTH); Path ps = null; PathSegment pe = null; int nowSize = pathSegments.size();//集合中已經有的 if(nowSize == 0){ ps = new Path(); pm.getSegment(0, length, ps, true); pe = new PathSegment(ps); pe.setAlpha(255); pe.setWidth(DEFAULT_WIDTH); pathSegments.add(pe); } else{ for (int i = nowSize; i < segmentSize; i++) { ps = new Path(); pm.getSegment((i - 1) * DEFAULT_SEGMENT_LENGTH - 0.4f, Math.min(i * DEFAULT_SEGMENT_LENGTH, length), ps, true); pe = new PathSegment(ps); pe.setAlpha(255); pe.setWidth((float) Math.min(MAX_WIDTH, i * 0.3 + DEFAULT_WIDTH)); pathSegments.add(pe); } } }
public class TailView2 extends View{ private Paint paint; private Path mFingerPath; private float mOriginX; private float mOriginY; private ListpathSegments; private class PathSegment{ Path path; float width; int alpha; public PathSegment(Path path) { this.path = path; } public Path getPath() { return path; } public void setPath(Path path) { this.path = path; } public float getWidth() { return width; } public void setWidth(float width) { this.width = width; } public int getAlpha() { return alpha; } public void setAlpha(int alpha) { this.alpha = alpha; } } public TailView2(Context context) { this(context, null, 0); } public TailView2(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TailView2(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.RED); //------------------------------------------------- mFingerPath = new Path(); pathSegments = new ArrayList<>(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); for (PathSegment p: pathSegments) { paint.setAlpha(p.getAlpha()); paint.setStrokeWidth(p.getWidth()); canvas.drawPath(p.getPath(), paint); } } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: pathSegments.clear(); mOriginX = x; mOriginY = y; mFingerPath.reset(); mFingerPath.moveTo(mOriginX, mOriginY); break; case MotionEvent.ACTION_MOVE: getPaths(mFingerPath); mFingerPath.lineTo(x, y); break; case MotionEvent.ACTION_UP: break; } invalidate(); return true; } /** * 越小,線條鋸齒度越小 */ private static final float DEFAULT_SEGMENT_LENGTH = 10F; private static final float DEFAULT_WIDTH = 3F; private static final float MAX_WIDTH = 45F; /** * 截取path * @param path */ private void getPaths(Path path){ PathMeasure pm = new PathMeasure(path, false); float length = pm.getLength(); int segmentSize = (int) Math.ceil(length / DEFAULT_SEGMENT_LENGTH); Path ps = null; PathSegment pe = null; int nowSize = pathSegments.size();//集合中已經有的 if(nowSize == 0){ ps = new Path(); pm.getSegment(0, length, ps, true); pe = new PathSegment(ps); pe.setAlpha(255); pe.setWidth(DEFAULT_WIDTH); pathSegments.add(pe); } else{ for (int i = nowSize; i < segmentSize; i++) { ps = new Path(); pm.getSegment((i - 1) * DEFAULT_SEGMENT_LENGTH - 0.4f, Math.min(i * DEFAULT_SEGMENT_LENGTH, length), ps, true); pe = new PathSegment(ps); pe.setAlpha(255); pe.setWidth((float) Math.min(MAX_WIDTH, i * 0.3 + DEFAULT_WIDTH)); pathSegments.add(pe); } } } }
要實現的效果如下考慮到關鍵是動畫效果,所以直接繼承View。不過CheckBox的超類CompoundButton實現了Checkable接口,這一點值得借鑒。下面記錄一
前言 在做移動開發過程中底部導航欄是十分常見的功能,且市面上見到的做法也有很多種,這篇博文記錄一下使用Fragment實現底部導航欄的功能,算是對這幾天學習Andr
Android安全加密專題文章索引 Android安全加密:對稱加密 Android安全加密:非對稱加密 Android安全加密:消