标签:instance get 搜索 store 遇见 rup dir count case
GuideView源码仅有300余行代码;GuideView使用起来只需要4行代码。
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import static android.animation.ValueAnimator.REVERSE;
/**
* 引导图层
* Created by ZSC on 2017/7/11.
*/
public class GuideView extends View {
public View guideParent;
private Context context;
private float density;
public GuideView(Context context) {
super(context);
this.context = context;
initSourcePaint();
initBgPaint();
initGuidePaint();
initTextPaint();
setLayerType(View.LAYER_TYPE_SOFTWARE, null);//用到Xfermode时必要的设置
}
private int bgWidth;//背景宽
private int bgHeight;//背景高
private int guideX;//需要引导的view的x坐标
private int guideY;//需要引导的view的y坐标
private int guideWidth;//需要引导的view的宽
private int guideHeight;//需要引导的view的高
private void initSize() {
if (context instanceof Activity) {
DisplayMetrics dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
bgWidth = dm.widthPixels;//设置背景宽为屏幕宽
bgHeight = dm.heightPixels;//设置背景高为屏幕高
int[] location = new int[2];
guideParent.getLocationOnScreen(location);//得到需要引导的view在整个屏幕中的坐标
guideX = location[0];
guideY = location[1];
guideWidth = guideParent.getWidth();
guideHeight = guideParent.getHeight();
density = dm.density;//获取像素密度 2.0,2.5,3.0
distance = 10 * density;//箭头与需要引导的view之间的距离
}
}
public void setGuideParent(View guideParent) {
this.guideParent = guideParent;
initSize();
invalidate();
}
private Paint sourcePaint;
private Paint bgPaint;
private Paint guidePaint;
private Paint textPaint;
/**
* 绘制需要引导的view的区域的画笔
*/
private void initSourcePaint() {
sourcePaint = new Paint();
sourcePaint.setColor(Color.BLUE);
sourcePaint.setStyle(Paint.Style.FILL);
sourcePaint.setAntiAlias(true);
sourcePaint.setAlpha(255);
}
/**
* 半透明背景的画笔
*/
private void initBgPaint() {
bgPaint = new Paint();
bgPaint.setColor(Color.BLACK);
bgPaint.setStyle(Paint.Style.FILL);
bgPaint.setAntiAlias(true);
bgPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));//遮盖效果详细信息可以百度搜索PorterDuffXfermode
bgPaint.setAlpha(225);
}
/**
* 引导箭头的画笔
*/
private void initGuidePaint() {
guidePaint = new Paint();
guidePaint.setColor(Color.WHITE);
guidePaint.setStyle(Paint.Style.FILL);
guidePaint.setAntiAlias(true);
guidePaint.setAlpha(255);
}
/**
* 文字的画笔
*/
private void initTextPaint() {
textPaint = new Paint();
textPaint.setTextAlign(Paint.Align.LEFT);
textPaint.setColor(Color.WHITE);
textPaint.setStrokeWidth(density * 2);
}
@Override
protected void onDraw(Canvas canvas) {
if (bgPaint == null) {
return;
}
if (sourcePaint == null) {
return;
}
int layerID = canvas.saveLayer(0, 0, bgWidth, bgHeight, bgPaint, Canvas.ALL_SAVE_FLAG);
canvas.drawRect(guideX, guideY, guideX + guideWidth, guideY + guideHeight, sourcePaint);
canvas.drawRect(0, 0, bgWidth, bgHeight, bgPaint);
int direction;
if (guideY < bgHeight / 4) {
direction = TOP;
drawArrow(direction, canvas, guideX + guideWidth / 2, guideY + guideHeight + distance);
} else if (guideY > bgHeight / 4 * 3) {
direction = BOTTOM;
drawArrow(direction, canvas, guideX + guideWidth / 2, guideY - distance);
} else if (guideX < bgWidth / 4) {
direction = LEFT;
drawArrow(direction, canvas, guideX + guideWidth + distance, guideY + guideHeight / 2);
} else if (guideX > bgWidth / 4 * 3) {
direction = RIGHT;
drawArrow(direction, canvas, guideX - distance, guideY + guideHeight / 2);
}
drawGuideText(canvas);
canvas.restoreToCount(layerID);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private String guideStr;
public void setGuideStr(String guideStr) {
this.guideStr = guideStr;
invalidate();
}
private void drawGuideText(Canvas canvas) {
if (!TextUtils.isEmpty(guideStr)) {
Rect bounds = new Rect();
float textSize = density * 20.0f;
textPaint.setTextSize(textSize);
textPaint.getTextBounds(guideStr, 0, guideStr.length(), bounds);
canvas.drawText(guideStr, bgWidth / 2 - bounds.width() / 2, bgHeight / 2 + bounds.height() / 2, textPaint);
}
}
private final int TOP = 0x01;
private final int BOTTOM = 0x02;
private final int LEFT = 0x03;
private final int RIGHT = 0x04;
private float distance;
/**
* 画箭头
*
* @param direction 上或者下方向的箭头
* @param canvas 画布
* @param x 箭头顶点x坐标
* @param y 箭头顶点y坐标
*/
private void drawArrow(int direction, Canvas canvas, float x, float y) {
final float triangleWidth = 20 * density;
final float triangleHeight = 20 * density;
final float rectWidth = 10 * density;
final float rectHeight = 35 * density;
float vertexOneX = x;
float vertexOneY = y;
float vertexTwoX = x;
float vertexTwoY = y;
float rectOneX = x;
float rectOneY = y;
float rectTwoX = x;
float rectTwoY = y;
float rectThreeX = x;
float rectThreeY = y;
float rectFourX = x;
float rectFourY = y;
switch (direction) {
case TOP:
vertexOneX = x - triangleWidth / 2;
vertexOneY = y + triangleHeight;
vertexTwoX = x + triangleWidth / 2;
vertexTwoY = y + triangleHeight;
rectOneX = x - rectWidth / 2;
rectOneY = y + triangleHeight;
rectTwoX = x + rectWidth / 2;
rectTwoY = y + triangleHeight;
rectThreeX = x + rectWidth / 2;
rectThreeY = y + triangleHeight + rectHeight;
rectFourX = x - rectWidth / 2;
rectFourY = y + triangleHeight + rectHeight;
break;
case BOTTOM:
vertexOneX = x + triangleWidth / 2;
vertexOneY = y - triangleHeight;
vertexTwoX = x - triangleWidth / 2;
vertexTwoY = y - triangleHeight;
rectOneX = x + rectWidth / 2;
rectOneY = y - triangleHeight;
rectTwoX = x - rectWidth / 2;
rectTwoY = y - triangleHeight;
rectThreeX = x - rectWidth / 2;
rectThreeY = y - triangleHeight - rectHeight;
rectFourX = x + rectWidth / 2;
rectFourY = y - triangleHeight - rectHeight;
break;
case LEFT:
vertexOneX = x + triangleHeight;
vertexOneY = y + triangleWidth / 2;
vertexTwoX = x + triangleHeight;
vertexTwoY = y - triangleWidth / 2;
rectOneX = x + triangleHeight;
rectOneY = y + rectWidth / 2;
rectTwoX = x + triangleHeight;
rectTwoY = y - rectWidth / 2;
rectThreeX = x + triangleHeight + rectHeight;
rectThreeY = y - rectWidth / 2;
rectFourX = x + triangleHeight + rectHeight;
rectFourY = y + rectWidth / 2;
break;
case RIGHT:
vertexOneX = x - triangleHeight;
vertexOneY = y - triangleWidth / 2;
vertexTwoX = x - triangleHeight;
vertexTwoY = y + triangleWidth / 2;
rectOneX = x - triangleHeight;
rectOneY = y - rectWidth / 2;
rectTwoX = x - triangleHeight;
rectTwoY = y + rectWidth / 2;
rectThreeX = x - triangleHeight - rectHeight;
rectThreeY = y + rectWidth / 2;
rectFourX = x - triangleHeight - rectHeight;
rectFourY = y - rectWidth / 2;
break;
}
Path trianglePath = new Path();
trianglePath.moveTo(x, y);
trianglePath.lineTo(vertexOneX, vertexOneY);
trianglePath.lineTo(vertexTwoX, vertexTwoY);
trianglePath.close();
canvas.drawPath(trianglePath, guidePaint);
Path rectPath = new Path();
rectPath.moveTo(rectOneX, rectOneY);
rectPath.lineTo(rectTwoX, rectTwoY);
rectPath.lineTo(rectThreeX, rectThreeY);
rectPath.lineTo(rectFourX, rectFourY);
rectPath.close();
canvas.drawPath(rectPath, guidePaint);
}
/**
* 重写onTouchEvent,实现触摸之后就销毁GuideView的功能
* 因为重写了onTouchEvent 所有View 的OnClickListener等将不能正常使用
*
* @param event 触摸
* @return boolean true-触摸被自己消耗掉,false-触摸传到下一层
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (added) {
((ViewGroup) ((Activity) context).getWindow().getDecorView()).removeView(this);
added = false;
}
if (animator != null) {
if (animator.isRunning()) {
animator.end();
}
}
return true;
}
private ValueAnimator animator;
private void initAnim() {
animator = ValueAnimator.ofFloat(0.0f, 1.0f);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cValue = (float) animation.getAnimatedValue();
distance = density * 10 * cValue;
invalidate();
}
});
animator.setDuration(350);
animator.setInterpolator(new DecelerateInterpolator());
animator.setRepeatMode(REVERSE);
animator.setRepeatCount(-1);
}
private boolean added = false;
public void startAnim() {
if (animator == null) {
initAnim();
}
if (!added) {
//将guideView直接添加到window中,获取DecorView并把guideView作为child添加到其中,从而实现全屏显示
setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
((ViewGroup) ((Activity) context).getWindow().getDecorView()).addView(this);
added = true;
}
if (!animator.isRunning()) {
animator.start();
}
}
}
GuideViewguideView=newGuideView(this);
guideView.setGuideParent(tvFunctionTitle);//设置需要引导的view
guideView.setGuideStr("点击这里创建一个新的旅途相册");//设置提示文字
guideView.startAnim();
标签:instance get 搜索 store 遇见 rup dir count case
原文地址:http://www.cnblogs.com/gongxiaojiu/p/7236733.html