今天是我第一次在掘金發表文章,作為一個菜鳥,經常找UI哥.為啥呢?因為有些效果需要點九圖啊,雖然SDK帶有工具,但是首先你得有那個原圖,才能在四周加線啊!所以今兒我們就來實現一個利用Path繪製一個類似點九圖的效果背景!
首先,還是來個圖說明哈,無圖無真相!
看官感興趣就往下看!在這裡感謝 github.com/lguipeng/Bu…,
我們是站在了巨人的肩膀上,才能看得更遠!下面我就參考大神的樣例,加上我自己的一些體會,講講具體實現過程!
在這裡我們需要使用 Path,所以先說下我們需要使用和 Path 相關的幾個API
- moveTo(float x, float y),將畫筆移動到某一個點,畫筆的原始位置在螢幕的左上方,即(0,0)位置.
- lineTo(float x, float y),從畫筆所在位置劃線到(float x,float y).
- arcTo(RectF oval, float startAngle, float sweepAngle),其中oval 確定了圓弧的起點和終點,startAngle是圓弧的起始角度,sweepAngle是圓弧角度,也就是圓心和起點的連線與圓心和終點的連線的夾角角度.
接下來我們將效果從簡單到複雜三步走, 第一步 我們畫一個矩形.
package com.jooyer.bubbleview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* 使用 Path 實現點九圖效果
* Created by Jooyer on 2017/3/11
*/
public class JooyerBubbleView extends TextView {
private Paint mPaint;
private Path mPath;
// 畫筆描邊預設寬度
private static final float DEFAULT_STROKE_WIDTH = 10;
public JooyerBubbleView(Context context) {
this(context, null);
}
public JooyerBubbleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public JooyerBubbleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mPaint = new Paint();
// 抗鋸齒
mPaint.setAntiAlias(true);
// 畫筆顏色
mPaint.setColor(Color.GREEN);
// 畫筆的填充模式
mPaint.setStyle(Paint.Style.STROKE);
// 畫筆描邊寬度
mPaint.setStrokeWidth(DEFAULT_STROKE_WIDTH);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawRect(canvas);
}
private void drawRect(Canvas canvas) {
mPath.moveTo(100,100);
mPath.lineTo(500,100);
mPath.lineTo(500,300);
mPath.lineTo(100,300);
mPath.close();
canvas.drawPath(mPath,mPaint);
}
}
複製程式碼
這裡貼個佈局程式碼,方便大家直接拷貝過去執行,就看到效果啦!
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.jooyer.bubbleview.MainActivity">
<com.jooyer.bubbleview.JooyerBubbleView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>複製程式碼
得到的效果如圖
有的朋友可能會問了,畫個矩形,直接 canvas.drawRect()不就好了嘛!
是的,條條大路通羅馬.不過我們這裡因為要用到四個角,對其進行圓弧處理,所以用 path 更方便處理了!
廢話那麼多,我自己都不好意思了,那麼接下來實現 第二步 四個圓角部分.
package com.jooyer.bubbleview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* 使用 Path 實現點九圖效果
* Created by Jooyer on 2017/3/11
*/
public class JooyerBubbleView extends TextView {
private Paint mPaint;
private Path mPath;
// 預設圓角半徑
private static final float DEFAULT_RADIUS = 50;
// 畫筆描邊預設寬度
private static final float DEFAULT_STROKE_WIDTH = 10;
public JooyerBubbleView(Context context) {
this(context, null);
}
public JooyerBubbleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public JooyerBubbleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mPaint = new Paint();
// 抗鋸齒
mPaint.setAntiAlias(true);
// 畫筆顏色
mPaint.setColor(Color.GREEN);
// 畫筆的填充模式
mPaint.setStyle(Paint.Style.STROKE);
// 畫筆描邊寬度
mPaint.setStrokeWidth(DEFAULT_STROKE_WIDTH);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawRect(canvas);
}
private void drawRect(Canvas canvas) {
// 這個地方因為圓弧的關係,起點需要有(100,100)改變為(100 + DEFAULT_RADIUS,100)
mPath.moveTo(100 + DEFAULT_RADIUS, 100);
// 因為繪製了一段圓弧,所以這裡的終點是圓弧的起點,所以這裡的值不能是(500,100)
mPath.lineTo(500 - DEFAULT_RADIUS, 100);
//繪製右上第一個圓角
mPath.arcTo(new RectF((500 - DEFAULT_RADIUS), 100, 500, (100 + DEFAULT_RADIUS)), 270, 90);
//同理這裡的終點則是下一段圓弧的起點
mPath.lineTo(500, 300 - DEFAULT_RADIUS);
mPath.arcTo(new RectF((500 - DEFAULT_RADIUS), (300 - DEFAULT_RADIUS), 500, 300), 0, 90);
mPath.lineTo(100 + DEFAULT_RADIUS, 300);
mPath.arcTo(new RectF(100, (300 - DEFAULT_RADIUS), (100 + DEFAULT_RADIUS), 300), 90, 90);
mPath.lineTo(100, 300 - DEFAULT_RADIUS);
mPath.arcTo(new RectF(100, 100, (100 + DEFAULT_RADIUS), (100 + DEFAULT_RADIUS)), 180, 90);
mPath.close();
canvas.drawPath(mPath, mPaint);
}
}
複製程式碼
得到的效果如圖:
估計大家有個疑問,第一個圓弧那裡:
mPath.arcTo(new RectF((500 - DEFAULT_RADIUS), 100, 500, (100 + DEFAULT_RADIUS)), 270, 90); 為何是270°呢?
開始我也沒搞明白,後來才知道,Android裡面繪圖角度是順時針轉動的,朝右為正,朝下為正.請看下圖:
註釋比較清楚了,其他的如果有問題就給我發郵件吧?Jooyer@outlook.com,注意第一個字元大寫哦!
好了,終於到了我們最後階段了.
package com.jooyer.bubbleview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* 使用 Path 實現點九圖效果
* Created by Jooyer on 2017/3/11
*/
public class JooyerBubbleView extends TextView {
private Paint mPaint;
private Path mPath;
// 預設圓角半徑
private static final float DEFAULT_RADIUS = 50;
// 畫筆描邊預設寬度
private static final float DEFAULT_STROKE_WIDTH = 10;
public JooyerBubbleView(Context context) {
this(context, null);
}
public JooyerBubbleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public JooyerBubbleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mPaint = new Paint();
// 抗鋸齒
mPaint.setAntiAlias(true);
// 畫筆顏色
mPaint.setColor(Color.GREEN);
// 畫筆的填充模式
mPaint.setStyle(Paint.Style.STROKE);
// 畫筆描邊寬度
mPaint.setStrokeWidth(DEFAULT_STROKE_WIDTH);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawRect(canvas);
}
private void drawRect(Canvas canvas) {
// 這個地方因為圓弧的關係,起點需要有(100,100)改變為(100 + DEFAULT_RADIUS,100)
mPath.moveTo(100 + DEFAULT_RADIUS, 100);
// 因為繪製了一段圓弧,所以這裡的終點是圓弧的起點,所以這裡的值不能是(500,100)
mPath.lineTo(500 - DEFAULT_RADIUS, 100);
//繪製右上第一個圓角
mPath.arcTo(new RectF((500 - DEFAULT_RADIUS), 100, 500, (100 + DEFAULT_RADIUS)), 270, 90);
//同理這裡的終點則是下一段圓弧的起點
mPath.lineTo(500, 300 - DEFAULT_RADIUS);
mPath.arcTo(new RectF((500 - DEFAULT_RADIUS), (300 - DEFAULT_RADIUS), 500, 300), 0, 90);
mPath.lineTo(100 + DEFAULT_RADIUS, 300);
mPath.arcTo(new RectF(100, (300 - DEFAULT_RADIUS), (100 + DEFAULT_RADIUS), 300), 90, 90);
// 假設我們想凸起部分在左側,其實我們知道凸起部分就是2條線段而已,所以處理就簡單了
// 我們假設凸起部分的高度為 50 ,寬度也為50,也就是三角的底邊長度50,底邊高度也是50
// mPath.lineTo(100, 100 + DEFAULT_RADIUS);
// 那麼上面的這個線則不能移動到 (100, 100 + DEFAULT_RADIUS),必須加上一個三角形底邊長度
mPath.lineTo(100, 100 + DEFAULT_RADIUS + 50);
// 等腰三角形,所以其定點高度值為底邊一半
mPath.lineTo(100 - 50, 100 + DEFAULT_RADIUS + 25);
mPath.lineTo(100,100 + DEFAULT_RADIUS);
mPath.arcTo(new RectF(100, 100, (100 + DEFAULT_RADIUS), (100 + DEFAULT_RADIUS)), 180, 90);
mPath.close();
canvas.drawPath(mPath, mPaint);
}
}
複製程式碼
得到的效果如圖:
是不是覺得三角很醜呢,這個你可以根據需要調整其大小,就好看咯!
三部曲完成了,那麼接下來就是我們的實際使用時間了.上面只是演示 Path 具體用法,但是如果想把上面的效果當作點九圖來使用,也為了以後的複用,我們將畫筆操作單獨提出來,放在一個自定義的drawble中,這個 drawable僅僅使用了以上畫筆的功能,也就是把畫筆的這部分功能封裝在drawable 裡面了而已!
首先我們看看 JooyerBubbleDrawable 這個類
package com.jooyer.bubbleview;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.Log;
/**
* Created by Jooyer on 2017/3/11
*/
public class JooyerBubbleDrawable extends Drawable {
private static final String TAG = JooyerBubbleDrawable.class.getSimpleName();
/**
* 儲存座標(自定義控制元件的大小)
*/
private RectF mRect;
/**
* 氣泡的路徑
*/
private Path mPath = new Path();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
/**
* 箭頭寬度
*/
private float mArrowWidth;
/**
* 箭頭寬度
*/
private float mArrowHeight;
/**
* 圓弧半徑
*/
private float mRadius;
/**
* 箭頭所在位置偏移量
*/
private float mArrowOffset;
/**
* 氣泡背景色
*/
private int mBubbleColor;
/**
* 三角箭頭所在位置
*/
private ArrowDirection mArrowDirection;
/**
* 箭頭是否居中
*/
private boolean mArrowCenter;
/**
* 重寫此方法,在這裡實現和 自定義控制元件中 onDraw 類似的功能
*/
@Override
public void draw(Canvas canvas) {
mPaint.setColor(mBubbleColor);
setUpPath(mArrowDirection, mPath);
canvas.drawPath(mPath, mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT; //視窗透明化
}
private void setUpPath(ArrowDirection arrowDirection, Path path) {
switch (arrowDirection) {
case LEFT:
setUpLeftPath(mRect, path);
break;
case TOP:
setUpTopPath(mRect, path);
break;
case RIGHT:
setUpRightPath(mRect, path);
break;
case BOTTOM:
setUpBottomPath(mRect,path);
break;
}
}
/**
* 箭頭朝左
*/
private void setUpLeftPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.bottom - rect.top - mArrowWidth) / 2;
path.moveTo(rect.left + mArrowWidth + mRadius, rect.top);
path.lineTo(rect.width() - mRadius, rect.top); // 這裡的rect.width() 是可以使用rect.right
Log.i(TAG, "====setUpLeftPath========" + (rect.width() - mRadius) + "======= : " + (rect.right - mRadius));
path.arcTo(new RectF(rect.right - mRadius, rect.top, rect.right, rect.top + mRadius), 270, 90);
path.lineTo(rect.right, rect.bottom - mRadius);
path.arcTo(new RectF(rect.right - mRadius, mRect.bottom - mRadius, rect.right, rect.bottom), 0, 90);
path.lineTo(rect.left + mArrowWidth + mRadius, rect.bottom);
path.arcTo(new RectF(rect.left + mArrowWidth, rect.bottom - mRadius, rect.left + mArrowWidth + mRadius, rect.bottom), 90, 90);
path.lineTo(rect.left + mArrowWidth, mArrowHeight + mArrowOffset);
path.lineTo(rect.left, mArrowOffset + mArrowHeight / 2);
path.lineTo(rect.left + mArrowWidth, mArrowOffset);
path.lineTo(rect.left + mArrowWidth, rect.top + mRadius);
path.arcTo(new RectF(rect.left + mArrowWidth, mRect.top, rect.left + mArrowWidth + mRadius, rect.top + mRadius), 180, 90);
path.close();
}
/**
* 箭頭朝上
*/
private void setUpTopPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.right - rect.left - mArrowWidth) / 2;
path.moveTo(rect.left + Math.min(mRadius, mArrowOffset), rect.top + mArrowHeight);
path.lineTo(rect.left + mArrowOffset, rect.top + mArrowHeight);
path.lineTo(rect.left + mArrowOffset + mArrowWidth / 2, rect.top);
path.lineTo(rect.left + mArrowOffset + mArrowWidth, rect.top + mArrowHeight);
path.lineTo(rect.right - mRadius, rect.top + mArrowHeight);
path.arcTo(new RectF(rect.right - mRadius, rect.top + mArrowHeight, rect.right, rect.top + mArrowHeight + mRadius), 270, 90);
path.lineTo(rect.right, rect.bottom - mRadius);
path.arcTo(new RectF(rect.right - mRadius, rect.bottom - mRadius, rect.right, rect.bottom), 0, 90);
path.lineTo(rect.left + mRadius, rect.bottom);
path.arcTo(new RectF(rect.left, rect.bottom - mRadius, rect.left + mRadius, rect.bottom), 90, 90);
path.lineTo(rect.left, rect.top + mArrowHeight + mRadius);
path.arcTo(new RectF(rect.left, rect.top + mArrowHeight, rect.left + mRadius, rect.top + mArrowHeight + mRadius), 180, 90);
path.close();
}
/**
* 箭頭朝右
*/
private void setUpRightPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.bottom - rect.top - mArrowWidth) / 2;
path.moveTo(rect.left + mRadius, rect.top);
path.lineTo(rect.right - mRadius - mArrowWidth, rect.top);
path.arcTo(new RectF(rect.right - mArrowWidth - mRadius, rect.top, rect.right - mArrowWidth, rect.top + mRadius), 270, 90);
path.lineTo(rect.right - mArrowWidth, rect.top + mArrowOffset);
path.lineTo(rect.right, rect.top + mArrowOffset + mArrowHeight / 2);
path.lineTo(rect.right - mArrowWidth, rect.top + mArrowOffset + mArrowHeight);
path.lineTo(rect.right - mArrowWidth, rect.bottom - mRadius);
path.arcTo(new RectF(rect.right - mArrowWidth - mRadius, rect.bottom - mRadius, rect.right - mArrowWidth, rect.bottom), 0, 90);
path.lineTo(rect.right - mArrowWidth - mRadius, rect.bottom);
path.arcTo(new RectF(rect.left, rect.bottom - mRadius, rect.left + mRadius, rect.bottom), 90, 90);
path.lineTo(rect.left, rect.top + mRadius);
path.arcTo(new RectF(rect.left, rect.top, rect.left + mRadius, rect.top + mRadius), 180, 90);
path.close();
}
/**
* 箭頭朝下
*/
private void setUpBottomPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.right - rect.left - mArrowWidth) / 2;
path.moveTo(rect.left + mRadius, rect.top);
path.lineTo(rect.right - mRadius, rect.top);
path.arcTo(new RectF(rect.right - mRadius, rect.top, rect.right, rect.top + mRadius), 270, 90);
path.lineTo(rect.right, rect.bottom - mArrowHeight - mRadius);
path.arcTo(new RectF(rect.right - mRadius, rect.bottom - mArrowHeight - mRadius, rect.right, rect.bottom - mArrowHeight), 0, 90);
path.lineTo(rect.left + mArrowOffset + mArrowWidth, rect.bottom - mArrowHeight);
path.lineTo(rect.left + mArrowOffset + mArrowWidth / 2, rect.bottom);
path.lineTo(rect.left + mArrowOffset, rect.bottom - mArrowHeight);
path.lineTo(rect.left + mRadius, rect.bottom - mArrowHeight);
path.arcTo(new RectF(rect.left, rect.bottom - mArrowHeight - mRadius, rect.left + mRadius, rect.bottom - mArrowHeight), 90, 90);
path.lineTo(rect.left, rect.top + mRadius);
path.arcTo(new RectF(rect.left, rect.top,rect.left + mRadius,rect.top + mRadius),180,90);
path.close();
}
private JooyerBubbleDrawable(Builder builder) {
this.mRect = builder.mRectF;
this.mRadius = builder.mRadius;
this.mArrowWidth = builder.mArrowWidth;
this.mArrowHeight = builder.mArrowHeight;
this.mArrowOffset = builder.mArrowOffset;
this.mBubbleColor = builder.mBubbleColor;
this.mArrowDirection = builder.mArrowDirection;
this.mArrowCenter = builder.mArrowCenter;
}
/**
* 建造者模式
*/
public static class Builder {
/**
* 箭頭預設寬度
*/
public static float DEFAULT_ARROW_WIDTH = 25;
/**
* 箭頭預設高度
*/
public static float DEFAULT_ARROW_HEIGHT = 25;
/**
* 預設圓角半徑
*/
public static float DEFAULT_RADIUS = 20;
/**
* 預設箭頭偏移量
*/
public static float DEFAULT_ARROW_OFFSET = 50;
/**
* 氣泡預設背景顏色
*/
public static int DEFAULT_BUBBLE_COLOR = Color.RED;
private RectF mRectF;
private float mArrowWidth = DEFAULT_ARROW_WIDTH;
private float mArrowHeight = DEFAULT_ARROW_HEIGHT;
private float mRadius = DEFAULT_RADIUS;
private float mArrowOffset = DEFAULT_ARROW_OFFSET;
private int mBubbleColor = DEFAULT_BUBBLE_COLOR;
private ArrowDirection mArrowDirection = ArrowDirection.LEFT;
private boolean mArrowCenter;
public Builder rect(RectF rect) {
this.mRectF = rect;
return this;
}
public Builder arrowWidth(float width) {
this.mArrowWidth = width;
return this;
}
public Builder arrowHeight(float height) {
this.mArrowHeight = height;
return this;
}
public Builder radius(float angle) {
this.mRadius = angle; //TODO
return this;
}
public Builder arrowOffset(float position) {
this.mArrowOffset = position;
return this;
}
public Builder bubbleColor(int color) {
this.mBubbleColor = color;
return this;
}
public Builder arrowDirection(ArrowDirection direction) {
this.mArrowDirection = direction;
return this;
}
public Builder arrowCenter(boolean arrowCenter) {
this.mArrowCenter = arrowCenter;
return this;
}
public JooyerBubbleDrawable build() {
if (null == mRectF) {
throw new IllegalArgumentException("BubbleDrawable RectF can not be null");
}
return new JooyerBubbleDrawable(this);
}
}
/**
* 箭頭位置
*/
public enum ArrowDirection {
LEFT(0x00),
TOP(0x01),
RIGHT(0x02),
BOTTOM(0x03);
private int mValue;
ArrowDirection(int value) {
mValue = value;
}
private int getIntValue() {
return mValue;
}
public static ArrowDirection getDefault() {
return LEFT;
}
public static ArrowDirection mapIntToValue(int stateInt) {
for (ArrowDirection value : ArrowDirection.values()) {
if (stateInt == value.getIntValue()) {
return value;
}
}
return getDefault();
}
}
}
複製程式碼
然後看看 JooyerTextView 這個類:
package com.jooyer.bubbleview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* Created by Jooyer on 2017/3/11
*/
public class JooyerTextView extends TextView {
private static String TAG = JooyerTextView.class.getSimpleName();
private JooyerBubbleDrawable mBubbleDrawable;
private float mArrowWidth;
private float mArrowHeight;
private float mRadius;
private float mArrowOffset;
private int mBubbleColor;
private JooyerBubbleDrawable.ArrowDirection mArrowDirection;
private boolean mArrowCenter;
public JooyerTextView(Context context) {
this(context,null);
}
public JooyerTextView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public JooyerTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.JooyerBubble);
mArrowWidth = array.getDimension(R.styleable.JooyerBubble_jooyer_bubble_arrow_width,
JooyerBubbleDrawable.Builder.DEFAULT_ARROW_WIDTH);
mArrowHeight = array.getDimension(R.styleable.JooyerBubble_jooyer_bubble_arrow_width,
JooyerBubbleDrawable.Builder.DEFAULT_ARROW_HEIGHT);
mArrowOffset = array.getDimension(R.styleable.JooyerBubble_jooyer_bubble_arrow_width,
JooyerBubbleDrawable.Builder.DEFAULT_ARROW_OFFSET);
mRadius = array.getDimension(R.styleable.JooyerBubble_jooyer_bubble_arrow_width,
JooyerBubbleDrawable.Builder.DEFAULT_RADIUS);
mBubbleColor = array.getColor(R.styleable.JooyerBubble_jooyer_bubble_arrow_color,
JooyerBubbleDrawable.Builder.DEFAULT_BUBBLE_COLOR);
mArrowCenter = array.getBoolean(R.styleable.JooyerBubble_jooyer_bubble_arrow_center,
false);
int direction = array.getInt(R.styleable.JooyerBubble_jooyer_bubble_arrow_direction,
0);
mArrowDirection = JooyerBubbleDrawable.ArrowDirection.mapIntToValue(direction);
array.recycle();
setPadding();
}
/**
* 由於箭頭的問題,當有 padding 時我們需要再加三角箭頭的尺寸
*/
private void setPadding() {
int left = getPaddingLeft();
int top = getPaddingTop();
int right = getPaddingRight();
int bottom = getPaddingBottom();
switch (mArrowDirection){
case LEFT:
left += mArrowWidth;
break;
case TOP:
top += mArrowHeight;
break;
case RIGHT:
right += mArrowWidth;
break;
case BOTTOM:
bottom += mArrowHeight;
break;
}
setPadding(left,top,right,bottom);
}
/**
* 當大小發生改變時,我們需要重繪
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0) {
reset(w, h);
}
}
/**
* 當位置發生改變時,我們需要重繪
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
reset(getWidth(),getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
// 繪製背景
if (null != mBubbleDrawable){
mBubbleDrawable.draw(canvas);
}
super.onDraw(canvas);
}
private void reset(int width, int height) {
reset(0,0,width,height);
}
private void reset(int left, int top, int right, int bottom) {
RectF rectF = new RectF(left,top,right,bottom);
mBubbleDrawable = new JooyerBubbleDrawable.Builder()
.rect(rectF)
.arrowWidth(mArrowWidth)
.arrowHeight(mArrowHeight)
.radius(mRadius)
.arrowOffset(mArrowOffset)
.arrowDirection(mArrowDirection)
.arrowCenter(mArrowCenter)
.bubbleColor(mBubbleColor)
.build();
}
}
複製程式碼
接著看下 jooyer_bobbleview_attrs 這個檔案:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="JooyerBubble">
<!-- 三角箭頭寬度 -->
<attr name="jooyer_bubble_arrow_width" format="dimension"/>
<!-- 三角箭頭高度 -->
<attr name="jooyer_bubble_arrow_height" format="dimension"/>
<!-- 三角箭頭位置(相對偏移量) -->
<attr name="jooyer_bubble_arrow_offset" format="dimension"/>
<!-- 氣泡圓角半徑 -->
<attr name="jooyer_bubble_arrow_radius" format="dimension"/>
<!-- 氣泡背景顏色 -->
<attr name="jooyer_bubble_arrow_color" format="color"/>
<!-- 三角箭頭是否居中 -->
<attr name="jooyer_bubble_arrow_center" format="boolean"/>
<!-- 三角箭頭方向朝向 -->
<attr name="jooyer_bubble_arrow_direction" format="enum">
<enum name="jooyer_bubble_arrow_direction_left" value="0x00"/>
<enum name="jooyer_bubble_arrow_direction_top" value="0x01"/>
<enum name="jooyer_bubble_arrow_direction_right" value="0x02"/>
<enum name="jooyer_bubble_arrow_direction_bottom" value="0x03"/>
</attr>
</declare-styleable>
</resources>複製程式碼
還有佈局檔案:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.jooyer.bubbleview.MainActivity">
<com.jooyer.bubbleview.JooyerTextView
android:text="@string/test"
android:textSize="20sp"
android:textColor="@color/color_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
app:jooyer_bubble_arrow_width="20dp"
app:jooyer_bubble_arrow_height="20dp"
app:jooyer_bubble_arrow_offset="20dp"
app:jooyer_bubble_arrow_radius="20dp"
app:jooyer_bubble_arrow_color="#e363e134"
app:jooyer_bubble_arrow_center="false"
app:jooyer_bubble_arrow_direction="jooyer_bubble_arrow_direction_left"
/>
</LinearLayout>複製程式碼
最後來看下執行的效果圖:
是不是覺得不錯呢,哈哈!如果喜歡記得點贊收藏和關注哦哦!下一章我們們就理由今天的學習實現常見toolbar點選彈出選單效果,歡喜前來踢場!