不多說直接上代碼
1.color文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="transparent">#4D808080</color>
<color name="shadow">#cc222222</color>
<color name="Red_800">#ffb93221</color>
<color name="white">#fff</color>
</resources>
2.drawable中圖片 img_new_task_guide.png (如果下載不了這個圖片 你就那你公司ui給的 引導線那個圖)
3.創建GuideView類 直接複製即可
public class GuideView extends RelativeLayout implements ViewTreeObserver.OnGlobalLayoutListener {
private final String TAG = getClass().getSimpleName();
private Context mContent;
private List<View> mViews;
private boolean first = true;
/**
* targetView前綴。SHOW_GUIDE_PREFIX + targetView.getId()作爲保存在SP文件的key。
*/
private static final String SHOW_GUIDE_PREFIX = "show_guide_on_view_";
/**
* GuideView 偏移量
*/
private int offsetX, offsetY;
/**
* targetView 的外切圓半徑
*/
private int radius;
/**
* 需要顯示提示信息的View
*/
private View targetView;
/**
* 自定義View
*/
private View customGuideView;
/**
* 透明圓形畫筆
*/
private Paint mCirclePaint;
/**
* 背景色畫筆
*/
private Paint mBackgroundPaint;
/**
* targetView是否已測量
*/
private boolean isMeasured;
/**
* targetView圓心
*/
private int[] center;
/**
* 繪圖層疊模式
*/
private PorterDuffXfermode porterDuffXfermode;
/**
* 繪製前景bitmap
*/
private Bitmap bitmap;
/**
* 背景色和透明度,格式 #aarrggbb
*/
private int backgroundColor;
/**
* Canvas,繪製bitmap
*/
private Canvas temp;
/**
* 相對於targetView的位置.在target的那個方向
*/
private Direction direction;
/**
* 形狀
*/
private MyShape myShape;
/**
* targetView左上角座標
*/
private int[] location;
private boolean onClickExit;
private OnClickCallback onclickListener;
private RelativeLayout guideViewLayout;
public void restoreState() {
Log.v(TAG, "restoreState");
offsetX = offsetY = 0;
radius = 0;
mCirclePaint = null;
mBackgroundPaint = null;
isMeasured = false;
center = null;
porterDuffXfermode = null;
bitmap = null;
needDraw = true;
// backgroundColor = Color.parseColor("#00000000");
temp = null;
// direction = null;
}
public int[] getLocation() {
return location;
}
public void setLocation(int[] location) {
this.location = location;
}
public GuideView(Context context) {
super(context);
this.mContent = context;
init();
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public void setOffsetX(int offsetX) {
this.offsetX = offsetX;
}
public void setOffsetY(int offsetY) {
this.offsetY = offsetY;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void setShape(MyShape shape) {
this.myShape = shape;
}
public void setCustomGuideView(View customGuideView) {
this.customGuideView = customGuideView;
if (!first) {
restoreState();
}
}
public void setBgColor(int background_color) {
this.backgroundColor = background_color;
}
public View getTargetView() {
return targetView;
}
public void setTargetView(View targetView) {
this.targetView = targetView;
// restoreState();
if (!first) {
// guideViewLayout.removeAllViews();
}
}
private void init() {
}
public void showOnce() {
if (targetView != null) {
mContent.getSharedPreferences(TAG, Context.MODE_PRIVATE).edit().putBoolean(generateUniqId(targetView), true).commit();
}
}
private boolean hasShown() {
if (targetView == null)
return true;
return mContent.getSharedPreferences(TAG, Context.MODE_PRIVATE).getBoolean(generateUniqId(targetView), false);
}
private String generateUniqId(View v) {
return SHOW_GUIDE_PREFIX + v.getId();
}
public int[] getCenter() {
return center;
}
public void setCenter(int[] center) {
this.center = center;
}
public void hide() {
Log.v(TAG, "hide");
if (customGuideView != null) {
targetView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
this.removeAllViews();
((FrameLayout) ((Activity) mContent).getWindow().getDecorView()).removeView(this);
restoreState();
}
}
public void show() {
Log.v(TAG, "show");
if (hasShown()){
return;
}
if (targetView != null) {
targetView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
this.setBackgroundResource(R.color.transparent);
((FrameLayout) ((Activity) mContent).getWindow().getDecorView()).addView(this);
first = false;
}
/**
* 添加提示文字,位置在targetView的下邊
* 在屏幕窗口,添加蒙層,蒙層繪製總背景和透明圓形,圓形下邊繪製說明文字
*/
private void createGuideView() {
Log.v(TAG, "createGuideView");
// 添加到蒙層
// if (guideViewLayout == null) {
// guideViewLayout = new RelativeLayout(mContent);
// }
// Tips佈局參數
LayoutParams guideViewParams;
guideViewParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
guideViewParams.setMargins(0, center[1] + radius + 10, 0, 0);
if (customGuideView != null) {
// LayoutParams guideViewParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
if (direction != null) {
int width = this.getWidth();
int height = this.getHeight();
int left = center[0] - radius;
int right = center[0] + radius;
int top = center[1] - radius;
int bottom = center[1] + radius;
switch (direction) {
case TOP:
this.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
guideViewParams.setMargins(offsetX, offsetY - height + top, -offsetX, height - top - offsetY);
break;
case LEFT:
this.setGravity(Gravity.RIGHT);
guideViewParams.setMargins(offsetX - width + left, top + offsetY, width - left - offsetX, -top - offsetY);
break;
case BOTTOM:
this.setGravity(Gravity.CENTER_HORIZONTAL);
guideViewParams.setMargins(offsetX, bottom + offsetY, -offsetX, -bottom - offsetY);
break;
case RIGHT:
guideViewParams.setMargins(right + offsetX, top + offsetY, -right - offsetX, -top - offsetY);
break;
case LEFT_TOP:
this.setGravity(Gravity.RIGHT | Gravity.BOTTOM);
guideViewParams.setMargins(offsetX - width + left, offsetY - height + top, width - left - offsetX, height - top - offsetY);
break;
case LEFT_BOTTOM:
this.setGravity(Gravity.RIGHT);
guideViewParams.setMargins(offsetX - width + left, bottom + offsetY, width - left - offsetX, -bottom - offsetY);
break;
case RIGHT_TOP:
this.setGravity(Gravity.BOTTOM);
guideViewParams.setMargins(right + offsetX, offsetY - height + top, -right - offsetX, height - top - offsetY);
break;
case RIGHT_BOTTOM:
guideViewParams.setMargins(right + offsetX, bottom + offsetY, -right - offsetX, -top - offsetY);
break;
}
} else {
guideViewParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
guideViewParams.setMargins(offsetX, offsetY, -offsetX, -offsetY);
}
// guideViewLayout.addView(customGuideView);
this.addView(customGuideView, guideViewParams);
}
}
/**
* 獲得targetView 的寬高,如果未測量,返回{-1, -1}
*
* @return
*/
private int[] getTargetViewSize() {
int[] location = {-1, -1};
if (isMeasured) {
location[0] = targetView.getWidth();
location[1] = targetView.getHeight();
}
return location;
}
/**
* 獲得targetView 的半徑
*
* @return
*/
private int getTargetViewRadius() {
if (isMeasured) {
int[] size = getTargetViewSize();
int x = size[0];
int y = size[1];
return (int) (Math.sqrt(x * x + y * y) / 2);
}
return -1;
}
boolean needDraw = true;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.v(TAG, "onDraw");
if (!isMeasured){
return;
}
if (targetView == null){
return;
}
// if (!needDraw) return;
drawBackground(canvas);
}
private void drawBackground(Canvas canvas) {
Log.v(TAG, "drawBackground");
needDraw = false;
// 先繪製bitmap,再將bitmap繪製到屏幕
bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
temp = new Canvas(bitmap);
// 背景畫筆
Paint bgPaint = new Paint();
if (backgroundColor != 0){
bgPaint.setColor(backgroundColor);
} else{
bgPaint.setColor(getResources().getColor(R.color.shadow));
// 繪製屏幕背景
temp.drawRect(0, 0, temp.getWidth(), temp.getHeight(), bgPaint);
}
// targetView 的透明圓形畫筆
if (mCirclePaint == null){
mCirclePaint = new Paint();
porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT);// 或者CLEAR
mCirclePaint.setXfermode(porterDuffXfermode);
mCirclePaint.setAntiAlias(true);
}
if (myShape != null) {
RectF oval = new RectF();
switch (myShape) {
case CIRCULAR://圓形
temp.drawCircle(center[0], center[1], radius, mCirclePaint);//繪製圓形
break;
case ELLIPSE://橢圓
//RectF對象
oval.left = center[0] - 150; //左邊
oval.top = center[1] - 50; //上邊
oval.right = center[0] + 150; //右邊
oval.bottom = center[1] + 50; //下邊
temp.drawOval(oval, mCirclePaint); //繪製橢圓
break;
case RECTANGULAR://圓角矩形
//RectF對象
oval.left = center[0] - 150; //左邊
oval.top = center[1] - 50; //上邊
oval.right = center[0] + 150; //右邊
oval.bottom = center[1] + 50; //下邊
temp.drawRoundRect(oval, radius, radius, mCirclePaint); //繪製圓角矩形
break;
}
} else {
temp.drawCircle(center[0], center[1], radius, mCirclePaint);//繪製圓形
}
// 繪製到屏幕
canvas.drawBitmap(bitmap, 0, 0, bgPaint);
bitmap.recycle();
}
public void setOnClickExit(boolean onClickExit) {
this.onClickExit = onClickExit;
}
public void setOnclickListener(OnClickCallback onclickListener) {
this.onclickListener = onclickListener;
}
private void setClickInfo() {
final boolean exit = onClickExit;
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onclickListener != null) {
onclickListener.onClickedGuideView();
}
if (exit) {
hide();
}
}
});
}
@Override
public void onGlobalLayout() {
if (isMeasured){
return;
}
if (targetView.getHeight() > 0 && targetView.getWidth() > 0) {
isMeasured = true;
}
// 獲取targetView的中心座標
if (center == null) {
// 獲取右上角座標
location = new int[2];
targetView.getLocationInWindow(location);
center = new int[2];
// 獲取中心座標
center[0] = location[0] + targetView.getWidth() / 2;
center[1] = location[1] + targetView.getHeight() / 2;
}
// 獲取targetView外切圓半徑
if (radius == 0) {
radius = getTargetViewRadius();
}
// 添加GuideView
createGuideView();
}
/**
* 定義GuideView相對於targetView的方位,共八種。不設置則默認在targetView下方
*/
public enum Direction {
LEFT, TOP, RIGHT, BOTTOM,
LEFT_TOP, LEFT_BOTTOM,
RIGHT_TOP, RIGHT_BOTTOM
}
/**
* 定義目標控件的形狀,共3種。圓形,橢圓,帶圓角的矩形(可以設置圓角大小),不設置則默認是圓形
*/
public enum MyShape {
CIRCULAR, ELLIPSE, RECTANGULAR
}
/**
* GuideView點擊Callback
*/
public interface OnClickCallback {
void onClickedGuideView();
}
public static class Builder {
static GuideView guiderView;
static Builder instance = new Builder();
Context mContext;
private Builder() {
}
public Builder(Context ctx) {
mContext = ctx;
}
public static Builder newInstance(Context ctx) {
guiderView = new GuideView(ctx);
return instance;
}
public Builder setTargetView(View target) {
guiderView.setTargetView(target);
return instance;
}
public Builder setBgColor(int color) {
guiderView.setBgColor(color);
return instance;
}
public Builder setDirction(Direction dir) {
guiderView.setDirection(dir);
return instance;
}
public Builder setShape(MyShape shape) {
guiderView.setShape(shape);
return instance;
}
public Builder setOffset(int x, int y) {
guiderView.setOffsetX(x);
guiderView.setOffsetY(y);
return instance;
}
public Builder setRadius(int radius) {
guiderView.setRadius(radius);
return instance;
}
public Builder setCustomGuideView(View view) {
guiderView.setCustomGuideView(view);
return instance;
}
public Builder setCenter(int X, int Y) {
guiderView.setCenter(new int[]{X, Y});
return instance;
}
public Builder showOnce() {
guiderView.showOnce();
return instance;
}
public GuideView build() {
guiderView.setClickInfo();
return guiderView;
}
public Builder setOnclickExit(boolean onclickExit) {
guiderView.setOnClickExit(onclickExit);
return instance;
}
public Builder setOnclickListener(final OnClickCallback callback) {
guiderView.setOnclickListener(callback);
return instance;
}
}
}
4.正式使用在activity中 (第五步有說這每一個set什麼意思)
@Override
protected void onResume() {
super.onResume();
//直接獲取焦點就展示蒙層
setGuideView();
}
private void setGuideView() {
// 使用圖片
final ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.img_new_task_guide);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
iv.setLayoutParams(params);
// 使用文字
TextView tv = new TextView(this);
tv.setText("歡迎使用");
tv.setTextColor(getResources().getColor(R.color.white));
tv.setTextSize(30);
tv.setGravity(Gravity.CENTER);
// 使用文字
final TextView tv2 = new TextView(this);
tv2.setText("歡迎使用2");
tv2.setTextColor(getResources().getColor(R.color.white));
tv2.setTextSize(30);
tv2.setGravity(Gravity.CENTER);
guideView = GuideView.Builder
.newInstance(this)
.setTargetView(numTwo)//設置目標
.setCustomGuideView(iv)
.setDirction(GuideView.Direction.LEFT_BOTTOM)
.setShape(GuideView.MyShape.CIRCULAR) // 設置圓形顯示區域,
.setBgColor(getResources().getColor(R.color.shadow))
.setOnclickListener(new GuideView.OnClickCallback() {
@Override
public void onClickedGuideView() {
guideView.hide();
guideView2.show();
}
})
.build();
guideView2 = GuideView.Builder
.newInstance(this)
.setTargetView(numTwo)
.setCustomGuideView(tv)
.setDirction(GuideView.Direction.LEFT_BOTTOM)
.setShape(GuideView.MyShape.ELLIPSE) // 設置橢圓形顯示區域,
.setBgColor(getResources().getColor(R.color.shadow))
.setOnclickListener(new GuideView.OnClickCallback() {
@Override
public void onClickedGuideView() {
guideView2.hide();
guideView3.show();
}
})
.build();
guideView3 = GuideView.Builder
.newInstance(this)
.setTargetView(numTwo)
.setCustomGuideView(tv2)
.setDirction(GuideView.Direction.LEFT_BOTTOM)
.setShape(GuideView.MyShape.RECTANGULAR) // 設置矩形顯示區域,
.setRadius(80) // 設置圓形或矩形透明區域半徑,默認是targetView的顯示矩形的半徑,如果是矩形,這裏是設置矩形圓角大小
.setBgColor(getResources().getColor(R.color.shadow))
.setOnclickListener(new GuideView.OnClickCallback() {
@Override
public void onClickedGuideView() {
guideView3.hide();
}
})
.build();
guideView.show();
}
5.解釋
.newInstance(context)
.setTargetView(itemWork) //設置目標view
.setTextGuideView(iv1) //設置文字圖片
.setCustomGuideView(iv2) //設置 圖片
.setOffset(0, 80) //偏移量 x=0 y=80
.setDirction(GuideView.Direction.BOTTOM) //方向
.setShape(GuideView.MyShape.RECTANGULAR) //矩形
.setRadius(10) //圓角
.setContain(false) //透明的方塊時候包含目標view 默認false
.setBgColor(getResources().getColor(R.color.bg_shadow)) //背景顏色