* setARGB(int a,int r,int g,int b); 設置繪製的顏色,a表明透明度,r,g,b表明顏色值。 * setAlpha(int a); 設置繪製圖形的透明度。 * setColor(int color); 設置繪製的顏色,使用顏色值來表示,該顏色值包括透明度和RGB顏色。 * setAntiAlias(boolean aa); 設置是否使用抗鋸齒功能,會消耗較大資源,繪製圖形速度會變慢。 * setDither(boolean dither); 設定是否使用圖像抖動處理,會使繪製出來的圖片顏色更加平滑和飽滿,圖像更加清晰 * setFilterBitmap(boolean filter); 若是該項設置爲true,則圖像在動畫進行中會濾掉對Bitmap圖像的優化操做,加快顯示速度,本設置項依賴於dither和xfermode的設置 * setMaskFilter(MaskFilter maskfilter); 設置MaskFilter,能夠用不一樣的MaskFilter實現濾鏡的效果,如濾化,立體等 * setColorFilter(ColorFilter colorfilter); 設置顏色過濾器,能夠在繪製顏色時實現不用顏色的變換效果 * setPathEffect(PathEffect effect); 設置繪製路徑的效果,如點畫線等 * setShader(Shader shader); 設置圖像效果,使用Shader能夠繪製出各類漸變效果 * setShadowLayer(float radius ,float dx,float dy,int color); 在圖形下面設置陰影層,產生陰影效果,radius爲陰影的角度,dx和dy爲陰影在x軸和y軸上的距離,color爲陰影的顏色 * setStyle(Paint.Style style); 設置畫筆的樣式,爲FILL,FILL_AND_STROKE,或STROKE * setStrokeCap(Paint.Cap cap); 當畫筆樣式爲STROKE或FILL_AND_STROKE時,設置筆刷的圖形樣式,如圓形樣式 Cap.ROUND,或方形樣式Cap.SQUARE * setSrokeJoin(Paint.Join join); 設置繪製時各圖形的結合方式,如平滑效果等 * setStrokeWidth(float width); 當畫筆樣式爲STROKE或FILL_AND_STROKE時,設置筆刷的粗細度 * setXfermode(Xfermode xfermode); 設置圖形重疊時的處理方式,如合併,取交集或並集,常常用來製做橡皮的擦除效果
* setFakeBoldText(boolean fakeBoldText); 模擬實現粗體文字,設置在小字體上效果會很是差 * setSubpixelText(boolean subpixelText); 設置該項爲true,將有助於文本在LCD屏幕上的顯示效果 * setTextAlign(Paint.Align align); 設置繪製文字的對齊方向 * setTextScaleX(float scaleX); 設置繪製文字x軸的縮放比例,能夠實現文字的拉伸的效果 * setTextSize(float textSize); 設置繪製文字的字號大小 * setTextSkewX(float skewX); 設置斜體文字,skewX爲傾斜弧度 * setTypeface(Typeface typeface); 設置Typeface對象,即字體風格,包括粗體,斜體以及襯線體,非襯線體等 * setUnderlineText(boolean underlineText); 設置帶有下劃線的文字效果 * setStrikeThruText(boolean strikeThruText); 設置帶有刪除線的效果
* Canvas(Bitmap bitmap): 以bitmap對象建立一個畫布,則將內容都繪製在bitmap上,所以bitmap不得爲null。 * Canvas(GL gl): 在繪製3D效果時使用,與OpenGL相關。 * isOpaque(boolean isOpaque):檢測是否支持透明。 * setViewport(int left, int top, int right, int bottom, int clipflag): 設置畫布中顯示窗口。 * drawColor(int color): 設置Canvas的背景顏色。 * setBitmap(Bitmap mBitmap): 設置具體畫布,畫的內容,保存爲一個Bitmap。 * clipRect(float left, float top, float right, float bottom): 設置顯示區域,即設置裁剪區。 * translate(float x, float y): 平移畫布。 * rotate(float degree, float px, float py): 旋轉畫布 。 * skew(float sx, float sy): 設置偏移量。 * save(): 將Canvas當前狀態保存在堆棧,save以後能夠調用Canvas的平移、旋轉、錯切、剪裁等操做。 * restore(): 恢復爲以前堆棧保存的Canvas狀態,防止save後對Canvas執行的操做對後續的繪製有影響。restore和save要配對使用,restore能夠比save少,但不能比save多,不然會引起error。save和restore之間,每每夾雜的是對Canvas的特殊操做。 * save(int num):將Canvas當前狀態保存在堆棧,並予以編號int * restoreToCount(int num):恢復爲以前堆棧保存的編號爲int的Canvas狀態 * concat(Matrix matrix):畫布關聯矩陣,畫出來的內容按矩陣改變,而不是畫布改變。 * Drawable.draw(Canvas canvas):將Drawable畫到Canvas中 注:這種方式畫Drawable怎麼設置透明度呢?((BitmapDrawable)Drawable).getPaint().setAlpha(mBgAlpha);
* canvas.drawPaint(Paint paint) 將畫筆設置的顏色和透明度鋪滿畫布 * drawRect(RectF rect, Paint paint) 繪製矩形,參數一爲RectF一個區域 * drawRect(float left, float top, float right, float bottom, Paint paint) 繪製矩形,left:矩形left的x座標,top:矩形top的y座標,right:矩形right的x座標,bottom:矩形bottom的y座標 * drawRoundRect(RectF rect, float rx, float ry, Paint paint) 繪製圓角矩形, rx:x方向的圓角半徑,ry:y方向的圓角半徑 * drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) * drawPath(Path path, Paint paint) 繪製一個路徑,參數一爲Path路徑對象 * drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 貼圖,參數一就是咱們常規的Bitmap對象,參數二是源區域(這裏是bitmap),參數三是目標區域(應該在canvas的位置和大小),參數四是Paint畫刷對象,由於用到了縮放和拉伸的可能,當原始Rect不等於目標Rect時性能將會有大幅損失。 * drawBitmap (Bitmap bitmap, float left, float top, Paint paint) * drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) 畫線,參數一塊兒始點的x軸位置,參數二起始點的y軸位置,參數三終點的x軸水平位置,參數四y軸垂直位置,最後一個參數爲Paint 畫刷對象。 * drawPoint(float x, float y, Paint paint) 畫點,參數一水平x軸,參數二垂直y軸,第三個參數爲Paint對象。 * drawText(String text, float x, floaty, Paint paint) 渲染文本,Canvas類除了上面的還能夠描繪文字,參數一是String類型的文本,參數二文字左側到x軸距離,參數三文字BaseLine到y軸距離,參數四是Paint對象。 * drawOval(RectF oval, Paint paint) 繪製橢圓,參數一是掃描區域,參數二爲paint對象 * drawOval(float left, float top, float right, float bottom, Paint paint) * drawCircle(float cx, float cy, float radius,Paint paint) 繪製圓,參數一是中心點的x軸,參數二是中心點的y軸,參數三是半徑,參數四是paint對象; * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 畫弧,參數一是RectF對象,指定圓弧的外輪廓矩形區域,參數二是起始角(度)在電弧的開始,參數三掃描角(度)開始順時針測量的,參數四是若是這是真的話,包括橢圓中心的電弧,並關閉它,若是它是假這將是一個弧線,參數五是Paint對象;
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } Canvas canvas = new Canvas();
private Paint paint = new Paint(); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setAntiAlias(true); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(200,200,100 , paint); }
private Paint paint = new Paint(); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawRect(100, 100, 200, 200, paint); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { canvas.drawRoundRect(400, 100, 600, 300, 30, 30, paint); } paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(20); canvas.drawRect(100, 400, 300, 600, paint); }
private Paint paint = new Paint(); @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setTextSize(100); canvas.drawText("瀟湘劍雨", 100, 100, paint); }
private Paint paint = new Paint(); @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setAntiAlias(true); paint.setColor(Color.RED); RectF rel = new RectF(50, 50, 150, 150); //實心圓弧 canvas.drawArc(rel, 0, 135, false, paint); //實心圓弧 將圓心包含在內 RectF rel2 = new RectF(50, 200, 150, 300); canvas.drawArc(rel2, 0, 135, true, paint); //設置空心Style paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(20); RectF rel3 = new RectF(50, 350, 150, 450); canvas.drawArc(rel3, 0, 270, false, paint); RectF rel4 = new RectF(50, 250, 150, 600); canvas.drawArc(rel4, 0, 270, true, paint); }
private Paint paint = new Paint(); @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Path angle = new Path(); angle.moveTo(250, 0); angle.lineTo(0, 500); angle.lineTo(100, 300); angle.lineTo(200, 350); angle.lineTo(500, 500); angle.close(); canvas.drawPath(angle, paint); }
private Paint mPaint = new Paint(); @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.BLUE); mPaint.setColor(Color.RED); canvas.drawRect(new Rect(0, 0, 800, 800), mPaint); canvas.save(); mPaint.setColor(Color.GREEN); canvas.rotate(45,400,400); canvas.drawRect(new Rect(0, 0, 800, 800), mPaint); canvas.restore(); }
/** * Preconcat the current matrix with the specified rotation. * @param degrees The amount to rotate, in degrees */ public native void rotate(float degrees); /** * Preconcat the current matrix with the specified rotation. * @param degrees The amount to rotate, in degrees * @param px The x-coord for the pivot point (unchanged by the rotation) * @param py The y-coord for the pivot point (unchanged by the rotation) */ public final void rotate(float degrees, float px, float py) { translate(px, py); rotate(degrees); translate(-px, -py); }
private Paint mPaint = new Paint(); @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.YELLOW); mPaint.setColor(Color.RED); canvas.drawRect(new Rect(0, 0, 800, 800), mPaint); // 保存畫布狀態 canvas.save(); canvas.scale(0.5f, 0.5f); mPaint.setColor(Color.GREEN); canvas.drawRect(new Rect(0, 0, 800, 800), mPaint); // 畫布狀態回滾 canvas.restore(); canvas.scale(0.5f, 0.5f, 400, 400); mPaint.setColor(Color.BLUE); canvas.drawRect(new Rect(0, 0, 800, 800), mPaint); }
/** * Preconcat the current matrix with the specified scale. * @param sx The amount to scale in X * @param sy The amount to scale in Y */ public native void scale(float sx, float sy); /** * Preconcat the current matrix with the specified scale. * @param sx The amount to scale in X * @param sy The amount to scale in Y * @param px The x-coord for the pivot point (unchanged by the scale) * @param py The y-coord for the pivot point (unchanged by the scale) */ public final void scale(float sx, float sy, float px, float py) { translate(px, py); scale(sx, sy); translate(-px, -py); }
public int left; public int top; public int right; public int bottom;
public Rect(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } public Rect(Rect r) { if (r == null) { left = top = right = bottom = 0; } else { left = r.left; top = r.top; right = r.right; bottom = r.bottom; } }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Rect r = (Rect) o; return left == r.left && top == r.top && right == r.right && bottom == r.bottom; } @Override public int hashCode() { int result = left; result = 31 * result + top; result = 31 * result + right; result = 31 * result + bottom; return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(32); sb.append("Rect("); sb.append(left); sb.append(", "); sb.append(top); sb.append(" - "); sb.append(right); sb.append(", "); sb.append(bottom); sb.append(")"); return sb.toString(); }
//文章開頭說的公式在這裏獲得了應驗 public final int width() { return right - left; }
public final int height() { return bottom - top; }
//由於left是最左側,right比left還小不就不成形了麼?寬高同是如此 public final boolean isEmpty() { return left >= right || top >= bottom; }
public void setEmpty() { left = right = top = bottom = 0; }
public void set(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; }
/** * <pre> * @author yangchong * blog : https://github.com/yangchong211 * time : 2016/5/18 * desc : 紅點自定義控件 * revise: 建議設置紅點寬高同樣,不然是橢圓 * </pre> */ public class DotView extends View { private boolean isInit = false; private boolean isSelected = false; private float mViewHeight; private float mViewWidth; private float mRadius; private Paint mPaintBg = new Paint(); private int mBgUnselectedColor = Color.parseColor("#1A000000"); private int mBgSelectedColor = Color.parseColor("#FDE26E"); private static final float mArcWidth = 2.0f; public DotView(Context context) { super(context); } public DotView(Context context, AttributeSet attrs) { super(context, attrs); } public DotView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (!isInit) { isInit = true; mViewHeight = getHeight(); mViewWidth = getWidth(); if (mViewHeight >= mViewWidth) { mRadius = mViewWidth / 2.f; } else { mRadius = mViewHeight / 2.f; } } //是否選中 if (isSelected){ drawSelectedDot(canvas); } else{ drawUnSelectedDot(canvas); } } /** * 繪製選中指示器紅點 * @param canvas canvas */ private void drawSelectedDot(Canvas canvas) { //設置paint相關屬性 mPaintBg.setAntiAlias(true); mPaintBg.setColor(mBgSelectedColor); mPaintBg.setStyle(Style.FILL); //繪製圓 canvas.drawCircle(mViewWidth / 2.f, mViewHeight / 2.f, mRadius - 8.f, mPaintBg); mPaintBg.setStyle(Style.STROKE); float offset = 1.f + mArcWidth; RectF oval = new RectF(mViewWidth / 2.f - mRadius + offset, mViewHeight / 2.f - mRadius + offset, mViewWidth / 2.f + mRadius - offset, mViewHeight / 2.f + mRadius - offset); //繪製指定的弧線,該弧線將被縮放以適應指定的橢圓形。 canvas.drawArc(oval, 0.f, 360.f, false, mPaintBg); } /** * 繪製未選中指示器紅點 * @param canvas canvas */ private void drawUnSelectedDot(Canvas canvas) { mPaintBg.setAntiAlias(true); mPaintBg.setColor(mBgUnselectedColor); mPaintBg.setStyle(Style.FILL); canvas.drawCircle(mViewWidth / 2.f, mViewHeight / 2.f, mRadius - 8.f, mPaintBg); } /** * 設置是否選中 * @param isSelected isSelected */ public void setIsSelected(boolean isSelected) { this.isSelected = isSelected; //使整個視圖無效。若是視圖是可見的,則{@link#onDraw(android.Graphics.Canvas)}將在未來的某個時候被調用。 //調用該方法,會進行從新繪製,也就是調用onDraw方法 this.invalidate(); } }
5.2.1 需求分析php
5.2.2 代碼介紹android
public class ARoundImageView extends AppCompatImageView { /* * Paint:畫筆 * Canvas:畫布 * Matrix:變換矩陣 * * 業務需求:能夠設置圓角,能夠設置圓形,若是是圓角則必須設置半徑,默認圓角半徑爲10dp */ /** * 圓形模式 */ private static final int MODE_CIRCLE = 1; /** * 普通模式 */ private static final int MODE_NONE = 0; /** * 圓角模式 */ private static final int MODE_ROUND = 2; /** * 圓角半徑 */ private int currRound = dp2px(10); /** * 畫筆 */ private Paint mPaint; /** * 默認是普通模式 */ private int currMode = 0; public ARoundImageView(Context context) { this(context,null); } public ARoundImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ARoundImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); obtainStyledAttrs(context, attrs, defStyleAttr); initViews(); } private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ARoundImageView, defStyleAttr, 0); currMode = a.hasValue(R.styleable.ARoundImageView_type) ? a.getInt(R.styleable.ARoundImageView_type, MODE_NONE) : MODE_NONE; currRound = a.hasValue(R.styleable.ARoundImageView_radius) ? a.getDimensionPixelSize(R.styleable.ARoundImageView_radius, currRound) : currRound; a.recycle(); } private void initViews() { //ANTI_ALIAS_FLAG 用於繪製時抗鋸齒 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); } /** * 當模式爲圓形模式的時候,咱們強制讓寬高一致 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (currMode == MODE_CIRCLE) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int result = Math.min(getMeasuredHeight(), getMeasuredWidth()); // 此方法必須由{@link#onMeasure(int,int)}調用,以存儲已測量的寬度和測量的高度。 // 若是不這樣作,將在測量時觸發異常。 setMeasuredDimension(result, result); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { //獲取ImageView圖片資源 Drawable mDrawable = getDrawable(); //獲取Matrix對象 Matrix mDrawMatrix = getImageMatrix(); if (mDrawable == null) { return; } if (mDrawable.getIntrinsicWidth() == 0 || mDrawable.getIntrinsicHeight() == 0) { return; } if (mDrawMatrix == null && getPaddingTop() == 0 && getPaddingLeft() == 0) { mDrawable.draw(canvas); } else { final int saveCount = canvas.getSaveCount(); canvas.save(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (getCropToPadding()) { final int scrollX = getScrollX(); final int scrollY = getScrollY(); canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(), scrollX + getRight() - getLeft() - getPaddingRight(), scrollY + getBottom() - getTop() - getPaddingBottom()); } } canvas.translate(getPaddingLeft(), getPaddingTop()); switch (currMode){ case MODE_CIRCLE: Bitmap bitmap1 = drawable2Bitmap(mDrawable); mPaint.setShader(new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, mPaint); break; case MODE_ROUND: Bitmap bitmap2 = drawable2Bitmap(mDrawable); mPaint.setShader(new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); canvas.drawRoundRect(new RectF(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()), currRound, currRound, mPaint); break; case MODE_NONE: default: if (mDrawMatrix != null) { canvas.concat(mDrawMatrix); } mDrawable.draw(canvas); break; } canvas.restoreToCount(saveCount); } } /** * drawable轉換成bitmap */ private Bitmap drawable2Bitmap(Drawable drawable) { if (drawable == null) { return null; } Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); //根據傳遞的scaleType獲取matrix對象,設置給bitmap Matrix matrix = getImageMatrix(); if (matrix != null) { canvas.concat(matrix); } drawable.draw(canvas); return bitmap; } private int dp2px(float value) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics()); } }