Android高亮新手引导蒙层实现

编程入门 行业动态 更新时间:2024-10-26 14:27:24

Android高亮<a href=https://www.elefans.com/category/jswz/34/1769482.html style=新手引导蒙层实现"/>

Android高亮新手引导蒙层实现



市面上的 APP 大多都有这个功能,我们这次做的新手高亮引导蒙层有什么特殊之处呢?

最基础的蒙层就是盖在页面的上方大概位置,不能精确定位。也不会随着 view 的变化蒙层的高亮区域和 tips 指示区域跟随底部 view 的位置变化而变化,也不能进行点击事件透传。一般都是点击蒙层后蒙层消失然后需要再次点击 view

我们这次开发的蒙层具备哪些功能,和解决了哪些技术难点,和市面上大多数蒙层博客有什么异同呢。

1 : 蒙层的高亮区域跟随底部目标 view ( 以下简称 targetView )

我们的 APP 可能包含多个 ABTest 可能一个页面同一个 view 不同的 AB 版本 view 所在的位置一样(例如底部 tab 5 个按钮可能变成 4 个),不可能每个版本都去开发一个对应的蒙层,这样工作量大而且代码复杂冗余势必我们需要兼容 view 的位置随时可能变化的问题。

Rect targetRect = new Rect();targetView.getGlobalVisibleRect(targetRect);

通过传入的 targetView 在其 view 测绘完后,我们拿到这个 view 的尺寸以及在全局的坐标,去计算我们覆盖物和 tips 需要覆盖的位置然后 add 到 parent 中。注意这个时机在蒙层 show 的时机去做,过早去计算可能会因为 view 的测量还未完成拿到的是 0 值的 x,y 坐标

2 : 支持贴覆盖物以及自绘制高亮区域

这一期需求的高亮区域为贴的覆盖物,但是实际不管是覆盖物还是自己绘制高亮区域。都支持

@IntDef({HShape.CIRCLE,HShape.RECTANGLE,HShape.OVAL
})
public @interface HShape {int CIRCLE = 0;int RECTANGLE = 1;int OVAL = 2;
}

目前支持的自绘制的形状有三(见上方注解) 1 圆形 2 方形 3 椭圆

3: 点击事件透传

获取到持有的 targetView 计算他的四个边的边界。然后拿到 touch 事件监听的 MotionEvent x,y 判断是够在边界区域内,如果是调用 view 的 performClick

核心代码:

@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {···if (view != null && inRangeOfView(view, event)) {view.performClick();}···}}public boolean inRangeOfView(View view, MotionEvent ev) {int[] location = new int[2];view.getLocationOnScreen(location);int x = location[0];int y = location[1];if (ev.getX() < x || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y + view.getHeight())) {return false;}return true;}

解决业务上的问题

1 适应埋点需求的 Listener

当用户对蒙层操作或者可见等各种状态时,我们需要会用户的操作做埋点采集。来统计数据进行大数据分析,产品获得更可靠的值。

蒙层有 1 蒙层 show 时候的曝光 、 2 蒙层高亮区域被点击 、 3 蒙层高亮区域之外被点击、4 蒙层的 dissmiss

根据上述四类每个蒙层的 guider 都可以设置 OnStateChangedListener

public interface OnStateChangedListener {void onShow();void onDismiss();void onExcludeHighlightDismiss();void onHeightLightViewClick(View view);void onOcclusionListener();
}2 某 targetView 被顶出屏幕外的兜底策略处理

如上图: 立即找房按钮的高亮可能随着 fragment 找房按钮的上方 view 元素多过被 底 tab 遮盖。更多甚者可能会被顶出屏幕外,处理方式: 获取 targetView Y 轴最底部随即和屏幕的最底部做比较,此处还要减去底 tab 的高度如果立即找房按钮被底 tab 遮挡部分也做兜底策略处理

3 弹出蒙层前被阻止的弹窗用户点击蒙层后继续弹出

当弹出蒙层前原本 APP 存在检查用户登录 和 活动弹窗的 dialog 如果在蒙层前后弹出就会存在视觉和逻辑上的混乱。从业务层面我们需要在蒙层弹出前阻塞,用户点击蒙层后还要把之前阻塞的弹窗再次弹出。

处理方式,检查用户是否是第一次安装且符合蒙层弹出条件,如果这个时候有其他 dialog 需要弹出将其次数和类型记录到容器里,阻止 dialog 弹出,采集到的容器释放时机是在用户点击完最后一个蒙层后的 dismiss

    if (GuiderManager.getInstance().isExistOnScreen() || SPUtils.getBoolean(SPUtils.IS_PLAY_GUIDER)) {Log.e("guider", "add handlePopup");GuiderManager.getInstance().addPrevent(2);return;}

总结:

这版蒙层技术上完成了

跟随 view 移动

点击事件透传

覆盖物和自绘制高亮区域

业务上实现了

多埋点适配 listener

targetView 被顶出兜底处理

采集阻塞弹窗后释放逻辑处理

这版本蒙层较为良好的从技术和业务上实现了产品需求,代码逻辑清晰无太多冗余。

源码:

public class GuideView extends RelativeLayout {private int mScreenWidth;private int mScreenHeight;private int mBgColor = 0x99000000;private float mStrokeWidth;private Paint mPaint;private Bitmap mBitmap;private RectF mBitmapRect;private RectF outRect = new RectF();private Canvas mCanvas;private List<HighlightArea> mHighlightList;private Xfermode mode;public GuideView(Context context) {this(context, null);}public GuideView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public GuideView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);Point point = new Point();wm.getDefaultDisplay().getSize(point);mScreenWidth = point.x;mScreenHeight = point.y;initView();}private void initView() {initPaint();mBitmapRect = new RectF();mode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);setWillNotDraw(false);setClickable(true);}private void initPaint() {mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setColor(mBgColor);mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.INNER));}private void initCanvas() {if (mBitmapRect.width() > 0 && mBitmapRect.height() > 0) {mBitmap = Bitmap.createBitmap((int) mBitmapRect.width(),(int) mBitmapRect.height(),Bitmap.Config.ARGB_8888);} else {mBitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);}// 矩形最大边距mStrokeWidth = Math.max(Math.max(mBitmapRect.left, mBitmapRect.top),Math.max(mScreenWidth - mBitmapRect.right, mScreenHeight - mBitmapRect.bottom));outRect.left = mBitmapRect.left - mStrokeWidth / 2;outRect.top = mBitmapRect.top - mStrokeWidth / 2;outRect.right = mBitmapRect.right + mStrokeWidth / 2;outRect.bottom = mBitmapRect.bottom + mStrokeWidth / 2;mCanvas = new Canvas(mBitmap);mCanvas.drawColor(mBgColor);}/*** 设置高亮区域** @param list*/public void setHightLightAreas(List<HighlightArea> list) {mHighlightList = list;if (list != null && !list.isEmpty()) {for (HighlightArea area : list) {// 合并矩形框mBitmapRect.union(area.getRectF());}}initCanvas();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (mHighlightList != null && mHighlightList.size() > 0) {mPaint.setXfermode(mode);mPaint.setStyle(Paint.Style.FILL);for (HighlightArea area : mHighlightList) {RectF rectF = area.getRectF();rectF.offset(-mBitmapRect.left, -mBitmapRect.top);switch (area.mShape) {case HShape.CIRCLE:mCanvas.drawCircle(rectF.centerX(), rectF.centerY(),Math.min(area.mHighLightView.getWidth(), area.mHighLightView.getHeight()) / 2,mPaint);break;case HShape.RECTANGLE:mCanvas.drawRect(rectF, mPaint);break;case HShape.OVAL:mCanvas.drawOval(rectF, mPaint);break;}}canvas.drawBitmap(mBitmap, mBitmapRect.left, mBitmapRect.top, null);//绘制剩余空间的矩形mPaint.setXfermode(null);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(mStrokeWidth + 0.1f);canvas.drawRect(outRect, mPaint);}}public void recyclerBitmap() {if (mBitmap != null) {mBitmap.recycle();mBitmap = null;}}@Overridepublic boolean performClick() {return super.performClick();}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();recyclerBitmap();}
}
public class Guider implements Comparable<Guider> {private Activity mActivity;private FrameLayout mParentView;private GuideView mGuideView;private LinearLayout mTipView;private List<HighlightArea> mAreas = new ArrayList<>();private List<TipsView> mIndicators = new ArrayList<>();private List<Message> mMessages = new ArrayList<>();private Confirm mConfirm;private boolean dismissAnyWhere;private boolean performViewClick;public int guideType;  // 1 搜索  2 情报站 3 金刚 4 智能找房private View targetView;private @DrawableResint overlay;private OnStateChangedListener listener;public Guider(Activity activity) {this(activity, null, null, null, null, true, false, 0, null, 0);}public Guider(Activity activity, List<HighlightArea> areas, List<TipsView> indicators,List<Message> messages, Confirm confirm, boolean dismissAnyWhere, boolean performViewClick, int guideType, View targetView, int overlay) {this.mActivity = activity;this.mAreas = areas;this.mIndicators = indicators;this.mMessages = messages;this.mConfirm = confirm;this.dismissAnyWhere = dismissAnyWhere;this.performViewClick = performViewClick;this.guideType = guideType;this.targetView = targetView;this.overlay = overlay;mParentView = (FrameLayout) mActivity.getWindow().getDecorView();}/*** 设置引导提示 状态改变(显示/取消) 监听** @param listener*/public void setOnStateChangedListener(OnStateChangedListener listener) {this.listener = listener;}public void showByOverlay() {mGuideView = new GuideView(mActivity);mGuideView.setBackgroundColor(mActivity.getResources().getColor(R.color.color_99000000));ImageView imageView = new ImageView(mActivity);imageView.setImageResource(overlay);RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);params.alignWithParent = true;imageView.setLayoutParams(params);imageView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);Rect targetRect = new Rect();targetView.getGlobalVisibleRect(targetRect);imageView.setY(targetRect.top);imageView.setX(targetRect.left + (targetRect.right - targetRect.left) / 2 - imageView.getMeasuredWidth() / 2);if (guideType == 4 && mParentView.getHeight() > 0 && targetRect.bottom > 0) {if (targetRect.bottom > mParentView.getHeight()) {if (listener != null) {listener.onOcclusionListener();return;}//在屏幕外} else {//在屏幕内if (targetRect.bottom > mParentView.getHeight() - GuiderManager.getInstance().getIntelligenceTabHeight()) {if (listener != null) {listener.onOcclusionListener();return;}//在屏幕内但是有且有部分被 底 tab 遮盖}}}View tipsView = null;// 1 搜索  2 情报站 3 金刚 4 智能找房if (guideType == 2) { // 底部情报站tipsView = LayoutInflater.from(mActivity).inflate(R.layout.guide_tips_intelligence, mGuideView, false);tipsView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);tipsView.setY(targetRect.top - tipsView.getMeasuredHeight() - dip2px(mActivity, 10));tipsView.setX(targetRect.left + (targetRect.right - targetRect.left) / 2 - tipsView.getMeasuredWidth() / 2);} else if (guideType == 1) { //搜索tipsView = new ImageView(mActivity);tipsView.setBackground(mActivity.getResources().getDrawable(R.drawable.search_guide_tips));RelativeLayout.LayoutParams searchParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);searchParams.alignWithParent = true;searchParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);searchParams.rightMargin = dip2px(mActivity, 15);tipsView.setLayoutParams(searchParams);tipsView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);tipsView.setY(targetRect.bottom + dip2px(mActivity, 10));tipsView.setX(mGuideView.getX());} else if (guideType == 3) { //金刚tipsView = new ImageView(mActivity);tipsView.setBackground(mActivity.getResources().getDrawable(R.drawable.find_house_guide_tips));RelativeLayout.LayoutParams searchParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);searchParams.alignWithParent = true;searchParams.addRule(RelativeLayout.ALIGN_LEFT);searchParams.leftMargin = dip2px(mActivity, 15);tipsView.setLayoutParams(searchParams);tipsView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);tipsView.setY(targetRect.bottom + dip2px(mActivity, 10));} else if (guideType == 4) {//智能卡片找房tipsView = new ImageView(mActivity);tipsView.setBackground(mActivity.getResources().getDrawable(R.drawable.find_house_card_guide_tips));RelativeLayout.LayoutParams searchParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);searchParams.alignWithParent = true;searchParams.addRule(RelativeLayout.ALIGN_RIGHT);searchParams.rightMargin = dip2px(mActivity, 15);tipsView.setLayoutParams(searchParams);tipsView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);tipsView.setY(targetRect.top - dip2px(mActivity, 10) - tipsView.getMeasuredHeight());}if (tipsView != null) {mGuideView.addView(tipsView);}mGuideView.addView(imageView);mParentView.addView(mGuideView, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));mGuideView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if (ACTION_UP == event.getAction()) {if (mAreas.size() > 0) {for (HighlightArea area : mAreas) {final View view = area.mHighLightView;// 如果点击事件作用在该View上if (view != null && inRangeOfView(view, event)) {dismiss();if (listener != null) {listener.onHeightLightViewClick(view);}if (performViewClick) {view.performClick();}} else if (dismissAnyWhere) {if (listener != null) {listener.onExcludeHighlightDismiss();}dismiss();}}return true;} else {dismiss();return false;}}return false;}});if (listener != null) {listener.onShow();}}/*** 显示引导提示*/public void show() {mGuideView = new GuideView(mActivity);mGuideView.setHightLightAreas(mAreas);mTipView = new LinearLayout(mActivity);mTipView.setGravity(Gravity.CENTER_HORIZONTAL);mTipView.setLayoutParams(new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));mTipView.setOrientation(LinearLayout.VERTICAL);if (mIndicators != null) {for (TipsView tipsView : mIndicators) {addView(tipsView.view, tipsView.offsetX, tipsView.offsetY, tipsView.params);}}if (mMessages != null) {int padding = dip2px(mActivity, 5);for (Message message : mMessages) {TextView tvMsg = new TextView(mActivity);tvMsg.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));tvMsg.setPadding(padding, padding, padding, padding);tvMsg.setGravity(Gravity.CENTER);tvMsg.setText(message.message);tvMsg.setTextColor(Color.WHITE);tvMsg.setTextSize(message.textSize == -1 ? 12 : message.textSize);mTipView.addView(tvMsg);}}if (mConfirm != null) {TextView tvConfirm = new TextView(mActivity);tvConfirm.setGravity(Gravity.CENTER);tvConfirm.setText(mConfirm.text);tvConfirm.setTextColor(Color.WHITE);tvConfirm.setTextSize(mConfirm.textSize == -1 ? 13 : mConfirm.textSize);tvConfirm.setBackgroundResource(R.drawable.btn_selector);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);params.topMargin = dip2px(mActivity, 10);tvConfirm.setLayoutParams(params);int lr = dip2px(mActivity, 8);int tb = dip2px(mActivity, 5);tvConfirm.setPadding(lr, tb, lr, tb);tvConfirm.setOnClickListener(mConfirm.listener != null ?mConfirm.listener : new View.OnClickListener() {@Overridepublic void onClick(View v) {dismiss();}});mTipView.addView(tvConfirm);}addView(mTipView, Constants.CENTER, Constants.CENTER, new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));if (dismissAnyWhere || performViewClick) {mGuideView.setClickable(true);mGuideView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case ACTION_UP:if (mAreas.size() > 0) {for (HighlightArea area : mAreas) {final View view = area.mHighLightView;// 如果点击事件作用在该View上if (view != null && inRangeOfView(view, event)) {dismiss();if (listener != null) {listener.onHeightLightViewClick(view);}if (performViewClick) {view.performClick();}} else if (dismissAnyWhere) {dismiss();}}return true;} else {dismiss();return false;}default:break;}return true;}});}if (listener != null) {listener.onShow();}}/*** 取消引导提示*/public void dismiss() {mGuideView.recyclerBitmap();if (mParentView.indexOfChild(mGuideView) > 0) {mParentView.removeView(mGuideView);if (listener != null) {listener.onDismiss();}}}/*** 添加任意 View 到引导提示的布局上** @param view* @param offsetX X轴偏移,正数表示从布局的左侧往右偏移量,负数表示从布局的右侧往左偏移量。{@link Constants#CENTER}表示居中* @param offsetY Y轴偏移,正数表示从上往下,负数表示从下往上。{@link Constants#CENTER}表示居中* @param params  参数*/private void addView(View view, int offsetX, int offsetY, RelativeLayout.LayoutParams params) {if (params == null)params = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);if (offsetX == Constants.CENTER) {params.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);} else if (offsetX < 0) {params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);params.rightMargin = -offsetX;} else {params.leftMargin = offsetX;}if (offsetY == Constants.CENTER) {params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);} else if (offsetY < 0) {params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);params.bottomMargin = -offsetY;} else {params.topMargin = offsetY;}mGuideView.addView(view, params);}public boolean isShowing() {return mParentView.indexOfChild(mGuideView) > 0;}public boolean inRangeOfView(View view, MotionEvent ev) {int[] location = new int[2];view.getLocationOnScreen(location);int x = location[0];int y = location[1];if (ev.getX() < x || ev.getX() > (x + view.getWidth()) || ev.getY() < y || ev.getY() > (y + view.getHeight())) {return false;}return true;}@Overridepublic int compareTo(Guider o) {return this.guideType - o.guideType;}public static class Builder {Activity activity;List<HighlightArea> areas = new ArrayList<>();List<TipsView> views = new ArrayList<>();List<Message> messages = new ArrayList<>();Confirm confirm;boolean dismissAnyWhere = true;boolean performViewClick;int guideType; // 1 搜索  2 情报站 3 金刚 4 智能找房View targetView; //底部高亮目标 view@DrawableResint overlay;  //底部高亮上面覆盖资源public Builder(Activity activity) {this.activity = activity;}/*** 添加高亮区域** @param view* @param shape 高亮区域形状* @return*/public Builder addHightArea(View view, @HShape int shape) {HighlightArea area = new HighlightArea(view, shape);areas.add(area);return this;}public Builder addHightLightArea(HighlightArea area) {areas.add(area);return this;}/*** 添加箭头指示的图片资源** @param resId* @param offX  X轴偏移 正数表示从布局的左侧往右偏移量,负数表示从布局的右侧往左偏移量。{@link Constants#CENTER}表示居中* @param offY  Y轴偏移 正数表示从布局的上侧往下偏移量,负数表示从布局的下侧往上偏移量。{@link Constants#CENTER}表示居中* @return*/public Builder addIndicator(int resId, int offX, int offY) {ImageView ivIndicator = new ImageView(activity);ivIndicator.setImageResource(resId);views.add(new TipsView(ivIndicator, offX, offY));return this;}public Builder addView(View view, int offX, int offY) {views.add(new TipsView(view, offX, offY));return this;}/*** 添加任意的View** @param view* @param offX   X轴偏移 正数表示从布局的左侧往右偏移量,负数表示从布局的右侧往左偏移量。{@link Constants#CENTER}表示居中* @param offY   Y轴偏移 正数表示从布局的上侧往下偏移量,负数表示从布局的下侧往上偏移量。{@link Constants#CENTER}表示居中* @param params 参数* @return*/public Builder addView(View view, int offX, int offY, RelativeLayout.LayoutParams params) {views.add(new TipsView(view, offX, offY, params));return this;}/*** 添加提示信息,默认居中显示** @param message* @param textSize* @return*/public Builder addMessage(String message, int textSize) {messages.add(new Message(message, textSize));return this;}/*** 添加确定按钮,默认居中显示在提示信息下方** @param btnText* @param textSize* @return*/public Builder setPositiveButton(String btnText, int textSize) {this.confirm = new Confirm(btnText, textSize);return this;}public Builder setPositiveButton(String btnText, int textSize, View.OnClickListener listener) {this.confirm = new Confirm(btnText, textSize, listener);return this;}/*** 是否点击任意区域消失。默认true** @param dismissAnyWhere* @return*/public Builder dismissAnyWhere(boolean dismissAnyWhere) {this.dismissAnyWhere = dismissAnyWhere;return this;}// 1 搜索  2 情报站 3 金刚 4 智能找房public Builder addType(int guideType) {this.guideType = guideType;return this;}public Builder addTargetView(View targetView) {this.targetView = targetView;addHightArea(targetView, HShape.RECTANGLE);return this;}public Builder addTargetOverlay(@DrawableRes int overlay) {this.overlay = overlay;return this;}/*** 若点击作用在高亮区域,是否执行高亮区域的点击事件** @param performViewClick* @return*/public Builder performViewClick(boolean performViewClick) {this.performViewClick = performViewClick;return this;}public Guider build() {return new Guider(activity, areas, views, messages, confirm, dismissAnyWhere, performViewClick, guideType, targetView, overlay);}}public static int dip2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}/*** 获取情报站底部高度*/public int getTargetViewHeight() {if (targetView != null && guideType == 2) {Log.e("getTargetViewHeight", "getHeight : " + targetView.getHeight());Log.e("getTargetViewHeight", "getMeasuredHeight" + targetView.getMeasuredHeight());return targetView.getHeight();}return 0;}}
public class GuiderManager {private List<Guider> guiderList = new ArrayList<>();/*** 1 登录 2 活动*/private List<Integer> preventList = new ArrayList<>();//阻止过的登录弹窗或者活动冲屏弹窗点击蒙层后继续弹private static GuiderManager mInstance;private int intelligenceTabHeight;private GuiderManager() {}public static GuiderManager getInstance() {if (mInstance == null) {mInstance = new GuiderManager();}return mInstance;}private Guider firstGuider;private Guider nextGuider;/*** 被阻止过的弹窗和类型 1 登录 2 活动*/public void addPrevent(int prevent) {if (!preventList.contains(prevent)) {preventList.add(prevent);}}// 金刚 和 智能找房卡片可能依赖网络public void addGuider(Guider guider) {//1 满足实验 Cif (!ABIntellgentHelper.getNoviceGuide(NewEventConstants.P_HOME).equals("C")) {return;}//2 满足机器人引导if (!SPUtils.getBoolean(SPUtils.IS_PLAY_GUIDER)) {return;}if (guider == null) {return;}if (!guiderList.contains(guider)) {//1 搜索 2 情报站 3 金刚 4 智能找房guiderList.add(guider);if (guider.guideType == 2) {intelligenceTabHeight = guider.getTargetViewHeight();}}if (guiderList.size() == 4) {Collections.sort(guiderList);/*** 1 有意向房源有意向楼盘;* 引导第一步;搜索* 引导第二步:智能找房* 2 有意向房源无意向楼盘;* 引导第一步:智能找房;* 引导第二步:楼盘列表;* 3 无意向房源无意向楼盘* 引导第一步:智能找房;* 引导第二步:情报局;*/int route = SPUtils.getInt(SPUtils.SMART_ROBOT_ROUTE);if (route == 0 || route == 3) {firstGuider = guiderList.get(3);nextGuider = guiderList.get(1);} else if (route == 1) {firstGuider = guiderList.get(0);nextGuider = guiderList.get(3);} else if (route == 2) {firstGuider = guiderList.get(3);nextGuider = guiderList.get(2);}if (firstGuider == null || nextGuider == null) {return;}firstGuider.setOnStateChangedListener(new OnStateChangedListener() {@Overridepublic void onOcclusionListener() {//当 firstGuider 是智能找房卡片被遮挡 走 next 路径if (nextGuider != null) {nextGuider.showByOverlay();}}@Overridepublic void onShow() {if (firstGuider.guideType == 1) {  // 1 搜索  2 情报站 3 金刚 4 智能找房Track_pHome._8762_eModuleExposure();//搜索曝光} else if (firstGuider.guideType == 2) {Track_pHome._8772_eModuleExposure();// 情报局曝光} else if (firstGuider.guideType == 3) {Track_pHome._8769_eModuleExposure();//楼盘查询曝光} else if (firstGuider.guideType == 4) {Track_pHome._8765_eModuleExposure(String.valueOf(route));//立即找房曝光}}@Overridepublic void onExcludeHighlightDismiss() {if (firstGuider.guideType == 1) {  // 1 搜索  2 情报站 3 金刚 4 智能找房Track_pHome._8764_eClickSmectite();//搜索蒙层} else if (firstGuider.guideType == 2) {Track_pHome._8774_eClickSmectite();// 情报局蒙层} else if (firstGuider.guideType == 3) {Track_pHome._8771_eClickSmectite();//楼盘查询蒙层} else if (firstGuider.guideType == 4) {Track_pHome._8767_eClickSmectite(String.valueOf(route));//立即找房蒙层}//点击第一个蒙层非高亮区域nextGuider.showByOverlay();}@Overridepublic void onDismiss() {}@Overridepublic void onHeightLightViewClick(View view) {//点击第一个蒙层高亮区域SPUtils.put(SPUtils.IS_PLAY_GUIDER, false); //点击过第二次蒙层后 下次杀死应用不再展示引导if (firstGuider.guideType == 1) {  // 1 搜索  2 情报站 3 金刚 4 智能找房SPUtils.put(SPUtils.IS_SEARCH_FIRST, true);Track_pHome._8763_eClickHighlight();//搜索高亮} else if (firstGuider.guideType == 2) {Track_pHome._8773_eClickHighlight();// 情报局高亮} else if (firstGuider.guideType == 3) {SPUtils.put(SPUtils.IS_HOUSELIST_FIRST, true);Track_pHome._8770_eClickHighlight();//楼盘查询高亮} else if (firstGuider.guideType == 4) {Track_pHome._8766_eClickHighlight(NewEventConstants.P_HOME, String.valueOf(route));//立即找房高亮}}});firstGuider.showByOverlay();nextGuider.setOnStateChangedListener(new OnStateChangedListener() {@Overridepublic void onOcclusionListener() {//当 nextGuider 是智能找房卡片被遮挡 路径 1 搜索 + 智能找房SPUtils.put(SPUtils.IS_PLAY_GUIDER, false); //点击过第二次蒙层后 下次杀死应用不再展示引导}@Overridepublic void onShow() {if (nextGuider.guideType == 1) {  // 1 搜索  2 情报站 3 金刚 4 智能找房Track_pHome._8762_eModuleExposure();//搜索曝光} else if (nextGuider.guideType == 2) {Track_pHome._8772_eModuleExposure();// 情报局曝光} else if (nextGuider.guideType == 3) {Track_pHome._8769_eModuleExposure();//楼盘查询曝光} else if (nextGuider.guideType == 4) {Track_pHome._8765_eModuleExposure(String.valueOf(route));//立即找房曝光}}@Overridepublic void onDismiss() {SPUtils.put(SPUtils.IS_PLAY_GUIDER, false); //点击过第二次蒙层后 下次杀死应用不再展示引导SPUtils.put(SPUtils.IS_HOUSELIST_FIRST, false);SPUtils.put(SPUtils.IS_SEARCH_FIRST, false);}@Overridepublic void onExcludeHighlightDismiss() {//点击第二个蒙层非高亮区域if (nextGuider.guideType == 1) {  // 1 搜索  2 情报站 3 金刚 4 智能找房Track_pHome._8764_eClickSmectite();//搜索蒙层} else if (nextGuider.guideType == 2) {Track_pHome._8774_eClickSmectite();// 情报局蒙层} else if (nextGuider.guideType == 3) {Track_pHome._8771_eClickSmectite();//楼盘查询蒙层} else if (nextGuider.guideType == 4) {Track_pHome._8767_eClickSmectite(String.valueOf(route));//立即找房蒙层}if (mOnGuiderPreventDialogListener != null && preventList.size() > 0) {mOnGuiderPreventDialogListener.continuePopup(preventList);}}@Overridepublic void onHeightLightViewClick(View view) {//点击第二个蒙层高亮区域if (nextGuider.guideType == 1) {  // 1 搜索  2 情报站 3 金刚 4 智能找房SPUtils.put(SPUtils.IS_SEARCH_FIRST, true);Track_pHome._8763_eClickHighlight();//搜索高亮} else if (nextGuider.guideType == 2) {Track_pHome._8773_eClickHighlight();// 情报局高亮} else if (nextGuider.guideType == 3) {SPUtils.put(SPUtils.IS_HOUSELIST_FIRST, true);Track_pHome._8770_eClickHighlight();//楼盘查询高亮} else if (nextGuider.guideType == 4) {Track_pHome._8766_eClickHighlight(NewEventConstants.P_HOME, String.valueOf(route));//立即找房高亮}}});}}public List<Guider> getGuiderList() {return guiderList;}/*** 当前是否有蒙层存在屏幕上展示*/public boolean isExistOnScreen() {if (guiderList.size() == 0) {return false;}for (Guider guider : guiderList) {if (guider.isShowing()) {return true;}}return false;}public void destroy() {guiderList.clear();guiderList = null;}private OnGuiderPreventDialogListener mOnGuiderPreventDialogListener;/*** 阻止过的弹窗 继续弹出的监听** @param onGuiderPreventDialogListener*/public void setOnGuiderPreventDialogListener(OnGuiderPreventDialogListener onGuiderPreventDialogListener) {mOnGuiderPreventDialogListener = onGuiderPreventDialogListener;}public void clearGuiderPrevent() {if (mOnGuiderPreventDialogListener != null) {mOnGuiderPreventDialogListener = null;}preventList.clear();}public int getIntelligenceTabHeight() {return intelligenceTabHeight;}
}

更多推荐

Android高亮新手引导蒙层实现

本文发布于:2024-03-05 20:35:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1713348.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:新手   Android   高亮

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!