新手指引的最终实现效果如下所示:
一 首先自定义包括背景半透明和全透明显示的部分的自定义view,代码如下
public class MaskView extends View { private Context context; public final static String CIRCULAR = "circular"; public final static String RECTANGULAR = "rectangular"; private boolean readLoad = true; private String shape = RECTANGULAR; private View targetView; private Paint targetPaint; private int radius = 10; private int[] center = new int[2]; private int[] location = new int[2]; private int rectificationalStart = 0; private int rectificationalTop = 0; private int rectificationalEnd = 0; private int rectificationalBottom = 0; public MaskView(Context context) { super(context); this.context = context; } public MaskView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public MaskView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBackground(canvas); } private void drawBackground(Canvas canvas) { Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);// 先绘制bitmap,再将bitmap绘制到屏幕 Canvas temp = new Canvas(bitmap); Paint bgPaint = new Paint(); bgPaint.setColor(Color.parseColor("#CC000000")); temp.drawRect(0, 0, temp.getWidth(), temp.getHeight(), bgPaint);// 绘制屏幕背景 if (targetPaint == null) { targetPaint = new Paint(); } //透明效果 PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); //SRC_OUT或者CLEAR都可以 targetPaint.setXfermode(porterDuffXfermode); targetPaint.setAntiAlias(true); RectF oval = new RectF(); switch (shape) { case CIRCULAR://圆形 temp.drawCircle(center[0] + radius/2, center[1] + radius/2, radius, targetPaint); break; case RECTANGULAR://圆角矩形 oval.left = center[0] + rectificationalStart; oval.top = center[1] + rectificationalTop; oval.right = center[0] + location[0] + rectificationalEnd; oval.bottom = center[1] + location[1] + rectificationalBottom; temp.drawRoundRect(oval, radius, radius, targetPaint); break; } canvas.drawBitmap(bitmap, 0, 0, bgPaint); bitmap.recycle(); } //导入全透明的矩形相关控件和圆形边角, 偏移距离 public void setRectangular(View targetView, int radius, int rectificationalStart, int rectificationalTop, int rectificationalEnd, int rectificationalBottom){ shape = RECTANGULAR; this.targetView = targetView; this.radius = radius; this.rectificationalStart = rectificationalStart; this.rectificationalTop = rectificationalTop; this.rectificationalEnd = rectificationalEnd; this.rectificationalBottom = rectificationalBottom; relocation(); } //对矩形位置进行定位 public void relocation(){ targetView.getLocationInWindow(center); location[0] = targetView.getWidth() ; location[1] = targetView.getHeight() ; } public void setRectangularMeasure(int width, int height){ location[0] = width ; location[1] = height ; }
二 添加图片的自定义布局文件
由于要在Activity中定位其中fragment内容中的控件,在自定义布局文件中添加回调接口管理类。
public class GuildView extends RelativeLayout { private Context context; private MaskView maskView; private RelativeLayout container; public interface OnShowGuildViewListener{ void onShowGuildView(View view); } public GuildView(Context context) { super(context); this.context = context; initLayout(); } public GuildView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; initLayout(); } public GuildView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; initLayout(); } private void initLayout() { LayoutInflater.from(context).inflate(R.layout.view_guild, this, true); maskView = this.findViewById(R.id.maskView); container = this.findViewById(R.id.layout_container); } public void setTitleIcon(int marginStart, int marginTop, int marginLeft, int MarginEnd, int imageResource){ ImageView imageView = new ImageView(context); imageView.setImageResource(imageResource); RelativeLayout.LayoutParams params= new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); params.setMargins(ParamaterUtils.dpToPx(marginStart, context), ParamaterUtils.dpToPx(marginTop, context), ParamaterUtils.dpToPx(marginLeft, context), ParamaterUtils.dpToPx(MarginEnd, context)); imageView.setLayoutParams(params); container.addView(imageView); } public void setRectangular(View targetView, int radius, int rectificationalStart, int rectificationalTop, int rectificationalEnd, int rectificationalBottom){ maskView.setRectangular(targetView, radius, rectificationalStart, rectificationalTop, rectificationalEnd, rectificationalBottom); maskView.setVisibility(VISIBLE); } public void setRectangularMeasure(int width, int height){ maskView.setRectangularMeasure(width, height); } public static class GuildManager{ private static GuildManager instance; private OnShowGuildViewListener onShowGuildViewListener; private GuildManager(){} public static GuildManager newInstance() { if (instance == null){ instance = new GuildManager(); } return instance; } public void setOnShowGuildViewListener(OnShowGuildViewListener onShowGuildViewListener) { this.onShowGuildViewListener = onShowGuildViewListener; } public void onShowGuildView(View view) { if (onShowGuildViewListener != null){ onShowGuildViewListener.onShowGuildView(view); } } } }
三 实现调用
GuildView.GuildManager.newInstance().setOnShowGuildViewListener(new GuildView.OnShowGuildViewListener() { @Override public void onShowGuildView(View view) { if (SharedPref.get(MyConfig.GUILD_PATH_ONE_TEMP, true)){ SharedPref.put(MyConfig.GUILD_PATH_ONE_TEMP, false); guideView.setRectangular(view, 30, 25, -10, -25, 10); guideView.setTitleIcon(20, 120, 0, 0, R.mipmap.icon_guild_1); guideView.setTitleIcon(46, 300, 0, 0, R.mipmap.icon_guild_2); guideView.setVisibility(View.VISIBLE); } } });
四 将dp转换成px要用的工具方法
public static int dpToPx(float dp, Context context) { return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); }
END