{"id":13644954,"url":"https://github.com/hongyangAndroid/Highlight","last_synced_at":"2025-04-21T11:32:14.127Z","repository":{"id":2178293,"uuid":"43896763","full_name":"hongyangAndroid/Highlight","owner":"hongyangAndroid","description":"一个用于app指向性功能高亮的库","archived":false,"fork":false,"pushed_at":"2022-01-12T03:01:36.000Z","size":2985,"stargazers_count":3156,"open_issues_count":63,"forks_count":588,"subscribers_count":84,"default_branch":"master","last_synced_at":"2025-04-14T08:05:38.110Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hongyangAndroid.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-10-08T15:03:40.000Z","updated_at":"2025-04-03T14:27:23.000Z","dependencies_parsed_at":"2022-07-21T22:48:20.095Z","dependency_job_id":null,"html_url":"https://github.com/hongyangAndroid/Highlight","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hongyangAndroid%2FHighlight","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hongyangAndroid%2FHighlight/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hongyangAndroid%2FHighlight/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hongyangAndroid%2FHighlight/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hongyangAndroid","download_url":"https://codeload.github.com/hongyangAndroid/Highlight/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250013217,"owners_count":21360800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T01:02:21.260Z","updated_at":"2025-04-21T11:32:14.064Z","avatar_url":"https://github.com/hongyangAndroid.png","language":"Java","readme":"# Highlight\n[ ![Download](https://api.bintray.com/packages/isanwenyu/maven/Highlight/images/download.svg) ](https://bintray.com/isanwenyu/maven/Highlight/_latestVersion)\n\n一个用于app指向性功能高亮的库。\n\n有任何意见，欢迎提issue。新建dev分支，欢迎pull request。\n\n## 效果图\n\n竖屏：\n\n\u003cimg src=\"gif/high_light_demo.gif\" width=\"320px\"/\u003e\n\n横屏：\n\n\u003cimg src=\"gif/highlight3.png\" width=\"320px\"/\u003e\n\n\n## 引入\n\n下载代码，然后：\n\n```xml\ndependencies {\n       compile project(':highlight')\n}\n\n```\n\n或者\n\n```\n    compile 'com.isanwenyu.highlight:highlight:1.8.0'\n```\n再或者\n\n```\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.isanwenyu.highlight\u003c/groupId\u003e\n  \u003cartifactId\u003ehighlight\u003c/artifactId\u003e\n  \u003cversion\u003e1.8.0\u003c/version\u003e\n  \u003ctype\u003epom\u003c/type\u003e\n\u003c/dependency\u003e\n\n```\n## 用法\n\n\u003e 最新用法详情：[https://isanwenyu.github.io/2016/11/23/HighLight-latest-usage/\n](https://isanwenyu.github.io/2016/11/23/HighLight-latest-usage/)\n\n### Next Mode 下一步模式\n\u003e Enable next mode and invoke show() method then invoke next() method in HighLight to display tip view in order till remove itself\n\u003e 调用`enableNext()`开启next模式并显示，然后调用next()方法显示下一个提示布局 直到删除自己\n\n#### 1. 开启next模式并显示\n\n\n```\n    /**\n     * 显示 next模式 我知道了提示高亮布局\n     * @param view id为R.id.iv_known的控件\n     * @author isanwenyu@163.com\n     */\n    public  void showNextKnownTipView(View view)\n    {\n        mHightLight = new HighLight(MainActivity.this)//\n                .autoRemove(false)//设置背景点击高亮布局自动移除为false 默认为true\n//                .intercept(false)//设置拦截属性为false 高亮布局不影响后面布局的滑动效果\n                .intercept(true)//拦截属性默认为true 使下方ClickCallback生效\n                .enableNext()//开启next模式并通过show方法显示 然后通过调用next()方法切换到下一个提示布局，直到移除自身\n//                .setClickCallback(new HighLight.OnClickCallback() {\n//                    @Override\n//                    public void onClick() {\n//                        Toast.makeText(MainActivity.this, \"clicked and remove HightLight view by yourself\", Toast.LENGTH_SHORT).show();\n//                        remove(null);\n//                    }\n//                })\n                .anchor(findViewById(R.id.id_container))//如果是Activity上增加引导层，不需要设置anchor\n                .addHighLight(R.id.btn_rightLight,R.layout.info_known,new OnLeftPosCallback(45),new RectLightShape(0,0,15,0,0))//矩形去除圆角\n                .addHighLight(R.id.btn_light,R.layout.info_known,new OnRightPosCallback(5),new BaseLightShape(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()), TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()),0) {\n                    @Override\n                    protected void resetRectF4Shape(RectF viewPosInfoRectF, float dx, float dy) {\n                        //缩小高亮控件范围\n                        viewPosInfoRectF.inset(dx,dy);\n                    }\n\n                    @Override\n                    protected void drawShape(Bitmap bitmap, HighLight.ViewPosInfo viewPosInfo) {\n                        //custom your hight light shape 自定义高亮形状\n                        Canvas canvas = new Canvas(bitmap);\n                        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n                        paint.setDither(true);\n                        paint.setAntiAlias(true);\n                        //blurRadius必须大于0\n                        if(blurRadius\u003e0){\n                            paint.setMaskFilter(new BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.SOLID));\n                        }\n                        RectF rectF = viewPosInfo.rectF;\n                        canvas.drawOval(rectF, paint);\n                    }\n                })\n                .addHighLight(R.id.btn_bottomLight,R.layout.info_known,new OnTopPosCallback(),new CircleLightShape())\n                .addHighLight(view,R.layout.info_known,new OnBottomPosCallback(10),new OvalLightShape(5,5,20))\n                .setOnRemoveCallback(new HighLightInterface.OnRemoveCallback() {//监听移除回调 \n                    @Override\n                    public void onRemove() {\n                        Toast.makeText(MainActivity.this, \"The HightLight view has been removed\", Toast.LENGTH_SHORT).show();\n\n                    }\n                })\n                .setOnShowCallback(new HighLightInterface.OnShowCallback() {//监听显示回调\n                    @Override\n                    public void onShow(HightLightView hightLightView) {\n                        Toast.makeText(MainActivity.this, \"The HightLight view has been shown\", Toast.LENGTH_SHORT).show();\n                    }\n                }).setOnNextCallback(new HighLightInterface.OnNextCallback() {\n                    @Override\n                    public void onNext(HightLightView hightLightView, View targetView, View tipView) {\n                        // targetView 目标按钮 tipView添加的提示布局 可以直接找到'我知道了'按钮添加监听事件等处理\n                        Toast.makeText(MainActivity.this, \"The HightLight show next TipView，targetViewID:\"+(targetView==null?null:targetView.getId())+\",tipViewID:\"+(tipView==null?null:tipView.getId()), Toast.LENGTH_SHORT).show();\n                    }\n                });\n        mHightLight.show();\n    }\n```\n\n#### 2. 调用next()方法依次显示之前添加到提示布局 最后自动移除\n\n```\n/**\n     * 响应所有R.id.iv_known的控件的点击事件\n     * \u003cp\u003e\n     *  移除高亮布局\n     * \u003c/p\u003e\n     *\n     * @param view\n     */\n    public void clickKnown(View view)\n    {\n        if(mHightLight.isShowing() \u0026\u0026 mHightLight.isNext())//如果开启next模式\n        {\n            mHightLight.next();\n        }else\n        {\n            remove(null);\n        }\n    }\n```\n#### 3. 下一步回调监听\n\n```\n    /**\n     * 下一个回调监听 只有Next模式下生效\n     */\n    public static interface OnNextCallback {\n        /**\n         * 监听下一步动作\n         *\n         * @param hightLightView 高亮布局控件\n         * @param targetView     高亮目标控件\n         * @param tipView        高亮提示控件\n         */\n        void onNext(HightLightView hightLightView, View targetView, View tipView);\n    }\n```\n\n#### 4. mAnchor根布局完成回调监听(页面加载完成，自动显示)\n\u003e 针对下方问题4的优化方案 在Activity或Fragment onCreated方法中构造HighLight\n\u003e 通过mAnchor.getViewTreeObserver().addOnGlobalLayoutListener(this)实现\n\n\n```\n    /**\n     * 当界面布局完成显示next模式提示布局\n     * 显示方法必须在onLayouted中调用\n     * 适用于Activity及Fragment中使用\n     * 可以直接在onCreated方法中调用\n     * @author isanwenyu@163.com\n     */\n    public  void showNextTipViewOnCreated(){\n        mHightLight = new HighLight(MainActivity.this)//\n                .anchor(findViewById(R.id.id_container))//如果是Activity上增加引导层，不需要设置anchor\n                .autoRemove(false)\n                .enableNext()\n                .setOnLayoutCallback(new HighLightInterface.OnLayoutCallback() {\n                    @Override\n                    public void onLayouted() {\n                        //mAnchor界面布局完成添加tipview\n                        mHightLight.addHighLight(R.id.btn_rightLight,R.layout.info_gravity_left_down,new OnLeftPosCallback(45),new RectLightShape())\n                                .addHighLight(R.id.btn_light,R.layout.info_gravity_left_down,new OnRightPosCallback(5),new CircleLightShape())\n                                .addHighLight(R.id.btn_bottomLight,R.layout.info_gravity_left_down,new OnTopPosCallback(),new CircleLightShape());\n                        //然后显示高亮布局\n                        mHightLight.show();\n                    }\n                })\n                .setClickCallback(new HighLight.OnClickCallback() {\n                    @Override\n                    public void onClick() {\n                        Toast.makeText(MainActivity.this, \"clicked and show next tip view by yourself\", Toast.LENGTH_SHORT).show();\n                        mHightLight.next();\n                    }\n                });\n    }\n    \n```\n\n### Nomarl Mode 普通模式\n\n对于上面效果图中的一个需要高亮的View，需要通过下面的代码\n\n```\n    /**\n     * 显示我知道了提示高亮布局\n     * @param view id为R.id.iv_known的控件\n     * @author isanwenyu@163.com\n     */\n    public  void showKnownTipView(View view)\n    {\n        mHightLight = new HighLight(MainActivity.this)//\n                .autoRemove(false)//设置背景点击高亮布局自动移除为false 默认为true\n                .intercept(false)//设置拦截属性为false 高亮布局不影响后面布局的滑动效果 而且使下方点击回调失效\n                .setClickCallback(new HighLight.OnClickCallback() {\n                    @Override\n                    public void onClick() {\n                        Toast.makeText(MainActivity.this, \"clicked and remove HightLight view by yourself\", Toast.LENGTH_SHORT).show();\n                        remove(null);\n                    }\n                })\n                .anchor(findViewById(R.id.id_container))//如果是Activity上增加引导层，不需要设置anchor\n                .addHighLight(R.id.btn_rightLight,R.layout.info_known,new OnLeftPosCallback(45),new RectLightShape())\n                .addHighLight(R.id.btn_light,R.layout.info_known,new OnRightPosCallback(5),new CircleLightShape(0,0,0))\n                .addHighLight(R.id.btn_bottomLight,R.layout.info_known,new OnTopPosCallback(),new CircleLightShape())\n                .addHighLight(view,R.layout.info_known,new OnBottomPosCallback(10),new OvalLightShape(5,5,20));\n        mHightLight.show();\n\n//        //added by isanwenyu@163.com 设置监听器只有最后一个添加到HightLightView的knownView响应了事件\n//        //优化在布局中声明onClick方法 {@link #clickKnown(view)}响应所有R.id.iv_known的控件的点击事件\n//        View decorLayout = mHightLight.getHightLightView();\n//        ImageView knownView = (ImageView) decorLayout.findViewById(R.id.iv_known);\n//        knownView.setOnClickListener(new View.OnClickListener()\n//          {\n//            @Override\n//            public void onClick(View view) {\n//                remove(null);\n//            }\n//        });\n    }\n\n```\n\nanchor()指你需要在哪个view上加一层透明的蒙版，如果不设置，默认为android.R.id.content。也就是说，该库支持局部范围内去高亮某些View.\n\naddHighLight包含3个参数：\n\n* 参数1：需要高亮view的id，这个没什么说的\n* 参数2：你的tip布局的layoutId，也就是箭头和文字，你自己编写个布局，参考demo即可。\n* 参数3：是个接口，接口包含一系列的位置信息，如下\n\t\n\t```xml\n\t/**\n\t * @param rightMargin 高亮view在anchor中的右边距\n\t * @param bottomMargin 高亮view在anchor中的下边距\n\t * @param rectF 高亮view的l,t,r,b,w,h都有\n\t * @param marginInfo 设置你的布局的位置，一般设置l,t或者r,b\n\t */\n\t```\n\t哈，提供了一堆的位置信息，但是你要做的，只是去设置leftMargin和topMargin；或者rightMargin和bottomMargin。\n\t\n\t目前看起来，我觉得位置信息够了，当然如果你有想法欢迎提出。\n\t\n\t哈，是不是参数比较多，看着烦，如果你图省事，可以提供一个枚举，提供4个或者8个默认的位置，这个事呢，dota1群`@李志云`已经完成~认识的话可以去找他。\n* 参数4：高亮形状  抽象类BaseLightShape(dx,dy,blurRadius)\n\n\t```xml\n    /**\n     * @param dx 水平方向偏移\n     * @param dy 垂直方向偏移\n     * @param blurRadius 模糊半径 默认15px 0不模糊\n     */\n   ```\n   两个抽象方法：\n   \n   ```\n    /**\n     * reset RectF for Shape by dx and dy. 根据dx，dy重置viewPosInfoRectF大小\n     * @param viewPosInfoRectF\n     * @param dx\n     * @param dy\n     */\n    protected abstract void resetRectF4Shape(RectF viewPosInfoRectF, float dx, float dy);\n\n    /**\n     * draw shape into bitmap. 绘制高亮形状到传递过来的图片画布上\n     * @param bitmap\n     * @param viewPosInfo\n     * @see zhy.com.highlight.view.HightLightView#addViewForEveryTip(HighLight.ViewPosInfo)\n     * @see HightLightView#buildMask()\n     */\n    protected abstract void drawShape(Bitmap bitmap, HighLight.ViewPosInfo viewPosInfo);\n   ```\n   BaseLightShape的实现类：RectLightShape（矩形）、CircleLightShape（圆形）、OvalLightShape（椭圆），具体实现请查看代码\n\n## Question 问题\n\n1. 添加的提示布局怎么在屏幕中水平居中显示（垂直居中类似）\n\t\u003e 提示布局根布局`android:layout_width=\"match_parent\"` `android:gravity=\"center_horizontal\"`\n\n\t\u003e 自定义定位参数`rightMargin=0`\n\t\n2. 怎么针对同一个高亮控件添加多个提示布局\n\n\t\u003e `addHighLight` 多次添加 第一个参数使用同一个控件id即可\n\t\n3. 高亮布局显示后 底层布局有变化 怎么更新高亮布局\n\t\u003e `mHighLight.getHightLightView().requestLayout()` 掉用后高亮布局会重新布局及绘制\n4. ~~页面加载完成，自动显示，应该放在哪里调用？~~\n\t\t\n\t**v1.8.0及以后版本建议使用`setOnLayoutCallback`方式 老版本使用下面方案** \n\t\t\n\t```\n\t    @Override\n\t    public void onWindowFocusChanged(boolean hasFocus) {\n\t        super.onWindowFocusChanged(hasFocus);\n\t        //界面初始化后显示高亮布局\n\t        mHightLight.show();\n\t    }\n\t    \n\t\t或者:\n\t\t\n\t  \tgetWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {\n\t            @Override\n\t            public void onGlobalLayout() {\n\t                if (Build.VERSION.SDK_INT \u003e= Build.VERSION_CODES.JELLY_BEAN) {\n\t                    getWindow().getDecorView().getViewTreeObserver()\n\t                            .removeOnGlobalLayoutListener(this);\n\t                }\n\t                \n\t\t        \t//界面初始化后显示高亮布局\n\t              \tinitHightLight();\n\t              \tmHightLight.show();\n\t            }\n\t\n\t        });\t \n\t```\n\t\t\n5.  ~~如果使用viewpager非第一页高亮布局 有可能定位到屏幕外~~\n\t\n\t**v1.7.2版本已修复 具体方案参考#21**  \n\n\t\u003e 感谢 @liyanxi 提供的方案 会更新到 [README.md](https://github.com/isanwenyu/Highlight/blob/master/README.md)\n\n\t```\n    //自定义高亮形状\n    final HighLight.LightShape mLightShape = new BaseLightShape() {\n        @Override\n        protected void resetRectF4Shape(RectF viewPosInfoRectF, float dx, float dy) {\n           //重置viewPosInfoRectF 模掉屏幕宽度 得到真实的left\n            viewPosInfoRectF.offsetTo(viewPosInfoRectF.left % DeviceUtil.getScreenDispaly(getActivity())[0], viewPosInfoRectF.top);\n        }\n      ......\n\t```\t\n\n## Changelog 更改历史\n\nSee details in [CHANGELOG.md](CHANGELOG.md) file.\n\n## 致谢\n\n- 感谢android day day dota1群，苏苏，提供的图片资源。\n- thx for `李志云@dota1`的测试、修改、提议。\n- thx for [@zj593743143](https://github.com/zj593743143)的测试和建议\n\n","funding_links":[],"categories":["用户引导","Java"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FhongyangAndroid%2FHighlight","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FhongyangAndroid%2FHighlight","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FhongyangAndroid%2FHighlight/lists"}