[
  {
    "path": ".gitignore",
    "content": "# Built application files\r\n*.apk\r\n*.ap_\r\n\r\n# Files for the Dalvik VM\r\n*.dex\r\n\r\n# Java class files\r\n*.class\r\n\r\n# Generated files\r\nbin/\r\ngen/\r\n\r\n# Gradle files\r\n.gradle/\r\nbuild/\r\n\r\n# Local configuration file (sdk path, etc)\r\nlocal.properties\r\n\r\n# Proguard folder generated by Eclipse\r\nproguard/\r\n\r\n# Log Files\r\n*.log\r\n\r\n# Android Studio Navigation editor temp files\r\n.navigation/\r\n\r\n# Android Studio captures folder\r\ncaptures/\r\n.idea\r\n/banner.iml\r\n/gradlew\r\n/gradlew.bat\r\n/gradle.properties\r\n"
  },
  {
    "path": "BannerExample.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"BannerExample\" external.linked.project.path=\"$MODULE_DIR$\" external.root.project.path=\"$MODULE_DIR$\" external.system.id=\"GRADLE\" external.system.module.group=\"\" external.system.module.version=\"unspecified\" type=\"JAVA_MODULE\" version=\"4\">\n  <component name=\"FacetManager\">\n    <facet type=\"java-gradle\" name=\"Java-Gradle\">\n      <configuration>\n        <option name=\"BUILD_FOLDER_PATH\" value=\"$MODULE_DIR$/build\" />\n        <option name=\"BUILDABLE\" value=\"false\" />\n      </configuration>\n    </facet>\n  </component>\n  <component name=\"NewModuleRootManager\" inherit-compiler-output=\"true\">\n    <exclude-output />\n    <content url=\"file://$MODULE_DIR$\">\n      <excludeFolder url=\"file://$MODULE_DIR$/.gradle\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/build\" />\n    </content>\n    <orderEntry type=\"inheritedJdk\" />\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "\r\n## Banner 2.0 全新升级\r\n> 只做一个可以自定义的轮播容器，不侵入UI ———— Banner 2.0\r\n\r\n```\r\n> 各位老铁反馈的问题我都有看，不是不解决，有时真的很难复现，\r\n> 如果能在提交问题时，有条件提供个demo发到我邮箱，方便定位问题，毕竟大家的场景和使用方式都有差异，\r\n> 我自己也在使用，在多个千万级APP上一直稳定运行，如果真有严重问题肯定第一时间就修复了\r\n```\r\n\r\n<a href=\"https://github.com/youth5201314/banner/tree/release-1.4.10\" target=\"_blank\">Banner 1.4.10(还想看老版本的可以点击这里)</a>\r\n\r\n### 阔别已久，从新回归\r\n\r\n* 首先我声明几点：\r\n    * 这只是一个开源库，如果满意你可以使用、可以借鉴修改，希望对你们有所帮助。\r\n    * 如果不满意请友好的提出，注明错误的详细信息或者修改建议，好的想法和自定义的东西亦可以直接提交，大家都能来一起完善。\r\n    * 如果你觉得实在是没用，也请你做一个有自我修养的人。\r\n   \r\n### 主要改进功能介绍\r\n最开始是想上传以前基于viewpager更新好的版本，但是看着viewpager2正式版已经出来了，就上新的吧，viewpager2确实比viewpager性能好很多。\r\n\r\n- [x] 使用了ViewPager2为基础控件  <a href=\"https://developer.android.google.cn/jetpack/androidx/releases/viewpager2\" target=\"_blank\">ViewPager2介绍</a>\r\n- [x] 支持了androidx兼容包\r\n- [x] 方便了UI、Indicator自定义\r\n- [x] 支持画廊效果、魅族效果\r\n- [x] 兼容了水平和垂直轮播，也可以实现类似淘宝头条的效果\r\n- [x] 依赖包目前只需要导入了ViewPager2\r\n\r\n\r\n\r\n### 效果图\r\n更多效果运行demo查看\r\n\r\n![默认](images/banner_example.gif)\r\n\r\n![画廊](images/banner_example2.gif)\r\n\r\n![魅族](images/banner_example1.gif)\r\n\r\n![头条](images/banner_example3.gif)\r\n\r\n##### 内置了多种PageTransformer效果\r\n\r\n![DepthPageTransformer](images/DepthPageTransformer.gif)\r\n![ZoomOutPageTransformer](images/ZoomOutPageTransformer.gif)\r\n\r\n|内置的PageTransformer|\r\n|---|\r\n|AlphaPageTransformer|\r\n|DepthPageTransformer|\r\n|RotateDownPageTransformer|\r\n|RotateUpPageTransformer|\r\n|RotateYTransformer|\r\n|ScaleInTransformer|\r\n|ZoomOutPageTransformer|\r\n 也可以组合使用效果更佳\r\n\r\n## 方法\r\n更多方法以实际使用为准，下面不一定全部列出了\r\n\r\n|方法名|返回类型|描述|\r\n|---|---|---|\r\n|getAdapter()|extends BannerAdapter|获取你设置的BannerAdapter\r\n|getViewPager2()|ViewPager2|获取ViewPager2\r\n|getIndicator()|Indicator|获取你设置的指示器（没有设置直接获取会抛异常哦）\r\n|getIndicatorConfig()|IndicatorConfig|获取你设置的指示器配置信息（没有设置直接获取会抛异常哦）\r\n|getRealCount()|int|返回banner真实总数\r\n|setUserInputEnabled(boolean)|this|禁止手动滑动Banner;true 允许，false 禁止\r\n|setDatas(List<T>)|this|重新设置banner数据\r\n|isAutoLoop(boolean)|this|是否允许自动轮播\r\n|setLoopTime(long)|this|设置轮播间隔时间（默认3000毫秒）\r\n|setScrollTime(long)|this|设置轮播滑动的时间（默认800毫秒）\r\n|start()|this|开始轮播(主要配合生命周期使用)，或者你手动暂停再次启动\r\n|stop()|this|停止轮播(主要配合生命周期使用)，或者你需要手动暂停\r\n|setAdapter(T extends BannerAdapter)|this|设置banner的适配器\r\n|setAdapter(T extends BannerAdapter,boolean)|this|设置banner的适配器,是否支持无限循环\r\n|setOrientation(@Orientation)|this|设置banner轮播方向(垂直or水平)\r\n|setOnBannerListener(this)|this|设置点击事件，下标是从0开始\r\n|addOnPageChangeListener(this)|this|添加viewpager2的滑动监听\r\n|setPageTransformer(PageTransformer)|this|设置viewpager的切换效果\r\n|addPageTransformer(PageTransformer)|this|添加viewpager的切换效果（可以设置多个）\r\n|setIndicator(Indicator)|this|设置banner轮播指示器(提供有base和接口，可以自定义)\r\n|setIndicator(Indicator,boolean)|this|设置指示器（传false代表不将指示器添加到banner上，配合布局文件，可以自我发挥）\r\n|setIndicatorSelectedColor(@ColorInt)|this|设置指示器选中颜色\r\n|setIndicatorSelectedColorRes(@ColorRes)|this|设置指示器选中颜色\r\n|setIndicatorNormalColor(@ColorInt)|this|设置指示器默认颜色\r\n|setIndicatorNormalColorRes(@ColorRes)|this|设置指示器默认颜色\r\n|setIndicatorGravity(@IndicatorConfig.Direction)|this|设置指示器位置（左，中，右）\r\n|setIndicatorSpace(int)|this|设置指示器之间的间距\r\n|setIndicatorMargins(IndicatorConfig.Margins)|this|设置指示器的Margins\r\n|setIndicatorWidth(int,int)|this|设置指示器选中和未选中的宽度，直接影响绘制指示器的大小\r\n|setIndicatorNormalWidth(int)|this|设置指示器未选中的宽度\r\n|setIndicatorSelectedWidth(int)|this|设置指示器选中的宽度\r\n|setIndicatorRadius(int)|this|设置指示器圆角，不要圆角可以设置为0\r\n|setIndicatorHeight(int)|this|设置指示器高度\r\n|setBannerRound(float)|this|设置banner圆角（还有一种setBannerRound2方法，需要5.0以上）\r\n|setBannerGalleryEffect(int,int,float)|this|画廊效果\r\n|setBannerGalleryMZ(int,float)|this|魅族效果\r\n|setStartPosition(int)|this|设置开始的位置 (需要在setAdapter或者setDatas之前调用才有效哦)\r\n|setIndicatorPageChange()|this|设置指示器改变监听 (一般是为了配合数据操作使用，看情况自己发挥)\r\n|setCurrentItem()|this|设置当前位置，和原生使用效果一样\r\n|addBannerLifecycleObserver()|this|给banner添加生命周期观察者，内部自动管理banner的生命周期\r\n\r\n\r\n## Attributes属性\r\n>在banner布局文件中调用,如果你自定义了indicator请做好兼容处理。\r\n下面的属性并不是每个指示器都用得到，所以使用时要注意！\r\n\r\n|Attributes|format|describe\r\n|---|---|---|\r\n|banner_loop_time|integer|轮播间隔时间，默认3000\r\n|banner_auto_loop|boolean|是否自动轮播，默认true\r\n|banner_infinite_loop|boolean|是否支持无限循环（即首尾直接过渡），默认true\r\n|banner_orientation|enum|轮播方向：horizontal（默认） or vertical\r\n|banner_radius|dimension|banner圆角半径，默认0（不绘制圆角）\r\n|banner_indicator_normal_width|dimension|指示器默认的宽度，默认5dp （对RoundLinesIndicator无效）\r\n|banner_indicator_selected_width|dimension|指示器选中的宽度，默认7dp \r\n|banner_indicator_normal_color|color|指示器默认颜色，默认0x88ffffff\r\n|banner_indicator_selected_color|color|指示器选中颜色，默认0x88000000\r\n|banner_indicator_space|dimension|指示器之间的间距，默认5dp （对RoundLinesIndicator无效）\r\n|banner_indicator_gravity|dimension|指示器位置，默认center\r\n|banner_indicator_margin|dimension|指示器的margin,默认5dp，不能和下面的同时使用\r\n|banner_indicator_marginLeft|dimension|指示器左边的margin\r\n|banner_indicator_marginTop|dimension|指示器上边的margin\r\n|banner_indicator_marginRight|dimension|指示器右边的margin\r\n|banner_indicator_marginBottom|dimension|指示器下边的margin\r\n|banner_indicator_height|dimension|指示器高度（对CircleIndicator无效）\r\n|banner_indicator_radius|dimension|指示器圆角（对CircleIndicator无效）\r\n|banner_round_top_left|boolean|设置要绘制的banner圆角方向（如果都不设置默认全部）\r\n|banner_round_top_right|boolean|设置要绘制的banner圆角方向（如果都不设置默认全部）\r\n|banner_round_bottom_left|boolean|设置要绘制的banner圆角方向（如果都不设置默认全部）\r\n|banner_round_bottom_right|boolean|设置要绘制的banner圆角方向（如果都不设置默认全部）\r\n\r\n\r\n\r\n## 使用步骤\r\n>以下提供的是最简单的步骤，需要复杂的样式自己可以自定义\r\n\r\n#### Step 1.依赖banner\r\nGradle \r\n```groovy\r\n\r\nrepositories {\r\n    maven { url \"https://s01.oss.sonatype.org/content/groups/public\" }\r\n}\r\n\r\ndependencies{\r\n    //2.1.0以前jcenter的依赖\r\n    //implementation 'com.youth.banner:banner:2.1.0'\r\n    //现在Maven Central\r\n    implementation 'io.github.youth5201314:banner:2.2.3'\r\n\r\n}\r\n```\r\n\r\n#### Step 2.添加权限到你的 AndroidManifest.xml\r\n```xml\r\n<!-- if you want to load images from the internet -->\r\n<uses-permission android:name=\"android.permission.INTERNET\" /> \r\n\r\n```\r\n\r\n#### Step 3.在布局文件中添加Banner，可以设置自定义属性\r\n！！！此步骤可以省略，可以直接在Activity或者Fragment中new Banner();\r\n```xml\r\n<com.youth.banner.Banner\r\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\r\n    android:id=\"@+id/banner\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"高度自己设置\" />\r\n```\r\n\r\n#### Step 4.继承BannerAdapter，和RecyclerView的Adapter一样（如果你只是图片轮播也可以使用默认的）\r\n！！！此步骤可以省略，图片轮播提供有默认适配器，其他的没有提供是因为大家的可变性要求不确定，所以直接自定义的比较好。\r\n```java\r\n\r\n/**\r\n * 自定义布局，下面是常见的图片样式，更多实现可以看demo，可以自己随意发挥\r\n */\r\npublic class ImageAdapter extends BannerAdapter<DataBean, ImageAdapter.BannerViewHolder> {\r\n\r\n    public ImageAdapter(List<DataBean> mDatas) {\r\n        //设置数据，也可以调用banner提供的方法,或者自己在adapter中实现\r\n        super(mDatas);\r\n    }\r\n\r\n    //创建ViewHolder，可以用viewType这个字段来区分不同的ViewHolder\r\n    @Override\r\n    public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {\r\n        ImageView imageView = new ImageView(parent.getContext());\r\n        //注意，必须设置为match_parent，这个是viewpager2强制要求的\r\n        imageView.setLayoutParams(new ViewGroup.LayoutParams(\r\n                ViewGroup.LayoutParams.MATCH_PARENT,\r\n                ViewGroup.LayoutParams.MATCH_PARENT));\r\n        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);\r\n        return new BannerViewHolder(imageView);\r\n    }\r\n\r\n    @Override\r\n    public void onBindView(BannerViewHolder holder, DataBean data, int position, int size) {\r\n        holder.imageView.setImageResource(data.imageRes);\r\n    }\r\n\r\n    class BannerViewHolder extends RecyclerView.ViewHolder {\r\n        ImageView imageView;\r\n\r\n        public BannerViewHolder(@NonNull ImageView view) {\r\n            super(view);\r\n            this.imageView = view;\r\n        }\r\n    }\r\n}\r\n\r\n```\r\n\r\n#### Step 5.Banner具体方法调用 \r\n\r\n```java\r\npublic class BannerActivity extends AppCompatActivity {\r\n    public void useBanner() {\r\n        //--------------------------简单使用-------------------------------\r\n        banner.addBannerLifecycleObserver(this)//添加生命周期观察者\r\n                .setAdapter(new BannerExampleAdapter(DataBean.getTestData()))\r\n                .setIndicator(new CircleIndicator(this));\r\n        \r\n        //—————————————————————————如果你想偷懒，而又只是图片轮播————————————————————————\r\n         banner.setAdapter(new BannerImageAdapter<DataBean>(DataBean.getTestData3()) {\r\n                    @Override\r\n                    public void onBindView(BannerImageHolder holder, DataBean data, int position, int size) {\r\n                        //图片加载自己实现\r\n                        Glide.with(holder.itemView)\r\n                             .load(data.imageUrl)\r\n                             .apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))\r\n                             .into(holder.imageView);\r\n                    }\r\n                })\r\n                .addBannerLifecycleObserver(this)//添加生命周期观察者\r\n                .setIndicator(new CircleIndicator(this));\r\n        //更多使用方法仔细阅读文档，或者查看demo\r\n    }\r\n}\r\n```\r\n\r\n## Banner使用中优化体验\r\n**如果你需要考虑更好的体验，可以看看下面的代码**\r\n#### Step 1.（可选）生命周期改变时\r\n```java\r\npublic class BannerActivity {\r\n  \r\n    //方法一：自己控制banner的生命周期\r\n    \r\n    @Override\r\n    protected void onStart() {\r\n        super.onStart();\r\n        //开始轮播\r\n        banner.start();\r\n    }\r\n    \r\n    @Override\r\n    protected void onStop() {\r\n        super.onStop();\r\n        //停止轮播\r\n        banner.stop();\r\n    }\r\n    \r\n    @Override\r\n    protected void onDestroy() {\r\n        super.onDestroy();\r\n        //销毁\r\n        banner.destroy();\r\n    }\r\n    \r\n    //方法二：调用banner的addBannerLifecycleObserver()方法，让banner自己控制\r\n   \r\n    protected void onCreate(Bundle savedInstanceState) {\r\n         //添加生命周期观察者\r\n        banner.addBannerLifecycleObserver(this);\r\n    }\r\n}\r\n```\r\n\r\n\r\n## 常见问题（收录被反复询问的问题）\r\n\r\n* 网络图片加载不出来？\r\n\r\n  `banner本身不提供图片加载功能，首先确认banner本身使用是否正确，具体参考demo，\r\n  然后请检查你的图片加载框架或者网络请求框架，服务端也可能加了https安全认证，是看下是否报有证书相关错误`\r\n  \r\n* 怎么实现视频轮播？\r\n\r\n  `demo中有实现类似淘宝商品详情的效果，第一个放视频，后面的放的是图片，并且可以设置首尾不能滑动。\r\n  因为大家使用的播放器不一样业务环境也不同，具体情况自己把握，demo就是给一个思路哈！可以参考和修改`\r\n\r\n* 我想指定轮播开始的位置？\r\n\r\n  `现在提供了setStartPosition()方法，在sheAdapter和setDatas直接调用一次就行了，当然setAdapter后通过setCurrentItem设置也行`\r\n\r\n* 父控件滑动时，banner切换会获取焦点，然后自动全部显示。不想让banner获取焦点可以给父控件加上：\r\n\r\n    ```\r\n        //banner也一定要用最新版哦！\r\n        android:focusable=\"true\"\r\n        android:focusableInTouchMode=\"true\"\r\n    ```\r\n* 怎么设置圆角？\r\n  1、调用提供的方法或者自定义属性进行设置，这里设置的是banner本身的圆角，不是轮播内view的圆角\r\n  2、在adapter中对自定义的view进行自己实现，就拿图片举例：可以自己定义一个圆角的ImageView控件，或者使用glide渲染都行。请举一反三，view都自定义了还有什么不能改的？\r\n  \r\n    \r\n## Thanks\r\n\r\n- [MZBannerView](https://github.com/pinguo-zhouwei/MZBannerView)\r\n- [MagicViewPager](https://github.com/hongyangAndroid/MagicViewPager)\r\n- [zguop的viewpager2的滑动时间解决方案](https://github.com/zguop/banner/blob/master/pager2banner/src/main/java/com/to/aboomy/pager2banner/Banner.java)\r\n\r\n\r\n### 联系方式  <a target=\"_blank\" href=\"http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=KBkYGhAfGhEYEB5oWVkGS0dF\" style=\"text-decoration:none;\"><img src=\"images/mailme.png\"/></a>\r\n* 我的个人微博：https://weibo.com/u/3013494003 有兴趣的也可以关注，大家一起交流\r\n* 有问题可以加群大家一起交流，如果你觉得对你有帮助可以扫描下面支付宝二维码随意打赏下哦！\r\n\r\n<img src=\"images/qq.png\" width=\"220\"/> <img src=\"images/pay.jpg\" width=\"220\"/>\r\n\r\n\r\n## 更新说明\r\n[更新说明](update_message.md)\r\n\r\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdk 33\n\n    defaultConfig {\n        applicationId \"com.test.banner\"\n        minSdk 21\n        targetSdk 33\n        versionCode 1\n        versionName \"1.0\"\n        consumerProguardFiles 'proguard-rules.pro'\n    }\n    buildTypes {\n        debug {\n            minifyEnabled true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n        release {\n            minifyEnabled true\n            shrinkResources true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation 'androidx.appcompat:appcompat:1.1.0'\n    implementation 'androidx.recyclerview:recyclerview:1.2.0'\n    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'\n    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'\n    implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'\n    implementation 'androidx.viewpager:viewpager:1.0.0'\n    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.2'\n    implementation 'androidx.cardview:cardview:1.0.0'\n    implementation 'com.github.bumptech.glide:glide:4.12.0'\n    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'\n    implementation 'com.google.android.material:material:1.2.0-alpha06'\n    implementation 'com.jakewharton:butterknife:10.2.3'\n    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'\n\n    implementation 'com.shuyu:GSYVideoPlayer:7.1.3'\n\n\n    implementation project(':banner')\n//    implementation 'io.github.youth5201314:banner:2.2.1'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "#指定代码的压缩级别\n-optimizationpasses 5\n#包明不混合大小写\n-dontusemixedcaseclassnames\n#不去忽略非公共的库类\n-dontskipnonpubliclibraryclasses\n#优化  不优化输入的类文件\n-dontoptimize\n#预校验\n-dontpreverify\n#混淆时是否记录日志\n-verbose\n# 混淆时所采用的算法\n-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*\n#保护注解\n-keepattributes *Annotation*\n# 保持哪些类不被混淆\n-keep public class * extends android.app.Fragment\n-keep public class * extends android.app.Activity\n-keep public class * extends android.app.Application\n-keep public class * extends android.app.Service\n-keep public class * extends android.content.BroadcastReceiver\n-keep public class * extends android.content.ContentProvider\n-keep public class * extends android.app.backup.BackupAgentHelper\n-keep public class * extends android.preference.Preference\n-keep public class com.android.vending.licensing.ILicensingService\n\n#glide\n-keep public class * implements com.bumptech.glide.module.GlideModule\n-keep public class * extends com.bumptech.glide.module.AppGlideModule\n-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {\n  **[] $VALUES;\n  public *;\n}\n\n#butterknife\n-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }\n-keep class butterknife.*\n-keepclasseswithmembernames class * { @butterknife.* <methods>; }\n-keepclasseswithmembernames class * { @butterknife.* <fields>; }\n-keepclassmembers class * { @butterknife.* <methods>; }\n-keepclassmembers class * { @butterknife.* <fields>; }\n\n#gsyvideoplayer\n-keep class com.shuyu.gsyvideoplayer.video.** { *; }\n-dontwarn com.shuyu.gsyvideoplayer.video.**\n-keep class com.shuyu.gsyvideoplayer.video.base.** { *; }\n-dontwarn com.shuyu.gsyvideoplayer.video.base.**\n-keep class com.shuyu.gsyvideoplayer.utils.** { *; }\n-dontwarn com.shuyu.gsyvideoplayer.utils.**\n-keep class tv.danmaku.ijk.** { *; }\n-dontwarn tv.danmaku.ijk.**\n-keep public class * extends android.view.View{\n    *** get*();\n    void set*(***);\n    public <init>(android.content.Context);\n    public <init>(android.content.Context, android.util.AttributeSet);\n    public <init>(android.content.Context, android.util.AttributeSet, int);\n}\n\n-dontwarn com.google.android.exoplayer.**\n-keep class com.google.android.exoplayer.**{*;}\n\n\n\n\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.test.banner\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".ui.GalleryActivity\" />\n        <activity android:name=\".ui.TouTiaoActivity\" />\n        <activity android:name=\".ui.TVActivity\" />\n        <activity\n            android:name=\".MainActivity\"\n            android:label=\"@string/app_name\"\n            android:exported=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity android:name=\".ui.RecyclerViewBannerActivity\" />\n        <activity android:name=\".ui.ConstraintLayoutBannerActivity\" />\n        <activity android:name=\".ui.VideoActivity\" />\n        <activity\n            android:name=\".ui.Vp2FragmentRecyclerviewActivity\"\n            android:theme=\"@style/Theme.AppCompat.Light.NoActionBar\" />\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/test/banner/MainActivity.java",
    "content": "package com.test.banner;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.view.View;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.resource.bitmap.RoundedCorners;\nimport com.bumptech.glide.request.RequestOptions;\nimport com.google.android.material.snackbar.Snackbar;\nimport com.test.banner.adapter.ImageAdapter;\nimport com.test.banner.adapter.ImageTitleAdapter;\nimport com.test.banner.adapter.ImageTitleNumAdapter;\nimport com.test.banner.adapter.MultipleTypesAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.indicator.DrawableIndicator;\nimport com.test.banner.ui.ConstraintLayoutBannerActivity;\nimport com.test.banner.ui.GalleryActivity;\nimport com.test.banner.ui.RecyclerViewBannerActivity;\nimport com.test.banner.ui.TVActivity;\nimport com.test.banner.ui.TouTiaoActivity;\nimport com.test.banner.ui.VideoActivity;\nimport com.test.banner.ui.Vp2FragmentRecyclerviewActivity;\nimport com.youth.banner.Banner;\nimport com.youth.banner.adapter.BannerImageAdapter;\nimport com.youth.banner.holder.BannerImageHolder;\nimport com.youth.banner.config.BannerConfig;\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.indicator.CircleIndicator;\nimport com.youth.banner.indicator.RoundLinesIndicator;\nimport com.youth.banner.listener.OnPageChangeListener;\nimport com.youth.banner.util.BannerUtils;\nimport com.youth.banner.util.LogUtils;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.swiperefreshlayout.widget.SwipeRefreshLayout;\n\nimport java.util.List;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\nimport butterknife.OnClick;\n\npublic class MainActivity extends AppCompatActivity {\n    @BindView(R.id.banner)\n    Banner banner;\n    @BindView(R.id.indicator)\n    RoundLinesIndicator indicator;\n    @BindView(R.id.swipeRefresh)\n    SwipeRefreshLayout refresh;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        ButterKnife.bind(this);\n\n        List<DataBean> datas =  DataBean.getTestData2();\n\n        //自定义的图片适配器，也可以使用默认的BannerImageAdapter\n        ImageAdapter adapter = new ImageAdapter(datas);\n\n        banner.setAdapter(adapter)\n//              .setCurrentItem(0,false)\n                //添加生命周期观察者\n                .addBannerLifecycleObserver(this)\n                //设置指示器\n                .setIndicator(new CircleIndicator(this))\n                .setOnBannerListener((data, position) -> {\n                    Snackbar.make(banner, ((DataBean) data).title, Snackbar.LENGTH_SHORT).show();\n                    LogUtils.d(\"position：\" + position);\n                });\n\n        //添加item之间切换时的间距(如果使用了画廊效果就不要添加间距了，因为内部已经添加过了)\n//        banner.addPageTransformer(new MarginPageTransformer( BannerUtils.dp2px(10)));\n\n        //和下拉刷新配套使用\n        refresh.setOnRefreshListener(() -> {\n            //模拟网络请求需要3秒，请求完成，设置setRefreshing 为false\n            new Handler().postDelayed(() -> {\n                refresh.setRefreshing(false);\n\n                //给banner重新设置数据（完全覆盖）\n                banner.setDatas(DataBean.getTestData());\n\n                //模拟请求成功（原数据减少） 刷新banner\n//                datas.remove(0);\n//                adapter.notifyDataSetChanged();\n\n                //对setDatas()方法不满意？你可以自己在adapter控制数据，参考setDatas()的实现修改\n//                adapter.updateData(DataBean.getTestData());\n//                banner.setCurrentItem(banner.getStartPosition(), false);\n//                banner.setIndicatorPageChange();\n\n            }, 2000);\n        });\n\n    }\n\n\n    @OnClick({R.id.style_image, R.id.style_image_title, R.id.style_image_title_num, R.id.style_multiple,\n            R.id.style_net_image, R.id.change_indicator, R.id.rv_banner, R.id.cl_banner, R.id.vp_banner,\n            R.id.banner_video, R.id.banner_tv, R.id.gallery, R.id.topLine})\n    public void click(View view) {\n        indicator.setVisibility(View.GONE);\n        switch (view.getId()) {\n            case R.id.style_image:\n                refresh.setEnabled(true);\n                banner.setAdapter(new ImageAdapter(DataBean.getTestData()));\n                banner.setIndicator(new CircleIndicator(this));\n                banner.setIndicatorGravity(IndicatorConfig.Direction.CENTER);\n                break;\n            case R.id.style_image_title:\n                refresh.setEnabled(true);\n                banner.setAdapter(new ImageTitleAdapter(DataBean.getTestData()));\n                banner.setIndicator(new CircleIndicator(this));\n                banner.setIndicatorGravity(IndicatorConfig.Direction.RIGHT);\n                banner.setIndicatorMargins(new IndicatorConfig.Margins(0, 0,\n                        BannerConfig.INDICATOR_MARGIN, BannerUtils.dp2px(12)));\n                break;\n            case R.id.style_image_title_num:\n                refresh.setEnabled(true);\n                //这里是将数字指示器和title都放在adapter中的，如果不想这样你也可以直接设置自定义的数字指示器\n                banner.setAdapter(new ImageTitleNumAdapter(DataBean.getTestData()));\n                banner.removeIndicator();\n                break;\n            case R.id.style_multiple:\n                refresh.setEnabled(true);\n                banner.setIndicator(new CircleIndicator(this));\n                banner.setAdapter(new MultipleTypesAdapter(this, DataBean.getTestData()));\n                break;\n            case R.id.style_net_image:\n                refresh.setEnabled(false);\n                //方法一：使用自定义图片适配器\n//                banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));\n\n                //方法二：使用自带的图片适配器\n                banner.setAdapter(new BannerImageAdapter<DataBean>(DataBean.getTestData3()) {\n                    @Override\n                    public void onBindView(BannerImageHolder holder, DataBean data, int position, int size) {\n                        //图片加载自己实现\n                        Glide.with(holder.itemView)\n                                .load(data.imageUrl)\n                                .thumbnail(Glide.with(holder.itemView).load(R.drawable.loading))\n                                .apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))\n                                .into(holder.imageView);\n                    }\n                });\n                banner.setIndicator(new RoundLinesIndicator(this));\n                banner.setIndicatorSelectedWidth(BannerUtils.dp2px(15));\n                break;\n            case R.id.change_indicator:\n                indicator.setVisibility(View.VISIBLE);\n                //在布局文件中使用指示器，这样更灵活\n                banner.setIndicator(indicator, false);\n                banner.setIndicatorSelectedWidth(BannerUtils.dp2px(15));\n                break;\n            case R.id.gallery:\n                startActivity(new Intent(this, GalleryActivity.class));\n                break;\n            case R.id.rv_banner:\n                startActivity(new Intent(this, RecyclerViewBannerActivity.class));\n                break;\n            case R.id.cl_banner:\n                startActivity(new Intent(this, ConstraintLayoutBannerActivity.class));\n                break;\n            case R.id.vp_banner:\n                startActivity(new Intent(this, Vp2FragmentRecyclerviewActivity.class));\n                break;\n            case R.id.banner_video:\n                startActivity(new Intent(this, VideoActivity.class));\n                break;\n            case R.id.banner_tv:\n                startActivity(new Intent(this, TVActivity.class));\n                break;\n            case R.id.topLine:\n                startActivity(new Intent(this, TouTiaoActivity.class));\n                break;\n            default:\n                throw new IllegalStateException(\"Unexpected value: \" + view.getId());\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/ImageAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\n\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.viewholder.ImageHolder;\nimport com.youth.banner.adapter.BannerAdapter;\n\nimport java.util.List;\n\n/**\n * 自定义布局，图片\n */\npublic class ImageAdapter extends BannerAdapter<DataBean, ImageHolder> {\n\n    public ImageAdapter(List<DataBean> mDatas) {\n        //设置数据，也可以调用banner提供的方法,或者自己在adapter中实现\n        super(mDatas);\n    }\n\n    //更新数据\n    public void updateData(List<DataBean> data) {\n        //这里的代码自己发挥，比如如下的写法等等\n        mDatas.clear();\n        mDatas.addAll(data);\n        notifyDataSetChanged();\n    }\n\n\n    //创建ViewHolder，可以用viewType这个字段来区分不同的ViewHolder\n    @Override\n    public ImageHolder onCreateHolder(ViewGroup parent, int viewType) {\n        ImageView imageView = new ImageView(parent.getContext());\n        //注意，必须设置为match_parent，这个是viewpager2强制要求的\n        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT);\n        imageView.setLayoutParams(params);\n        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);\n        return new ImageHolder(imageView);\n    }\n\n    @Override\n    public void onBindView(ImageHolder holder, DataBean data, int position, int size) {\n        holder.imageView.setImageResource(data.imageRes);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/ImageNetAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.graphics.Bitmap;\nimport android.graphics.Outline;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewOutlineProvider;\nimport android.widget.ImageView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.RequiresApi;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.bumptech.glide.load.resource.bitmap.RoundedCorners;\nimport com.bumptech.glide.request.RequestOptions;\nimport com.bumptech.glide.request.target.BitmapImageViewTarget;\nimport com.bumptech.glide.request.target.SimpleTarget;\nimport com.bumptech.glide.request.transition.Transition;\nimport com.test.banner.R;\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.viewholder.ImageHolder;\nimport com.youth.banner.adapter.BannerAdapter;\nimport com.youth.banner.util.BannerUtils;\n\nimport java.util.List;\n\n/**\n * 自定义布局，网络图片\n */\npublic class ImageNetAdapter extends BannerAdapter<DataBean, ImageHolder> {\n\n    public ImageNetAdapter(List<DataBean> mDatas) {\n        super(mDatas);\n    }\n\n    @Override\n    public ImageHolder onCreateHolder(ViewGroup parent, int viewType) {\n        ImageView imageView = (ImageView) BannerUtils.getView(parent, R.layout.banner_image);\n        //通过裁剪实现圆角\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            BannerUtils.setBannerRound(imageView, 20);\n        }\n        return new ImageHolder(imageView);\n    }\n\n    @Override\n    public void onBindView(ImageHolder holder, DataBean data, int position, int size) {\n        //通过图片加载器实现圆角，你也可以自己使用圆角的imageview，实现圆角的方法很多，自己尝试哈\n        Glide.with(holder.itemView)\n             .load(data.imageUrl)\n             .thumbnail(Glide.with(holder.itemView).load(R.drawable.loading))\n             .skipMemoryCache(true)\n             .diskCacheStrategy(DiskCacheStrategy.NONE)\n//                .apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))\n             .into(holder.imageView);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/ImageTitleAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.R;\nimport com.test.banner.viewholder.ImageTitleHolder;\nimport com.youth.banner.adapter.BannerAdapter;\nimport com.youth.banner.util.BannerUtils;\n\nimport java.util.List;\n\n/**\n * 自定义布局，图片+标题\n */\n\npublic class ImageTitleAdapter extends BannerAdapter<DataBean, ImageTitleHolder> {\n\n    public ImageTitleAdapter(List<DataBean> mDatas) {\n        super(mDatas);\n    }\n\n    @Override\n    public ImageTitleHolder onCreateHolder(ViewGroup parent, int viewType) {\n        return new ImageTitleHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.banner_image_title, parent, false));\n    }\n\n    @Override\n    public void onBindView(ImageTitleHolder holder, DataBean data, int position, int size) {\n        holder.imageView.setImageResource(data.imageRes);\n        holder.title.setText(data.title);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/ImageTitleNumAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.R;\nimport com.youth.banner.adapter.BannerAdapter;\n\nimport java.util.List;\n\n/**\n * 自定义布局，图片+标题+数字指示器\n */\npublic class ImageTitleNumAdapter extends BannerAdapter<DataBean, ImageTitleNumAdapter.BannerViewHolder> {\n\n    public ImageTitleNumAdapter(List<DataBean> mDatas) {\n        //设置数据，也可以调用banner提供的方法\n        super(mDatas);\n    }\n\n    //创建ViewHolder，可以用viewType这个字段来区分不同的ViewHolder\n    @Override\n    public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {\n        //注意布局文件，item布局文件要设置为match_parent，这个是viewpager2强制要求的\n        //或者调用BannerUtils.getView(parent,R.layout.banner_image_title_num);\n        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.banner_image_title_num, parent, false);\n        return new BannerViewHolder(view);\n    }\n\n    //绑定数据\n    @Override\n    public void onBindView(BannerViewHolder holder, DataBean data, int position, int size) {\n        holder.imageView.setImageResource(data.imageRes);\n        holder.title.setText(data.title);\n        //可以在布局文件中自己实现指示器，亦可以使用banner提供的方法自定义指示器，目前样式较少，后面补充\n        holder.numIndicator.setText((position + 1) + \"/\" + size);\n    }\n\n\n    class BannerViewHolder extends RecyclerView.ViewHolder {\n        ImageView imageView;\n        TextView title;\n        TextView numIndicator;\n\n        public BannerViewHolder(@NonNull View view) {\n            super(view);\n            imageView = view.findViewById(R.id.image);\n            title = view.findViewById(R.id.bannerTitle);\n            numIndicator = view.findViewById(R.id.numIndicator);\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/MultipleTypesAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.util.SparseArray;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\n\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.viewholder.ImageHolder;\nimport com.test.banner.viewholder.TitleHolder;\nimport com.test.banner.viewholder.VideoHolder;\nimport com.youth.banner.adapter.BannerAdapter;\nimport com.youth.banner.util.BannerUtils;\n\nimport java.util.List;\n\n/**\n * 自定义布局,多个不同UI切换\n */\npublic class MultipleTypesAdapter extends BannerAdapter<DataBean, RecyclerView.ViewHolder> {\n    private Context context;\n    private SparseArray<RecyclerView.ViewHolder> mVHMap = new SparseArray<>();\n\n    public MultipleTypesAdapter(Context context, List<DataBean> mDatas) {\n        super(mDatas);\n        this.context = context;\n    }\n\n    @Override\n    public RecyclerView.ViewHolder onCreateHolder(ViewGroup parent, int viewType) {\n        switch (viewType) {\n            case 1:\n                return new ImageHolder(BannerUtils.getView(parent, R.layout.banner_image));\n            case 2:\n                return new VideoHolder(BannerUtils.getView(parent, R.layout.banner_video));\n            case 3:\n                return new TitleHolder(BannerUtils.getView(parent, R.layout.banner_title));\n        }\n        return new ImageHolder(BannerUtils.getView(parent, R.layout.banner_image));\n    }\n\n    @Override\n    public int getItemViewType(int position) {\n        //先取得真实的position,在获取实体\n//        return getData(getRealPosition(position)).viewType;\n        //直接获取真实的实体\n        return getRealData(position).viewType;\n        //或者自己直接去操作集合\n//        return mDatas.get(getRealPosition(position)).viewType;\n    }\n\n    @Override\n    public void onBindView(RecyclerView.ViewHolder holder, DataBean data, int position, int size) {\n        int viewType = holder.getItemViewType();\n        switch (viewType) {\n            case 1:\n                ImageHolder imageHolder = (ImageHolder) holder;\n                mVHMap.append(position,imageHolder);\n                imageHolder.imageView.setImageResource(data.imageRes);\n                break;\n            case 2:\n                VideoHolder videoHolder = (VideoHolder) holder;\n                mVHMap.append(position,videoHolder);\n                videoHolder.player.setUp(data.imageUrl, true, null);\n                videoHolder.player.getBackButton().setVisibility(View.GONE);\n                //增加封面\n                ImageView imageView = new ImageView(context);\n                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);\n                imageView.setImageResource(R.drawable.image4);\n                videoHolder.player.setThumbImageView(imageView);\n//                videoHolder.player.startPlayLogic();\n                break;\n            case 3:\n                TitleHolder titleHolder = (TitleHolder) holder;\n                mVHMap.append(position,titleHolder);\n                titleHolder.title.setText(data.title);\n                titleHolder.title.setBackgroundColor(Color.parseColor(DataBean.getRandColor()));\n                break;\n        }\n    }\n\n    public SparseArray<RecyclerView.ViewHolder> getVHMap() {\n        return mVHMap;\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/MyRecyclerViewAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport androidx.annotation.NonNull;\nimport androidx.cardview.widget.CardView;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.Banner;\nimport com.youth.banner.indicator.RoundLinesIndicator;\nimport com.youth.banner.util.BannerUtils;\n\npublic class MyRecyclerViewAdapter extends RecyclerView.Adapter {\n    private Context context;\n\n    public MyRecyclerViewAdapter(Context context) {\n        this.context = context;\n    }\n\n    @NonNull\n    @Override\n    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {\n        if (viewType==R.layout.item) {\n            return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));\n        }else{\n            return new MyBannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.banner, parent, false));\n        }\n    }\n\n    @Override\n    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {\n        if (holder instanceof MyViewHolder) {\n            ((MyViewHolder) holder).cardView.setBackgroundColor(Color.parseColor(DataBean.getRandColor()));\n        }else if (holder instanceof MyBannerViewHolder){\n            Banner banner=((MyBannerViewHolder) holder).banner;\n            banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));\n            banner.setBannerRound(BannerUtils.dp2px(5));\n            banner.setIndicator(new RoundLinesIndicator(context));\n            banner.setIndicatorSelectedWidth((int) BannerUtils.dp2px(15));\n        }\n\n    }\n\n    @Override\n    public int getItemViewType(int position) {\n        if (position%2==0){\n            return R.layout.item;\n        }else{\n            return R.layout.banner;\n        }\n    }\n\n    @Override\n    public int getItemCount() {\n        return 10;\n    }\n\n\n    //banner 内部已实现\n//    @Override\n//    public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {\n//        super.onViewDetachedFromWindow(holder);\n//        Log.e(\"banner_log\", \"onViewDetachedFromWindow:\" + holder.getAdapterPosition());\n//        //定位你的位置\n//        if (holder.getAdapterPosition()%2!=0) {\n//            if (holder instanceof MyBannerViewHolder) {\n//                ((MyBannerViewHolder) holder).banner.stop();\n//            }\n//        }\n//    }\n//\n//    @Override\n//    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {\n//        super.onViewAttachedToWindow(holder);\n//        Log.e(\"banner_log\", \"onViewAttachedToWindow:\" + holder.getAdapterPosition());\n//        if (holder.getAdapterPosition()%2!=0) {\n//            if (holder instanceof MyBannerViewHolder) {\n//                ((MyBannerViewHolder) holder).banner.start();\n//            }\n//        }\n//    }\n\n    class MyViewHolder extends RecyclerView.ViewHolder {\n        public CardView cardView;\n\n        public MyViewHolder(@NonNull View itemView) {\n            super(itemView);\n            cardView = itemView.findViewById(R.id.card_view);\n        }\n    }\n\n    class MyBannerViewHolder extends RecyclerView.ViewHolder {\n        public Banner banner;\n\n        public MyBannerViewHolder(@NonNull View itemView) {\n            super(itemView);\n            banner = itemView.findViewById(R.id.banner);\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/test/banner/adapter/TopLineAdapter.java",
    "content": "package com.test.banner.adapter;\n\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.R;\nimport com.youth.banner.adapter.BannerAdapter;\nimport com.youth.banner.util.BannerUtils;\n\nimport java.util.List;\n\n/**\n * 自定义布局，实现类似1号店、淘宝头条的滚动效果\n */\npublic class TopLineAdapter extends BannerAdapter<DataBean, TopLineAdapter.TopLineHolder> {\n\n    public TopLineAdapter(List<DataBean> mDatas) {\n        super(mDatas);\n    }\n\n    @Override\n    public TopLineHolder onCreateHolder(ViewGroup parent, int viewType) {\n        return new TopLineHolder(BannerUtils.getView(parent,R.layout.top_line_item2));\n    }\n\n    @Override\n    public void onBindView(TopLineHolder holder, DataBean data, int position, int size) {\n        holder.message.setText(data.title);\n        if (data.viewType==1) {\n            holder.source.setText(\"1号店\");\n        }else if (data.viewType==2) {\n            holder.source.setText(\"淘宝头条\");\n        }else if (data.viewType==3) {\n            holder.source.setText(\"京东快报\");\n        }\n    }\n\n    class TopLineHolder extends RecyclerView.ViewHolder {\n        public TextView message;\n        public TextView source;\n\n        public TopLineHolder(@NonNull View view) {\n            super(view);\n            message=view.findViewById(R.id.message);\n            source=view.findViewById(R.id.source);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/bean/DataBean.java",
    "content": "package com.test.banner.bean;\n\nimport com.test.banner.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\n\npublic class DataBean {\n    public Integer imageRes;\n    public String imageUrl;\n    public String title;\n    public int viewType;\n\n    public DataBean(Integer imageRes, String title, int viewType) {\n        this.imageRes = imageRes;\n        this.title = title;\n        this.viewType = viewType;\n    }\n\n    public DataBean(String imageUrl, String title, int viewType) {\n        this.imageUrl = imageUrl;\n        this.title = title;\n        this.viewType = viewType;\n    }\n\n    public static List<DataBean> getTestData() {\n        List<DataBean> list = new ArrayList<>();\n        list.add(new DataBean(R.drawable.image1, \"相信自己,你努力的样子真的很美\", 1));\n        list.add(new DataBean(R.drawable.image2, \"极致简约,梦幻小屋\", 3));\n        list.add(new DataBean(R.drawable.image3, \"超级卖梦人\", 3));\n        list.add(new DataBean(R.drawable.image4, \"夏季新搭配\", 1));\n        list.add(new DataBean(R.drawable.image5, \"绝美风格搭配\", 1));\n        list.add(new DataBean(R.drawable.image6, \"微微一笑 很倾城\", 3));\n        return list;\n    }\n\n    public static List<DataBean> getTestData2() {\n        List<DataBean> list = new ArrayList<>();\n        list.add(new DataBean(R.drawable.image7, \"听风.赏雨\", 3));\n        list.add(new DataBean(R.drawable.image8, \"迪丽热巴.迪力木拉提\", 1));\n        list.add(new DataBean(R.drawable.image9, \"爱美.人间有之\", 3));\n        list.add(new DataBean(R.drawable.image10, \"洋洋洋.气质篇\", 1));\n        list.add(new DataBean(R.drawable.image11, \"生活的态度\", 3));\n        return list;\n    }\n\n    /**\n     * 仿淘宝商品详情第一个是视频\n     * @return\n     */\n    public static List<DataBean> getTestDataVideo() {\n        List<DataBean> list = new ArrayList<>();\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/09/mp4/190309153658147087.mp4\", \"第一个放视频\", 2));\n        list.add(new DataBean(R.drawable.image7, \"听风.赏雨\", 1));\n        list.add(new DataBean(R.drawable.image8, \"迪丽热巴.迪力木拉提\", 1));\n        list.add(new DataBean(R.drawable.image9, \"爱美.人间有之\", 1));\n        list.add(new DataBean(R.drawable.image10, \"洋洋洋.气质篇\", 1));\n        list.add(new DataBean(R.drawable.image11, \"生活的态度\", 1));\n        return list;\n    }\n\n    public static List<DataBean> getTestData3() {\n        List<DataBean> list = new ArrayList<>();\n        list.add(new DataBean(\"https://img.zcool.cn/community/013de756fb63036ac7257948747896.jpg\", null, 1));\n        list.add(new DataBean(\"https://img.zcool.cn/community/01639a56fb62ff6ac725794891960d.jpg\", null, 1));\n        list.add(new DataBean(\"https://img.zcool.cn/community/01270156fb62fd6ac72579485aa893.jpg\", null, 1));\n        list.add(new DataBean(\"https://img.zcool.cn/community/01233056fb62fe32f875a9447400e1.jpg\", null, 1));\n        list.add(new DataBean(\"https://img.zcool.cn/community/016a2256fb63006ac7257948f83349.jpg\", null, 1));\n        return list;\n    }\n\n    public static List<DataBean> getVideos() {\n        List<DataBean> list = new ArrayList<>();\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4\", null, 0));\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/18/mp4/190318231014076505.mp4\", null, 0));\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/18/mp4/190318214226685784.mp4\", null, 0));\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/19/mp4/190319125415785691.mp4\", null, 0));\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/14/mp4/190314223540373995.mp4\", null, 0));\n        list.add(new DataBean(\"http://vfx.mtime.cn/Video/2019/03/14/mp4/190314102306987969.mp4\", null, 0));\n        return list;\n    }\n\n\n    public static List<String> getColors(int size) {\n        List<String> list = new ArrayList<>();\n        for(int i = 0; i < size; i++) {\n            list.add(getRandColor());\n        }\n        return list;\n    }\n\n    /**\n     * 获取十六进制的颜色代码.例如  \"#5A6677\"\n     * 分别取R、G、B的随机值，然后加起来即可\n     *\n     * @return String\n     */\n    public static String getRandColor() {\n        String R, G, B;\n        Random random = new Random();\n        R = Integer.toHexString(random.nextInt(256)).toUpperCase();\n        G = Integer.toHexString(random.nextInt(256)).toUpperCase();\n        B = Integer.toHexString(random.nextInt(256)).toUpperCase();\n\n        R = R.length() == 1 ? \"0\" + R : R;\n        G = G.length() == 1 ? \"0\" + G : G;\n        B = B.length() == 1 ? \"0\" + B : B;\n\n        return \"#\" + R + G + B;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/indicator/NumIndicator.java",
    "content": "package com.test.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.RectF;\nimport android.util.AttributeSet;\n\nimport com.youth.banner.indicator.BaseIndicator;\nimport com.youth.banner.util.BannerUtils;\n\n/**\n * 自定义数字指示器demo，比较简单，具体的自己发挥\n *\n * 这里没有用的自定义属性的参数，可以考虑加上\n */\npublic class NumIndicator extends BaseIndicator {\n    private int width;\n    private int height;\n    private int radius;\n\n    public NumIndicator(Context context) {\n        this(context, null);\n    }\n\n    public NumIndicator(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public NumIndicator(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        mPaint.setTextSize(BannerUtils.dp2px(10));\n        mPaint.setTextAlign(Paint.Align.CENTER);\n        width = (int) BannerUtils.dp2px(30);\n        height = (int) BannerUtils.dp2px(15);\n        radius = (int) BannerUtils.dp2px(20);\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n        setMeasuredDimension(width, height);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n\n        RectF rectF = new RectF(0, 0, width, height);\n        mPaint.setColor(Color.parseColor(\"#70000000\"));\n        canvas.drawRoundRect(rectF, radius, radius, mPaint);\n\n        String text = config.getCurrentPosition() + 1 + \"/\" + count;\n        mPaint.setColor(Color.WHITE);\n        canvas.drawText(text, width / 2, (float) (height * 0.7), mPaint);\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/BannerFragment.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.fragment.app.Fragment;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.ImageNetAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.Banner;\nimport com.youth.banner.indicator.RectangleIndicator;\nimport com.youth.banner.util.BannerUtils;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class BannerFragment extends Fragment {\n\n    @BindView(R.id.banner)\n    Banner banner;\n\n    public static Fragment newInstance() {\n        return new BannerFragment();\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.banner, container, false);\n        ButterKnife.bind(this, view);\n        return view;\n    }\n\n    @Override\n    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));\n        banner.setIndicator(new RectangleIndicator(getActivity()));\n        banner.setIndicatorSpace((int) BannerUtils.dp2px(4));\n        banner.setIndicatorRadius(0);\n    }\n\n    @Override\n    public void onStart() {\n        super.onStart();\n        banner.start();\n    }\n\n    @Override\n    public void onStop() {\n        super.onStop();\n        banner.stop();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/BannerListFragment.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.fragment.app.Fragment;\nimport androidx.recyclerview.widget.LinearLayoutManager;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.MyRecyclerViewAdapter;\nimport com.test.banner.util.ParentRecyclerView;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class BannerListFragment extends Fragment {\n    private static int index;\n    @BindView(R.id.net_rv)\n    RecyclerView recyclerView;\n    @BindView(R.id.text)\n    TextView text;\n\n    public static Fragment newInstance(int i) {\n        index = i;\n        return new BannerListFragment();\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.activity_recyclerview_banner, container, false);\n        ButterKnife.bind(this,view);\n        return view;\n    }\n\n    @Override\n    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        text.setText(\"当前页:\"+index);\n        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));\n        recyclerView.setAdapter(new MyRecyclerViewAdapter(getActivity()));\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/BlankFragment.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.fragment.app.Fragment;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.ImageNetAdapter;\nimport com.test.banner.adapter.MyRecyclerViewAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.indicator.NumIndicator;\nimport com.youth.banner.Banner;\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.indicator.CircleIndicator;\nimport com.youth.banner.util.BannerUtils;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class BlankFragment extends Fragment {\n\n    public static Fragment newInstance() {\n        return new BlankFragment();\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.test,null);\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        LinearLayout linearLayout = getView().findViewById(R.id.ll_view);\n\n        //通过new的方式创建banner\n        Banner banner = new Banner(getActivity());\n        banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));\n        banner.addBannerLifecycleObserver(this);\n        banner.setIndicator(new CircleIndicator(getActivity()));\n\n        //将banner加入到父容器中，实际使用不一定一样\n        linearLayout.addView(banner, LinearLayout.LayoutParams.MATCH_PARENT, (int) BannerUtils.dp2px(120));\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/ConstraintLayoutBannerActivity.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.KeyEvent;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.ImageAdapter;\nimport com.test.banner.adapter.ImageNetAdapter;\nimport com.test.banner.adapter.ImageTitleAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.Banner;\nimport com.youth.banner.config.BannerConfig;\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.indicator.CircleIndicator;\nimport com.youth.banner.util.BannerUtils;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class ConstraintLayoutBannerActivity extends AppCompatActivity {\n    private static final String TAG = \"banner_log\";\n    @BindView(R.id.banner)\n    Banner banner;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_constraint_layout_banner);\n        ButterKnife.bind(this);\n        banner.setAdapter(new ImageTitleAdapter(DataBean.getTestData()));\n        banner.setIndicator(new CircleIndicator(this));\n        banner.setIndicatorSelectedColorRes(R.color.main_color);\n        banner.setIndicatorGravity(IndicatorConfig.Direction.RIGHT);\n        banner.setIndicatorMargins(new IndicatorConfig.Margins(0, 0,\n                BannerConfig.INDICATOR_MARGIN, (int) BannerUtils.dp2px(12)));\n        banner.addBannerLifecycleObserver(this);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/GalleryActivity.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.View;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.ImageAdapter;\nimport com.test.banner.adapter.ImageNetAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.Banner;\nimport com.youth.banner.indicator.CircleIndicator;\nimport com.youth.banner.indicator.DrawableIndicator;\nimport com.youth.banner.transformer.AlphaPageTransformer;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\nimport butterknife.OnClick;\n\npublic class GalleryActivity extends AppCompatActivity {\n\n    @BindView(R.id.banner1)\n    Banner mBanner1;\n    @BindView(R.id.banner2)\n    Banner mBanner2;\n    @BindView(R.id.indicator)\n    DrawableIndicator indicator;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_gallery);\n        ButterKnife.bind(this);\n\n        /**\n         * 画廊效果\n         */\n        mBanner1.setAdapter(new ImageAdapter(DataBean.getTestData2()));\n        mBanner1.setIndicator(new CircleIndicator(this));\n        //添加画廊效果\n        mBanner1.setBannerGalleryEffect(50, 10);\n        //(可以和其他PageTransformer组合使用，比如AlphaPageTransformer，注意但和其他带有缩放的PageTransformer会显示冲突)\n        //添加透明效果(画廊配合透明效果更棒)\n        //mBanner1.addPageTransformer(new AlphaPageTransformer());\n\n\n        /**\n         * 魅族效果\n         */\n        mBanner2.setAdapter(new ImageAdapter(DataBean.getTestData()));\n        mBanner2.setIndicator(indicator,false);\n        //添加魅族效果\n        mBanner2.setBannerGalleryMZ(20);\n\n\n\n    }\n\n\n}"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/RecyclerViewBannerActivity.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.recyclerview.widget.LinearLayoutManager;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.MyRecyclerViewAdapter;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class RecyclerViewBannerActivity extends AppCompatActivity {\n    @BindView(R.id.net_rv)\n    RecyclerView recyclerView;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_recyclerview_banner);\n        ButterKnife.bind(this);\n        recyclerView.setLayoutManager(new LinearLayoutManager(this));\n        recyclerView.setAdapter(new MyRecyclerViewAdapter(this));\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/TVActivity.java",
    "content": "package com.test.banner.ui;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.KeyEvent;\n\nimport com.test.banner.R;\nimport com.test.banner.adapter.ImageAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.Banner;\nimport com.youth.banner.indicator.CircleIndicator;\nimport com.youth.banner.util.BannerUtils;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class TVActivity extends AppCompatActivity {\n\n    private static final String TAG = \"banner_log\";\n    @BindView(R.id.banner)\n    Banner banner;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_t_v);\n        ButterKnife.bind(this);\n        banner.setAdapter(new ImageAdapter(DataBean.getTestData()));\n        banner.setIndicator(new CircleIndicator(this));\n        banner.isAutoLoop(false);\n    }\n\n    @Override\n    public boolean onKeyDown(int keyCode, KeyEvent event) {\n        int count = banner.getItemCount();\n        switch (keyCode) {\n            case KeyEvent.KEYCODE_DPAD_LEFT:\n                Log.d(TAG, \"向左\");\n                int prev = (banner.getCurrentItem() - 1) % count;\n                if (prev == 0) {\n                    prev = banner.getRealCount();\n                } else if (prev == count - 1) {\n                    prev = 1;\n                }\n                banner.setCurrentItem(prev, false);\n                break;\n            case KeyEvent.KEYCODE_DPAD_RIGHT:\n                Log.d(TAG, \"向右\");\n                int next = (banner.getCurrentItem() + 1) % count;\n                if (next == 0) {\n                    next = banner.getRealCount();\n                } else if (next == count - 1) {\n                    next = 1;\n                }\n                banner.setCurrentItem(next, false);\n                break;\n        }\n        //如果没有设置指示器，就不用执行下面两行\n        int real = BannerUtils.getRealPosition(banner.isInfiniteLoop(), banner.getCurrentItem(), banner.getRealCount());\n        banner.getIndicator().onPageSelected(real);\n        return super.onKeyDown(keyCode, event);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/TouTiaoActivity.java",
    "content": "package com.test.banner.ui;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\nimport android.os.Bundle;\n\nimport com.google.android.material.snackbar.Snackbar;\nimport com.test.banner.R;\nimport com.test.banner.adapter.TopLineAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.youth.banner.Banner;\nimport com.youth.banner.transformer.ZoomOutPageTransformer;\nimport com.youth.banner.util.LogUtils;\n\npublic class TouTiaoActivity extends AppCompatActivity {\n    @BindView(R.id.banner)\n    Banner banner;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_tou_tiao);\n        ButterKnife.bind(this);\n\n        //实现1号店和淘宝头条类似的效果\n        banner.setAdapter(new TopLineAdapter(DataBean.getTestData2()))\n               .setOrientation(Banner.VERTICAL)\n               .setPageTransformer(new ZoomOutPageTransformer())\n               .setOnBannerListener((data, position) -> {\n                   Snackbar.make(banner, ((DataBean) data).title, Snackbar.LENGTH_SHORT).show();\n                   LogUtils.d(\"position：\" + position);\n               });\n\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/VideoActivity.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.util.Log;\n\nimport com.shuyu.gsyvideoplayer.GSYVideoManager;\nimport com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;\nimport com.test.banner.R;\nimport com.test.banner.adapter.MultipleTypesAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.indicator.NumIndicator;\nimport com.test.banner.viewholder.VideoHolder;\nimport com.youth.banner.Banner;\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.listener.OnPageChangeListener;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.recyclerview.widget.RecyclerView;\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\n/**\n * 仿淘宝商品详情，banner第一个放视频,然后首尾不能自己滑动，加上自定义数字指示器\n */\npublic class VideoActivity extends AppCompatActivity {\n    @BindView(R.id.banner)\n    Banner banner;\n    StandardGSYVideoPlayer player;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_video);\n        ButterKnife.bind(this);\n\n        banner.addBannerLifecycleObserver(this)\n                .setAdapter(new MultipleTypesAdapter(this, DataBean.getTestDataVideo()))\n                .setIndicator(new NumIndicator(this))\n                .setIndicatorGravity(IndicatorConfig.Direction.RIGHT)\n                .addOnPageChangeListener(new OnPageChangeListener() {\n                    @Override\n                    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n                        stopVideo(position);\n                    }\n\n                    @Override\n                    public void onPageSelected(int position) {\n                        Log.e(\"--\",\"position:\"+position);\n                        stopVideo(position);\n                    }\n\n                    @Override\n                    public void onPageScrollStateChanged(int state) {\n\n                    }\n                });\n    }\n\n    private void stopVideo(int position) {\n        if (player == null) {\n            RecyclerView.ViewHolder viewHolder = banner.getAdapter().getViewHolder();\n            if (viewHolder instanceof VideoHolder) {\n                VideoHolder holder = (VideoHolder) viewHolder;\n                player = holder.player;\n                if (position != 0) {\n                    player.onVideoPause();\n                }\n            }\n        }else {\n            if (position != 0) {\n                player.onVideoPause();\n            }\n        }\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        if (player != null)\n            player.onVideoPause();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        if (player != null)\n            player.onVideoResume();\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        GSYVideoManager.releaseAllVideos();\n    }\n\n    @Override\n    public void onBackPressed() {\n        //释放所有\n        if (player != null)\n            player.setVideoAllCallBack(null);\n        super.onBackPressed();\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/ui/Vp2FragmentRecyclerviewActivity.java",
    "content": "package com.test.banner.ui;\n\nimport android.os.Bundle;\n\nimport com.google.android.material.tabs.TabLayout;\nimport com.test.banner.R;\nimport com.test.banner.adapter.ImageAdapter;\nimport com.test.banner.bean.DataBean;\nimport com.test.banner.util.TabLayoutMediator;\nimport com.youth.banner.Banner;\nimport com.youth.banner.indicator.CircleIndicator;\n\nimport androidx.annotation.NonNull;\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.fragment.app.Fragment;\nimport androidx.viewpager2.adapter.FragmentStateAdapter;\nimport androidx.viewpager2.widget.ViewPager2;\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class Vp2FragmentRecyclerviewActivity extends AppCompatActivity {\n\n    @BindView(R.id.vp2)\n    ViewPager2 viewPager2;\n    @BindView(R.id.tab_layout)\n    TabLayout mTabLayout;\n    @BindView(R.id.banner)\n    Banner mBanner;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_vp2_fragment_recyclerview);\n        ButterKnife.bind(this);\n\n        viewPager2.setAdapter(new FragmentStateAdapter(this) {\n            @NonNull\n            @Override\n            public Fragment createFragment(int position) {\n                if (position == 0) {\n                    return BannerListFragment.newInstance(position);\n                } else if (position == 1) {\n                    return BlankFragment.newInstance();\n                } else {\n                    return BannerFragment.newInstance();\n                }\n            }\n\n            @Override\n            public int getItemCount() {\n                return 3;\n            }\n        });\n\n        new TabLayoutMediator(mTabLayout, viewPager2, (tab, position) -> {\n            tab.setText(\"页面\" + position);\n        }).attach();\n\n\n        mBanner.addBannerLifecycleObserver(this)\n               .setAdapter(new ImageAdapter(DataBean.getTestData()))\n               .setIntercept(false)\n               .setIndicator(new CircleIndicator(this));\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/util/ParentRecyclerView.java",
    "content": "package com.test.banner.util;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.view.MotionEvent;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.recyclerview.widget.RecyclerView;\n\npublic class ParentRecyclerView extends RecyclerView {\n    public ParentRecyclerView(@NonNull Context context) {\n        super(context);\n    }\n\n    public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n    private float mStartX, mStartY;\n\n    @Override\n    public boolean dispatchTouchEvent(MotionEvent ev) {\n        switch (ev.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mStartX = ev.getX();\n                mStartY = ev.getY();\n                break;\n            case MotionEvent.ACTION_MOVE:\n                float endX = ev.getX();\n                float endY = ev.getY();\n                float distanceX = Math.abs(endX - mStartX);\n                float distanceY = Math.abs(endY - mStartY);\n                getParent().requestDisallowInterceptTouchEvent(!(distanceX > 4 && distanceX > distanceY));\n                break;\n        }\n        return super.dispatchTouchEvent(ev);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/util/TabLayoutMediator.java",
    "content": "package com.test.banner.util;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.RestrictTo;\nimport androidx.recyclerview.widget.RecyclerView;\nimport androidx.viewpager2.widget.ViewPager2;\n\nimport com.google.android.material.tabs.TabLayout;\n\nimport java.lang.ref.WeakReference;\nimport java.lang.reflect.Method;\n\nimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;\nimport static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_DRAGGING;\nimport static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_IDLE;\nimport static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_SETTLING;\n\n/**\n * A mediator to link a TabLayout with a ViewPager2. The mediator will synchronize the ViewPager2's\n * position with the selected tab when a tab is selected, and the TabLayout's scroll position when\n * the user drags the ViewPager2.\n *\n * Establish the link by creating an instance of this class, make sure the ViewPager2 has an adapter\n * and then call {@link #attach()} on it. When creating an instance of this class, you must supply\n * an implementation of {@link OnConfigureTabCallback} in which you set the text of the tab, and/or\n * perform any styling of the tabs that you require.\n *\n * @hide\n */\n@RestrictTo(LIBRARY_GROUP)\npublic final class TabLayoutMediator {\n    private final @NonNull TabLayout mTabLayout;\n    private final @NonNull ViewPager2 mViewPager;\n    private final boolean mAutoRefresh;\n    private final OnConfigureTabCallback mOnConfigureTabCallback;\n    private RecyclerView.Adapter mAdapter;\n    private boolean mAttached;\n\n    private TabLayoutOnPageChangeCallback mOnPageChangeCallback;\n    private TabLayout.OnTabSelectedListener mOnTabSelectedListener;\n    private RecyclerView.AdapterDataObserver mPagerAdapterObserver;\n\n    /**\n     * A callback interface that must be implemented to set the text and styling of newly created\n     * tabs.\n     */\n    public interface OnConfigureTabCallback {\n        /**\n         * Called to configure the tab for the page at the specified position. Typically calls\n         * {@link TabLayout.Tab#setText(CharSequence)}, but any form of styling can be applied.\n         *\n         * @param tab The Tab which should be configured to represent the title of the item at the\n         *        given position in the data set.\n         * @param position The position of the item within the adapter's data set.\n         */\n        void onConfigureTab(@NonNull TabLayout.Tab tab, int position);\n    }\n\n    /**\n     * Creates a TabLayoutMediator to synchronize a TabLayout and a ViewPager2 together. It will\n     * update the tabs automatically when the data set of the view pager's adapter changes. The link\n     * will be established after {@link #attach()} is called.\n     *\n     * @param tabLayout The tab bar to link\n     * @param viewPager The view pager to link\n     */\n    public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager,\n                             @NonNull OnConfigureTabCallback onConfigureTabCallback) {\n        this(tabLayout, viewPager, true, onConfigureTabCallback);\n    }\n\n    /**\n     * Creates a TabLayoutMediator to synchronize a TabLayout and a ViewPager2 together. If {@code\n     * autoRefresh} is true, it will update the tabs automatically when the data set of the view\n     * pager's adapter changes. The link will be established after {@link #attach()} is called.\n     *\n     * @param tabLayout The tab bar to link\n     * @param viewPager The view pager to link\n     * @param autoRefresh If {@code true}, will recreate all tabs when the data set of the view\n     *                   pager's adapter changes.\n     */\n    public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager,\n                             boolean autoRefresh, @NonNull OnConfigureTabCallback onConfigureTabCallback) {\n        mTabLayout = tabLayout;\n        mViewPager = viewPager;\n        mAutoRefresh = autoRefresh;\n        mOnConfigureTabCallback = onConfigureTabCallback;\n    }\n\n    /**\n     * Link the TabLayout and the ViewPager2 together.\n     * @throws IllegalStateException If the mediator is already attached, or the ViewPager2 has no\n     *         adapter.\n     */\n    public void attach() {\n        if (mAttached) {\n            throw new IllegalStateException(\"TabLayoutMediator is already attached\");\n        }\n        mAdapter = mViewPager.getAdapter();\n        if (mAdapter == null) {\n            throw new IllegalStateException(\"TabLayoutMediator attached before ViewPager2 has an \"\n                    + \"adapter\");\n        }\n        mAttached = true;\n\n        // Add our custom OnPageChangeCallback to the ViewPager\n        mOnPageChangeCallback = new TabLayoutOnPageChangeCallback(mTabLayout);\n        mViewPager.registerOnPageChangeCallback(mOnPageChangeCallback);\n\n        // Now we'll add a tab selected listener to set ViewPager's current item\n        mOnTabSelectedListener = new ViewPagerOnTabSelectedListener(mViewPager);\n        mTabLayout.addOnTabSelectedListener(mOnTabSelectedListener);\n\n        // Now we'll populate ourselves from the pager adapter, adding an observer if\n        // autoRefresh is enabled\n        if (mAutoRefresh) {\n            // Register our observer on the new adapter\n            mPagerAdapterObserver = new PagerAdapterObserver();\n            mAdapter.registerAdapterDataObserver(mPagerAdapterObserver);\n        }\n\n        populateTabsFromPagerAdapter();\n\n        // Now update the scroll position to match the ViewPager's current item\n        mTabLayout.setScrollPosition(mViewPager.getCurrentItem(), 0f, true);\n    }\n\n    /**\n     * Unlink the TabLayout and the ViewPager\n     */\n    public void detach() {\n        mAdapter.unregisterAdapterDataObserver(mPagerAdapterObserver);\n        mTabLayout.removeOnTabSelectedListener(mOnTabSelectedListener);\n        mViewPager.unregisterOnPageChangeCallback(mOnPageChangeCallback);\n        mPagerAdapterObserver = null;\n        mOnTabSelectedListener = null;\n        mOnPageChangeCallback = null;\n        mAttached = false;\n    }\n\n    @SuppressWarnings(\"WeakerAccess\")\n    void populateTabsFromPagerAdapter() {\n        mTabLayout.removeAllTabs();\n\n        if (mAdapter != null) {\n            int adapterCount = mAdapter.getItemCount();\n            for (int i = 0; i < adapterCount; i++) {\n                TabLayout.Tab tab = mTabLayout.newTab();\n                mOnConfigureTabCallback.onConfigureTab(tab, i);\n                mTabLayout.addTab(tab, false);\n            }\n\n            // Make sure we reflect the currently set ViewPager item\n            if (adapterCount > 0) {\n                int currItem = mViewPager.getCurrentItem();\n                if (currItem != mTabLayout.getSelectedTabPosition()) {\n                    mTabLayout.getTabAt(currItem).select();\n                }\n            }\n        }\n    }\n\n    /**\n     * A {@link ViewPager2.OnPageChangeCallback} class which contains the necessary calls back to\n     * the provided {@link TabLayout} so that the tab position is kept in sync.\n     *\n     * <p>This class stores the provided TabLayout weakly, meaning that you can use {@link\n     * ViewPager2#registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback)} without removing\n     * the callback and not cause a leak.\n     */\n    private static class TabLayoutOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {\n        private final WeakReference<TabLayout> mTabLayoutRef;\n        private int mPreviousScrollState;\n        private int mScrollState;\n\n        TabLayoutOnPageChangeCallback(TabLayout tabLayout) {\n            mTabLayoutRef = new WeakReference<>(tabLayout);\n            reset();\n        }\n\n        @Override\n        public void onPageScrollStateChanged(final int state) {\n            mPreviousScrollState = mScrollState;\n            mScrollState = state;\n        }\n\n        @Override\n        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n            TabLayout tabLayout = mTabLayoutRef.get();\n            if (tabLayout != null) {\n                // Only update the text selection if we're not settling, or we are settling after\n                // being dragged\n                boolean updateText = mScrollState != SCROLL_STATE_SETTLING\n                        || mPreviousScrollState == SCROLL_STATE_DRAGGING;\n                // Update the indicator if we're not settling after being idle. This is caused\n                // from a setCurrentItem() call and will be handled by an animation from\n                // onPageSelected() instead.\n                boolean updateIndicator = !(mScrollState == SCROLL_STATE_SETTLING\n                        && mPreviousScrollState == SCROLL_STATE_IDLE);\n                setScrollPosition(tabLayout, position, positionOffset, updateText, updateIndicator);\n            }\n        }\n\n        @Override\n        public void onPageSelected(final int position) {\n            TabLayout tabLayout = mTabLayoutRef.get();\n            if (tabLayout != null\n                    && tabLayout.getSelectedTabPosition() != position\n                    && position < tabLayout.getTabCount()) {\n                // Select the tab, only updating the indicator if we're not being dragged/settled\n                // (since onPageScrolled will handle that).\n                boolean updateIndicator = mScrollState == SCROLL_STATE_IDLE\n                        || (mScrollState == SCROLL_STATE_SETTLING\n                        && mPreviousScrollState == SCROLL_STATE_IDLE);\n                selectTab(tabLayout, tabLayout.getTabAt(position), updateIndicator);\n            }\n        }\n\n        void reset() {\n            mPreviousScrollState = mScrollState = SCROLL_STATE_IDLE;\n        }\n    }\n\n    // region Reflective calls\n\n    // Temporarily call methods TabLayout.setScrollPosition(int, float, boolean, boolean) and\n    // TabLayout.selectTab(TabLayout.Tab, boolean) through reflection, until they have been made\n    // public in the Material Design Components library.\n\n    private static Method sSetScrollPosition;\n    private static Method sSelectTab;\n    private static final String SET_SCROLL_POSITION_NAME = \"TabLayout.setScrollPosition(int, float,\"\n            + \" boolean, boolean)\";\n    private static final String SELECT_TAB_NAME = \"TabLayout.selectTab(TabLayout.Tab, boolean)\";\n\n    static {\n        try {\n            sSetScrollPosition = TabLayout.class.getDeclaredMethod(\"setScrollPosition\", int.class,\n                    float.class, boolean.class, boolean.class);\n            sSetScrollPosition.setAccessible(true);\n\n            sSelectTab = TabLayout.class.getDeclaredMethod(\"selectTab\", TabLayout.Tab.class,\n                    boolean.class);\n            sSelectTab.setAccessible(true);\n        } catch (NoSuchMethodException e) {\n            throw new IllegalStateException(\"Can't reflect into method TabLayout\"\n                    + \".setScrollPosition(int, float, boolean, boolean)\");\n        }\n    }\n\n    @SuppressWarnings(\"WeakerAccess\")\n    static void setScrollPosition(TabLayout tabLayout, int position, float positionOffset,\n                                  boolean updateSelectedText, boolean updateIndicatorPosition) {\n        try {\n            if (sSetScrollPosition != null) {\n                sSetScrollPosition.invoke(tabLayout, position, positionOffset, updateSelectedText,\n                        updateIndicatorPosition);\n            } else {\n                throwMethodNotFound(SET_SCROLL_POSITION_NAME);\n            }\n        } catch (Exception e) {\n            throwInvokeFailed(SET_SCROLL_POSITION_NAME);\n        }\n    }\n\n    @SuppressWarnings(\"WeakerAccess\")\n    static void selectTab(TabLayout tabLayout, TabLayout.Tab tab, boolean updateIndicator) {\n        try {\n            if (sSelectTab != null) {\n                sSelectTab.invoke(tabLayout, tab, updateIndicator);\n            } else {\n                throwMethodNotFound(SELECT_TAB_NAME);\n            }\n        } catch (Exception e) {\n            throwInvokeFailed(SELECT_TAB_NAME);\n        }\n    }\n\n    private static void throwMethodNotFound(String method) {\n        throw new IllegalStateException(\"Method \" + method + \" not found\");\n    }\n\n    private static void throwInvokeFailed(String method) {\n        throw new IllegalStateException(\"Couldn't invoke method \" + method);\n    }\n\n    // endregion\n\n    /**\n     * A {@link TabLayout.OnTabSelectedListener} class which contains the necessary calls back to\n     * the provided {@link ViewPager2} so that the tab position is kept in sync.\n     */\n    private static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {\n        private final ViewPager2 mViewPager;\n\n        ViewPagerOnTabSelectedListener(ViewPager2 viewPager) {\n            this.mViewPager = viewPager;\n        }\n\n        @Override\n        public void onTabSelected(TabLayout.Tab tab) {\n            mViewPager.setCurrentItem(tab.getPosition(), true);\n        }\n\n        @Override\n        public void onTabUnselected(TabLayout.Tab tab) {\n            // No-op\n        }\n\n        @Override\n        public void onTabReselected(TabLayout.Tab tab) {\n            // No-op\n        }\n    }\n\n    private class PagerAdapterObserver extends RecyclerView.AdapterDataObserver {\n        PagerAdapterObserver() {}\n\n        @Override\n        public void onChanged() {\n            populateTabsFromPagerAdapter();\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount) {\n            populateTabsFromPagerAdapter();\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {\n            populateTabsFromPagerAdapter();\n        }\n\n        @Override\n        public void onItemRangeInserted(int positionStart, int itemCount) {\n            populateTabsFromPagerAdapter();\n        }\n\n        @Override\n        public void onItemRangeRemoved(int positionStart, int itemCount) {\n            populateTabsFromPagerAdapter();\n        }\n\n        @Override\n        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {\n            populateTabsFromPagerAdapter();\n        }\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/viewholder/ImageHolder.java",
    "content": "package com.test.banner.viewholder;\n\nimport android.view.View;\nimport android.widget.ImageView;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\npublic class ImageHolder extends RecyclerView.ViewHolder {\n    public ImageView imageView;\n\n    public ImageHolder(@NonNull View view) {\n        super(view);\n        this.imageView = (ImageView) view;\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/test/banner/viewholder/ImageTitleHolder.java",
    "content": "package com.test.banner.viewholder;\n\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\n\npublic class ImageTitleHolder extends RecyclerView.ViewHolder {\n    public ImageView imageView;\n    public TextView title;\n\n    public ImageTitleHolder(@NonNull View view) {\n        super(view);\n        imageView = view.findViewById(R.id.image);\n        title = view.findViewById(R.id.bannerTitle);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/viewholder/TitleHolder.java",
    "content": "package com.test.banner.viewholder;\n\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.test.banner.R;\n\npublic class TitleHolder extends RecyclerView.ViewHolder {\n    public TextView title;\n\n    public TitleHolder(@NonNull View view) {\n        super(view);\n        title = view.findViewById(R.id.bannerTitle);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/test/banner/viewholder/VideoHolder.java",
    "content": "package com.test.banner.viewholder;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;\nimport com.test.banner.R;\n\npublic class VideoHolder extends RecyclerView.ViewHolder {\n    public StandardGSYVideoPlayer player;\n\n    public VideoHolder(@NonNull View view) {\n        super(view);\n        player = view.findViewById(R.id.player);\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <gradient\n    android:startColor=\"#09000000\"\n    android:endColor=\"#aa000000\"\n    android:angle=\"270\" />\n\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/default_selecter.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@color/main_color\" android:state_pressed=\"true\"/>\n    <item android:drawable=\"@color/main_color\" android:state_selected=\"true\"/>\n    <item android:drawable=\"@android:color/transparent\"/>\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/green.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <corners android:radius=\"5dp\" />\n    <padding\n        android:bottom=\"2dp\"\n        android:left=\"6dp\"\n        android:right=\"6dp\"\n        android:top=\"2dp\" />\n    <stroke android:color=\"@color/main_color\" android:width=\"0.5dp\"/>\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/selected_radius.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n    <solid android:color=\"@color/main_color\" />\n    <corners android:radius=\"5dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/unselected_radius.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"oval\">\n    <solid android:color=\"#ffffff\" />\n    <corners android:radius=\"5dp\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/white.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <solid android:color=\"#55ffffff\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/layout/activity_constraint_layout_banner.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.ConstraintLayoutBannerActivity\">\n\n\n    <TextView\n        android:id=\"@+id/textView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"15dp\"\n        android:text=\"ConstraintLayout嵌套banner\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <com.youth.banner.Banner\n        android:id=\"@+id/banner\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:layout_constraintDimensionRatio=\"2:1\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@id/textView\" />\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_gallery.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:banner=\"http://schemas.android.com/apk/res-auto\"    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n    <com.youth.banner.Banner\n        android:id=\"@+id/banner1\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"140dp\"\n        android:layout_margin=\"10dp\"\n        banner:banner_radius=\"5dp\"\n        banner:banner_indicator_normal_color=\"@android:color/white\"\n        banner:banner_indicator_selected_color=\"@color/colorPrimary\" />\n\n    <com.youth.banner.Banner\n        android:id=\"@+id/banner2\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"140dp\"\n        android:layout_margin=\"10dp\"\n        banner:banner_radius=\"5dp\"\n        banner:banner_indicator_normal_color=\"@android:color/white\"\n        banner:banner_indicator_selected_color=\"@color/colorPrimary\" />\n\n    <com.youth.banner.indicator.DrawableIndicator\n        android:id=\"@+id/indicator\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center_horizontal\"\n        banner:normal_drawable=\"@drawable/indicator_normal\"\n        banner:selected_drawable=\"@drawable/indicator_selected\"/>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<androidx.swiperefreshlayout.widget.SwipeRefreshLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:banner=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/swipeRefresh\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"#f5f5f5\">\n\n        <com.youth.banner.Banner\n            android:id=\"@+id/banner\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"180dp\"\n            android:layout_margin=\"10dp\"\n            banner:banner_indicator_normal_color=\"@android:color/white\"\n            banner:banner_indicator_selected_color=\"@color/colorPrimary\"\n            banner:banner_radius=\"5dp\"/>\n\n        <com.youth.banner.indicator.RoundLinesIndicator\n            android:id=\"@+id/indicator\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"20dp\"\n            android:layout_below=\"@+id/banner\"\n            android:layout_centerHorizontal=\"true\"\n            android:visibility=\"gone\" />\n\n        <androidx.core.widget.NestedScrollView\n            android:id=\"@+id/scroll\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_below=\"@+id/banner\"\n            android:layout_marginTop=\"20dp\">\n\n            <RelativeLayout\n                android:id=\"@+id/rl_main\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:background=\"#f5f5f5\"\n                android:scrollbars=\"none\">\n\n                <Button\n                    android:id=\"@+id/style_image\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"图片\" />\n\n                <Button\n                    android:id=\"@+id/style_image_title\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_toRightOf=\"@id/style_image\"\n                    android:text=\"图片+标题+指示器\" />\n\n                <Button\n                    android:id=\"@+id/style_image_title_num\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_toRightOf=\"@+id/style_image_title\"\n                    android:text=\"图片+标题+数字\" />\n\n                <Button\n                    android:id=\"@+id/style_multiple\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/style_image\"\n                    android:text=\"多类型UI\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/style_net_image\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/style_image\"\n                    android:layout_toRightOf=\"@+id/style_multiple\"\n                    android:text=\"网络图片\" />\n\n                <Button\n                    android:id=\"@+id/change_indicator\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_toRightOf=\"@+id/style_net_image\"\n                    android:layout_below=\"@+id/style_image_title_num\"\n                    android:text=\"外部指示器\" />\n\n\n                <Button\n                    android:id=\"@+id/gallery\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/change_indicator\"\n                    android:text=\"画廊,魅族效果,Drawable指示器\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/topLine\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/gallery\"\n                    android:text=\"用banner实现类似淘宝头条的效果\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/rv_banner\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/topLine\"\n                    android:text=\"RecyclerView嵌套banner\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/cl_banner\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/rv_banner\"\n                    android:text=\"ConstraintLayout嵌套banner\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/vp_banner\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/cl_banner\"\n                    android:text=\"viewpaer2+fragment+RecyclerView嵌套banner\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/banner_video\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/vp_banner\"\n                    android:text=\"仿淘宝商品详情banner\"\n                    android:textAllCaps=\"false\" />\n\n                <Button\n                    android:id=\"@+id/banner_tv\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_below=\"@+id/banner_video\"\n                    android:text=\"测试在tv中，遥控切换banner\"\n                    android:textAllCaps=\"false\" />\n            </RelativeLayout>\n        </androidx.core.widget.NestedScrollView>\n    </RelativeLayout>\n\n</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_recyclerview_banner.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n    <TextView\n        android:id=\"@+id/text\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"RecyclerView+banner\"\n        android:padding=\"10dp\"\n        android:gravity=\"center\"/>\n\n    <androidx.recyclerview.widget.RecyclerView\n        android:id=\"@+id/net_rv\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_t_v.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.TVActivity\">\n\n    <TextView\n        android:id=\"@+id/textView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:padding=\"15dp\"\n        android:text=\"TV中遥控控制banner切换，因为没有真机测试，所以不确定有没有问题，有测试环境的朋友可以多多反馈，或者修改哈\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintHorizontal_bias=\"0.5\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <com.youth.banner.Banner\n        android:id=\"@+id/banner\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"0dp\"\n        app:banner_indicator_selected_color=\"@color/colorPrimary\"\n        app:layout_constraintDimensionRatio=\"2:1\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@id/textView\" />\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_tou_tiao.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.TouTiaoActivity\">\n    <RelativeLayout\n        android:id=\"@+id/topLine\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"65dp\"\n        android:layout_below=\"@+id/tip2\"\n        android:background=\"#ffffff\"\n        android:layout_margin=\"5dp\"\n        android:paddingTop=\"10dp\"\n        android:paddingBottom=\"10dp\"\n        android:orientation=\"horizontal\"\n        tools:ignore=\"MissingConstraints\">\n\n        <ImageView\n            android:id=\"@+id/image_top\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:src=\"@drawable/home_hotpoint\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_marginRight=\"10dp\"\n            android:layout_centerVertical=\"true\"/>\n\n        <com.youth.banner.Banner\n            android:id=\"@+id/banner\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_toRightOf=\"@+id/image_top\"\n            android:layout_toLeftOf=\"@+id/image_right\"\n            android:layout_centerVertical=\"true\"/>\n        <ImageView\n            android:id=\"@+id/image_right\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:src=\"@drawable/home_right_arrow\"\n            android:layout_marginLeft=\"10dp\"\n            android:layout_marginRight=\"10dp\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_centerVertical=\"true\"/>\n    </RelativeLayout>\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_video.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.VideoActivity\">\n\n    <com.youth.banner.Banner\n        android:id=\"@+id/banner\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"200dp\"\n        app:banner_infinite_loop=\"false\"\n        app:layout_constraintTop_toTopOf=\"parent\"/>\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_vp2_fragment_recyclerview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <androidx.viewpager2.widget.ViewPager2\n        android:id=\"@+id/vp2\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\" />\n\n\n    <com.google.android.material.appbar.AppBarLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <com.google.android.material.appbar.CollapsingToolbarLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            app:layout_scrollFlags=\"scroll|exitUntilCollapsed\"\n            app:titleEnabled=\"false\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"180dp\"\n                android:orientation=\"vertical\">\n\n                <com.youth.banner.Banner\n                    android:id=\"@+id/banner\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"180dp\"/>\n\n            </LinearLayout>\n\n            <androidx.appcompat.widget.Toolbar\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"40dp\"\n                app:layout_collapseMode=\"pin\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"match_parent\"\n                    android:layout_centerVertical=\"true\"\n                    android:layout_gravity=\"center_vertical|center_horizontal\"\n                    android:gravity=\"center_vertical\"\n                    android:text=\"Banner\"\n                    android:textColor=\"#fff\"\n                    android:textStyle=\"bold\"\n                    android:textSize=\"20sp\" />\n            </androidx.appcompat.widget.Toolbar>\n        </com.google.android.material.appbar.CollapsingToolbarLayout>\n\n        <com.google.android.material.tabs.TabLayout\n            android:id=\"@+id/tab_layout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"#fff\"\n            app:tabSelectedTextColor=\"@color/colorPrimary\"\n            app:tabIndicatorColor=\"@color/colorPrimary\"/>\n    </com.google.android.material.appbar.AppBarLayout>\n\n</androidx.coordinatorlayout.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/banner.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n    <com.youth.banner.Banner\n        android:id=\"@+id/banner\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"100dp\"\n        android:layout_margin=\"10dp\"/>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/banner_image.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ImageView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/image\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:scaleType=\"centerCrop\"/>"
  },
  {
    "path": "app/src/main/res/layout/banner_image_title.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ImageView\n        android:id=\"@+id/image\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:scaleType=\"centerCrop\" />\n\n    <TextView\n        android:id=\"@+id/bannerTitle\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"#66000000\"\n        android:ellipsize=\"marquee\"\n        android:focusable=\"true\"\n        android:focusableInTouchMode=\"true\"\n        android:gravity=\"center_vertical\"\n        android:padding=\"10dp\"\n        android:singleLine=\"true\"\n        android:textColor=\"#ffffff\"\n        android:layout_alignParentBottom=\"true\"/>\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/banner_image_title_num.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ImageView\n        android:id=\"@+id/image\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:scaleType=\"centerCrop\" />\n\n    <LinearLayout\n        android:id=\"@+id/titleView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:layout_alignParentBottom=\"true\"\n        android:background=\"#44000000\"\n        android:orientation=\"horizontal\"\n        android:padding=\"5dp\">\n\n        <TextView\n            android:id=\"@+id/bannerTitle\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_weight=\"1000\"\n            android:ellipsize=\"marquee\"\n            android:focusable=\"true\"\n            android:focusableInTouchMode=\"true\"\n            android:gravity=\"center_vertical\"\n            android:paddingLeft=\"10dp\"\n            android:singleLine=\"true\"\n            android:textColor=\"#ffffff\" />\n\n        <TextView\n            android:id=\"@+id/numIndicator\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"match_parent\"\n            android:gravity=\"center_vertical\"\n            android:text=\"1/1\"\n            android:textColor=\"#ffffff\" />\n    </LinearLayout>\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/banner_title.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n    <TextView\n        android:id=\"@+id/bannerTitle\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:textColor=\"#ffffff\"\n        android:textSize=\"25dp\"\n        android:gravity=\"center\"\n        android:background=\"#5CB85C\" />\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/banner_video.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer\n        android:id=\"@+id/player\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.cardview.widget.CardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:card_view=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/card_view\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"120dp\"\n    android:layout_gravity=\"center\"\n    android:layout_marginLeft=\"5dp\"\n    android:layout_marginRight=\"5dp\"\n    android:foreground=\"?android:attr/selectableItemBackground\"\n    card_view:cardCornerRadius=\"4dp\"\n    card_view:cardElevation=\"2dp\"\n    card_view:cardUseCompatPadding=\"true\"\n    card_view:cardBackgroundColor=\"@color/main_color\">\n\n</androidx.cardview.widget.CardView>"
  },
  {
    "path": "app/src/main/res/layout/test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/ll_view\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:padding=\"10dp\">\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:gravity=\"center\"\n        android:text=\"测试\"\n        android:textColor=\"@color/colorPrimary\"\n        android:textSize=\"20dp\" />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/top_line_item2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <TextView\n        android:id=\"@+id/message\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:lines=\"1\"\n        android:text=\"实现1号店热点效果\"\n        android:textColor=\"#444444\"\n        android:layout_marginBottom=\"10dp\"\n        android:textSize=\"14sp\" />\n    <TextView\n        android:id=\"@+id/source\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:lines=\"1\"\n        android:layout_below=\"@id/message\"\n        android:layout_marginRight=\"10dp\"\n        android:textColor=\"@color/main_color\"\n        android:background=\"@drawable/green\"\n        android:textSize=\"10dp\"\n        android:text=\"1号店\"/>\n    <TextView\n        android:id=\"@+id/time\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:lines=\"1\"\n        android:textSize=\"13sp\"\n        android:layout_toRightOf=\"@id/source\"\n        android:layout_below=\"@id/message\"\n        android:text=\"2020年1月23日\"/>\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/values/arrays.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <array name=\"url\">\n        <item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic1xjab4j30ci08cjrv.jpg</item>\n        <item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic21363tj30ci08ct96.jpg</item>\n        <item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic259ohaj30ci08c74r.jpg</item>\n        <item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic2b16zuj30ci08cwf4.jpg</item>\n        <item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic2e7vsaj30ci08cglz.jpg</item>\n    </array>\n\n    <array name=\"url1\">\n        <item>http://img.zcool.cn/community/01700557a7f42f0000018c1bd6eb23.jpg</item>\n    </array>\n    <array name=\"url2\">\n        <item>http://img.zcool.cn/community/01d28457d621800000018c1bb7877e.jpg</item>\n        <item>http://img.zcool.cn/community/01ae5656e1427f6ac72531cb72bac5.jpg</item>\n    </array>\n    <array name=\"url4\">\n        <item>http://img.zcool.cn/community/01b72057a7e0790000018c1bf4fce0.png</item>\n        <item>http://img.zcool.cn/community/01fca557a7f5f90000012e7e9feea8.jpg</item>\n        <item>http://img.zcool.cn/community/01996b57a7f6020000018c1bedef97.jpg</item>\n        <item>http://img.zcool.cn/community/01700557a7f42f0000018c1bd6eb23.jpg</item>\n    </array>\n    <!-- http://588ku.com/image/daitengmandelitizi.html -->\n    <array name=\"test_num_url\">\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f19cc0079.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1ac12d1d.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1bad97d1.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1c83c228.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1d53e3dd.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1e37fea9.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1ef4d709.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f20b3ea10.jpg</item>\n        <item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f21927f8d.jpg</item>\n    </array>\n    <array name=\"title\">\n        <item>51巅峰钜惠</item>\n        <item>十大星级品牌联盟，全场2折起</item>\n        <item>生命不是要超越别人，而是要超越自己。</item>\n        <item>己所不欲，勿施于人。——孔子</item>\n        <item>嗨购5折不要停</item>\n    </array>\n    <array name=\"demo_list\">\n        <item>banner动画预览</item>\n        <item>banner内置样式预览</item>\n        <item>banner指示器位置设置预览</item>\n        <item>banner一些自定义样式方法预览</item>\n        <item>banner加载本地图片</item>\n        <item>banner自定义布局文件（这里通过修改ViewPager举一反三吧）</item>\n        <item>！！banner更多用法请看文档，这里就不一一列举了！</item>\n    </array>\n    <array name=\"anim\">\n        <item>Default</item>\n        <item>Accordion</item>\n        <item>BackgroundToForeground</item>\n        <item>ForegroundToBackground</item>\n        <item>CubeIn</item>\n        <item>CubeOut</item>\n        <item>DepthPage</item>\n        <item>FlipHorizontal</item>\n        <item>FlipVertical</item>\n        <item>RotateDown</item>\n        <item>RotateUp</item>\n        <item>ScaleInOut</item>\n        <item>Stack</item>\n        <item>Tablet</item>\n        <item>ZoomIn</item>\n        <item>ZoomOut</item>\n        <item>ZoomOutSlide</item>\n    </array>\n    <string-array name=\"style\">\n        <item>NOT_INDICATOR</item>\n        <item>CIRCLE_INDICATOR</item>\n        <item>NUM_INDICATOR</item>\n        <item>NUM_INDICATOR_TITLE</item>\n        <item>CIRCLE_INDICATOR_TITLE</item>\n        <item>CIRCLE_INDICATOR_TITLE_INSIDE</item>\n    </string-array>\n    <string-array name=\"indicator\">\n        <item>LEFT</item>\n        <item>CENTER</item>\n        <item>RIGHT</item>\n    </string-array>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">@color/main_color</color>\n    <color name=\"colorPrimaryDark\">@color/main_color</color>\n    <color name=\"colorAccent\">@color/main_color</color>\n\n    <color name=\"textColor\">#BDBDBD</color>\n\n    <color name=\"main_color\">#5CB85C</color>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Banner</string>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "banner/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "banner/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'maven-publish'\napply plugin: 'signing'\n\nversion = '2.2.3'\n\nandroid {\n    compileSdk 33\n\n    defaultConfig {\n        minSdk 14\n        targetSdk 33\n        versionCode 202003\n        versionName version\n        consumerProguardFiles 'proguard-rules.pro'\n    }\n\n    lintOptions {\n        abortOnError false\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    implementation \"androidx.viewpager2:viewpager2:1.1.0-beta02\"\n}\n\ntask androidSourcesJar(type: Jar) {\n    archiveClassifier.set(\"sources\")\n    from android.sourceSets.main.java.source\n    exclude \"**/R.class\"\n    exclude \"**/BuildConfig.class\"\n}\n\npublishing {\n    publications {\n        release(MavenPublication) {\n            // group id，发布后引用的依赖的 group id\n            groupId 'io.github.youth5201314'\n            // 发布后引用的依赖的 artifact id\n            artifactId 'banner'\n            // 发布的版本\n            version version\n            // 发布的 arr 的文件和源码文件\n            artifact(\"$buildDir/outputs/aar/${project.getName()}-release.aar\")\n            artifact androidSourcesJar\n            pom {\n                // 构件名称，可以自定义\n                name = 'banner'\n                // 构件描述\n                description = 'Android Banner 2.0 全新轮播控件，采用viewpager2为基础控件，支持AndroidX'\n                // 构件主页\n                url = 'https://github.com/youth5201314/banner'\n                // 许可证名称和地址\n                licenses {\n                    license {\n                        name = 'The Apache License, Version 2.0'\n                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                    }\n                }\n                // 开发者信息\n                developers {\n                    developer {\n                        name = '春'\n                        email = '1028729086@qq.com'\n                    }\n                }\n                // 版本控制仓库地址\n                scm {\n                    url = 'https://github.com/youth5201314/banner'\n                    connection = 'scm:git:github.com/youth5201314/banner.git'\n                    developerConnection = 'scm:git:ssh://git@github.com/youth5201314/banner.git'\n                }\n            }\n        }\n    }\n    repositories {\n        maven {\n            // 发布的位置，这里根据发布的版本区分了 SNAPSHOT 和最终版本两种情况\n            def releasesRepoUrl = \"https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/\"\n            def snapshotsRepoUrl = \"https://s01.oss.sonatype.org/content/repositories/snapshots/\"\n            url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl\n            credentials {\n                // 这里就是之前在 issues.sonatype.org 注册的账号\n                username sonatypeUsername\n                password sonatypePassword\n            }\n        }\n    }\n}\n\nsigning {\n    sign publishing.publications\n}\n\n"
  },
  {
    "path": "banner/proguard-rules.pro",
    "content": "-dontwarn androidx.viewpager2.**\n-keep class androidx.viewpager2.** {*;}\n-dontwarn androidx.recyclerview.widget.RecyclerView\n-keep class androidx.recyclerview.widget.RecyclerView{*;}\n-dontwarn com.youth.banner.**\n-keep class com.youth.banner.** {*;}\n\n"
  },
  {
    "path": "banner/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.youth.banner\">\n\n\n\n</manifest>\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/Banner.java",
    "content": "package com.youth.banner;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.PaintFlagsDrawFilter;\nimport android.graphics.Path;\nimport android.graphics.PorterDuff;\nimport android.graphics.PorterDuffXfermode;\nimport android.graphics.RectF;\nimport android.os.Build;\nimport android.util.AttributeSet;\nimport android.view.MotionEvent;\nimport android.view.ViewConfiguration;\nimport android.view.ViewGroup;\nimport android.widget.FrameLayout;\n\nimport androidx.annotation.ColorInt;\nimport androidx.annotation.ColorRes;\nimport androidx.annotation.IntDef;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.RequiresApi;\nimport androidx.core.content.ContextCompat;\nimport androidx.lifecycle.LifecycleOwner;\nimport androidx.recyclerview.widget.RecyclerView;\nimport androidx.viewpager.widget.ViewPager;\nimport androidx.viewpager2.widget.CompositePageTransformer;\nimport androidx.viewpager2.widget.MarginPageTransformer;\nimport androidx.viewpager2.widget.ViewPager2;\n\nimport com.youth.banner.adapter.BannerAdapter;\nimport com.youth.banner.config.BannerConfig;\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.indicator.Indicator;\nimport com.youth.banner.listener.OnBannerListener;\nimport com.youth.banner.listener.OnPageChangeListener;\nimport com.youth.banner.transformer.MZScaleInTransformer;\nimport com.youth.banner.transformer.ScaleInTransformer;\nimport com.youth.banner.util.BannerLifecycleObserverAdapter;\nimport com.youth.banner.util.BannerUtils;\nimport com.youth.banner.util.BannerLifecycleObserver;\nimport com.youth.banner.util.LogUtils;\nimport com.youth.banner.util.ScrollSpeedManger;\n\nimport java.lang.annotation.Retention;\nimport java.lang.ref.WeakReference;\nimport java.util.List;\n\nimport static java.lang.annotation.RetentionPolicy.SOURCE;\n\n\npublic class Banner<T, BA extends BannerAdapter<T, ? extends RecyclerView.ViewHolder>> extends FrameLayout implements BannerLifecycleObserver {\n    public static final int INVALID_VALUE = -1;\n    private ViewPager2 mViewPager2;\n    private AutoLoopTask mLoopTask;\n    private OnPageChangeListener mOnPageChangeListener;\n    private BA mAdapter;\n    private Indicator mIndicator;\n    private CompositePageTransformer mCompositePageTransformer;\n    private BannerOnPageChangeCallback mPageChangeCallback;\n\n    // 是否允许无限轮播（即首尾直接切换）\n    private boolean mIsInfiniteLoop = BannerConfig.IS_INFINITE_LOOP;\n    // 是否自动轮播\n    private boolean mIsAutoLoop = BannerConfig.IS_AUTO_LOOP;\n    // 轮播切换间隔时间\n    private long mLoopTime = BannerConfig.LOOP_TIME;\n    // 轮播切换时间\n    private int mScrollTime = BannerConfig.SCROLL_TIME;\n    // 轮播开始位置\n    private int mStartPosition = 1;\n    // banner圆角半径，默认没有圆角\n    private float mBannerRadius = 0;\n    // banner圆角方向，如果一个都不设置，默认四个角全部圆角\n    private boolean mRoundTopLeft, mRoundTopRight, mRoundBottomLeft, mRoundBottomRight;\n\n    // 指示器相关配置\n    private int normalWidth = BannerConfig.INDICATOR_NORMAL_WIDTH;\n    private int selectedWidth = BannerConfig.INDICATOR_SELECTED_WIDTH;\n    private int normalColor = BannerConfig.INDICATOR_NORMAL_COLOR;\n    private int selectedColor = BannerConfig.INDICATOR_SELECTED_COLOR;\n    private int indicatorGravity = IndicatorConfig.Direction.CENTER;\n    private int indicatorSpace;\n    private int indicatorMargin;\n    private int indicatorMarginLeft;\n    private int indicatorMarginTop;\n    private int indicatorMarginRight;\n    private int indicatorMarginBottom;\n    private int indicatorHeight = BannerConfig.INDICATOR_HEIGHT;\n    private int indicatorRadius = BannerConfig.INDICATOR_RADIUS;\n\n    public static final int HORIZONTAL = 0;\n    public static final int VERTICAL = 1;\n    private int mOrientation = HORIZONTAL;\n\n    // 滑动距离范围\n    private int mTouchSlop;\n    // 记录触摸的位置（主要用于解决事件冲突问题）\n    private float mStartX, mStartY;\n    // 记录viewpager2是否被拖动\n    private boolean mIsViewPager2Drag;\n    // 是否要拦截事件\n    private boolean isIntercept = true;\n\n    //绘制圆角视图\n    private Paint mRoundPaint;\n    private Paint mImagePaint;\n\n    @Retention(SOURCE)\n    @IntDef( {HORIZONTAL, VERTICAL})\n    public @interface Orientation {\n    }\n\n    public Banner(Context context) {\n        this(context, null);\n    }\n\n    public Banner(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public Banner(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context);\n        initTypedArray(context, attrs);\n    }\n\n    private void init(Context context) {\n        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop() / 2;\n        mCompositePageTransformer = new CompositePageTransformer();\n        mPageChangeCallback = new BannerOnPageChangeCallback();\n        mLoopTask = new AutoLoopTask(this);\n        mViewPager2 = new ViewPager2(context);\n        mViewPager2.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));\n        mViewPager2.setOffscreenPageLimit(2);\n        mViewPager2.registerOnPageChangeCallback(mPageChangeCallback);\n        mViewPager2.setPageTransformer(mCompositePageTransformer);\n        ScrollSpeedManger.reflectLayoutManager(this);\n        addView(mViewPager2);\n\n        mRoundPaint = new Paint();\n        mRoundPaint.setColor(Color.WHITE);\n        mRoundPaint.setAntiAlias(true);\n        mRoundPaint.setStyle(Paint.Style.FILL);\n        mRoundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));\n        mImagePaint = new Paint();\n        mImagePaint.setXfermode(null);\n    }\n\n    private void initTypedArray(Context context, AttributeSet attrs) {\n        if (attrs != null) {\n            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Banner);\n            mBannerRadius = a.getDimensionPixelSize(R.styleable.Banner_banner_radius, 0);\n            mLoopTime = a.getInt(R.styleable.Banner_banner_loop_time, BannerConfig.LOOP_TIME);\n            mIsAutoLoop = a.getBoolean(R.styleable.Banner_banner_auto_loop, BannerConfig.IS_AUTO_LOOP);\n            mIsInfiniteLoop = a.getBoolean(R.styleable.Banner_banner_infinite_loop, BannerConfig.IS_INFINITE_LOOP);\n            normalWidth = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_normal_width, BannerConfig.INDICATOR_NORMAL_WIDTH);\n            selectedWidth = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_selected_width, BannerConfig.INDICATOR_SELECTED_WIDTH);\n            normalColor = a.getColor(R.styleable.Banner_banner_indicator_normal_color, BannerConfig.INDICATOR_NORMAL_COLOR);\n            selectedColor = a.getColor(R.styleable.Banner_banner_indicator_selected_color, BannerConfig.INDICATOR_SELECTED_COLOR);\n            indicatorGravity = a.getInt(R.styleable.Banner_banner_indicator_gravity, IndicatorConfig.Direction.CENTER);\n            indicatorSpace = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_space, 0);\n            indicatorMargin = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_margin, 0);\n            indicatorMarginLeft = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginLeft, 0);\n            indicatorMarginTop = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginTop, 0);\n            indicatorMarginRight = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginRight, 0);\n            indicatorMarginBottom = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginBottom, 0);\n            indicatorHeight = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_height, BannerConfig.INDICATOR_HEIGHT);\n            indicatorRadius = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_radius, BannerConfig.INDICATOR_RADIUS);\n            mOrientation = a.getInt(R.styleable.Banner_banner_orientation, HORIZONTAL);\n            mRoundTopLeft = a.getBoolean(R.styleable.Banner_banner_round_top_left, false);\n            mRoundTopRight = a.getBoolean(R.styleable.Banner_banner_round_top_right, false);\n            mRoundBottomLeft = a.getBoolean(R.styleable.Banner_banner_round_bottom_left, false);\n            mRoundBottomRight = a.getBoolean(R.styleable.Banner_banner_round_bottom_right, false);\n            a.recycle();\n        }\n        setOrientation(mOrientation);\n        setInfiniteLoop();\n    }\n\n    private void initIndicatorAttr() {\n        if (indicatorMargin != 0) {\n            setIndicatorMargins(new IndicatorConfig.Margins(indicatorMargin));\n        } else if (indicatorMarginLeft != 0\n                || indicatorMarginTop != 0\n                || indicatorMarginRight != 0\n                || indicatorMarginBottom != 0) {\n            setIndicatorMargins(new IndicatorConfig.Margins(\n                    indicatorMarginLeft,\n                    indicatorMarginTop,\n                    indicatorMarginRight,\n                    indicatorMarginBottom));\n        }\n        if (indicatorSpace > 0) {\n            setIndicatorSpace(indicatorSpace);\n        }\n        if (indicatorGravity != IndicatorConfig.Direction.CENTER) {\n            setIndicatorGravity(indicatorGravity);\n        }\n        if (normalWidth > 0) {\n            setIndicatorNormalWidth(normalWidth);\n        }\n        if (selectedWidth > 0) {\n            setIndicatorSelectedWidth(selectedWidth);\n        }\n\n        if (indicatorHeight > 0) {\n            setIndicatorHeight(indicatorHeight);\n        }\n        if (indicatorRadius > 0) {\n            setIndicatorRadius(indicatorRadius);\n        }\n        setIndicatorNormalColor(normalColor);\n        setIndicatorSelectedColor(selectedColor);\n    }\n\n    @Override\n    public boolean dispatchTouchEvent(MotionEvent ev) {\n        if (!getViewPager2().isUserInputEnabled()) {\n            return super.dispatchTouchEvent(ev);\n        }\n\n        int action = ev.getActionMasked();\n        if (action == MotionEvent.ACTION_UP\n                || action == MotionEvent.ACTION_CANCEL\n                || action == MotionEvent.ACTION_OUTSIDE) {\n            start();\n        } else if (action == MotionEvent.ACTION_DOWN) {\n            stop();\n        }\n        return super.dispatchTouchEvent(ev);\n    }\n\n    @Override\n    public boolean onInterceptTouchEvent(MotionEvent event) {\n        if (!getViewPager2().isUserInputEnabled() || !isIntercept) {\n            return super.onInterceptTouchEvent(event);\n        }\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mStartX = event.getX();\n                mStartY = event.getY();\n                getParent().requestDisallowInterceptTouchEvent(true);\n                break;\n            case MotionEvent.ACTION_MOVE:\n                float endX = event.getX();\n                float endY = event.getY();\n                float distanceX = Math.abs(endX - mStartX);\n                float distanceY = Math.abs(endY - mStartY);\n                if (getViewPager2().getOrientation() == HORIZONTAL) {\n                    mIsViewPager2Drag = distanceX > mTouchSlop && distanceX > distanceY;\n                } else {\n                    mIsViewPager2Drag = distanceY > mTouchSlop && distanceY > distanceX;\n                }\n                getParent().requestDisallowInterceptTouchEvent(mIsViewPager2Drag);\n                break;\n            case MotionEvent.ACTION_UP:\n            case MotionEvent.ACTION_CANCEL:\n                getParent().requestDisallowInterceptTouchEvent(false);\n                break;\n        }\n        return super.onInterceptTouchEvent(event);\n    }\n\n    @Override\n    protected void dispatchDraw(Canvas canvas) {\n        if (mBannerRadius > 0) {\n            canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), mImagePaint, Canvas.ALL_SAVE_FLAG);\n            super.dispatchDraw(canvas);\n            //绘制外圆环边框圆环\n            //默认四个角都设置\n            if (!mRoundTopRight && !mRoundTopLeft && !mRoundBottomRight && !mRoundBottomLeft) {\n                drawTopLeft(canvas);\n                drawTopRight(canvas);\n                drawBottomLeft(canvas);\n                drawBottomRight(canvas);\n                canvas.restore();\n                return;\n            }\n            if (mRoundTopLeft) {\n                drawTopLeft(canvas);\n            }\n            if (mRoundTopRight) {\n                drawTopRight(canvas);\n            }\n            if (mRoundBottomLeft) {\n                drawBottomLeft(canvas);\n            }\n            if (mRoundBottomRight) {\n                drawBottomRight(canvas);\n            }\n            canvas.restore();\n        } else {\n            super.dispatchDraw(canvas);\n        }\n    }\n\n    private void drawTopLeft(Canvas canvas) {\n        Path path = new Path();\n        path.moveTo(0, mBannerRadius);\n        path.lineTo(0, 0);\n        path.lineTo(mBannerRadius, 0);\n        path.arcTo(new RectF(0, 0, mBannerRadius * 2, mBannerRadius * 2), -90, -90);\n        path.close();\n        canvas.drawPath(path, mRoundPaint);\n    }\n\n    private void drawTopRight(Canvas canvas) {\n        int width = getWidth();\n        Path path = new Path();\n        path.moveTo(width - mBannerRadius, 0);\n        path.lineTo(width, 0);\n        path.lineTo(width, mBannerRadius);\n        path.arcTo(new RectF(width - 2 * mBannerRadius, 0, width, mBannerRadius * 2), 0, -90);\n        path.close();\n        canvas.drawPath(path, mRoundPaint);\n    }\n\n    private void drawBottomLeft(Canvas canvas) {\n        int height = getHeight();\n        Path path = new Path();\n        path.moveTo(0, height - mBannerRadius);\n        path.lineTo(0, height);\n        path.lineTo(mBannerRadius, height);\n        path.arcTo(new RectF(0, height - 2 * mBannerRadius, mBannerRadius * 2, height), 90, 90);\n        path.close();\n        canvas.drawPath(path, mRoundPaint);\n    }\n\n    private void drawBottomRight(Canvas canvas) {\n        int height = getHeight();\n        int width = getWidth();\n        Path path = new Path();\n        path.moveTo(width - mBannerRadius, height);\n        path.lineTo(width, height);\n        path.lineTo(width, height - mBannerRadius);\n        path.arcTo(new RectF(width - 2 * mBannerRadius, height - 2 * mBannerRadius, width, height), 0, 90);\n        path.close();\n        canvas.drawPath(path, mRoundPaint);\n    }\n\n    @Override\n    protected void onAttachedToWindow() {\n        super.onAttachedToWindow();\n        start();\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        stop();\n    }\n\n    class BannerOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {\n        private int mTempPosition = INVALID_VALUE;\n        private boolean isScrolled;\n\n        @Override\n        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n            int realPosition = BannerUtils.getRealPosition(isInfiniteLoop(), position, getRealCount());\n            if (mOnPageChangeListener != null && realPosition == getCurrentItem() - 1) {\n                mOnPageChangeListener.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);\n            }\n            if (getIndicator() != null && realPosition == getCurrentItem() - 1) {\n                getIndicator().onPageScrolled(realPosition, positionOffset, positionOffsetPixels);\n            }\n        }\n\n        @Override\n        public void onPageSelected(int position) {\n            if (isScrolled) {\n                mTempPosition = position;\n                int realPosition = BannerUtils.getRealPosition(isInfiniteLoop(), position, getRealCount());\n                if (mOnPageChangeListener != null) {\n                    mOnPageChangeListener.onPageSelected(realPosition);\n                }\n                if (getIndicator() != null) {\n                    getIndicator().onPageSelected(realPosition);\n                }\n            }\n        }\n\n        @Override\n        public void onPageScrollStateChanged(int state) {\n            //手势滑动中,代码执行滑动中\n            if (state == ViewPager2.SCROLL_STATE_DRAGGING || state == ViewPager2.SCROLL_STATE_SETTLING) {\n                isScrolled = true;\n            } else if (state == ViewPager2.SCROLL_STATE_IDLE) {\n                //滑动闲置或滑动结束\n                isScrolled = false;\n                if (mTempPosition != INVALID_VALUE && mIsInfiniteLoop) {\n                    if (mTempPosition == 0) {\n                        setCurrentItem(getRealCount(), false);\n                    } else if (mTempPosition == getItemCount() - 1) {\n                        setCurrentItem(1, false);\n                    }\n                }\n            }\n            if (mOnPageChangeListener != null) {\n                mOnPageChangeListener.onPageScrollStateChanged(state);\n            }\n            if (getIndicator() != null) {\n                getIndicator().onPageScrollStateChanged(state);\n            }\n        }\n\n    }\n\n    static class AutoLoopTask implements Runnable {\n        private final WeakReference<Banner> reference;\n\n        AutoLoopTask(Banner banner) {\n            this.reference = new WeakReference<>(banner);\n        }\n\n        @Override\n        public void run() {\n            Banner banner = reference.get();\n            if (banner != null && banner.mIsAutoLoop) {\n                int count = banner.getItemCount();\n                if (count == 0) {\n                    return;\n                }\n                int next = (banner.getCurrentItem() + 1) % count;\n                banner.setCurrentItem(next);\n                banner.postDelayed(banner.mLoopTask, banner.mLoopTime);\n            }\n        }\n    }\n\n    private final RecyclerView.AdapterDataObserver mAdapterDataObserver = new RecyclerView.AdapterDataObserver() {\n        @Override\n        public void onChanged() {\n            if (getItemCount() <= 1) {\n                stop();\n            } else {\n                start();\n            }\n            setIndicatorPageChange();\n        }\n    };\n\n    private void initIndicator() {\n        if (getIndicator() == null || getAdapter() == null) {\n            return;\n        }\n        if (getIndicator().getIndicatorConfig().isAttachToBanner()) {\n            removeIndicator();\n            addView(getIndicator().getIndicatorView());\n        }\n        initIndicatorAttr();\n        setIndicatorPageChange();\n    }\n\n    private void setInfiniteLoop() {\n        // 当不支持无限循环时，要关闭自动轮播\n        if (!isInfiniteLoop()) {\n            isAutoLoop(false);\n        }\n        setStartPosition(isInfiniteLoop() ? mStartPosition : 0);\n    }\n\n    private void setRecyclerViewPadding(int itemPadding) {\n        setRecyclerViewPadding(itemPadding, itemPadding);\n    }\n\n    private void setRecyclerViewPadding(int leftItemPadding, int rightItemPadding) {\n        RecyclerView recyclerView = (RecyclerView) getViewPager2().getChildAt(0);\n        if (getViewPager2().getOrientation() == ViewPager2.ORIENTATION_VERTICAL) {\n            recyclerView.setPadding(mViewPager2.getPaddingLeft(), leftItemPadding, mViewPager2.getPaddingRight(), rightItemPadding);\n        } else {\n            recyclerView.setPadding(leftItemPadding, mViewPager2.getPaddingTop(), rightItemPadding, mViewPager2.getPaddingBottom());\n        }\n        recyclerView.setClipToPadding(false);\n    }\n\n\n    /**\n     * **********************************************************************\n     * ------------------------ 对外公开API ---------------------------------*\n     * **********************************************************************\n     */\n\n    public int getCurrentItem() {\n        return getViewPager2().getCurrentItem();\n    }\n\n    public int getItemCount() {\n        if (getAdapter() != null) {\n            return getAdapter().getItemCount();\n        }\n        return 0;\n\n    }\n\n    public int getScrollTime() {\n        return mScrollTime;\n    }\n\n    public boolean isInfiniteLoop() {\n        return mIsInfiniteLoop;\n    }\n\n    public BannerAdapter getAdapter() {\n        return mAdapter;\n    }\n\n    public ViewPager2 getViewPager2() {\n        return mViewPager2;\n    }\n\n    public Indicator getIndicator() {\n        return mIndicator;\n    }\n\n    public IndicatorConfig getIndicatorConfig() {\n        if (getIndicator() != null) {\n            return getIndicator().getIndicatorConfig();\n        }\n        return null;\n    }\n\n    /**\n     * 返回banner真实总数\n     */\n    public int getRealCount() {\n        if (getAdapter() != null) {\n            return getAdapter().getRealCount();\n        }\n        return 0;\n\n    }\n\n    //-----------------------------------------------------------------------------------------\n\n    /**\n     * 是否要拦截事件\n     * @param intercept\n     * @return\n     */\n    public Banner setIntercept(boolean intercept) {\n        isIntercept = intercept;\n        return this;\n    }\n\n    /**\n     * 跳转到指定位置（最好在设置了数据后在调用，不然没有意义）\n     * @param position\n     * @return\n     */\n    public Banner setCurrentItem(int position) {\n        return setCurrentItem(position, true);\n    }\n\n    /**\n     * 跳转到指定位置（最好在设置了数据后在调用，不然没有意义）\n     * @param position\n     * @param smoothScroll\n     * @return\n     */\n    public Banner setCurrentItem(int position, boolean smoothScroll) {\n        getViewPager2().setCurrentItem(position, smoothScroll);\n        return this;\n    }\n\n    public Banner setIndicatorPageChange() {\n        if (getIndicator() != null) {\n            int realPosition = BannerUtils.getRealPosition(isInfiniteLoop(), getCurrentItem(), getRealCount());\n            getIndicator().onPageChanged(getRealCount(), realPosition);\n        }\n        return this;\n    }\n\n    public Banner removeIndicator() {\n        if (getIndicator() != null) {\n            removeView(getIndicator().getIndicatorView());\n        }\n        return this;\n    }\n\n\n    /**\n     * 设置开始的位置 (需要在setAdapter或者setDatas之前调用才有效哦)\n     */\n    public Banner setStartPosition(int mStartPosition) {\n        this.mStartPosition = mStartPosition;\n        return this;\n    }\n\n    public int getStartPosition() {\n        return mStartPosition;\n    }\n\n    /**\n     * 禁止手动滑动\n     *\n     * @param enabled true 允许，false 禁止\n     */\n    public Banner setUserInputEnabled(boolean enabled) {\n        getViewPager2().setUserInputEnabled(enabled);\n        return this;\n    }\n\n    /**\n     * 添加PageTransformer，可以组合效果\n     * {@link ViewPager2.PageTransformer}\n     * 如果找不到请导入implementation \"androidx.viewpager2:viewpager2:1.0.0\"\n     */\n    public Banner addPageTransformer(@Nullable ViewPager2.PageTransformer transformer) {\n        mCompositePageTransformer.addTransformer(transformer);\n        return this;\n    }\n\n    /**\n     * 设置PageTransformer，和addPageTransformer不同，这个只支持一种transformer\n     */\n    public Banner setPageTransformer(@Nullable ViewPager2.PageTransformer transformer) {\n        getViewPager2().setPageTransformer(transformer);\n        return this;\n    }\n\n    public Banner removeTransformer(ViewPager2.PageTransformer transformer) {\n        mCompositePageTransformer.removeTransformer(transformer);\n        return this;\n    }\n\n    /**\n     * 添加 ItemDecoration\n     */\n    public Banner addItemDecoration(RecyclerView.ItemDecoration decor) {\n        getViewPager2().addItemDecoration(decor);\n        return this;\n    }\n\n    public Banner addItemDecoration(RecyclerView.ItemDecoration decor, int index) {\n        getViewPager2().addItemDecoration(decor, index);\n        return this;\n    }\n\n    /**\n     * 是否允许自动轮播\n     *\n     * @param isAutoLoop ture 允许，false 不允许\n     */\n    public Banner isAutoLoop(boolean isAutoLoop) {\n        this.mIsAutoLoop = isAutoLoop;\n        return this;\n    }\n\n\n    /**\n     * 设置轮播间隔时间\n     *\n     * @param loopTime 时间（毫秒）\n     */\n    public Banner setLoopTime(long loopTime) {\n        this.mLoopTime = loopTime;\n        return this;\n    }\n\n    /**\n     * 设置轮播滑动过程的时间\n     */\n    public Banner setScrollTime(int scrollTime) {\n        this.mScrollTime = scrollTime;\n        return this;\n    }\n\n    /**\n     * 开始轮播\n     */\n    public Banner start() {\n        if (mIsAutoLoop) {\n            stop();\n            postDelayed(mLoopTask, mLoopTime);\n        }\n        return this;\n    }\n\n    /**\n     * 停止轮播\n     */\n    public Banner stop() {\n        if (mIsAutoLoop) {\n            removeCallbacks(mLoopTask);\n        }\n        return this;\n    }\n\n    /**\n     * 移除一些引用\n     */\n    public void destroy() {\n        if (getViewPager2() != null && mPageChangeCallback != null) {\n            getViewPager2().unregisterOnPageChangeCallback(mPageChangeCallback);\n            mPageChangeCallback = null;\n        }\n        stop();\n    }\n\n    /**\n     * 设置banner的适配器\n     */\n    public Banner setAdapter(BA adapter) {\n        if (adapter == null) {\n            throw new NullPointerException(getContext().getString(R.string.banner_adapter_null_error));\n        }\n        this.mAdapter = adapter;\n        if (!isInfiniteLoop()) {\n            getAdapter().setIncreaseCount(0);\n        }\n        getAdapter().registerAdapterDataObserver(mAdapterDataObserver);\n        mViewPager2.setAdapter(adapter);\n        setCurrentItem(mStartPosition, false);\n        initIndicator();\n        return this;\n    }\n\n    /**\n     * 设置banner的适配器\n     * @param adapter\n     * @param isInfiniteLoop 是否支持无限循环\n     * @return\n     */\n    public Banner setAdapter(BA adapter,boolean isInfiniteLoop) {\n        mIsInfiniteLoop=isInfiniteLoop;\n        setInfiniteLoop();\n        setAdapter(adapter);\n        return this;\n    }\n\n    /**\n     * 重新设置banner数据，当然你也可以在你adapter中自己操作数据,不要过于局限在这个方法，举一反三哈\n     *\n     * @param datas 数据集合，当传null或者datas没有数据时，banner会变成空白的，请做好占位UI处理\n     */\n    public Banner setDatas(List<T> datas) {\n        if (getAdapter() != null) {\n            getAdapter().setDatas(datas);\n            setCurrentItem(mStartPosition, false);\n            setIndicatorPageChange();\n            start();\n        }\n        return this;\n    }\n\n    /**\n     * 设置banner轮播方向\n     *\n     * @param orientation {@link Orientation}\n     */\n    public Banner setOrientation(@Orientation int orientation) {\n        getViewPager2().setOrientation(orientation);\n        return this;\n    }\n\n    /**\n     * 改变最小滑动距离\n     */\n    public Banner setTouchSlop(int mTouchSlop) {\n        this.mTouchSlop = mTouchSlop;\n        return this;\n    }\n\n    /**\n     * 设置点击事件\n     */\n    public Banner setOnBannerListener(OnBannerListener<T> listener) {\n        if (getAdapter() != null) {\n            getAdapter().setOnBannerListener(listener);\n        }\n        return this;\n    }\n\n    /**\n     * 添加viewpager切换事件\n     * <p>\n     * 在viewpager2中切换事件{@link ViewPager2.OnPageChangeCallback}是一个抽象类，\n     * 为了方便使用习惯这里用的是和viewpager一样的{@link ViewPager.OnPageChangeListener}接口\n     * </p>\n     */\n    public Banner addOnPageChangeListener(OnPageChangeListener pageListener) {\n        this.mOnPageChangeListener = pageListener;\n        return this;\n    }\n\n    /**\n     * 设置banner圆角\n     * <p>\n     * 默认没有圆角，需要取消圆角把半径设置为0即可\n     *\n     * @param radius 圆角半径\n     */\n    public Banner setBannerRound(float radius) {\n        mBannerRadius = radius;\n        return this;\n    }\n\n    /**\n     * 设置banner圆角(第二种方式，和上面的方法不要同时使用)，只支持5.0以上\n     */\n    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)\n    public Banner setBannerRound2(float radius) {\n        BannerUtils.setBannerRound(this, radius);\n        return this;\n    }\n\n    /**\n     * 为banner添加画廊效果\n     *\n     * @param itemWidth  item左右展示的宽度,单位dp\n     * @param pageMargin 页面间距,单位dp\n     */\n    public Banner setBannerGalleryEffect(int itemWidth, int pageMargin) {\n        return setBannerGalleryEffect(itemWidth, pageMargin, .85f);\n    }\n\n    /**\n     * 为banner添加画廊效果\n     *\n     * @param leftItemWidth  item左展示的宽度,单位dp\n     * @param rightItemWidth item右展示的宽度,单位dp\n     * @param pageMargin     页面间距,单位dp\n     */\n    public Banner setBannerGalleryEffect(int leftItemWidth, int rightItemWidth, int pageMargin) {\n        return setBannerGalleryEffect(leftItemWidth,rightItemWidth, pageMargin, .85f);\n    }\n\n    /**\n     * 为banner添加画廊效果\n     *\n     * @param itemWidth  item左右展示的宽度,单位dp\n     * @param pageMargin 页面间距,单位dp\n     * @param scale      缩放[0-1],1代表不缩放\n     */\n    public Banner setBannerGalleryEffect(int itemWidth, int pageMargin, float scale) {\n        return setBannerGalleryEffect(itemWidth, itemWidth, pageMargin, scale);\n    }\n\n    /**\n     * 为banner添加画廊效果\n     *\n     * @param leftItemWidth  item左展示的宽度,单位dp\n     * @param rightItemWidth item右展示的宽度,单位dp\n     * @param pageMargin     页面间距,单位dp\n     * @param scale          缩放[0-1],1代表不缩放\n     */\n    public Banner setBannerGalleryEffect(int leftItemWidth, int rightItemWidth, int pageMargin, float scale) {\n        if (pageMargin > 0) {\n            addPageTransformer(new MarginPageTransformer(BannerUtils.dp2px(pageMargin)));\n        }\n        if (scale < 1 && scale > 0) {\n            addPageTransformer(new ScaleInTransformer(scale));\n        }\n        setRecyclerViewPadding(leftItemWidth > 0 ? BannerUtils.dp2px(leftItemWidth + pageMargin) : 0,\n                rightItemWidth > 0 ? BannerUtils.dp2px(rightItemWidth + pageMargin) : 0);\n        return this;\n    }\n\n    /**\n     * 为banner添加魅族效果\n     *\n     * @param itemWidth item左右展示的宽度,单位dp\n     */\n    public Banner setBannerGalleryMZ(int itemWidth) {\n        return setBannerGalleryMZ(itemWidth, .88f);\n    }\n\n    /**\n     * 为banner添加魅族效果\n     *\n     * @param itemWidth item左右展示的宽度,单位dp\n     * @param scale     缩放[0-1],1代表不缩放\n     */\n    public Banner setBannerGalleryMZ(int itemWidth, float scale) {\n        if (scale < 1 && scale > 0) {\n            addPageTransformer(new MZScaleInTransformer(scale));\n        }\n        setRecyclerViewPadding(BannerUtils.dp2px(itemWidth));\n        return this;\n    }\n\n    /**\n     * **********************************************************************\n     * ------------------------ 指示器相关设置 --------------------------------*\n     * **********************************************************************\n     */\n\n    /**\n     * 设置轮播指示器(显示在banner上)\n     */\n    public Banner setIndicator(Indicator indicator) {\n        return setIndicator(indicator, true);\n    }\n\n    /**\n     * 设置轮播指示器(如果你的指示器写在布局文件中，attachToBanner传false)\n     *\n     * @param attachToBanner 是否将指示器添加到banner中，false 代表你可以将指示器通过布局放在任何位置\n     *                       注意：设置为false后，内置的 setIndicatorGravity()和setIndicatorMargins() 方法将失效。\n     *                       想改变可以自己调用系统提供的属性在布局文件中进行设置。具体可以参照demo\n     */\n    public Banner setIndicator(Indicator indicator, boolean attachToBanner) {\n        removeIndicator();\n        indicator.getIndicatorConfig().setAttachToBanner(attachToBanner);\n        this.mIndicator = indicator;\n        initIndicator();\n        return this;\n    }\n\n\n    public Banner setIndicatorSelectedColor(@ColorInt int color) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setSelectedColor(color);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorSelectedColorRes(@ColorRes int color) {\n        setIndicatorSelectedColor(ContextCompat.getColor(getContext(), color));\n        return this;\n    }\n\n    public Banner setIndicatorNormalColor(@ColorInt int color) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setNormalColor(color);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorNormalColorRes(@ColorRes int color) {\n        setIndicatorNormalColor(ContextCompat.getColor(getContext(), color));\n        return this;\n    }\n\n    public Banner setIndicatorGravity(@IndicatorConfig.Direction int gravity) {\n        if (getIndicatorConfig() != null && getIndicatorConfig().isAttachToBanner()) {\n            getIndicatorConfig().setGravity(gravity);\n            getIndicator().getIndicatorView().postInvalidate();\n        }\n        return this;\n    }\n\n    public Banner setIndicatorSpace(int indicatorSpace) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setIndicatorSpace(indicatorSpace);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorMargins(IndicatorConfig.Margins margins) {\n        if (getIndicatorConfig() != null && getIndicatorConfig().isAttachToBanner()) {\n            getIndicatorConfig().setMargins(margins);\n            getIndicator().getIndicatorView().requestLayout();\n        }\n        return this;\n    }\n\n    public Banner setIndicatorWidth(int normalWidth, int selectedWidth) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setNormalWidth(normalWidth);\n            getIndicatorConfig().setSelectedWidth(selectedWidth);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorNormalWidth(int normalWidth) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setNormalWidth(normalWidth);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorSelectedWidth(int selectedWidth) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setSelectedWidth(selectedWidth);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorRadius(int indicatorRadius) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setRadius(indicatorRadius);\n        }\n        return this;\n    }\n\n    public Banner setIndicatorHeight(int indicatorHeight) {\n        if (getIndicatorConfig() != null) {\n            getIndicatorConfig().setHeight(indicatorHeight);\n        }\n        return this;\n    }\n\n    /**\n     * **********************************************************************\n     * ------------------------ 生命周期控制 --------------------------------*\n     * **********************************************************************\n     */\n\n    public Banner addBannerLifecycleObserver(LifecycleOwner owner) {\n        if (owner != null) {\n            owner.getLifecycle().addObserver(new BannerLifecycleObserverAdapter(owner, this));\n        }\n        return this;\n    }\n\n    @Override\n    public void onStart(LifecycleOwner owner) {\n        start();\n    }\n\n    @Override\n    public void onStop(LifecycleOwner owner) {\n        stop();\n    }\n\n    @Override\n    public void onDestroy(LifecycleOwner owner) {\n        destroy();\n    }\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/adapter/BannerAdapter.java",
    "content": "package com.youth.banner.adapter;\n\nimport android.view.ViewGroup;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.youth.banner.R;\nimport com.youth.banner.config.BannerConfig;\nimport com.youth.banner.holder.IViewHolder;\nimport com.youth.banner.listener.OnBannerListener;\nimport com.youth.banner.util.BannerUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\n\npublic abstract class BannerAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> implements IViewHolder<T, VH> {\n    protected List<T> mDatas = new ArrayList<>();\n    private OnBannerListener<T> mOnBannerListener;\n    private VH mViewHolder;\n    private int mIncreaseCount = BannerConfig.INCREASE_COUNT;\n\n    public BannerAdapter(List<T> datas) {\n        setDatas(datas);\n    }\n\n    /**\n     * 设置实体集合（可以在自己的adapter自定义，不一定非要使用）\n     *\n     * @param datas\n     */\n    public void setDatas(List<T> datas) {\n        if (datas == null) {\n            datas = new ArrayList<>();\n        }\n        mDatas.clear();\n        mDatas.addAll(datas);\n        notifyDataSetChanged();\n    }\n\n    /**\n     * 获取指定的实体（可以在自己的adapter自定义，不一定非要使用）\n     *\n     * @param position 真实的position\n     * @return\n     */\n    public T getData(int position) {\n        if (position > mDatas.size()-1) {\n            return null;\n        }\n        return mDatas.get(position);\n    }\n\n    /**\n     * 获取指定的实体（可以在自己的adapter自定义，不一定非要使用）\n     *\n     * @param position 这里传的position不是真实的，获取时转换了一次\n     * @return\n     */\n    public T getRealData(int position) {\n        int realPosition = getRealPosition(position);\n        if (realPosition > mDatas.size()-1) {\n            return null;\n        }\n        return mDatas.get(realPosition);\n    }\n\n\n    @Override\n    public final void onBindViewHolder(@NonNull VH holder, int position) {\n        mViewHolder = holder;\n        int real = getRealPosition(position);\n        T data = mDatas.get(real);\n        holder.itemView.setTag(R.id.banner_data_key, data);\n        holder.itemView.setTag(R.id.banner_pos_key, real);\n        onBindView(holder, mDatas.get(real), real, getRealCount());\n        if (mOnBannerListener != null) {\n            holder.itemView.setOnClickListener(view -> mOnBannerListener.OnBannerClick(data, real));\n        }\n    }\n\n    @NonNull\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {\n        VH vh = onCreateHolder(parent, viewType);\n        vh.itemView.setOnClickListener(v -> {\n            if (mOnBannerListener != null) {\n                T data = (T) vh.itemView.getTag(R.id.banner_data_key);\n                int real = (int) vh.itemView.getTag(R.id.banner_pos_key);\n                mOnBannerListener.OnBannerClick(data, real);\n            }\n        });\n        return vh;\n    }\n\n    @Override\n    public int getItemCount() {\n        return getRealCount() > 1 ? getRealCount() + mIncreaseCount : getRealCount();\n    }\n\n    public int getRealCount() {\n        return mDatas == null ? 0 : mDatas.size();\n    }\n\n    public int getRealPosition(int position) {\n        return BannerUtils.getRealPosition(mIncreaseCount == BannerConfig.INCREASE_COUNT, position, getRealCount());\n    }\n\n    public void setOnBannerListener(OnBannerListener<T> listener) {\n        this.mOnBannerListener = listener;\n    }\n\n    public VH getViewHolder() {\n        return mViewHolder;\n    }\n\n    public void setIncreaseCount(int increaseCount) {\n        this.mIncreaseCount = increaseCount;\n    }\n}"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/adapter/BannerImageAdapter.java",
    "content": "package com.youth.banner.adapter;\n\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\n\nimport com.youth.banner.holder.BannerImageHolder;\n\nimport java.util.List;\n\n/**\n * 默认实现的图片适配器，图片加载需要自己实现\n */\npublic abstract class BannerImageAdapter<T> extends BannerAdapter<T, BannerImageHolder> {\n\n    public BannerImageAdapter(List<T> mData) {\n        super(mData);\n    }\n\n    @Override\n    public BannerImageHolder onCreateHolder(ViewGroup parent, int viewType) {\n        ImageView imageView = new ImageView(parent.getContext());\n        //注意，必须设置为match_parent，这个是viewpager2强制要求的\n        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(\n                ViewGroup.LayoutParams.MATCH_PARENT,\n                ViewGroup.LayoutParams.MATCH_PARENT);\n        imageView.setLayoutParams(params);\n        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);\n        return new BannerImageHolder(imageView);\n    }\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/config/BannerConfig.java",
    "content": "package com.youth.banner.config;\n\nimport com.youth.banner.util.BannerUtils;\n\n/**\n * 不忘初心\n *\n * ┌───┐   ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐  ┌┐    ┌┐    ┌┐\n * │Esc│   │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│  └┘    └┘    └┘\n * └───┘   └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘\n * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐\n * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │\n * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤\n * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \\ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │   │\n * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │\n * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│\" '│ Enter  │               │ 4 │ 5 │ 6 │   │\n * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤     ┌───┐     ├───┼───┼───┼───┤\n * │ Shift  │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│  Shift   │     │ ↑ │     │ 1 │ 2 │ 3 │   │\n * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││\n * │ Ctrl│    │Alt │         Space         │ Alt│    │    │Ctrl│ │ ← │ ↓ │ → │ │   0   │ . │←─┘│\n * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘\n *\n *  @author youth5201314/spring\n *  @date 2020/1/24\n *  banner 配置参数\n */\npublic class BannerConfig {\n    public static final boolean IS_AUTO_LOOP = true;\n    public static final boolean IS_INFINITE_LOOP = true;\n    public static final int LOOP_TIME = 3000;\n    public static final int SCROLL_TIME = 600;\n    public static final int INCREASE_COUNT = 2;\n    public static final int INDICATOR_NORMAL_COLOR = 0x88ffffff;\n    public static final int INDICATOR_SELECTED_COLOR = 0x88000000;\n    public static final int INDICATOR_NORMAL_WIDTH = (int) BannerUtils.dp2px(5);\n    public static final int INDICATOR_SELECTED_WIDTH = (int) BannerUtils.dp2px(7);\n    public static final int INDICATOR_SPACE = (int) BannerUtils.dp2px(5);\n    public static final int INDICATOR_MARGIN = (int) BannerUtils.dp2px(5);\n\n    public static final int INDICATOR_HEIGHT = (int) BannerUtils.dp2px(3);\n    public static final int INDICATOR_RADIUS = (int) BannerUtils.dp2px(3);\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/config/IndicatorConfig.java",
    "content": "package com.youth.banner.config;\n\nimport androidx.annotation.ColorInt;\nimport androidx.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\npublic class IndicatorConfig {\n\n    private int indicatorSize;\n    private int currentPosition;\n    private int gravity = Direction.CENTER;\n    private int indicatorSpace = BannerConfig.INDICATOR_SPACE;\n    private int normalWidth = BannerConfig.INDICATOR_NORMAL_WIDTH;\n    private int selectedWidth = BannerConfig.INDICATOR_SELECTED_WIDTH;\n    @ColorInt\n    private int normalColor = BannerConfig.INDICATOR_NORMAL_COLOR;\n    @ColorInt\n    private int selectedColor = BannerConfig.INDICATOR_SELECTED_COLOR;\n\n    private int radius = BannerConfig.INDICATOR_RADIUS;\n    private int height = BannerConfig.INDICATOR_HEIGHT;\n\n    private Margins margins;\n\n    //是将指示器添加到banner上\n    private boolean attachToBanner = true;\n\n    @IntDef({Direction.LEFT, Direction.CENTER, Direction.RIGHT})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface Direction {\n        int LEFT = 0;\n        int CENTER = 1;\n        int RIGHT = 2;\n    }\n\n    public static class Margins {\n        public int leftMargin;\n        public int topMargin;\n        public int rightMargin;\n        public int bottomMargin;\n\n        public Margins() {\n            this(BannerConfig.INDICATOR_MARGIN);\n        }\n\n        public Margins(int marginSize) {\n            this(marginSize, marginSize, marginSize, marginSize);\n        }\n\n        public Margins(int leftMargin, int topMargin, int rightMargin, int bottomMargin) {\n            this.leftMargin = leftMargin;\n            this.topMargin = topMargin;\n            this.rightMargin = rightMargin;\n            this.bottomMargin = bottomMargin;\n        }\n    }\n\n    public Margins getMargins() {\n        if (margins == null) {\n            setMargins(new Margins());\n        }\n        return margins;\n    }\n\n    public IndicatorConfig setMargins(Margins margins) {\n        this.margins = margins;\n        return this;\n    }\n\n    public int getIndicatorSize() {\n        return indicatorSize;\n    }\n\n    public IndicatorConfig setIndicatorSize(int indicatorSize) {\n        this.indicatorSize = indicatorSize;\n        return this;\n    }\n\n    public int getNormalColor() {\n        return normalColor;\n    }\n\n    public IndicatorConfig setNormalColor(int normalColor) {\n        this.normalColor = normalColor;\n        return this;\n    }\n\n    public int getSelectedColor() {\n        return selectedColor;\n    }\n\n    public IndicatorConfig setSelectedColor(int selectedColor) {\n        this.selectedColor = selectedColor;\n        return this;\n    }\n\n    public int getIndicatorSpace() {\n        return indicatorSpace;\n    }\n\n    public IndicatorConfig setIndicatorSpace(int indicatorSpace) {\n        this.indicatorSpace = indicatorSpace;\n        return this;\n    }\n\n    public int getCurrentPosition() {\n        return currentPosition;\n    }\n\n    public IndicatorConfig setCurrentPosition(int currentPosition) {\n        this.currentPosition = currentPosition;\n        return this;\n    }\n\n    public int getNormalWidth() {\n        return normalWidth;\n    }\n\n    public IndicatorConfig setNormalWidth(int normalWidth) {\n        this.normalWidth = normalWidth;\n        return this;\n    }\n\n    public int getSelectedWidth() {\n        return selectedWidth;\n    }\n\n    public IndicatorConfig setSelectedWidth(int selectedWidth) {\n        this.selectedWidth = selectedWidth;\n        return this;\n    }\n\n    public int getGravity() {\n        return gravity;\n    }\n\n    public IndicatorConfig setGravity(@Direction int gravity) {\n        this.gravity = gravity;\n        return this;\n    }\n\n    public boolean isAttachToBanner() {\n        return attachToBanner;\n    }\n\n    public IndicatorConfig setAttachToBanner(boolean attachToBanner) {\n        this.attachToBanner = attachToBanner;\n        return this;\n    }\n\n    public int getRadius() {\n        return radius;\n    }\n\n    public IndicatorConfig setRadius(int radius) {\n        this.radius = radius;\n        return this;\n    }\n\n    public int getHeight() {\n        return height;\n    }\n\n    public IndicatorConfig setHeight(int height) {\n        this.height = height;\n        return this;\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/holder/BannerImageHolder.java",
    "content": "package com.youth.banner.holder;\n\nimport android.view.View;\nimport android.widget.ImageView;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\n\npublic\nclass BannerImageHolder extends RecyclerView.ViewHolder {\n    public ImageView imageView;\n\n    public BannerImageHolder(@NonNull View view) {\n        super(view);\n        this.imageView = (ImageView) view;\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/holder/IViewHolder.java",
    "content": "package com.youth.banner.holder;\n\nimport android.view.ViewGroup;\n\npublic interface IViewHolder<T, VH> {\n\n    /**\n     * 创建ViewHolder\n     *\n     * @return XViewHolder\n     */\n    VH onCreateHolder(ViewGroup parent, int viewType);\n\n    /**\n     * 绑定布局数据\n     *\n     * @param holder   XViewHolder\n     * @param data     数据实体\n     * @param position 当前位置\n     * @param size     总数\n     */\n    void onBindView(VH holder, T data, int position, int size);\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/indicator/BaseIndicator.java",
    "content": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.animation.DecelerateInterpolator;\nimport android.view.animation.Interpolator;\nimport android.widget.FrameLayout;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.util.LogUtils;\n\npublic class BaseIndicator extends View implements Indicator {\n    protected IndicatorConfig config;\n    protected Paint mPaint;\n    protected float offset;\n\n    public BaseIndicator(Context context) {\n        this(context, null);\n    }\n\n    public BaseIndicator(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public BaseIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        config = new IndicatorConfig();\n        mPaint = new Paint();\n        mPaint.setAntiAlias(true);\n        mPaint.setColor(Color.TRANSPARENT);\n        mPaint.setColor(config.getNormalColor());\n    }\n\n    @NonNull\n    @Override\n    public View getIndicatorView() {\n        if (config.isAttachToBanner()) {\n            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(\n                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n            switch (config.getGravity()) {\n                case IndicatorConfig.Direction.LEFT:\n                    layoutParams.gravity = Gravity.BOTTOM | Gravity.START;\n                    break;\n                case IndicatorConfig.Direction.CENTER:\n                    layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;\n                    break;\n                case IndicatorConfig.Direction.RIGHT:\n                    layoutParams.gravity = Gravity.BOTTOM | Gravity.END;\n                    break;\n            }\n            layoutParams.leftMargin = config.getMargins().leftMargin;\n            layoutParams.rightMargin = config.getMargins().rightMargin;\n            layoutParams.topMargin = config.getMargins().topMargin;\n            layoutParams.bottomMargin = config.getMargins().bottomMargin;\n            setLayoutParams(layoutParams);\n        }\n        return this;\n    }\n\n    @Override\n    public IndicatorConfig getIndicatorConfig() {\n        return config;\n    }\n\n    @Override\n    public void onPageChanged(int count, int currentPosition) {\n        config.setIndicatorSize(count);\n        config.setCurrentPosition(currentPosition);\n        requestLayout();\n    }\n\n    @Override\n    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n        offset = positionOffset;\n        invalidate();\n\n    }\n\n    @Override\n    public void onPageSelected(int position) {\n        config.setCurrentPosition(position);\n        invalidate();\n    }\n\n    @Override\n    public void onPageScrollStateChanged(int state) {\n\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/indicator/CircleIndicator.java",
    "content": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.util.AttributeSet;\n\n/**\n * 圆形指示器\n * 如果想要大小一样，可以将选中和默认设置成同样大小\n */\npublic class CircleIndicator extends BaseIndicator {\n    private int mNormalRadius;\n    private int mSelectedRadius;\n    private int maxRadius;\n\n    public CircleIndicator(Context context) {\n        this(context, null);\n    }\n\n    public CircleIndicator(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public CircleIndicator(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        mNormalRadius = config.getNormalWidth() / 2;\n        mSelectedRadius = config.getSelectedWidth() / 2;\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n\n        mNormalRadius = config.getNormalWidth() / 2;\n        mSelectedRadius = config.getSelectedWidth() / 2;\n        //考虑当 选中和默认 的大小不一样的情况\n        maxRadius = Math.max(mSelectedRadius, mNormalRadius);\n        //间距*（总数-1）+选中宽度+默认宽度*（总数-1）\n        int width = (count - 1) * config.getIndicatorSpace() + config.getSelectedWidth() + config.getNormalWidth() * (count - 1);\n        setMeasuredDimension(width, Math.max(config.getNormalWidth(), config.getSelectedWidth()));\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n        float left = 0;\n        for (int i = 0; i < count; i++) {\n            mPaint.setColor(config.getCurrentPosition() == i ? config.getSelectedColor() : config.getNormalColor());\n            int indicatorWidth = config.getCurrentPosition() == i ? config.getSelectedWidth() : config.getNormalWidth();\n            int radius = config.getCurrentPosition() == i ? mSelectedRadius : mNormalRadius;\n            canvas.drawCircle(left + radius, maxRadius, radius, mPaint);\n            left += indicatorWidth + config.getIndicatorSpace();\n        }\n//        mPaint.setColor(config.getNormalColor());\n//        for (int i = 0; i < count; i++) {\n//            canvas.drawCircle(left + maxRadius, maxRadius, mNormalRadius, mPaint);\n//            left += config.getNormalWidth() + config.getIndicatorSpace();\n//        }\n//        mPaint.setColor(config.getSelectedColor());\n//        left = maxRadius + (config.getNormalWidth() + config.getIndicatorSpace()) * config.getCurrentPosition();\n//        canvas.drawCircle(left, maxRadius, mSelectedRadius, mPaint);\n    }\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/indicator/DrawableIndicator.java",
    "content": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.drawable.BitmapDrawable;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\n\nimport androidx.annotation.DrawableRes;\nimport androidx.annotation.IdRes;\n\nimport com.youth.banner.R;\n\n\n/**\n * Drawable指示器\n */\npublic class DrawableIndicator extends BaseIndicator {\n    private Bitmap normalBitmap;\n    private Bitmap selectedBitmap;\n\n    /**\n     * 实例化Drawable指示器 ，也可以通过自定义属性设置\n     * @param context\n     * @param normalResId\n     * @param selectedResId\n     */\n    public DrawableIndicator(Context context, @DrawableRes int normalResId, @DrawableRes int selectedResId) {\n        super(context);\n        normalBitmap = BitmapFactory.decodeResource(getResources(), normalResId);\n        selectedBitmap = BitmapFactory.decodeResource(getResources(), selectedResId);\n    }\n\n    public DrawableIndicator(Context context) {\n        this(context, null);\n    }\n\n    public DrawableIndicator(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public DrawableIndicator(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableIndicator);\n        if (a != null) {\n            BitmapDrawable normal = (BitmapDrawable) a.getDrawable(R.styleable.DrawableIndicator_normal_drawable);\n            BitmapDrawable selected = (BitmapDrawable) a.getDrawable(R.styleable.DrawableIndicator_selected_drawable);\n            normalBitmap = normal.getBitmap();\n            selectedBitmap = selected.getBitmap();\n        }\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n        setMeasuredDimension(selectedBitmap.getWidth() * (count - 1) + selectedBitmap.getWidth() + config.getIndicatorSpace() * (count - 1),\n                Math.max(normalBitmap.getHeight(), selectedBitmap.getHeight()));\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        int count = config.getIndicatorSize();\n        if (count <= 1 || normalBitmap == null || selectedBitmap == null) {\n            return;\n        }\n\n        float left = 0;\n        for (int i = 0; i < count; i++) {\n            canvas.drawBitmap(config.getCurrentPosition() == i ? selectedBitmap : normalBitmap, left, 0, mPaint);\n            left += normalBitmap.getWidth() + config.getIndicatorSpace();\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/indicator/Indicator.java",
    "content": "package com.youth.banner.indicator;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\nimport com.youth.banner.config.IndicatorConfig;\nimport com.youth.banner.listener.OnPageChangeListener;\n\npublic interface Indicator extends OnPageChangeListener {\n    @NonNull\n    View getIndicatorView();\n\n    IndicatorConfig getIndicatorConfig();\n\n    void onPageChanged(int count, int currentPosition);\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/indicator/RectangleIndicator.java",
    "content": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.RectF;\nimport android.util.AttributeSet;\n\nimport com.youth.banner.config.BannerConfig;\n\n/**\n * 矩形（条形）指示器\n * 1、可以设置选中和默认的宽度、指示器的圆角\n * 2、如果需要正方形将圆角设置为0，可将宽度和高度设置为一样\n * 3、如果不想选中时变长，可将选中的宽度和默认宽度设置为一样\n */\npublic class RectangleIndicator extends BaseIndicator {\n    RectF rectF;\n\n    public RectangleIndicator(Context context) {\n        this(context, null);\n    }\n\n    public RectangleIndicator(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public RectangleIndicator(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        rectF = new RectF();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n        //间距*（总数-1）+默认宽度*（总数-1）+选中宽度\n        int space = config.getIndicatorSpace() * (count - 1);\n        int normal = config.getNormalWidth() * (count - 1);\n        setMeasuredDimension(space + normal + config.getSelectedWidth(), config.getHeight());\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        int count = config.getIndicatorSize();\n        if (count <= 1) {\n            return;\n        }\n        float left = 0;\n        for (int i = 0; i < count; i++) {\n            mPaint.setColor(config.getCurrentPosition() == i ? config.getSelectedColor() : config.getNormalColor());\n            int indicatorWidth = config.getCurrentPosition() == i ? config.getSelectedWidth() : config.getNormalWidth();\n            rectF.set(left, 0, left + indicatorWidth, config.getHeight());\n            left += indicatorWidth + config.getIndicatorSpace();\n            canvas.drawRoundRect(rectF, config.getRadius(), config.getRadius(), mPaint);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/indicator/RoundLinesIndicator.java",
    "content": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.RectF;\nimport android.util.AttributeSet;\n\nimport androidx.annotation.Nullable;\n\nimport com.youth.banner.util.BannerUtils;\n\npublic class RoundLinesIndicator extends BaseIndicator {\n\n    public RoundLinesIndicator(Context context) {\n        this(context, null);\n    }\n\n    public RoundLinesIndicator(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public RoundLinesIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        mPaint.setStyle(Paint.Style.FILL);\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        int count = config.getIndicatorSize();\n        if (count <= 1) return;\n        setMeasuredDimension((int) (config.getSelectedWidth() * count), config.getHeight());\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        int count = config.getIndicatorSize();\n        if (count <= 1) return;\n\n        mPaint.setColor(config.getNormalColor());\n        RectF oval = new RectF(0, 0, canvas.getWidth(), config.getHeight());\n        canvas.drawRoundRect(oval, config.getRadius(), config.getRadius(), mPaint);\n\n        mPaint.setColor(config.getSelectedColor());\n        int left = config.getCurrentPosition() * config.getSelectedWidth();\n        RectF rectF = new RectF(left, 0, left + config.getSelectedWidth(), config.getHeight());\n        canvas.drawRoundRect(rectF, config.getRadius(), config.getRadius(), mPaint);\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/itemdecoration/MarginDecoration.java",
    "content": "package com.youth.banner.itemdecoration;\n\nimport android.graphics.Rect;\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Px;\nimport androidx.recyclerview.widget.LinearLayoutManager;\nimport androidx.recyclerview.widget.RecyclerView;\n\nimport com.youth.banner.util.BannerUtils;\n\n\npublic class MarginDecoration extends RecyclerView.ItemDecoration {\n    private int mMarginPx;\n\n    public MarginDecoration(@Px int margin) {\n        mMarginPx = margin;\n    }\n\n    @Override\n    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,\n                               @NonNull RecyclerView.State state) {\n        LinearLayoutManager linearLayoutManager = requireLinearLayoutManager(parent);\n        if (linearLayoutManager.getOrientation() == LinearLayoutManager.VERTICAL) {\n            outRect.top = mMarginPx;\n            outRect.bottom = mMarginPx;\n        } else {\n            outRect.left = mMarginPx;\n            outRect.right = mMarginPx;\n        }\n    }\n\n    private LinearLayoutManager requireLinearLayoutManager(@NonNull RecyclerView parent) {\n        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();\n        if (layoutManager instanceof LinearLayoutManager) {\n            return (LinearLayoutManager) layoutManager;\n        }\n        throw new IllegalStateException(\"The layoutManager must be LinearLayoutManager\");\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/listener/OnBannerListener.java",
    "content": "package com.youth.banner.listener;\n\npublic interface OnBannerListener<T> {\n\n    /**\n     * 点击事件\n     *\n     * @param data     数据实体\n     * @param position 当前位置\n     */\n    void OnBannerClick(T data, int position);\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/listener/OnPageChangeListener.java",
    "content": "package com.youth.banner.listener;\n\nimport androidx.annotation.Px;\nimport androidx.viewpager2.widget.ViewPager2;\n\n\npublic interface OnPageChangeListener {\n    /**\n     * This method will be invoked when the current page is scrolled, either as part\n     * of a programmatically initiated smooth scroll or a user initiated touch scroll.\n     *\n     * @param position             Position index of the first page currently being displayed.\n     *                             Page position+1 will be visible if positionOffset is nonzero.\n     * @param positionOffset       Value from [0, 1) indicating the offset from the page at position.\n     * @param positionOffsetPixels Value in pixels indicating the offset from position.\n     */\n    void onPageScrolled(int position, float positionOffset, @Px int positionOffsetPixels);\n\n    /**\n     * This method will be invoked when a new page becomes selected. Animation is not\n     * necessarily complete.\n     *\n     * @param position Position index of the new selected page.\n     */\n    void onPageSelected(int position);\n\n    /**\n     * Called when the scroll state changes. Useful for discovering when the user begins\n     * dragging, when a fake drag is started, when the pager is automatically settling to the\n     * current page, or when it is fully stopped/idle. {@code state} can be one of\n     * {@link ViewPager2.SCROLL_STATE_IDLE},\n     * {@link ViewPager2.SCROLL_STATE_DRAGGING},\n     * {@link ViewPager2.SCROLL_STATE_SETTLING}.\n     */\n    void onPageScrollStateChanged(@ViewPager2.ScrollState int state);\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/AlphaPageTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class AlphaPageTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MIN_ALPHA = 0.5f;\n    private float mMinAlpha = DEFAULT_MIN_ALPHA;\n\n    public AlphaPageTransformer() {\n    }\n\n    public AlphaPageTransformer(float minAlpha) {\n        mMinAlpha = minAlpha;\n    }\n\n    @Override\n    public void transformPage(@NonNull View view, float position) {\n        view.setScaleX(0.999f);//hack\n\n        if (position < -1) { // [-Infinity,-1)\n            view.setAlpha(mMinAlpha);\n        } else if (position <= 1) { // [-1,1]\n            //[0，-1]\n            if (position < 0) {\n                //[1,min]\n                float factor = mMinAlpha + (1 - mMinAlpha) * (1 + position);\n                view.setAlpha(factor);\n            } else {//[1，0]\n                //[min,1]\n                float factor = mMinAlpha + (1 - mMinAlpha) * (1 - position);\n                view.setAlpha(factor);\n            }\n        } else { // (1,+Infinity]\n            view.setAlpha(mMinAlpha);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/BasePageTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport androidx.viewpager2.widget.ViewPager2;\n\npublic abstract class BasePageTransformer implements ViewPager2.PageTransformer {\n    public static final float DEFAULT_CENTER = 0.5f;\n\n\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/DepthPageTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.viewpager2.widget.ViewPager2;\n\npublic class DepthPageTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MIN_SCALE = 0.75f;\n    private float mMinScale = DEFAULT_MIN_SCALE;\n\n    public DepthPageTransformer() {\n    }\n\n    public DepthPageTransformer(float minScale) {\n        this.mMinScale = minScale;\n    }\n\n    public void transformPage(View view, float position) {\n        int pageWidth = view.getWidth();\n\n        if (position < -1) { // [-Infinity,-1)\n            // This page is way off-screen to the left.\n            view.setAlpha(0f);\n\n        } else if (position <= 0) { // [-1,0]\n            // Use the default slide transition when moving to the left page\n            view.setAlpha(1f);\n            view.setTranslationX(0f);\n            view.setScaleX(1f);\n            view.setScaleY(1f);\n\n        } else if (position <= 1) { // (0,1]\n            //进入页面时\n            view.setVisibility(View.VISIBLE);\n            // Fade the page out.\n            view.setAlpha(1 - position);\n\n            // Counteract the default slide transition\n            view.setTranslationX(pageWidth * -position);\n\n            // Scale the page down (between MIN_SCALE and 1)\n            float scaleFactor = mMinScale\n                    + (1 - mMinScale) * (1 - Math.abs(position));\n            view.setScaleX(scaleFactor);\n            view.setScaleY(scaleFactor);\n            //退出页面时\n            if(position ==1){\n                view.setVisibility(View.INVISIBLE);\n            }\n\n        } else { // (1,+Infinity]\n            // This page is way off-screen to the right.\n            view.setAlpha(0f);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/MZScaleInTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\nimport android.view.ViewParent;\n\nimport androidx.annotation.NonNull;\nimport androidx.recyclerview.widget.RecyclerView;\nimport androidx.viewpager2.widget.ViewPager2;\n\n/**\n * 内部实现魅族效果使用的，单独使用可能效果不一定好，自己可以尝试下看看是否满意，推荐使用ScaleInTransformer\n */\npublic class MZScaleInTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MIN_SCALE = 0.85f;\n    private float mMinScale = DEFAULT_MIN_SCALE;\n\n    public MZScaleInTransformer() {\n    }\n\n    public MZScaleInTransformer(float minScale) {\n        this.mMinScale = minScale;\n    }\n\n    @Override\n    public void transformPage(@NonNull View view, float position) {\n        ViewPager2 viewPager = requireViewPager(view);\n        float paddingLeft = viewPager.getPaddingLeft();\n        float paddingRight = viewPager.getPaddingRight();\n        float width = viewPager.getMeasuredWidth();\n        float offsetPosition = paddingLeft / (width - paddingLeft - paddingRight);\n        float currentPos = position - offsetPosition;\n        float reduceX = 0;\n        float itemWidth = view.getWidth();\n        //由于左右边的缩小而减小的x的大小的一半\n        reduceX = (1.0f - mMinScale) * itemWidth / 2.0f;\n        if (currentPos <= -1.0f) {\n            view.setTranslationX(reduceX);\n            view.setScaleX(mMinScale);\n            view.setScaleY(mMinScale);\n        } else if (currentPos <= 1.0) {\n            float scale = (1.0f - mMinScale) * Math.abs(1.0f - Math.abs(currentPos));\n            float translationX = currentPos * -reduceX;\n            if (currentPos <= -0.5) {//两个view中间的临界，这时两个view在同一层，左侧View需要往X轴正方向移动覆盖的值()\n                view.setTranslationX(translationX + Math.abs(Math.abs(currentPos) - 0.5f) / 0.5f);\n            } else if (currentPos <= 0.0f) {\n                view.setTranslationX(translationX);\n            } else if (currentPos >= 0.5) {//两个view中间的临界，这时两个view在同一层\n                view.setTranslationX(translationX - Math.abs(Math.abs(currentPos) - 0.5f) / 0.5f);\n            } else {\n                view.setTranslationX(translationX);\n            }\n            view.setScaleX(scale + mMinScale);\n            view.setScaleY(scale + mMinScale);\n        } else {\n            view.setScaleX(mMinScale);\n            view.setScaleY(mMinScale);\n            view.setTranslationX(-reduceX);\n        }\n\n    }\n\n    private ViewPager2 requireViewPager(@NonNull View page) {\n        ViewParent parent = page.getParent();\n        ViewParent parentParent = parent.getParent();\n\n        if (parent instanceof RecyclerView && parentParent instanceof ViewPager2) {\n            return (ViewPager2) parentParent;\n        }\n\n        throw new IllegalStateException(\n                \"Expected the page view to be managed by a ViewPager2 instance.\");\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/RotateDownPageTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class RotateDownPageTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MAX_ROTATE = 15.0f;\n    private float mMaxRotate = DEFAULT_MAX_ROTATE;\n\n    public RotateDownPageTransformer() {\n    }\n\n    public RotateDownPageTransformer(float maxRotate) {\n        mMaxRotate = maxRotate;\n    }\n\n    @Override\n    public void transformPage(@NonNull View view, float position) {\n        if (position < -1) {\n            // [-Infinity,-1)\n            // This page is way off-screen to the left.\n            view.setRotation(mMaxRotate * -1);\n            view.setPivotX(view.getWidth());\n            view.setPivotY(view.getHeight());\n\n        } else if (position <= 1) { // [-1,1]\n            if (position < 0) {//[0，-1]\n                view.setPivotX(view.getWidth() * (DEFAULT_CENTER + DEFAULT_CENTER * (-position)));\n                view.setPivotY(view.getHeight());\n                view.setRotation(mMaxRotate * position);\n            } else {//[1,0]\n                view.setPivotX(view.getWidth() * DEFAULT_CENTER * (1 - position));\n                view.setPivotY(view.getHeight());\n                view.setRotation(mMaxRotate * position);\n            }\n        } else {\n            // (1,+Infinity]\n            // This page is way off-screen to the right.\n            view.setRotation(mMaxRotate);\n            view.setPivotX(view.getWidth() * 0);\n            view.setPivotY(view.getHeight());\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/RotateUpPageTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class RotateUpPageTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MAX_ROTATE = 15.0f;\n    private float mMaxRotate = DEFAULT_MAX_ROTATE;\n\n    public RotateUpPageTransformer() {\n    }\n\n    public RotateUpPageTransformer(float maxRotate) {\n        mMaxRotate = maxRotate;\n    }\n\n    @Override\n    public void transformPage(@NonNull View view, float position) {\n        if (position < -1) { // [-Infinity,-1)\n            // This page is way off-screen to the left.\n            view.setRotation(mMaxRotate);\n            view.setPivotX(view.getWidth());\n            view.setPivotY(0);\n        } else if (position <= 1) {  // a页滑动至b页 ； a页从 0.0 ~ -1 ；b页从1 ~ 0.0\n            // [-1,1]\n            // Modify the default slide transition to shrink the page as well\n            if (position < 0) {//[0，-1]\n                view.setPivotX(view.getWidth() * (0.5f + 0.5f * (-position)));\n                view.setPivotY(0);\n                view.setRotation(-mMaxRotate * position);\n            } else {//[1,0]\n                view.setPivotX(view.getWidth() * 0.5f * (1 - position));\n                view.setPivotY(0);\n                view.setRotation(-mMaxRotate * position);\n            }\n        } else { // (1,+Infinity]\n            // This page is way off-screen to the right.\n            // ViewHelper.setRotation(view, ROT_MAX);\n            view.setRotation(-mMaxRotate);\n            view.setPivotX(0);\n            view.setPivotY(0);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/RotateYTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class RotateYTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MAX_ROTATE = 35f;\n    private float mMaxRotate = DEFAULT_MAX_ROTATE;\n\n    public RotateYTransformer() {\n    }\n\n    public RotateYTransformer(float maxRotate) {\n        mMaxRotate = maxRotate;\n    }\n\n    @Override\n    public void transformPage(@NonNull View view, float position) {\n        view.setPivotY(view.getHeight()/2);\n\n        if (position < -1) { // [-Infinity,-1)\n            // This page is way off-screen to the left.\n            view.setRotationY(-1 * mMaxRotate);\n            view.setPivotX(view.getWidth());\n        } else if (position <= 1) { // [-1,1]\n            // Modify the default slide transition to shrink the page as well\n            view.setRotationY(position * mMaxRotate);\n\n            //[0,-1]\n            if (position < 0) {\n                view.setPivotX(view.getWidth() * (DEFAULT_CENTER + DEFAULT_CENTER * (-position)));\n                view.setPivotX(view.getWidth());\n            } else {//[1,0]\n                view.setPivotX(view.getWidth() * DEFAULT_CENTER * (1 - position));\n                view.setPivotX(0);\n            }\n\n            // Scale the page down (between MIN_SCALE and 1)\n        } else {\n            // (1,+Infinity]\n            // This page is way off-screen to the right.\n            view.setRotationY(1 * mMaxRotate);\n            view.setPivotX(0);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/ScaleInTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\nimport android.view.ViewParent;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Px;\nimport androidx.core.view.ViewCompat;\nimport androidx.recyclerview.widget.RecyclerView;\nimport androidx.viewpager2.widget.ViewPager2;\n\npublic class ScaleInTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MIN_SCALE = 0.85f;\n    private float mMinScale = DEFAULT_MIN_SCALE;\n\n    public ScaleInTransformer() {\n    }\n\n    public ScaleInTransformer(float minScale) {\n        this.mMinScale = minScale;\n    }\n\n    @Override\n    public void transformPage(@NonNull View view, float position) {\n        int pageWidth = view.getWidth();\n        int pageHeight = view.getHeight();\n\n        view.setPivotY(pageHeight / 2);\n        view.setPivotX(pageWidth / 2);\n        if (position < -1) { // [-Infinity,-1)\n            // This page is way off-screen to the left.\n            view.setScaleX(mMinScale);\n            view.setScaleY(mMinScale);\n            view.setPivotX(pageWidth);\n        } else if (position <= 1) { // [-1,1]\n            // Modify the default slide transition to shrink the page as well\n            if (position < 0) //1-2:1[0,-1] ;2-1:1[-1,0]\n            {\n\n                float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale;\n                view.setScaleX(scaleFactor);\n                view.setScaleY(scaleFactor);\n\n                view.setPivotX(pageWidth * (DEFAULT_CENTER + (DEFAULT_CENTER * -position)));\n\n            } else //1-2:2[1,0] ;2-1:2[0,1]\n            {\n                float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale;\n                view.setScaleX(scaleFactor);\n                view.setScaleY(scaleFactor);\n                view.setPivotX(pageWidth * ((1 - position) * DEFAULT_CENTER));\n            }\n\n\n        } else { // (1,+Infinity]\n            view.setPivotX(0);\n            view.setScaleX(mMinScale);\n            view.setScaleY(mMinScale);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/transformer/ZoomOutPageTransformer.java",
    "content": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.viewpager2.widget.ViewPager2;\n\n\npublic class ZoomOutPageTransformer extends BasePageTransformer {\n    private static final float DEFAULT_MIN_SCALE = 0.85f;\n    private static final float DEFAULT_MIN_ALPHA = 0.5f;\n    private float mMinScale = DEFAULT_MIN_SCALE;\n    private float mMinAlpha = DEFAULT_MIN_ALPHA;\n\n    public ZoomOutPageTransformer() {\n    }\n\n    public ZoomOutPageTransformer(float minScale,float minAlpha ) {\n        this.mMinScale = minScale;\n        this.mMinAlpha = minAlpha;\n    }\n\n    public void transformPage(View view, float position) {\n        int pageWidth = view.getWidth();\n        int pageHeight = view.getHeight();\n\n        if (position < -1) { // [-Infinity,-1)\n            // This page is way off-screen to the left.\n            view.setAlpha(0f);\n\n        } else if (position <= 1) { // [-1,1]\n            // Modify the default slide transition to shrink the page as well\n            float scaleFactor = Math.max(mMinScale, 1 - Math.abs(position));\n            float vertMargin = pageHeight * (1 - scaleFactor) / 2;\n            float horzMargin = pageWidth * (1 - scaleFactor) / 2;\n            if (position < 0) {\n                view.setTranslationX(horzMargin - vertMargin / 2);\n            } else {\n                view.setTranslationX(-horzMargin + vertMargin / 2);\n            }\n\n            // Scale the page down (between MIN_SCALE and 1)\n            view.setScaleX(scaleFactor);\n            view.setScaleY(scaleFactor);\n\n            // Fade the page relative to its size.\n            view.setAlpha(mMinAlpha +\n                    (scaleFactor - mMinScale) /\n                            (1 - mMinScale) * (1 - mMinAlpha));\n\n        } else { // (1,+Infinity]\n            // This page is way off-screen to the right.\n            view.setAlpha(0f);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/util/BannerLifecycleObserver.java",
    "content": "package com.youth.banner.util;\n\nimport androidx.lifecycle.LifecycleObserver;\nimport androidx.lifecycle.LifecycleOwner;\n\npublic interface BannerLifecycleObserver extends LifecycleObserver {\n\n    void onStop(LifecycleOwner owner);\n\n    void onStart(LifecycleOwner owner);\n\n    void onDestroy(LifecycleOwner owner);\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/util/BannerLifecycleObserverAdapter.java",
    "content": "package com.youth.banner.util;\n\nimport androidx.lifecycle.Lifecycle;\nimport androidx.lifecycle.LifecycleObserver;\nimport androidx.lifecycle.LifecycleOwner;\nimport androidx.lifecycle.OnLifecycleEvent;\n\npublic class BannerLifecycleObserverAdapter implements LifecycleObserver {\n    private final BannerLifecycleObserver mObserver;\n    private final LifecycleOwner mLifecycleOwner;\n\n    public BannerLifecycleObserverAdapter(LifecycleOwner lifecycleOwner, BannerLifecycleObserver observer) {\n        mLifecycleOwner = lifecycleOwner;\n        mObserver = observer;\n    }\n\n    @OnLifecycleEvent(Lifecycle.Event.ON_START)\n    public void onStart() {\n        LogUtils.i(\"onStart\");\n        mObserver.onStart(mLifecycleOwner);\n    }\n\n    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)\n    public void onStop() {\n        LogUtils.i(\"onStop\");\n        mObserver.onStop(mLifecycleOwner);\n    }\n\n    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)\n    public void onDestroy() {\n        LogUtils.i(\"onDestroy\");\n        mObserver.onDestroy(mLifecycleOwner);\n    }\n\n}"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/util/BannerUtils.java",
    "content": "package com.youth.banner.util;\n\nimport android.content.res.Resources;\nimport android.graphics.Outline;\nimport android.os.Build;\nimport android.util.TypedValue;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewOutlineProvider;\n\nimport androidx.annotation.LayoutRes;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.RequiresApi;\n\npublic class BannerUtils {\n\n    /**\n     * 获取真正的位置\n     *\n     * @param isIncrease 首尾是否有增加\n     * @param position  当前位置\n     * @param realCount 真实数量\n     * @return\n     */\n    public static int getRealPosition(boolean isIncrease, int position, int realCount) {\n        if (!isIncrease) {\n            return position;\n        }\n        int realPosition;\n        if (position == 0) {\n            realPosition = realCount - 1;\n        } else if (position == realCount + 1) {\n            realPosition = 0;\n        } else {\n            realPosition = position - 1;\n        }\n        return realPosition;\n    }\n\n    /**\n     * 将布局文件转成view，这里为了适配viewpager2中高宽必须为match_parent\n     *\n     * @param parent\n     * @param layoutId\n     * @return\n     */\n    public static View getView(@NonNull ViewGroup parent, @LayoutRes int layoutId) {\n        View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);\n        ViewGroup.LayoutParams params = view.getLayoutParams();\n        //这里判断高度和宽带是否都是match_parent\n        if (params.height != -1 || params.width != -1) {\n            params.height = -1;\n            params.width = -1;\n            view.setLayoutParams(params);\n        }\n        return view;\n    }\n\n    public static int dp2px(float dp) {\n        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());\n    }\n\n    /**\n     * 设置view圆角\n     *\n     * @param radius\n     * @return\n     */\n    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)\n    public static void setBannerRound(View view,float radius) {\n        view.setOutlineProvider(new ViewOutlineProvider() {\n            @Override\n            public void getOutline(View view, Outline outline) {\n                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), radius);\n            }\n        });\n        view.setClipToOutline(true);\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/util/LogUtils.java",
    "content": "package com.youth.banner.util;\n\nimport android.util.Log;\n\nimport com.youth.banner.BuildConfig;\n\npublic class LogUtils {\n    public static final String TAG = \"banner_log\";\n\n    private static final boolean DEBUG = BuildConfig.DEBUG;\n\n    public static void d(String msg) {\n        if (DEBUG) {\n            Log.d(TAG, msg);\n        }\n    }\n\n    public static void e(String msg) {\n        if (DEBUG) {\n            Log.e(TAG, msg);\n        }\n    }\n\n    public static void i(String msg) {\n        if (DEBUG) {\n            Log.i(TAG, msg);\n        }\n    }\n\n    public static void v( String msg) {\n        if (DEBUG) {\n            Log.v(TAG, msg);\n        }\n    }\n\n    public static void w(String msg) {\n        if (DEBUG) {\n            Log.w(TAG, msg);\n        }\n    }\n}\n"
  },
  {
    "path": "banner/src/main/java/com/youth/banner/util/ScrollSpeedManger.java",
    "content": "package com.youth.banner.util;\n\nimport androidx.recyclerview.widget.LinearLayoutManager;\nimport androidx.recyclerview.widget.LinearSmoothScroller;\nimport androidx.recyclerview.widget.RecyclerView;\nimport androidx.viewpager2.widget.ViewPager2;\n\nimport com.youth.banner.Banner;\n\nimport java.lang.reflect.Field;\n\n\n/**\n * 改变LinearLayoutManager的切换速度\n */\npublic class ScrollSpeedManger extends LinearLayoutManager {\n    private Banner banner;\n\n    public ScrollSpeedManger(Banner banner, LinearLayoutManager linearLayoutManager) {\n        super(banner.getContext(), linearLayoutManager.getOrientation(), false);\n        this.banner = banner;\n    }\n\n    @Override\n    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {\n        LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {\n            @Override\n            protected int calculateTimeForDeceleration(int dx) {\n                return banner.getScrollTime();\n            }\n        };\n        linearSmoothScroller.setTargetPosition(position);\n        startSmoothScroll(linearSmoothScroller);\n    }\n\n    public static void reflectLayoutManager(Banner banner) {\n        if (banner.getScrollTime() < 100) return;\n        try {\n            ViewPager2 viewPager2 = banner.getViewPager2();\n            RecyclerView recyclerView = (RecyclerView) viewPager2.getChildAt(0);\n            recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);\n\n            ScrollSpeedManger speedManger = new ScrollSpeedManger(banner, (LinearLayoutManager) recyclerView.getLayoutManager());\n            recyclerView.setLayoutManager(speedManger);\n\n\n            Field LayoutMangerField = ViewPager2.class.getDeclaredField(\"mLayoutManager\");\n            LayoutMangerField.setAccessible(true);\n            LayoutMangerField.set(viewPager2, speedManger);\n\n            Field pageTransformerAdapterField = ViewPager2.class.getDeclaredField(\"mPageTransformerAdapter\");\n            pageTransformerAdapterField.setAccessible(true);\n            Object mPageTransformerAdapter = pageTransformerAdapterField.get(viewPager2);\n            if (mPageTransformerAdapter != null) {\n                Class<?> aClass = mPageTransformerAdapter.getClass();\n                Field layoutManager = aClass.getDeclaredField(\"mLayoutManager\");\n                layoutManager.setAccessible(true);\n                layoutManager.set(mPageTransformerAdapter, speedManger);\n            }\n            Field scrollEventAdapterField = ViewPager2.class.getDeclaredField(\"mScrollEventAdapter\");\n            scrollEventAdapterField.setAccessible(true);\n            Object mScrollEventAdapter = scrollEventAdapterField.get(viewPager2);\n            if (mScrollEventAdapter != null) {\n                Class<?> aClass = mScrollEventAdapter.getClass();\n                Field layoutManager = aClass.getDeclaredField(\"mLayoutManager\");\n                layoutManager.setAccessible(true);\n                layoutManager.set(mScrollEventAdapter, speedManger);\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n}\n"
  },
  {
    "path": "banner/src/main/res/values/attr.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"Banner\">\n        <attr name=\"banner_loop_time\" format=\"integer\" />\n        <attr name=\"banner_auto_loop\" format=\"boolean\" />\n        <attr name=\"banner_infinite_loop\" format=\"boolean\" />\n\n        <!--RoundLinesIndicator、RectangleIndicator-->\n        <attr name=\"banner_indicator_height\" format=\"dimension\"/>\n        <attr name=\"banner_indicator_radius\" format=\"dimension\"/>\n\n        <!-- 以下为公用属性 -->\n        <attr name=\"banner_indicator_selected_width\" format=\"dimension\"/>\n        <!--CircleIndicator-->\n        <attr name=\"banner_indicator_normal_width\" format=\"dimension\"/>\n        <attr name=\"banner_indicator_space\" format=\"dimension\"/>\n\n        <attr name=\"banner_indicator_normal_color\" format=\"reference|color\"/>\n        <attr name=\"banner_indicator_selected_color\" format=\"reference|color\"/>\n        <attr name=\"banner_indicator_margin\" format=\"dimension\"/>\n        <attr name=\"banner_indicator_marginLeft\" format=\"dimension\"/>\n        <attr name=\"banner_indicator_marginTop\" format=\"dimension\"/>\n        <attr name=\"banner_indicator_marginRight\" format=\"dimension\"/>\n        <attr name=\"banner_indicator_marginBottom\" format=\"dimension\"/>\n\n        <attr name=\"banner_indicator_gravity\" format=\"enum\">\n            <enum name=\"left\" value=\"0\" />\n            <enum name=\"center\" value=\"1\" />\n            <enum name=\"right\" value=\"2\" />\n        </attr>\n\n        <attr name=\"banner_orientation\">\n            <enum name=\"horizontal\" value=\"0\" />\n            <enum name=\"vertical\" value=\"1\" />\n        </attr>\n\n        <attr name=\"banner_radius\" format=\"dimension\"/>\n\n        <!--设置需要圆角的方向，不设置默认全部设置-->\n        <attr name=\"banner_round_top_left\" format=\"boolean\"/>\n        <attr name=\"banner_round_top_right\" format=\"boolean\"/>\n        <attr name=\"banner_round_bottom_left\" format=\"boolean\"/>\n        <attr name=\"banner_round_bottom_right\" format=\"boolean\"/>\n\n    </declare-styleable>\n\n    <declare-styleable name=\"DrawableIndicator\">\n        <attr name=\"normal_drawable\" format=\"reference\"/>\n        <attr name=\"selected_drawable\" format=\"reference\"/>\n    </declare-styleable>\n</resources>\n"
  },
  {
    "path": "banner/src/main/res/values/ids.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <item name=\"banner_data_key\" type=\"id\"/>\n    <item name=\"banner_pos_key\" type=\"id\"/>\n</resources>"
  },
  {
    "path": "banner/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"indicator_color_error\">indicator color attribute : “@color/colorID or #000000”</string>\n    <string name=\"banner_adapter_null_error\">Adapter is NULL!</string>\n\n</resources>\n"
  },
  {
    "path": "build.gradle",
    "content": "\nbuildscript {\n    ext {\n        kotlin_version = '1.7.0'\n    }\n    repositories {\n        maven { url 'https://maven.aliyun.com/repository/public/' }\n        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }\n        maven { url 'https://jitpack.io' }\n        maven { url \"https://s01.oss.sonatype.org/content/groups/public\" }\n        google()\n    }\n    dependencies {\n\n        classpath 'com.android.tools.build:gradle:7.1.1'\n        classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n\n    }\n}\n\nallprojects {\n    repositories {\n        maven { url 'https://maven.aliyun.com/repository/public/' }\n        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }\n        maven { url 'https://jitpack.io' }\n        maven { url \"https://s01.oss.sonatype.org/content/groups/public\" }\n        mavenCentral()\n        google()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.2-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\ninclude ':banner'\ninclude ':usekotlin'\n"
  },
  {
    "path": "update_message.md",
    "content": "\n## 更新说明\n#### v2.2.3\n    * 修改adapter 数据相关操作方法\n    * banner 去掉泛型返回\n    * demo 添加更新数据注释\n    * 更新viewpager2到beta2\n\n#### v2.2.1-2.2.2\n   * 对kotlin使用的兼容支持\n   * 对kotlin使用demo进行了修改\n   * 新版本都将迁移至MavenCentral\n   * 更新viewpager2到1.1.0-alpha01\n   * 修改bug\n   \n#### v2.2.0\n   * 自定义属性中增加可选择设置banner圆角的具体方向\n   * 增加DrawableIndicator指示器,支持直接设置图片了，可以通过构造方法或者自定义属性设置\n   * 合并ZakAnun朋友提交的优化监听器的设置以及减少 onPageScrolled 回调\n   * 对demo进行了修改\n   * 新的版本迁移将至jitpack仓库\n\n#### v2.1.0\n   * 修改banner圆角锯齿\n   * 修改画廊支持左右不同的大小\n   * 内置增加了默认的图片适配器，方便偷懒的人，但是其他类型的没有内置是因为可变性太高了，大家自定义就好\n   * 自定义参数全部修改成banner_开头了，避免和其他库冲突。麻烦使用的大家修改下！\n\n#### v2.0.12\n   * 修改了new banner时无默认参数的问题\n   * 自带的指示器支持选中和默认的宽度\n   * setAdapter支持设置是否无限循环\n   \n#### v2.0.11\n   * 合并了lvshaojun朋友提交的代码\n    \n#### v2.0.9\n   * 增加了addBannerLifecycleObserver()方法，给banner添加生命周期观察者，将生命周期交给banner自己处理，\n     你也可以不使用这种方式自己象以前的方式自己控制，具体可以参考文档和demo\n   * 修改了DepthPageTransformer效果，现在使用这种效果返回的位置应该没有问题了\n   * 其他优化\n\n#### v2.0.8\n   * 修复bug\n   * 增加混淆配置\n\n#### v2.0.7\n   * 修复画廊问题\n   * 增加了多种PageTransformer\n   * 增加滑动距离方法\n   * demo中提供了adapter数据操作示例\n   * 工具类中增加view圆角裁剪方法\n   * 增加魅族轮播效果\n\n#### v2.0.6\n   * 修复指示器无法设置为白色问题\n   * 新增销毁方法\n   * 调小滑动距离\n\n#### v2.0.5\n   * demo中增加tv遥控器控件切换，我没有真机测试，所以只放到了demo中，使用的朋友有TV真机的帮忙测试下反馈给我哈！\n   * 增加了view的添加和分离回调时，分别暂停和开始轮播，主要解决滑动嵌套时不可见轮播。这个也可以自己监听实现哈\n    \n#### v2.0.3-2.0.4\n    banner 修复了几个紧急bug，圆角绘制引起的残影和焦点问题，替换layoutmanager为null的异常\n \n#### v2.0.2\n    banner bug修复\n * 有朋友想要在引导页使用banner，所以增加了is_infinite_loop属性来控制是否能无限循环\n * 增加了设置开始轮播位置的方法\n * 修复圆角裁剪和首次设置开始位置不对的bug\n * demo中增加了类似淘宝详情banner的案例，第一个放视频，不能无限循环\n * 设置指示器方法调整，demo增加自定义数字指示器案例\n * 对ProxyLayoutManger进行的优化\n\n#### v2.0.1\n    banner bug修改\n * 解决一系列嵌套banner的事件冲突和解决方案\n （如果我没有考虑到的场景，大家再反馈或者提交方案）\n\n#### v2.0.0\n    banner 正式版发布\n * 改变banner圆角实现方式，兼容低版本\n * 新增两种指示器效果，基本能满足大部分需求了\n\n#### v2.0.0-beta\n    banner 测试版发布\n * 修改banner内部轮播逻辑\n * 增加设置画廊效果方法\n * 内置有2种官方Transformer效果，更多效果你可以自定义\n * 优化切换事件和点击事件,去掉onBannerChanged方法\n * 新增轮播滑动时间控制，感谢zguop，这里的具体实现方法来自zguop的项目\n * 支持多PageTransformer组合设置\n\n#### v2.0.0-alpha03\n    banner 预览版使用中的问题优化。\n    这里要感谢BoldFruit朋友修复了一个bug；我爷爷得了癌症住院了需要照顾，公司事情也多，所以更新频率会慢很多。希望大家理解！\n    不过我更希望大家要是发现bug，亦可以自己修复提交，有什么想法新增的功能也可以提交过来。可以提供一个良好的开源环境哈！\n    还有不要一直夺命连环催，大家都有自己的事情，多多理解！\n    \n * 增加支持布局文件中使用自定义指示器了（自己发挥）\n * 增加支持Android5.0以上的设置banner圆角方法\n * 其他问题修复（有些实在是不好复现加上有点忙，只修改了部分bug）\n\n#### v2.0.0-alpha02\n    banner 预览版使用中的问题优化\n * #666 修改orientation自定义属性与其他库冲突问题：改成banner_orientation\n * 增加RecyclerView嵌套banner和ConstraintLayout中使用banner测试demo\n * #669 RecyclerView嵌套banner 轮播优化代码建议，demo中可以查看\n * 其他问题修复\n\n#### v2.0.0-alpha\n    banner 2.0全新基础升级，目前是预览版，使用中的问题慢慢迭代\n *  使用了ViewPager2为基础控件  \n * 支持了androidx兼容包\n * 方便了UI、Indicator自定义（现在还是基础版本，后面再提升）\n * 依赖包目前只需要导入了ViewPager2\n"
  },
  {
    "path": "usekotlin/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "usekotlin/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\n\nandroid {\n    compileSdkVersion 33\n\n    defaultConfig {\n        minSdkVersion 21\n        targetSdkVersion 33\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n        consumerProguardFiles 'consumer-rules.pro'\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility = 1.8\n        targetCompatibility = 1.8\n    }\n\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31'\n    implementation 'androidx.appcompat:appcompat:1.1.0'\n    implementation 'androidx.core:core-ktx:1.3.0'\n    implementation 'com.github.bumptech.glide:glide:4.12.0'\n    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'\n    testImplementation 'junit:junit:4.13.2'\n    androidTestImplementation 'androidx.test.ext:junit:1.1.1'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'\n    implementation project(path: ':banner')\n    implementation 'androidx.recyclerview:recyclerview:1.2.0'\n}\n"
  },
  {
    "path": "usekotlin/consumer-rules.pro",
    "content": ""
  },
  {
    "path": "usekotlin/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "usekotlin/src/androidTest/java/com/spring/usekotlin/ExampleInstrumentedTest.kt",
    "content": "package com.spring.usekotlin\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.runners.AndroidJUnit4\n\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\nimport org.junit.Assert.*\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\n@RunWith(AndroidJUnit4::class)\nclass ExampleInstrumentedTest {\n    @Test\n    fun useAppContext() {\n        // Context of the app under test.\n        val appContext = InstrumentationRegistry.getInstrumentation().targetContext\n        assertEquals(\"com.spring.usekotlin.test\", appContext.packageName)\n    }\n}\n"
  },
  {
    "path": "usekotlin/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.spring.usekotlin\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".MainActivity\"\n            android:label=\"@string/app_name\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n</manifest>"
  },
  {
    "path": "usekotlin/src/main/java/com/spring/usekotlin/ImageAdapter.kt",
    "content": "package com.spring.usekotlin\n\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport androidx.recyclerview.widget.RecyclerView\nimport com.bumptech.glide.Glide\nimport com.youth.banner.adapter.BannerAdapter\nimport com.youth.banner.util.BannerUtils\n\nclass ImageAdapter(imageUrls: List<String>) : BannerAdapter<String, ImageAdapter.ImageHolder>(imageUrls) {\n\n\n    override fun onCreateHolder(parent: ViewGroup?, viewType: Int): ImageHolder {\n        val imageView = ImageView(parent!!.context)\n        val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n        imageView.layoutParams = params\n        imageView.scaleType = ImageView.ScaleType.CENTER_CROP\n        //通过裁剪实现圆角\n        BannerUtils.setBannerRound(imageView, 20f)\n        return ImageHolder(imageView)\n    }\n\n    override fun onBindView(holder: ImageHolder, data: String, position: Int, size: Int) {\n        Glide.with(holder.itemView)\n                .load(data)\n                .into(holder.imageView)\n    }\n\n\n    class ImageHolder(view: View) : RecyclerView.ViewHolder(view) {\n        var imageView: ImageView = view as ImageView\n    }\n\n}\n\n"
  },
  {
    "path": "usekotlin/src/main/java/com/spring/usekotlin/MainActivity.kt",
    "content": "package com.spring.usekotlin\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport com.bumptech.glide.Glide\nimport com.youth.banner.Banner\nimport com.youth.banner.adapter.BannerImageAdapter\nimport com.youth.banner.holder.BannerImageHolder\nimport com.youth.banner.indicator.CircleIndicator\nimport com.youth.banner.indicator.RoundLinesIndicator\nimport kotlinx.android.synthetic.main.activity_main.*\n\nclass MainActivity : AppCompatActivity() {\n\n    var imageUrls = listOf(\n            \"https://img.zcool.cn/community/01b72057a7e0790000018c1bf4fce0.png\",\n            \"https://img.zcool.cn/community/016a2256fb63006ac7257948f83349.jpg\",\n            \"https://img.zcool.cn/community/01233056fb62fe32f875a9447400e1.jpg\",\n            \"https://img.zcool.cn/community/01700557a7f42f0000018c1bd6eb23.jpg\"\n    )\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n        //使用默认的图片适配器\n        var banner = (bannerLayout1 as Banner<String, BannerImageAdapter<String>>)\n        banner.apply {\n            addBannerLifecycleObserver(this@MainActivity)\n            setIndicator(CircleIndicator(this@MainActivity))\n            setAdapter(object : BannerImageAdapter<String>(imageUrls) {\n                override fun onBindView(holder: BannerImageHolder, data: String, position: Int, size: Int) {\n                    Glide.with(this@MainActivity)\n                            .load(data)\n                            .into(holder.imageView)\n                }\n            })\n        }\n\n\n        //使用自定义适配器，更多api方法自己尝试\n        var banner2 = (bannerLayout2 as Banner<String, ImageAdapter>)\n        banner2.apply {\n            addBannerLifecycleObserver(this@MainActivity)\n            setBannerRound(20f)\n            setIndicator(RoundLinesIndicator(this@MainActivity))\n            setAdapter(ImageAdapter(imageUrls))\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "usekotlin/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:padding=\"10dp\">\n\n    <com.youth.banner.Banner\n        android:id=\"@+id/bannerLayout1\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"180dp\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <com.youth.banner.Banner\n        android:id=\"@+id/bannerLayout2\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"180dp\"\n        android:layout_marginTop=\"20dp\"\n        app:layout_constraintTop_toBottomOf=\"@+id/bannerLayout1\"/>\n\n</androidx.constraintlayout.widget.ConstraintLayout>"
  },
  {
    "path": "usekotlin/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">@color/main_color</color>\n    <color name=\"colorPrimaryDark\">@color/main_color</color>\n    <color name=\"colorAccent\">@color/main_color</color>\n\n    <color name=\"textColor\">#BDBDBD</color>\n\n    <color name=\"main_color\">#5CB85C</color>\n\n</resources>\n"
  },
  {
    "path": "usekotlin/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Banner kotlin Example</string>\n</resources>\n"
  },
  {
    "path": "usekotlin/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "usekotlin/src/test/java/com/spring/usekotlin/ExampleUnitTest.kt",
    "content": "package com.spring.usekotlin\n\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\nclass ExampleUnitTest {\n    @Test\n    fun addition_isCorrect() {\n        assertEquals(4, 2 + 2)\n    }\n}\n"
  }
]