Android 快速实现APP新手蒙层引导

        最近在项目开发中,产品设计出了新功能的用户引导,非启动页面左右滑动类型的引导,而是在APP功能界面上,直接上层弹出蒙层形式展示,其实在过往的开发中,也有过相同的功能,但是都比较少,就基本上都采用简单粗暴的直接在XML中布局,然后控制Visible,然后添加点击事件就行。最近公司APP中,产品提出来的有点多,而且部分引导区域需要做到事件的穿透,部分不穿透,甚至出现了异形的镂空,再简单粗暴的去布局,对于后期XML布局的维护存在一定的成本。于是自己决心花费周末的一个时间,写一个公共的库。这个库一定要简单,不能再在XML中布局,并且容易理解。先来几张样例图(网图,和实现功能一样)

废话不多说,先下载Demo 看效果,非常小



网图:


上面是网络上的图片,下面是我的实现图片(图大,就用三张)

自己在线PS做的图,有点丑,将就看。

话不多说,源码:SmartGuideView 到Github去下载吧。

引用方式:

dependencies {

            implementation fileTree(include: ['*.jar'], dir: 'libs')

           implementation 'aiven.guide.view:library:1.0.1'

          //或者使用api

          // api 'aiven.guide.view:library:1.0.1'

}


还是说一下代码把,这里只是说一下怎么用,API的含义,具体有兴趣的朋友可以直接看源码。

类入口:SmartGuide

创建蒙层。

    SmartGuide.newGuide(this)  这里的this 需要传入一个Activity或者fragment。需要注意的是,fragment一定要在attach执行完毕之后才能去调用,因为归根接地用的还是activity。

第一个初始化方法:initBaseColor(颜色值)  初始化引导蒙层的默认背景颜色,一般都是半透明的黑色,所以默认我采用了50%透明度的黑色,可以之定义,如果不知道,就是默认值。

SmartGuide.newGuide(this) .initBaseColor(颜色值)   这样就构建完成了一个没有引导的蒙层。接下来在蒙层中创建一个用户引导。这里我将引导命名为层Layer。一个引导(Layer)包含一个蒙层中的镂空区域和图片介绍信息,具体例子就是上面蚂蚁花呗那张图中,白色蚂蚁花呗的横条就是镂空区域,下面一行白色文字和手就是图片介绍信息。

所以我将这两个分别命名为:Clip 和Panel。

newLayer(Tag) //创建一个引导,并给这个引导指定一个Tag,相当于Id。

所以一个Layer = Clip + Panel 。当然,都不是必须的。这就是接下来的API

buildViewRectClip、buildCustomClip、buildIntroPanel  

不是说两个嘛?怎么冒出了三个函数?

这里ViewRectClip和CustomeClip 都是Clip,两种镂空区域。

ViewRectClip 是一个根据界面上的一个View 在屏幕上的位置,尺寸计算出镂空区域和大小,CustomeClip 是一个绝对位置自定义的裁剪区域,以根布局左上角为坐标定点,自己设置区域和偏移,当然这里我增加了Align,这个就不解释了,程序员做布局基本上都懂。通过buildViewRectClip和buildCustomeClip来设置,参数都是一个Build内部接口,然后返回响应的Clip接口,具体Clip的构建参数见下面的例子中说明。这里不再详细说,或者直接到github上看。clip 有个API需要特殊说明:asIrregularShape(Bitmap)  这个是传入一个异形图片,以图片形状作为镂空形状,上图中有个实例,一个老鼠的造型。

Panel:也通过build方式内部接口回调,Panel也有一个Align,这里的Align和CustomClip的Align 有点区别,这里的Align是Panel 现对于Clip而言。也就是Pannel 局clip的,上、下、做、右。然后设置offsetX,offsetY设置偏移即可。


点击事件:OnGuidClickListener  接口,有三个回调函数,

emptyErrorClicked   点击了非Panel和clip区域,返回值:true 蒙层直接退出,false不退出

clipClicked    点击了clip镂空区域,这里要说明的是,Clip有个接口是API是setEventPassThrough(boolean),这个是标明是否镂空区域点击事件要穿透到APP自身功能布局中的UI响应。

introClicked   点击了Panel 图片介绍区域。

创建完成Layer后可以直接show() 显示,如果一个蒙层同时要显示多个Layer,则要先调用over()方法结束上一个layer的参数设置功能,直接newLayer即可,具体见github的多Layer展示方案。


代码之前,再附带一下传送门:SmartView

https://github.com/aiven163/SmartGuideView


代码实例一:

SmartGuide.newGuide(this)

.initBaseColor(0X80000000)//设置引蒙层背景颜色

            //新建一个引导

            .newLayer(TAG_USER_HEADER)

//创建一个镂空区域

            .buildCustomClip(new SmartGuide.ClipPositionBuilder() {

@Override

                public CustomClipbuildTarget() {

//构建镂空区域图形,支持CustomClip 和ViewRectClip

                    return CustomClip.newClipPos()

.setAlignX(SmartGuide.AlignX.ALIGN_RIGHT)//设置定位水平定位偏向

                            .setAlignY(SmartGuide.AlignY.ALIGN_TOP)//设置定位垂直定位偏向

                            .setOffsetX(SmartUtils.dip2px(getApplicationContext(),14))//根据水平定位偏向设置偏移,如果未ALIGN_LEFT,则是距离屏幕左侧偏移量,如果是ALIGN_RIGHT 则是距离屏幕右侧偏移量

                            .setOffsetY(SmartUtils.getStatusBarHeight(getApplicationContext())+SmartUtils.dip2px(getApplicationContext(),4))

//设置镂空裁剪区域尺寸

                            .setClipSize(SmartUtils.dip2px(getApplicationContext(),48),SmartUtils.dip2px(getApplicationContext(),48))

.clipRadius(SmartUtils.dip2px(getApplicationContext(),24));

                }

})

.buildIntroPanel(new SmartGuide.IntroPanelBuilder() {

@Override

                public IntroPanelbuildFacePanel() {

return IntroPanel.newIntroPanel(getApplicationContext())

//设置介绍图片与clipInfo的对齐信息

                            .setIntroBmp(R.mipmap.test_face)

.setAlign(SmartGuide.AlignX.ALIGN_LEFT,SmartGuide.AlignY.ALIGN_BOTTOM)

.setSize(SmartUtils.dip2px(getApplicationContext(),151),SmartUtils.dip2px(getApplicationContext(),97))

.setOffset(SmartUtils.dip2px(getApplicationContext(),-20),0);

                }

})

.over()//多个newLayer必须用over作为上一个newLayer的结束连接

            .newLayer(TAG_MUSIC_IMG)

//创建一个镂空区域

            .buildViewRectClip(new SmartGuide.ClipPositionBuilder() {

@Override

                public ViewRectClipbuildTarget() {

return ViewRectClip.newClipPos()

.setDstView(R.id.text_pos)

.setPadding(SmartUtils.dip2px(getApplicationContext(),5))

.clipRadius(SmartUtils.dip2px(getApplicationContext(),51));

                }

})

.buildIntroPanel(new SmartGuide.IntroPanelBuilder() {

@Override

                public IntroPanelbuildFacePanel() {

return IntroPanel.newIntroPanel(getApplicationContext())

//设置介绍图片与clipInfo的对齐信息

                            .setIntroBmp(R.mipmap.test_face_music)

.setAlign(SmartGuide.AlignX.ALIGN_LEFT,SmartGuide.AlignY.ALIGN_TOP)

.setSize(SmartUtils.dip2px(getApplicationContext(),120),SmartUtils.dip2px(getApplicationContext(),120))

.setOffset(SmartUtils.dip2px(getApplicationContext(),-100),0);

                }

})

.setOnGuidClickListener(new SmartGuide.OnGuidClickListener() {

@Override

                public boolean emptyErrorClicked() {

return true;

                }

@Override

                public void clipClicked(SmartGuide guide, GuidView view, String tag) {

if (TAG_USER_HEADER.equals(tag)) {

Toast.makeText(getApplicationContext(), "点击了左上角头像裁剪区域", Toast.LENGTH_SHORT).show();

                    }else if(TAG_MUSIC_IMG.equals(tag)){

Toast.makeText(getApplicationContext(), "点击了紫色音乐图标裁剪区域", Toast.LENGTH_SHORT).show();

                    }

}

@Override

                public void introClicked(SmartGuide guide, GuidView view, String tag) {

if (TAG_USER_HEADER.equals(tag)) {

Toast.makeText(getApplicationContext(), "点击了左上角头像图片介绍区域", Toast.LENGTH_SHORT).show();

                    }else if(TAG_MUSIC_IMG.equals(tag)){

Toast.makeText(getApplicationContext(), "点击了紫色音乐图片介绍区域", Toast.LENGTH_SHORT).show();

                    }

}

})

.show();

}




代码实例二:

/**

* 根据View 自身位置定位

* @param view

*/

public void showViewPosLayer(View view){

//构建引导

    SmartGuide.newGuide(this)

.initBaseColor(0X80000000)//设置引蒙层背景颜色

            //新建一个引导

            .newLayer(TAG_MUSIC_IMG)

//创建一个镂空区域

            .buildViewRectClip(new SmartGuide.ClipPositionBuilder() {

@Override

                public ViewRectClipbuildTarget() {

return ViewRectClip.newClipPos()

.setDstView(R.id.text_pos)

.setPadding(SmartUtils.dip2px(getApplicationContext(),5))

.clipRadius(SmartUtils.dip2px(getApplicationContext(),51));

                }

})

.buildIntroPanel(new SmartGuide.IntroPanelBuilder() {

@Override

                public IntroPanelbuildFacePanel() {

return IntroPanel.newIntroPanel(getApplicationContext())

//设置介绍图片与clipInfo的对齐信息

                            .setIntroBmp(R.mipmap.test_face_music)

.setAlign(SmartGuide.AlignX.ALIGN_LEFT,SmartGuide.AlignY.ALIGN_TOP)

.setSize(SmartUtils.dip2px(getApplicationContext(),120),SmartUtils.dip2px(getApplicationContext(),120))

.setOffset(SmartUtils.dip2px(getApplicationContext(),-100),0);

                }

})

.setOnGuidClickListener(new SmartGuide.OnGuidClickListener() {

@Override

                public boolean emptyErrorClicked() {

return true;

                }

@Override

                public void clipClicked(SmartGuide guide, GuidView view, String tag) {

Toast.makeText(getApplicationContext(), "点击了紫色音乐图标裁剪区域", Toast.LENGTH_SHORT).show();

                }

@Override

                public void introClicked(SmartGuide guide, GuidView view, String tag) {

Toast.makeText(getApplicationContext(), "点击了紫色音乐图标介绍图片区域", Toast.LENGTH_SHORT).show();

                }

})

.show();

}





最后多个Layer代码实例:

/**

* 单屏显示多个layer

* @param view

*/

public void showMultLayer(View view){

SmartGuide.newGuide(this)

.initBaseColor(0X80000000)//设置引蒙层背景颜色

            //新建一个引导

            .newLayer(TAG_USER_HEADER)

//创建一个镂空区域

            .buildCustomClip(new SmartGuide.ClipPositionBuilder() {

@Override

                public CustomClipbuildTarget() {

//构建镂空区域图形,支持CustomClip 和ViewRectClip

                    return CustomClip.newClipPos()

.setAlignX(SmartGuide.AlignX.ALIGN_RIGHT)//设置定位水平定位偏向

                            .setAlignY(SmartGuide.AlignY.ALIGN_TOP)//设置定位垂直定位偏向

                            .setOffsetX(SmartUtils.dip2px(getApplicationContext(),14))//根据水平定位偏向设置偏移,如果未ALIGN_LEFT,则是距离屏幕左侧偏移量,如果是ALIGN_RIGHT 则是距离屏幕右侧偏移量

                            .setOffsetY(SmartUtils.getStatusBarHeight(getApplicationContext())+SmartUtils.dip2px(getApplicationContext(),4))

//设置镂空裁剪区域尺寸

                            .setClipSize(SmartUtils.dip2px(getApplicationContext(),48),SmartUtils.dip2px(getApplicationContext(),48))

.clipRadius(SmartUtils.dip2px(getApplicationContext(),24));

                }

})

.buildIntroPanel(new SmartGuide.IntroPanelBuilder() {

@Override

                public IntroPanelbuildFacePanel() {

return IntroPanel.newIntroPanel(getApplicationContext())

//设置介绍图片与clipInfo的对齐信息

                            .setIntroBmp(R.mipmap.test_face)

.setAlign(SmartGuide.AlignX.ALIGN_LEFT,SmartGuide.AlignY.ALIGN_BOTTOM)

.setSize(SmartUtils.dip2px(getApplicationContext(),151),SmartUtils.dip2px(getApplicationContext(),97))

.setOffset(SmartUtils.dip2px(getApplicationContext(),-20),0);

                }

})

.over()//多个newLayer必须用over作为上一个newLayer的结束连接

            .newLayer(TAG_MUSIC_IMG)

//创建一个镂空区域

            .buildViewRectClip(new SmartGuide.ClipPositionBuilder() {

@Override

                public ViewRectClipbuildTarget() {

return ViewRectClip.newClipPos()

.setDstView(R.id.text_pos)

.setPadding(SmartUtils.dip2px(getApplicationContext(),5))

.clipRadius(SmartUtils.dip2px(getApplicationContext(),51));

                }

})

.buildIntroPanel(new SmartGuide.IntroPanelBuilder() {

@Override

                public IntroPanelbuildFacePanel() {

return IntroPanel.newIntroPanel(getApplicationContext())

//设置介绍图片与clipInfo的对齐信息

                            .setIntroBmp(R.mipmap.test_face_music)

.setAlign(SmartGuide.AlignX.ALIGN_LEFT,SmartGuide.AlignY.ALIGN_TOP)

.setSize(SmartUtils.dip2px(getApplicationContext(),120),SmartUtils.dip2px(getApplicationContext(),120))

.setOffset(SmartUtils.dip2px(getApplicationContext(),-100),0);

                }

})

.setOnGuidClickListener(new SmartGuide.OnGuidClickListener() {

@Override

                public boolean emptyErrorClicked() {

return true;

                }

@Override

                public void clipClicked(SmartGuide guide, GuidView view, String tag) {

if (TAG_USER_HEADER.equals(tag)) {

Toast.makeText(getApplicationContext(), "点击了左上角头像裁剪区域", Toast.LENGTH_SHORT).show();

                    }else if(TAG_MUSIC_IMG.equals(tag)){

Toast.makeText(getApplicationContext(), "点击了紫色音乐图标裁剪区域", Toast.LENGTH_SHORT).show();

                    }

}

@Override

                public void introClicked(SmartGuide guide, GuidView view, String tag) {

if (TAG_USER_HEADER.equals(tag)) {

Toast.makeText(getApplicationContext(), "点击了左上角头像图片介绍区域", Toast.LENGTH_SHORT).show();

                    }else if(TAG_MUSIC_IMG.equals(tag)){

Toast.makeText(getApplicationContext(), "点击了紫色音乐图片介绍区域", Toast.LENGTH_SHORT).show();

                    }

}

})

.show();

}

你可能感兴趣的:(Android 快速实现APP新手蒙层引导)