Showing preview only (250K chars total). Download the full file or copy to clipboard to get everything.
Repository: youth5201314/banner
Branch: master
Commit: 777c7dbfaa0a
Files: 118
Total size: 219.4 KB
Directory structure:
gitextract_a7zjbpp5/
├── .gitignore
├── BannerExample.iml
├── LICENSE
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── test/
│ │ └── banner/
│ │ ├── MainActivity.java
│ │ ├── adapter/
│ │ │ ├── ImageAdapter.java
│ │ │ ├── ImageNetAdapter.java
│ │ │ ├── ImageTitleAdapter.java
│ │ │ ├── ImageTitleNumAdapter.java
│ │ │ ├── MultipleTypesAdapter.java
│ │ │ ├── MyRecyclerViewAdapter.java
│ │ │ └── TopLineAdapter.java
│ │ ├── bean/
│ │ │ └── DataBean.java
│ │ ├── indicator/
│ │ │ └── NumIndicator.java
│ │ ├── ui/
│ │ │ ├── BannerFragment.java
│ │ │ ├── BannerListFragment.java
│ │ │ ├── BlankFragment.java
│ │ │ ├── ConstraintLayoutBannerActivity.java
│ │ │ ├── GalleryActivity.java
│ │ │ ├── RecyclerViewBannerActivity.java
│ │ │ ├── TVActivity.java
│ │ │ ├── TouTiaoActivity.java
│ │ │ ├── VideoActivity.java
│ │ │ └── Vp2FragmentRecyclerviewActivity.java
│ │ ├── util/
│ │ │ ├── ParentRecyclerView.java
│ │ │ └── TabLayoutMediator.java
│ │ └── viewholder/
│ │ ├── ImageHolder.java
│ │ ├── ImageTitleHolder.java
│ │ ├── TitleHolder.java
│ │ └── VideoHolder.java
│ └── res/
│ ├── drawable/
│ │ ├── background.xml
│ │ ├── default_selecter.xml
│ │ ├── green.xml
│ │ ├── selected_radius.xml
│ │ ├── unselected_radius.xml
│ │ └── white.xml
│ ├── layout/
│ │ ├── activity_constraint_layout_banner.xml
│ │ ├── activity_gallery.xml
│ │ ├── activity_main.xml
│ │ ├── activity_recyclerview_banner.xml
│ │ ├── activity_t_v.xml
│ │ ├── activity_tou_tiao.xml
│ │ ├── activity_video.xml
│ │ ├── activity_vp2_fragment_recyclerview.xml
│ │ ├── banner.xml
│ │ ├── banner_image.xml
│ │ ├── banner_image_title.xml
│ │ ├── banner_image_title_num.xml
│ │ ├── banner_title.xml
│ │ ├── banner_video.xml
│ │ ├── item.xml
│ │ ├── test.xml
│ │ └── top_line_item2.xml
│ ├── values/
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-w820dp/
│ └── dimens.xml
├── banner/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── youth/
│ │ └── banner/
│ │ ├── Banner.java
│ │ ├── adapter/
│ │ │ ├── BannerAdapter.java
│ │ │ └── BannerImageAdapter.java
│ │ ├── config/
│ │ │ ├── BannerConfig.java
│ │ │ └── IndicatorConfig.java
│ │ ├── holder/
│ │ │ ├── BannerImageHolder.java
│ │ │ └── IViewHolder.java
│ │ ├── indicator/
│ │ │ ├── BaseIndicator.java
│ │ │ ├── CircleIndicator.java
│ │ │ ├── DrawableIndicator.java
│ │ │ ├── Indicator.java
│ │ │ ├── RectangleIndicator.java
│ │ │ └── RoundLinesIndicator.java
│ │ ├── itemdecoration/
│ │ │ └── MarginDecoration.java
│ │ ├── listener/
│ │ │ ├── OnBannerListener.java
│ │ │ └── OnPageChangeListener.java
│ │ ├── transformer/
│ │ │ ├── AlphaPageTransformer.java
│ │ │ ├── BasePageTransformer.java
│ │ │ ├── DepthPageTransformer.java
│ │ │ ├── MZScaleInTransformer.java
│ │ │ ├── RotateDownPageTransformer.java
│ │ │ ├── RotateUpPageTransformer.java
│ │ │ ├── RotateYTransformer.java
│ │ │ ├── ScaleInTransformer.java
│ │ │ └── ZoomOutPageTransformer.java
│ │ └── util/
│ │ ├── BannerLifecycleObserver.java
│ │ ├── BannerLifecycleObserverAdapter.java
│ │ ├── BannerUtils.java
│ │ ├── LogUtils.java
│ │ └── ScrollSpeedManger.java
│ └── res/
│ └── values/
│ ├── attr.xml
│ ├── ids.xml
│ └── strings.xml
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle
├── update_message.md
└── usekotlin/
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── com/
│ └── spring/
│ └── usekotlin/
│ └── ExampleInstrumentedTest.kt
├── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── spring/
│ │ └── usekotlin/
│ │ ├── ImageAdapter.kt
│ │ └── MainActivity.kt
│ └── res/
│ ├── layout/
│ │ └── activity_main.xml
│ └── values/
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
└── test/
└── java/
└── com/
└── spring/
└── usekotlin/
└── ExampleUnitTest.kt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
.idea
/banner.iml
/gradlew
/gradlew.bat
/gradle.properties
================================================
FILE: BannerExample.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<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">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
## Banner 2.0 全新升级
> 只做一个可以自定义的轮播容器,不侵入UI ———— Banner 2.0
```
> 各位老铁反馈的问题我都有看,不是不解决,有时真的很难复现,
> 如果能在提交问题时,有条件提供个demo发到我邮箱,方便定位问题,毕竟大家的场景和使用方式都有差异,
> 我自己也在使用,在多个千万级APP上一直稳定运行,如果真有严重问题肯定第一时间就修复了
```
<a href="https://github.com/youth5201314/banner/tree/release-1.4.10" target="_blank">Banner 1.4.10(还想看老版本的可以点击这里)</a>
### 阔别已久,从新回归
* 首先我声明几点:
* 这只是一个开源库,如果满意你可以使用、可以借鉴修改,希望对你们有所帮助。
* 如果不满意请友好的提出,注明错误的详细信息或者修改建议,好的想法和自定义的东西亦可以直接提交,大家都能来一起完善。
* 如果你觉得实在是没用,也请你做一个有自我修养的人。
### 主要改进功能介绍
最开始是想上传以前基于viewpager更新好的版本,但是看着viewpager2正式版已经出来了,就上新的吧,viewpager2确实比viewpager性能好很多。
- [x] 使用了ViewPager2为基础控件 <a href="https://developer.android.google.cn/jetpack/androidx/releases/viewpager2" target="_blank">ViewPager2介绍</a>
- [x] 支持了androidx兼容包
- [x] 方便了UI、Indicator自定义
- [x] 支持画廊效果、魅族效果
- [x] 兼容了水平和垂直轮播,也可以实现类似淘宝头条的效果
- [x] 依赖包目前只需要导入了ViewPager2
### 效果图
更多效果运行demo查看




##### 内置了多种PageTransformer效果


|内置的PageTransformer|
|---|
|AlphaPageTransformer|
|DepthPageTransformer|
|RotateDownPageTransformer|
|RotateUpPageTransformer|
|RotateYTransformer|
|ScaleInTransformer|
|ZoomOutPageTransformer|
也可以组合使用效果更佳
## 方法
更多方法以实际使用为准,下面不一定全部列出了
|方法名|返回类型|描述|
|---|---|---|
|getAdapter()|extends BannerAdapter|获取你设置的BannerAdapter
|getViewPager2()|ViewPager2|获取ViewPager2
|getIndicator()|Indicator|获取你设置的指示器(没有设置直接获取会抛异常哦)
|getIndicatorConfig()|IndicatorConfig|获取你设置的指示器配置信息(没有设置直接获取会抛异常哦)
|getRealCount()|int|返回banner真实总数
|setUserInputEnabled(boolean)|this|禁止手动滑动Banner;true 允许,false 禁止
|setDatas(List<T>)|this|重新设置banner数据
|isAutoLoop(boolean)|this|是否允许自动轮播
|setLoopTime(long)|this|设置轮播间隔时间(默认3000毫秒)
|setScrollTime(long)|this|设置轮播滑动的时间(默认800毫秒)
|start()|this|开始轮播(主要配合生命周期使用),或者你手动暂停再次启动
|stop()|this|停止轮播(主要配合生命周期使用),或者你需要手动暂停
|setAdapter(T extends BannerAdapter)|this|设置banner的适配器
|setAdapter(T extends BannerAdapter,boolean)|this|设置banner的适配器,是否支持无限循环
|setOrientation(@Orientation)|this|设置banner轮播方向(垂直or水平)
|setOnBannerListener(this)|this|设置点击事件,下标是从0开始
|addOnPageChangeListener(this)|this|添加viewpager2的滑动监听
|setPageTransformer(PageTransformer)|this|设置viewpager的切换效果
|addPageTransformer(PageTransformer)|this|添加viewpager的切换效果(可以设置多个)
|setIndicator(Indicator)|this|设置banner轮播指示器(提供有base和接口,可以自定义)
|setIndicator(Indicator,boolean)|this|设置指示器(传false代表不将指示器添加到banner上,配合布局文件,可以自我发挥)
|setIndicatorSelectedColor(@ColorInt)|this|设置指示器选中颜色
|setIndicatorSelectedColorRes(@ColorRes)|this|设置指示器选中颜色
|setIndicatorNormalColor(@ColorInt)|this|设置指示器默认颜色
|setIndicatorNormalColorRes(@ColorRes)|this|设置指示器默认颜色
|setIndicatorGravity(@IndicatorConfig.Direction)|this|设置指示器位置(左,中,右)
|setIndicatorSpace(int)|this|设置指示器之间的间距
|setIndicatorMargins(IndicatorConfig.Margins)|this|设置指示器的Margins
|setIndicatorWidth(int,int)|this|设置指示器选中和未选中的宽度,直接影响绘制指示器的大小
|setIndicatorNormalWidth(int)|this|设置指示器未选中的宽度
|setIndicatorSelectedWidth(int)|this|设置指示器选中的宽度
|setIndicatorRadius(int)|this|设置指示器圆角,不要圆角可以设置为0
|setIndicatorHeight(int)|this|设置指示器高度
|setBannerRound(float)|this|设置banner圆角(还有一种setBannerRound2方法,需要5.0以上)
|setBannerGalleryEffect(int,int,float)|this|画廊效果
|setBannerGalleryMZ(int,float)|this|魅族效果
|setStartPosition(int)|this|设置开始的位置 (需要在setAdapter或者setDatas之前调用才有效哦)
|setIndicatorPageChange()|this|设置指示器改变监听 (一般是为了配合数据操作使用,看情况自己发挥)
|setCurrentItem()|this|设置当前位置,和原生使用效果一样
|addBannerLifecycleObserver()|this|给banner添加生命周期观察者,内部自动管理banner的生命周期
## Attributes属性
>在banner布局文件中调用,如果你自定义了indicator请做好兼容处理。
下面的属性并不是每个指示器都用得到,所以使用时要注意!
|Attributes|format|describe
|---|---|---|
|banner_loop_time|integer|轮播间隔时间,默认3000
|banner_auto_loop|boolean|是否自动轮播,默认true
|banner_infinite_loop|boolean|是否支持无限循环(即首尾直接过渡),默认true
|banner_orientation|enum|轮播方向:horizontal(默认) or vertical
|banner_radius|dimension|banner圆角半径,默认0(不绘制圆角)
|banner_indicator_normal_width|dimension|指示器默认的宽度,默认5dp (对RoundLinesIndicator无效)
|banner_indicator_selected_width|dimension|指示器选中的宽度,默认7dp
|banner_indicator_normal_color|color|指示器默认颜色,默认0x88ffffff
|banner_indicator_selected_color|color|指示器选中颜色,默认0x88000000
|banner_indicator_space|dimension|指示器之间的间距,默认5dp (对RoundLinesIndicator无效)
|banner_indicator_gravity|dimension|指示器位置,默认center
|banner_indicator_margin|dimension|指示器的margin,默认5dp,不能和下面的同时使用
|banner_indicator_marginLeft|dimension|指示器左边的margin
|banner_indicator_marginTop|dimension|指示器上边的margin
|banner_indicator_marginRight|dimension|指示器右边的margin
|banner_indicator_marginBottom|dimension|指示器下边的margin
|banner_indicator_height|dimension|指示器高度(对CircleIndicator无效)
|banner_indicator_radius|dimension|指示器圆角(对CircleIndicator无效)
|banner_round_top_left|boolean|设置要绘制的banner圆角方向(如果都不设置默认全部)
|banner_round_top_right|boolean|设置要绘制的banner圆角方向(如果都不设置默认全部)
|banner_round_bottom_left|boolean|设置要绘制的banner圆角方向(如果都不设置默认全部)
|banner_round_bottom_right|boolean|设置要绘制的banner圆角方向(如果都不设置默认全部)
## 使用步骤
>以下提供的是最简单的步骤,需要复杂的样式自己可以自定义
#### Step 1.依赖banner
Gradle
```groovy
repositories {
maven { url "https://s01.oss.sonatype.org/content/groups/public" }
}
dependencies{
//2.1.0以前jcenter的依赖
//implementation 'com.youth.banner:banner:2.1.0'
//现在Maven Central
implementation 'io.github.youth5201314:banner:2.2.3'
}
```
#### Step 2.添加权限到你的 AndroidManifest.xml
```xml
<!-- if you want to load images from the internet -->
<uses-permission android:name="android.permission.INTERNET" />
```
#### Step 3.在布局文件中添加Banner,可以设置自定义属性
!!!此步骤可以省略,可以直接在Activity或者Fragment中new Banner();
```xml
<com.youth.banner.Banner
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="高度自己设置" />
```
#### Step 4.继承BannerAdapter,和RecyclerView的Adapter一样(如果你只是图片轮播也可以使用默认的)
!!!此步骤可以省略,图片轮播提供有默认适配器,其他的没有提供是因为大家的可变性要求不确定,所以直接自定义的比较好。
```java
/**
* 自定义布局,下面是常见的图片样式,更多实现可以看demo,可以自己随意发挥
*/
public class ImageAdapter extends BannerAdapter<DataBean, ImageAdapter.BannerViewHolder> {
public ImageAdapter(List<DataBean> mDatas) {
//设置数据,也可以调用banner提供的方法,或者自己在adapter中实现
super(mDatas);
}
//创建ViewHolder,可以用viewType这个字段来区分不同的ViewHolder
@Override
public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
//注意,必须设置为match_parent,这个是viewpager2强制要求的
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return new BannerViewHolder(imageView);
}
@Override
public void onBindView(BannerViewHolder holder, DataBean data, int position, int size) {
holder.imageView.setImageResource(data.imageRes);
}
class BannerViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public BannerViewHolder(@NonNull ImageView view) {
super(view);
this.imageView = view;
}
}
}
```
#### Step 5.Banner具体方法调用
```java
public class BannerActivity extends AppCompatActivity {
public void useBanner() {
//--------------------------简单使用-------------------------------
banner.addBannerLifecycleObserver(this)//添加生命周期观察者
.setAdapter(new BannerExampleAdapter(DataBean.getTestData()))
.setIndicator(new CircleIndicator(this));
//—————————————————————————如果你想偷懒,而又只是图片轮播————————————————————————
banner.setAdapter(new BannerImageAdapter<DataBean>(DataBean.getTestData3()) {
@Override
public void onBindView(BannerImageHolder holder, DataBean data, int position, int size) {
//图片加载自己实现
Glide.with(holder.itemView)
.load(data.imageUrl)
.apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))
.into(holder.imageView);
}
})
.addBannerLifecycleObserver(this)//添加生命周期观察者
.setIndicator(new CircleIndicator(this));
//更多使用方法仔细阅读文档,或者查看demo
}
}
```
## Banner使用中优化体验
**如果你需要考虑更好的体验,可以看看下面的代码**
#### Step 1.(可选)生命周期改变时
```java
public class BannerActivity {
//方法一:自己控制banner的生命周期
@Override
protected void onStart() {
super.onStart();
//开始轮播
banner.start();
}
@Override
protected void onStop() {
super.onStop();
//停止轮播
banner.stop();
}
@Override
protected void onDestroy() {
super.onDestroy();
//销毁
banner.destroy();
}
//方法二:调用banner的addBannerLifecycleObserver()方法,让banner自己控制
protected void onCreate(Bundle savedInstanceState) {
//添加生命周期观察者
banner.addBannerLifecycleObserver(this);
}
}
```
## 常见问题(收录被反复询问的问题)
* 网络图片加载不出来?
`banner本身不提供图片加载功能,首先确认banner本身使用是否正确,具体参考demo,
然后请检查你的图片加载框架或者网络请求框架,服务端也可能加了https安全认证,是看下是否报有证书相关错误`
* 怎么实现视频轮播?
`demo中有实现类似淘宝商品详情的效果,第一个放视频,后面的放的是图片,并且可以设置首尾不能滑动。
因为大家使用的播放器不一样业务环境也不同,具体情况自己把握,demo就是给一个思路哈!可以参考和修改`
* 我想指定轮播开始的位置?
`现在提供了setStartPosition()方法,在sheAdapter和setDatas直接调用一次就行了,当然setAdapter后通过setCurrentItem设置也行`
* 父控件滑动时,banner切换会获取焦点,然后自动全部显示。不想让banner获取焦点可以给父控件加上:
```
//banner也一定要用最新版哦!
android:focusable="true"
android:focusableInTouchMode="true"
```
* 怎么设置圆角?
1、调用提供的方法或者自定义属性进行设置,这里设置的是banner本身的圆角,不是轮播内view的圆角
2、在adapter中对自定义的view进行自己实现,就拿图片举例:可以自己定义一个圆角的ImageView控件,或者使用glide渲染都行。请举一反三,view都自定义了还有什么不能改的?
## Thanks
- [MZBannerView](https://github.com/pinguo-zhouwei/MZBannerView)
- [MagicViewPager](https://github.com/hongyangAndroid/MagicViewPager)
- [zguop的viewpager2的滑动时间解决方案](https://github.com/zguop/banner/blob/master/pager2banner/src/main/java/com/to/aboomy/pager2banner/Banner.java)
### 联系方式 <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>
* 我的个人微博:https://weibo.com/u/3013494003 有兴趣的也可以关注,大家一起交流
* 有问题可以加群大家一起交流,如果你觉得对你有帮助可以扫描下面支付宝二维码随意打赏下哦!
<img src="images/qq.png" width="220"/> <img src="images/pay.jpg" width="220"/>
## 更新说明
[更新说明](update_message.md)
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
android {
compileSdk 33
defaultConfig {
applicationId "com.test.banner"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"
consumerProguardFiles 'proguard-rules.pro'
}
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.2.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
implementation 'androidx.viewpager:viewpager:1.0.0'
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.2'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation 'com.google.android.material:material:1.2.0-alpha06'
implementation 'com.jakewharton:butterknife:10.2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
implementation 'com.shuyu:GSYVideoPlayer:7.1.3'
implementation project(':banner')
// implementation 'io.github.youth5201314:banner:2.2.1'
}
================================================
FILE: app/proguard-rules.pro
================================================
#指定代码的压缩级别
-optimizationpasses 5
#包明不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
#优化 不优化输入的类文件
-dontoptimize
#预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保护注解
-keepattributes *Annotation*
# 保持哪些类不被混淆
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
#butterknife
-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }
-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }
-keepclassmembers class * { @butterknife.* <methods>; }
-keepclassmembers class * { @butterknife.* <fields>; }
#gsyvideoplayer
-keep class com.shuyu.gsyvideoplayer.video.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.video.**
-keep class com.shuyu.gsyvideoplayer.video.base.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.video.base.**
-keep class com.shuyu.gsyvideoplayer.utils.** { *; }
-dontwarn com.shuyu.gsyvideoplayer.utils.**
-keep class tv.danmaku.ijk.** { *; }
-dontwarn tv.danmaku.ijk.**
-keep public class * extends android.view.View{
*** get*();
void set*(***);
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-dontwarn com.google.android.exoplayer.**
-keep class com.google.android.exoplayer.**{*;}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.banner">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".ui.GalleryActivity" />
<activity android:name=".ui.TouTiaoActivity" />
<activity android:name=".ui.TVActivity" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.RecyclerViewBannerActivity" />
<activity android:name=".ui.ConstraintLayoutBannerActivity" />
<activity android:name=".ui.VideoActivity" />
<activity
android:name=".ui.Vp2FragmentRecyclerviewActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
</application>
</manifest>
================================================
FILE: app/src/main/java/com/test/banner/MainActivity.java
================================================
package com.test.banner;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.material.snackbar.Snackbar;
import com.test.banner.adapter.ImageAdapter;
import com.test.banner.adapter.ImageTitleAdapter;
import com.test.banner.adapter.ImageTitleNumAdapter;
import com.test.banner.adapter.MultipleTypesAdapter;
import com.test.banner.bean.DataBean;
import com.youth.banner.indicator.DrawableIndicator;
import com.test.banner.ui.ConstraintLayoutBannerActivity;
import com.test.banner.ui.GalleryActivity;
import com.test.banner.ui.RecyclerViewBannerActivity;
import com.test.banner.ui.TVActivity;
import com.test.banner.ui.TouTiaoActivity;
import com.test.banner.ui.VideoActivity;
import com.test.banner.ui.Vp2FragmentRecyclerviewActivity;
import com.youth.banner.Banner;
import com.youth.banner.adapter.BannerImageAdapter;
import com.youth.banner.holder.BannerImageHolder;
import com.youth.banner.config.BannerConfig;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.indicator.CircleIndicator;
import com.youth.banner.indicator.RoundLinesIndicator;
import com.youth.banner.listener.OnPageChangeListener;
import com.youth.banner.util.BannerUtils;
import com.youth.banner.util.LogUtils;
import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.banner)
Banner banner;
@BindView(R.id.indicator)
RoundLinesIndicator indicator;
@BindView(R.id.swipeRefresh)
SwipeRefreshLayout refresh;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
List<DataBean> datas = DataBean.getTestData2();
//自定义的图片适配器,也可以使用默认的BannerImageAdapter
ImageAdapter adapter = new ImageAdapter(datas);
banner.setAdapter(adapter)
// .setCurrentItem(0,false)
//添加生命周期观察者
.addBannerLifecycleObserver(this)
//设置指示器
.setIndicator(new CircleIndicator(this))
.setOnBannerListener((data, position) -> {
Snackbar.make(banner, ((DataBean) data).title, Snackbar.LENGTH_SHORT).show();
LogUtils.d("position:" + position);
});
//添加item之间切换时的间距(如果使用了画廊效果就不要添加间距了,因为内部已经添加过了)
// banner.addPageTransformer(new MarginPageTransformer( BannerUtils.dp2px(10)));
//和下拉刷新配套使用
refresh.setOnRefreshListener(() -> {
//模拟网络请求需要3秒,请求完成,设置setRefreshing 为false
new Handler().postDelayed(() -> {
refresh.setRefreshing(false);
//给banner重新设置数据(完全覆盖)
banner.setDatas(DataBean.getTestData());
//模拟请求成功(原数据减少) 刷新banner
// datas.remove(0);
// adapter.notifyDataSetChanged();
//对setDatas()方法不满意?你可以自己在adapter控制数据,参考setDatas()的实现修改
// adapter.updateData(DataBean.getTestData());
// banner.setCurrentItem(banner.getStartPosition(), false);
// banner.setIndicatorPageChange();
}, 2000);
});
}
@OnClick({R.id.style_image, R.id.style_image_title, R.id.style_image_title_num, R.id.style_multiple,
R.id.style_net_image, R.id.change_indicator, R.id.rv_banner, R.id.cl_banner, R.id.vp_banner,
R.id.banner_video, R.id.banner_tv, R.id.gallery, R.id.topLine})
public void click(View view) {
indicator.setVisibility(View.GONE);
switch (view.getId()) {
case R.id.style_image:
refresh.setEnabled(true);
banner.setAdapter(new ImageAdapter(DataBean.getTestData()));
banner.setIndicator(new CircleIndicator(this));
banner.setIndicatorGravity(IndicatorConfig.Direction.CENTER);
break;
case R.id.style_image_title:
refresh.setEnabled(true);
banner.setAdapter(new ImageTitleAdapter(DataBean.getTestData()));
banner.setIndicator(new CircleIndicator(this));
banner.setIndicatorGravity(IndicatorConfig.Direction.RIGHT);
banner.setIndicatorMargins(new IndicatorConfig.Margins(0, 0,
BannerConfig.INDICATOR_MARGIN, BannerUtils.dp2px(12)));
break;
case R.id.style_image_title_num:
refresh.setEnabled(true);
//这里是将数字指示器和title都放在adapter中的,如果不想这样你也可以直接设置自定义的数字指示器
banner.setAdapter(new ImageTitleNumAdapter(DataBean.getTestData()));
banner.removeIndicator();
break;
case R.id.style_multiple:
refresh.setEnabled(true);
banner.setIndicator(new CircleIndicator(this));
banner.setAdapter(new MultipleTypesAdapter(this, DataBean.getTestData()));
break;
case R.id.style_net_image:
refresh.setEnabled(false);
//方法一:使用自定义图片适配器
// banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));
//方法二:使用自带的图片适配器
banner.setAdapter(new BannerImageAdapter<DataBean>(DataBean.getTestData3()) {
@Override
public void onBindView(BannerImageHolder holder, DataBean data, int position, int size) {
//图片加载自己实现
Glide.with(holder.itemView)
.load(data.imageUrl)
.thumbnail(Glide.with(holder.itemView).load(R.drawable.loading))
.apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))
.into(holder.imageView);
}
});
banner.setIndicator(new RoundLinesIndicator(this));
banner.setIndicatorSelectedWidth(BannerUtils.dp2px(15));
break;
case R.id.change_indicator:
indicator.setVisibility(View.VISIBLE);
//在布局文件中使用指示器,这样更灵活
banner.setIndicator(indicator, false);
banner.setIndicatorSelectedWidth(BannerUtils.dp2px(15));
break;
case R.id.gallery:
startActivity(new Intent(this, GalleryActivity.class));
break;
case R.id.rv_banner:
startActivity(new Intent(this, RecyclerViewBannerActivity.class));
break;
case R.id.cl_banner:
startActivity(new Intent(this, ConstraintLayoutBannerActivity.class));
break;
case R.id.vp_banner:
startActivity(new Intent(this, Vp2FragmentRecyclerviewActivity.class));
break;
case R.id.banner_video:
startActivity(new Intent(this, VideoActivity.class));
break;
case R.id.banner_tv:
startActivity(new Intent(this, TVActivity.class));
break;
case R.id.topLine:
startActivity(new Intent(this, TouTiaoActivity.class));
break;
default:
throw new IllegalStateException("Unexpected value: " + view.getId());
}
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/ImageAdapter.java
================================================
package com.test.banner.adapter;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.test.banner.bean.DataBean;
import com.test.banner.viewholder.ImageHolder;
import com.youth.banner.adapter.BannerAdapter;
import java.util.List;
/**
* 自定义布局,图片
*/
public class ImageAdapter extends BannerAdapter<DataBean, ImageHolder> {
public ImageAdapter(List<DataBean> mDatas) {
//设置数据,也可以调用banner提供的方法,或者自己在adapter中实现
super(mDatas);
}
//更新数据
public void updateData(List<DataBean> data) {
//这里的代码自己发挥,比如如下的写法等等
mDatas.clear();
mDatas.addAll(data);
notifyDataSetChanged();
}
//创建ViewHolder,可以用viewType这个字段来区分不同的ViewHolder
@Override
public ImageHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
//注意,必须设置为match_parent,这个是viewpager2强制要求的
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return new ImageHolder(imageView);
}
@Override
public void onBindView(ImageHolder holder, DataBean data, int position, int size) {
holder.imageView.setImageResource(data.imageRes);
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/ImageNetAdapter.java
================================================
package com.test.banner.adapter;
import android.graphics.Bitmap;
import android.graphics.Outline;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.test.banner.R;
import com.test.banner.bean.DataBean;
import com.test.banner.viewholder.ImageHolder;
import com.youth.banner.adapter.BannerAdapter;
import com.youth.banner.util.BannerUtils;
import java.util.List;
/**
* 自定义布局,网络图片
*/
public class ImageNetAdapter extends BannerAdapter<DataBean, ImageHolder> {
public ImageNetAdapter(List<DataBean> mDatas) {
super(mDatas);
}
@Override
public ImageHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = (ImageView) BannerUtils.getView(parent, R.layout.banner_image);
//通过裁剪实现圆角
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BannerUtils.setBannerRound(imageView, 20);
}
return new ImageHolder(imageView);
}
@Override
public void onBindView(ImageHolder holder, DataBean data, int position, int size) {
//通过图片加载器实现圆角,你也可以自己使用圆角的imageview,实现圆角的方法很多,自己尝试哈
Glide.with(holder.itemView)
.load(data.imageUrl)
.thumbnail(Glide.with(holder.itemView).load(R.drawable.loading))
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
// .apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))
.into(holder.imageView);
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/ImageTitleAdapter.java
================================================
package com.test.banner.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.test.banner.bean.DataBean;
import com.test.banner.R;
import com.test.banner.viewholder.ImageTitleHolder;
import com.youth.banner.adapter.BannerAdapter;
import com.youth.banner.util.BannerUtils;
import java.util.List;
/**
* 自定义布局,图片+标题
*/
public class ImageTitleAdapter extends BannerAdapter<DataBean, ImageTitleHolder> {
public ImageTitleAdapter(List<DataBean> mDatas) {
super(mDatas);
}
@Override
public ImageTitleHolder onCreateHolder(ViewGroup parent, int viewType) {
return new ImageTitleHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.banner_image_title, parent, false));
}
@Override
public void onBindView(ImageTitleHolder holder, DataBean data, int position, int size) {
holder.imageView.setImageResource(data.imageRes);
holder.title.setText(data.title);
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/ImageTitleNumAdapter.java
================================================
package com.test.banner.adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.bean.DataBean;
import com.test.banner.R;
import com.youth.banner.adapter.BannerAdapter;
import java.util.List;
/**
* 自定义布局,图片+标题+数字指示器
*/
public class ImageTitleNumAdapter extends BannerAdapter<DataBean, ImageTitleNumAdapter.BannerViewHolder> {
public ImageTitleNumAdapter(List<DataBean> mDatas) {
//设置数据,也可以调用banner提供的方法
super(mDatas);
}
//创建ViewHolder,可以用viewType这个字段来区分不同的ViewHolder
@Override
public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {
//注意布局文件,item布局文件要设置为match_parent,这个是viewpager2强制要求的
//或者调用BannerUtils.getView(parent,R.layout.banner_image_title_num);
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.banner_image_title_num, parent, false);
return new BannerViewHolder(view);
}
//绑定数据
@Override
public void onBindView(BannerViewHolder holder, DataBean data, int position, int size) {
holder.imageView.setImageResource(data.imageRes);
holder.title.setText(data.title);
//可以在布局文件中自己实现指示器,亦可以使用banner提供的方法自定义指示器,目前样式较少,后面补充
holder.numIndicator.setText((position + 1) + "/" + size);
}
class BannerViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView title;
TextView numIndicator;
public BannerViewHolder(@NonNull View view) {
super(view);
imageView = view.findViewById(R.id.image);
title = view.findViewById(R.id.bannerTitle);
numIndicator = view.findViewById(R.id.numIndicator);
}
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/MultipleTypesAdapter.java
================================================
package com.test.banner.adapter;
import android.content.Context;
import android.graphics.Color;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
import com.test.banner.bean.DataBean;
import com.test.banner.viewholder.ImageHolder;
import com.test.banner.viewholder.TitleHolder;
import com.test.banner.viewholder.VideoHolder;
import com.youth.banner.adapter.BannerAdapter;
import com.youth.banner.util.BannerUtils;
import java.util.List;
/**
* 自定义布局,多个不同UI切换
*/
public class MultipleTypesAdapter extends BannerAdapter<DataBean, RecyclerView.ViewHolder> {
private Context context;
private SparseArray<RecyclerView.ViewHolder> mVHMap = new SparseArray<>();
public MultipleTypesAdapter(Context context, List<DataBean> mDatas) {
super(mDatas);
this.context = context;
}
@Override
public RecyclerView.ViewHolder onCreateHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 1:
return new ImageHolder(BannerUtils.getView(parent, R.layout.banner_image));
case 2:
return new VideoHolder(BannerUtils.getView(parent, R.layout.banner_video));
case 3:
return new TitleHolder(BannerUtils.getView(parent, R.layout.banner_title));
}
return new ImageHolder(BannerUtils.getView(parent, R.layout.banner_image));
}
@Override
public int getItemViewType(int position) {
//先取得真实的position,在获取实体
// return getData(getRealPosition(position)).viewType;
//直接获取真实的实体
return getRealData(position).viewType;
//或者自己直接去操作集合
// return mDatas.get(getRealPosition(position)).viewType;
}
@Override
public void onBindView(RecyclerView.ViewHolder holder, DataBean data, int position, int size) {
int viewType = holder.getItemViewType();
switch (viewType) {
case 1:
ImageHolder imageHolder = (ImageHolder) holder;
mVHMap.append(position,imageHolder);
imageHolder.imageView.setImageResource(data.imageRes);
break;
case 2:
VideoHolder videoHolder = (VideoHolder) holder;
mVHMap.append(position,videoHolder);
videoHolder.player.setUp(data.imageUrl, true, null);
videoHolder.player.getBackButton().setVisibility(View.GONE);
//增加封面
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(R.drawable.image4);
videoHolder.player.setThumbImageView(imageView);
// videoHolder.player.startPlayLogic();
break;
case 3:
TitleHolder titleHolder = (TitleHolder) holder;
mVHMap.append(position,titleHolder);
titleHolder.title.setText(data.title);
titleHolder.title.setBackgroundColor(Color.parseColor(DataBean.getRandColor()));
break;
}
}
public SparseArray<RecyclerView.ViewHolder> getVHMap() {
return mVHMap;
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/MyRecyclerViewAdapter.java
================================================
package com.test.banner.adapter;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
import com.test.banner.bean.DataBean;
import com.youth.banner.Banner;
import com.youth.banner.indicator.RoundLinesIndicator;
import com.youth.banner.util.BannerUtils;
public class MyRecyclerViewAdapter extends RecyclerView.Adapter {
private Context context;
public MyRecyclerViewAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType==R.layout.item) {
return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
}else{
return new MyBannerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.banner, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MyViewHolder) {
((MyViewHolder) holder).cardView.setBackgroundColor(Color.parseColor(DataBean.getRandColor()));
}else if (holder instanceof MyBannerViewHolder){
Banner banner=((MyBannerViewHolder) holder).banner;
banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));
banner.setBannerRound(BannerUtils.dp2px(5));
banner.setIndicator(new RoundLinesIndicator(context));
banner.setIndicatorSelectedWidth((int) BannerUtils.dp2px(15));
}
}
@Override
public int getItemViewType(int position) {
if (position%2==0){
return R.layout.item;
}else{
return R.layout.banner;
}
}
@Override
public int getItemCount() {
return 10;
}
//banner 内部已实现
// @Override
// public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {
// super.onViewDetachedFromWindow(holder);
// Log.e("banner_log", "onViewDetachedFromWindow:" + holder.getAdapterPosition());
// //定位你的位置
// if (holder.getAdapterPosition()%2!=0) {
// if (holder instanceof MyBannerViewHolder) {
// ((MyBannerViewHolder) holder).banner.stop();
// }
// }
// }
//
// @Override
// public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
// super.onViewAttachedToWindow(holder);
// Log.e("banner_log", "onViewAttachedToWindow:" + holder.getAdapterPosition());
// if (holder.getAdapterPosition()%2!=0) {
// if (holder instanceof MyBannerViewHolder) {
// ((MyBannerViewHolder) holder).banner.start();
// }
// }
// }
class MyViewHolder extends RecyclerView.ViewHolder {
public CardView cardView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.card_view);
}
}
class MyBannerViewHolder extends RecyclerView.ViewHolder {
public Banner banner;
public MyBannerViewHolder(@NonNull View itemView) {
super(itemView);
banner = itemView.findViewById(R.id.banner);
}
}
}
================================================
FILE: app/src/main/java/com/test/banner/adapter/TopLineAdapter.java
================================================
package com.test.banner.adapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.bean.DataBean;
import com.test.banner.R;
import com.youth.banner.adapter.BannerAdapter;
import com.youth.banner.util.BannerUtils;
import java.util.List;
/**
* 自定义布局,实现类似1号店、淘宝头条的滚动效果
*/
public class TopLineAdapter extends BannerAdapter<DataBean, TopLineAdapter.TopLineHolder> {
public TopLineAdapter(List<DataBean> mDatas) {
super(mDatas);
}
@Override
public TopLineHolder onCreateHolder(ViewGroup parent, int viewType) {
return new TopLineHolder(BannerUtils.getView(parent,R.layout.top_line_item2));
}
@Override
public void onBindView(TopLineHolder holder, DataBean data, int position, int size) {
holder.message.setText(data.title);
if (data.viewType==1) {
holder.source.setText("1号店");
}else if (data.viewType==2) {
holder.source.setText("淘宝头条");
}else if (data.viewType==3) {
holder.source.setText("京东快报");
}
}
class TopLineHolder extends RecyclerView.ViewHolder {
public TextView message;
public TextView source;
public TopLineHolder(@NonNull View view) {
super(view);
message=view.findViewById(R.id.message);
source=view.findViewById(R.id.source);
}
}
}
================================================
FILE: app/src/main/java/com/test/banner/bean/DataBean.java
================================================
package com.test.banner.bean;
import com.test.banner.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class DataBean {
public Integer imageRes;
public String imageUrl;
public String title;
public int viewType;
public DataBean(Integer imageRes, String title, int viewType) {
this.imageRes = imageRes;
this.title = title;
this.viewType = viewType;
}
public DataBean(String imageUrl, String title, int viewType) {
this.imageUrl = imageUrl;
this.title = title;
this.viewType = viewType;
}
public static List<DataBean> getTestData() {
List<DataBean> list = new ArrayList<>();
list.add(new DataBean(R.drawable.image1, "相信自己,你努力的样子真的很美", 1));
list.add(new DataBean(R.drawable.image2, "极致简约,梦幻小屋", 3));
list.add(new DataBean(R.drawable.image3, "超级卖梦人", 3));
list.add(new DataBean(R.drawable.image4, "夏季新搭配", 1));
list.add(new DataBean(R.drawable.image5, "绝美风格搭配", 1));
list.add(new DataBean(R.drawable.image6, "微微一笑 很倾城", 3));
return list;
}
public static List<DataBean> getTestData2() {
List<DataBean> list = new ArrayList<>();
list.add(new DataBean(R.drawable.image7, "听风.赏雨", 3));
list.add(new DataBean(R.drawable.image8, "迪丽热巴.迪力木拉提", 1));
list.add(new DataBean(R.drawable.image9, "爱美.人间有之", 3));
list.add(new DataBean(R.drawable.image10, "洋洋洋.气质篇", 1));
list.add(new DataBean(R.drawable.image11, "生活的态度", 3));
return list;
}
/**
* 仿淘宝商品详情第一个是视频
* @return
*/
public static List<DataBean> getTestDataVideo() {
List<DataBean> list = new ArrayList<>();
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/09/mp4/190309153658147087.mp4", "第一个放视频", 2));
list.add(new DataBean(R.drawable.image7, "听风.赏雨", 1));
list.add(new DataBean(R.drawable.image8, "迪丽热巴.迪力木拉提", 1));
list.add(new DataBean(R.drawable.image9, "爱美.人间有之", 1));
list.add(new DataBean(R.drawable.image10, "洋洋洋.气质篇", 1));
list.add(new DataBean(R.drawable.image11, "生活的态度", 1));
return list;
}
public static List<DataBean> getTestData3() {
List<DataBean> list = new ArrayList<>();
list.add(new DataBean("https://img.zcool.cn/community/013de756fb63036ac7257948747896.jpg", null, 1));
list.add(new DataBean("https://img.zcool.cn/community/01639a56fb62ff6ac725794891960d.jpg", null, 1));
list.add(new DataBean("https://img.zcool.cn/community/01270156fb62fd6ac72579485aa893.jpg", null, 1));
list.add(new DataBean("https://img.zcool.cn/community/01233056fb62fe32f875a9447400e1.jpg", null, 1));
list.add(new DataBean("https://img.zcool.cn/community/016a2256fb63006ac7257948f83349.jpg", null, 1));
return list;
}
public static List<DataBean> getVideos() {
List<DataBean> list = new ArrayList<>();
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4", null, 0));
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/18/mp4/190318231014076505.mp4", null, 0));
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/18/mp4/190318214226685784.mp4", null, 0));
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/19/mp4/190319125415785691.mp4", null, 0));
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/14/mp4/190314223540373995.mp4", null, 0));
list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/14/mp4/190314102306987969.mp4", null, 0));
return list;
}
public static List<String> getColors(int size) {
List<String> list = new ArrayList<>();
for(int i = 0; i < size; i++) {
list.add(getRandColor());
}
return list;
}
/**
* 获取十六进制的颜色代码.例如 "#5A6677"
* 分别取R、G、B的随机值,然后加起来即可
*
* @return String
*/
public static String getRandColor() {
String R, G, B;
Random random = new Random();
R = Integer.toHexString(random.nextInt(256)).toUpperCase();
G = Integer.toHexString(random.nextInt(256)).toUpperCase();
B = Integer.toHexString(random.nextInt(256)).toUpperCase();
R = R.length() == 1 ? "0" + R : R;
G = G.length() == 1 ? "0" + G : G;
B = B.length() == 1 ? "0" + B : B;
return "#" + R + G + B;
}
}
================================================
FILE: app/src/main/java/com/test/banner/indicator/NumIndicator.java
================================================
package com.test.banner.indicator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import com.youth.banner.indicator.BaseIndicator;
import com.youth.banner.util.BannerUtils;
/**
* 自定义数字指示器demo,比较简单,具体的自己发挥
*
* 这里没有用的自定义属性的参数,可以考虑加上
*/
public class NumIndicator extends BaseIndicator {
private int width;
private int height;
private int radius;
public NumIndicator(Context context) {
this(context, null);
}
public NumIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NumIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint.setTextSize(BannerUtils.dp2px(10));
mPaint.setTextAlign(Paint.Align.CENTER);
width = (int) BannerUtils.dp2px(30);
height = (int) BannerUtils.dp2px(15);
radius = (int) BannerUtils.dp2px(20);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
RectF rectF = new RectF(0, 0, width, height);
mPaint.setColor(Color.parseColor("#70000000"));
canvas.drawRoundRect(rectF, radius, radius, mPaint);
String text = config.getCurrentPosition() + 1 + "/" + count;
mPaint.setColor(Color.WHITE);
canvas.drawText(text, width / 2, (float) (height * 0.7), mPaint);
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/BannerFragment.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.test.banner.R;
import com.test.banner.adapter.ImageNetAdapter;
import com.test.banner.bean.DataBean;
import com.youth.banner.Banner;
import com.youth.banner.indicator.RectangleIndicator;
import com.youth.banner.util.BannerUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
public class BannerFragment extends Fragment {
@BindView(R.id.banner)
Banner banner;
public static Fragment newInstance() {
return new BannerFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.banner, container, false);
ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));
banner.setIndicator(new RectangleIndicator(getActivity()));
banner.setIndicatorSpace((int) BannerUtils.dp2px(4));
banner.setIndicatorRadius(0);
}
@Override
public void onStart() {
super.onStart();
banner.start();
}
@Override
public void onStop() {
super.onStop();
banner.stop();
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/BannerListFragment.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
import com.test.banner.adapter.MyRecyclerViewAdapter;
import com.test.banner.util.ParentRecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
public class BannerListFragment extends Fragment {
private static int index;
@BindView(R.id.net_rv)
RecyclerView recyclerView;
@BindView(R.id.text)
TextView text;
public static Fragment newInstance(int i) {
index = i;
return new BannerListFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_recyclerview_banner, container, false);
ButterKnife.bind(this,view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
text.setText("当前页:"+index);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(new MyRecyclerViewAdapter(getActivity()));
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/BlankFragment.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
import com.test.banner.adapter.ImageNetAdapter;
import com.test.banner.adapter.MyRecyclerViewAdapter;
import com.test.banner.bean.DataBean;
import com.test.banner.indicator.NumIndicator;
import com.youth.banner.Banner;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.indicator.CircleIndicator;
import com.youth.banner.util.BannerUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
public class BlankFragment extends Fragment {
public static Fragment newInstance() {
return new BlankFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.test,null);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LinearLayout linearLayout = getView().findViewById(R.id.ll_view);
//通过new的方式创建banner
Banner banner = new Banner(getActivity());
banner.setAdapter(new ImageNetAdapter(DataBean.getTestData3()));
banner.addBannerLifecycleObserver(this);
banner.setIndicator(new CircleIndicator(getActivity()));
//将banner加入到父容器中,实际使用不一定一样
linearLayout.addView(banner, LinearLayout.LayoutParams.MATCH_PARENT, (int) BannerUtils.dp2px(120));
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/ConstraintLayoutBannerActivity.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import androidx.appcompat.app.AppCompatActivity;
import com.test.banner.R;
import com.test.banner.adapter.ImageAdapter;
import com.test.banner.adapter.ImageNetAdapter;
import com.test.banner.adapter.ImageTitleAdapter;
import com.test.banner.bean.DataBean;
import com.youth.banner.Banner;
import com.youth.banner.config.BannerConfig;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.indicator.CircleIndicator;
import com.youth.banner.util.BannerUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ConstraintLayoutBannerActivity extends AppCompatActivity {
private static final String TAG = "banner_log";
@BindView(R.id.banner)
Banner banner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_constraint_layout_banner);
ButterKnife.bind(this);
banner.setAdapter(new ImageTitleAdapter(DataBean.getTestData()));
banner.setIndicator(new CircleIndicator(this));
banner.setIndicatorSelectedColorRes(R.color.main_color);
banner.setIndicatorGravity(IndicatorConfig.Direction.RIGHT);
banner.setIndicatorMargins(new IndicatorConfig.Margins(0, 0,
BannerConfig.INDICATOR_MARGIN, (int) BannerUtils.dp2px(12)));
banner.addBannerLifecycleObserver(this);
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/GalleryActivity.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.view.View;
import com.test.banner.R;
import com.test.banner.adapter.ImageAdapter;
import com.test.banner.adapter.ImageNetAdapter;
import com.test.banner.bean.DataBean;
import com.youth.banner.Banner;
import com.youth.banner.indicator.CircleIndicator;
import com.youth.banner.indicator.DrawableIndicator;
import com.youth.banner.transformer.AlphaPageTransformer;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class GalleryActivity extends AppCompatActivity {
@BindView(R.id.banner1)
Banner mBanner1;
@BindView(R.id.banner2)
Banner mBanner2;
@BindView(R.id.indicator)
DrawableIndicator indicator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery);
ButterKnife.bind(this);
/**
* 画廊效果
*/
mBanner1.setAdapter(new ImageAdapter(DataBean.getTestData2()));
mBanner1.setIndicator(new CircleIndicator(this));
//添加画廊效果
mBanner1.setBannerGalleryEffect(50, 10);
//(可以和其他PageTransformer组合使用,比如AlphaPageTransformer,注意但和其他带有缩放的PageTransformer会显示冲突)
//添加透明效果(画廊配合透明效果更棒)
//mBanner1.addPageTransformer(new AlphaPageTransformer());
/**
* 魅族效果
*/
mBanner2.setAdapter(new ImageAdapter(DataBean.getTestData()));
mBanner2.setIndicator(indicator,false);
//添加魅族效果
mBanner2.setBannerGalleryMZ(20);
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/RecyclerViewBannerActivity.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
import com.test.banner.adapter.MyRecyclerViewAdapter;
import butterknife.BindView;
import butterknife.ButterKnife;
public class RecyclerViewBannerActivity extends AppCompatActivity {
@BindView(R.id.net_rv)
RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview_banner);
ButterKnife.bind(this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new MyRecyclerViewAdapter(this));
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/TVActivity.java
================================================
package com.test.banner.ui;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import com.test.banner.R;
import com.test.banner.adapter.ImageAdapter;
import com.test.banner.bean.DataBean;
import com.youth.banner.Banner;
import com.youth.banner.indicator.CircleIndicator;
import com.youth.banner.util.BannerUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
public class TVActivity extends AppCompatActivity {
private static final String TAG = "banner_log";
@BindView(R.id.banner)
Banner banner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_t_v);
ButterKnife.bind(this);
banner.setAdapter(new ImageAdapter(DataBean.getTestData()));
banner.setIndicator(new CircleIndicator(this));
banner.isAutoLoop(false);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
int count = banner.getItemCount();
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
Log.d(TAG, "向左");
int prev = (banner.getCurrentItem() - 1) % count;
if (prev == 0) {
prev = banner.getRealCount();
} else if (prev == count - 1) {
prev = 1;
}
banner.setCurrentItem(prev, false);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
Log.d(TAG, "向右");
int next = (banner.getCurrentItem() + 1) % count;
if (next == 0) {
next = banner.getRealCount();
} else if (next == count - 1) {
next = 1;
}
banner.setCurrentItem(next, false);
break;
}
//如果没有设置指示器,就不用执行下面两行
int real = BannerUtils.getRealPosition(banner.isInfiniteLoop(), banner.getCurrentItem(), banner.getRealCount());
banner.getIndicator().onPageSelected(real);
return super.onKeyDown(keyCode, event);
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/TouTiaoActivity.java
================================================
package com.test.banner.ui;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import com.test.banner.R;
import com.test.banner.adapter.TopLineAdapter;
import com.test.banner.bean.DataBean;
import com.youth.banner.Banner;
import com.youth.banner.transformer.ZoomOutPageTransformer;
import com.youth.banner.util.LogUtils;
public class TouTiaoActivity extends AppCompatActivity {
@BindView(R.id.banner)
Banner banner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tou_tiao);
ButterKnife.bind(this);
//实现1号店和淘宝头条类似的效果
banner.setAdapter(new TopLineAdapter(DataBean.getTestData2()))
.setOrientation(Banner.VERTICAL)
.setPageTransformer(new ZoomOutPageTransformer())
.setOnBannerListener((data, position) -> {
Snackbar.make(banner, ((DataBean) data).title, Snackbar.LENGTH_SHORT).show();
LogUtils.d("position:" + position);
});
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/VideoActivity.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import android.util.Log;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.test.banner.R;
import com.test.banner.adapter.MultipleTypesAdapter;
import com.test.banner.bean.DataBean;
import com.test.banner.indicator.NumIndicator;
import com.test.banner.viewholder.VideoHolder;
import com.youth.banner.Banner;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.listener.OnPageChangeListener;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* 仿淘宝商品详情,banner第一个放视频,然后首尾不能自己滑动,加上自定义数字指示器
*/
public class VideoActivity extends AppCompatActivity {
@BindView(R.id.banner)
Banner banner;
StandardGSYVideoPlayer player;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
ButterKnife.bind(this);
banner.addBannerLifecycleObserver(this)
.setAdapter(new MultipleTypesAdapter(this, DataBean.getTestDataVideo()))
.setIndicator(new NumIndicator(this))
.setIndicatorGravity(IndicatorConfig.Direction.RIGHT)
.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
stopVideo(position);
}
@Override
public void onPageSelected(int position) {
Log.e("--","position:"+position);
stopVideo(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void stopVideo(int position) {
if (player == null) {
RecyclerView.ViewHolder viewHolder = banner.getAdapter().getViewHolder();
if (viewHolder instanceof VideoHolder) {
VideoHolder holder = (VideoHolder) viewHolder;
player = holder.player;
if (position != 0) {
player.onVideoPause();
}
}
}else {
if (position != 0) {
player.onVideoPause();
}
}
}
@Override
protected void onPause() {
super.onPause();
if (player != null)
player.onVideoPause();
}
@Override
protected void onResume() {
super.onResume();
if (player != null)
player.onVideoResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
GSYVideoManager.releaseAllVideos();
}
@Override
public void onBackPressed() {
//释放所有
if (player != null)
player.setVideoAllCallBack(null);
super.onBackPressed();
}
}
================================================
FILE: app/src/main/java/com/test/banner/ui/Vp2FragmentRecyclerviewActivity.java
================================================
package com.test.banner.ui;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import com.test.banner.R;
import com.test.banner.adapter.ImageAdapter;
import com.test.banner.bean.DataBean;
import com.test.banner.util.TabLayoutMediator;
import com.youth.banner.Banner;
import com.youth.banner.indicator.CircleIndicator;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import butterknife.BindView;
import butterknife.ButterKnife;
public class Vp2FragmentRecyclerviewActivity extends AppCompatActivity {
@BindView(R.id.vp2)
ViewPager2 viewPager2;
@BindView(R.id.tab_layout)
TabLayout mTabLayout;
@BindView(R.id.banner)
Banner mBanner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vp2_fragment_recyclerview);
ButterKnife.bind(this);
viewPager2.setAdapter(new FragmentStateAdapter(this) {
@NonNull
@Override
public Fragment createFragment(int position) {
if (position == 0) {
return BannerListFragment.newInstance(position);
} else if (position == 1) {
return BlankFragment.newInstance();
} else {
return BannerFragment.newInstance();
}
}
@Override
public int getItemCount() {
return 3;
}
});
new TabLayoutMediator(mTabLayout, viewPager2, (tab, position) -> {
tab.setText("页面" + position);
}).attach();
mBanner.addBannerLifecycleObserver(this)
.setAdapter(new ImageAdapter(DataBean.getTestData()))
.setIntercept(false)
.setIndicator(new CircleIndicator(this));
}
}
================================================
FILE: app/src/main/java/com/test/banner/util/ParentRecyclerView.java
================================================
package com.test.banner.util;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
public class ParentRecyclerView extends RecyclerView {
public ParentRecyclerView(@NonNull Context context) {
super(context);
}
public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private float mStartX, mStartY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = ev.getX();
mStartY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float endX = ev.getX();
float endY = ev.getY();
float distanceX = Math.abs(endX - mStartX);
float distanceY = Math.abs(endY - mStartY);
getParent().requestDisallowInterceptTouchEvent(!(distanceX > 4 && distanceX > distanceY));
break;
}
return super.dispatchTouchEvent(ev);
}
}
================================================
FILE: app/src/main/java/com/test/banner/util/TabLayoutMediator.java
================================================
package com.test.banner.util;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_DRAGGING;
import static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_IDLE;
import static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_SETTLING;
/**
* A mediator to link a TabLayout with a ViewPager2. The mediator will synchronize the ViewPager2's
* position with the selected tab when a tab is selected, and the TabLayout's scroll position when
* the user drags the ViewPager2.
*
* Establish the link by creating an instance of this class, make sure the ViewPager2 has an adapter
* and then call {@link #attach()} on it. When creating an instance of this class, you must supply
* an implementation of {@link OnConfigureTabCallback} in which you set the text of the tab, and/or
* perform any styling of the tabs that you require.
*
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final class TabLayoutMediator {
private final @NonNull TabLayout mTabLayout;
private final @NonNull ViewPager2 mViewPager;
private final boolean mAutoRefresh;
private final OnConfigureTabCallback mOnConfigureTabCallback;
private RecyclerView.Adapter mAdapter;
private boolean mAttached;
private TabLayoutOnPageChangeCallback mOnPageChangeCallback;
private TabLayout.OnTabSelectedListener mOnTabSelectedListener;
private RecyclerView.AdapterDataObserver mPagerAdapterObserver;
/**
* A callback interface that must be implemented to set the text and styling of newly created
* tabs.
*/
public interface OnConfigureTabCallback {
/**
* Called to configure the tab for the page at the specified position. Typically calls
* {@link TabLayout.Tab#setText(CharSequence)}, but any form of styling can be applied.
*
* @param tab The Tab which should be configured to represent the title of the item at the
* given position in the data set.
* @param position The position of the item within the adapter's data set.
*/
void onConfigureTab(@NonNull TabLayout.Tab tab, int position);
}
/**
* Creates a TabLayoutMediator to synchronize a TabLayout and a ViewPager2 together. It will
* update the tabs automatically when the data set of the view pager's adapter changes. The link
* will be established after {@link #attach()} is called.
*
* @param tabLayout The tab bar to link
* @param viewPager The view pager to link
*/
public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager,
@NonNull OnConfigureTabCallback onConfigureTabCallback) {
this(tabLayout, viewPager, true, onConfigureTabCallback);
}
/**
* Creates a TabLayoutMediator to synchronize a TabLayout and a ViewPager2 together. If {@code
* autoRefresh} is true, it will update the tabs automatically when the data set of the view
* pager's adapter changes. The link will be established after {@link #attach()} is called.
*
* @param tabLayout The tab bar to link
* @param viewPager The view pager to link
* @param autoRefresh If {@code true}, will recreate all tabs when the data set of the view
* pager's adapter changes.
*/
public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager,
boolean autoRefresh, @NonNull OnConfigureTabCallback onConfigureTabCallback) {
mTabLayout = tabLayout;
mViewPager = viewPager;
mAutoRefresh = autoRefresh;
mOnConfigureTabCallback = onConfigureTabCallback;
}
/**
* Link the TabLayout and the ViewPager2 together.
* @throws IllegalStateException If the mediator is already attached, or the ViewPager2 has no
* adapter.
*/
public void attach() {
if (mAttached) {
throw new IllegalStateException("TabLayoutMediator is already attached");
}
mAdapter = mViewPager.getAdapter();
if (mAdapter == null) {
throw new IllegalStateException("TabLayoutMediator attached before ViewPager2 has an "
+ "adapter");
}
mAttached = true;
// Add our custom OnPageChangeCallback to the ViewPager
mOnPageChangeCallback = new TabLayoutOnPageChangeCallback(mTabLayout);
mViewPager.registerOnPageChangeCallback(mOnPageChangeCallback);
// Now we'll add a tab selected listener to set ViewPager's current item
mOnTabSelectedListener = new ViewPagerOnTabSelectedListener(mViewPager);
mTabLayout.addOnTabSelectedListener(mOnTabSelectedListener);
// Now we'll populate ourselves from the pager adapter, adding an observer if
// autoRefresh is enabled
if (mAutoRefresh) {
// Register our observer on the new adapter
mPagerAdapterObserver = new PagerAdapterObserver();
mAdapter.registerAdapterDataObserver(mPagerAdapterObserver);
}
populateTabsFromPagerAdapter();
// Now update the scroll position to match the ViewPager's current item
mTabLayout.setScrollPosition(mViewPager.getCurrentItem(), 0f, true);
}
/**
* Unlink the TabLayout and the ViewPager
*/
public void detach() {
mAdapter.unregisterAdapterDataObserver(mPagerAdapterObserver);
mTabLayout.removeOnTabSelectedListener(mOnTabSelectedListener);
mViewPager.unregisterOnPageChangeCallback(mOnPageChangeCallback);
mPagerAdapterObserver = null;
mOnTabSelectedListener = null;
mOnPageChangeCallback = null;
mAttached = false;
}
@SuppressWarnings("WeakerAccess")
void populateTabsFromPagerAdapter() {
mTabLayout.removeAllTabs();
if (mAdapter != null) {
int adapterCount = mAdapter.getItemCount();
for (int i = 0; i < adapterCount; i++) {
TabLayout.Tab tab = mTabLayout.newTab();
mOnConfigureTabCallback.onConfigureTab(tab, i);
mTabLayout.addTab(tab, false);
}
// Make sure we reflect the currently set ViewPager item
if (adapterCount > 0) {
int currItem = mViewPager.getCurrentItem();
if (currItem != mTabLayout.getSelectedTabPosition()) {
mTabLayout.getTabAt(currItem).select();
}
}
}
}
/**
* A {@link ViewPager2.OnPageChangeCallback} class which contains the necessary calls back to
* the provided {@link TabLayout} so that the tab position is kept in sync.
*
* <p>This class stores the provided TabLayout weakly, meaning that you can use {@link
* ViewPager2#registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback)} without removing
* the callback and not cause a leak.
*/
private static class TabLayoutOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
private final WeakReference<TabLayout> mTabLayoutRef;
private int mPreviousScrollState;
private int mScrollState;
TabLayoutOnPageChangeCallback(TabLayout tabLayout) {
mTabLayoutRef = new WeakReference<>(tabLayout);
reset();
}
@Override
public void onPageScrollStateChanged(final int state) {
mPreviousScrollState = mScrollState;
mScrollState = state;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
TabLayout tabLayout = mTabLayoutRef.get();
if (tabLayout != null) {
// Only update the text selection if we're not settling, or we are settling after
// being dragged
boolean updateText = mScrollState != SCROLL_STATE_SETTLING
|| mPreviousScrollState == SCROLL_STATE_DRAGGING;
// Update the indicator if we're not settling after being idle. This is caused
// from a setCurrentItem() call and will be handled by an animation from
// onPageSelected() instead.
boolean updateIndicator = !(mScrollState == SCROLL_STATE_SETTLING
&& mPreviousScrollState == SCROLL_STATE_IDLE);
setScrollPosition(tabLayout, position, positionOffset, updateText, updateIndicator);
}
}
@Override
public void onPageSelected(final int position) {
TabLayout tabLayout = mTabLayoutRef.get();
if (tabLayout != null
&& tabLayout.getSelectedTabPosition() != position
&& position < tabLayout.getTabCount()) {
// Select the tab, only updating the indicator if we're not being dragged/settled
// (since onPageScrolled will handle that).
boolean updateIndicator = mScrollState == SCROLL_STATE_IDLE
|| (mScrollState == SCROLL_STATE_SETTLING
&& mPreviousScrollState == SCROLL_STATE_IDLE);
selectTab(tabLayout, tabLayout.getTabAt(position), updateIndicator);
}
}
void reset() {
mPreviousScrollState = mScrollState = SCROLL_STATE_IDLE;
}
}
// region Reflective calls
// Temporarily call methods TabLayout.setScrollPosition(int, float, boolean, boolean) and
// TabLayout.selectTab(TabLayout.Tab, boolean) through reflection, until they have been made
// public in the Material Design Components library.
private static Method sSetScrollPosition;
private static Method sSelectTab;
private static final String SET_SCROLL_POSITION_NAME = "TabLayout.setScrollPosition(int, float,"
+ " boolean, boolean)";
private static final String SELECT_TAB_NAME = "TabLayout.selectTab(TabLayout.Tab, boolean)";
static {
try {
sSetScrollPosition = TabLayout.class.getDeclaredMethod("setScrollPosition", int.class,
float.class, boolean.class, boolean.class);
sSetScrollPosition.setAccessible(true);
sSelectTab = TabLayout.class.getDeclaredMethod("selectTab", TabLayout.Tab.class,
boolean.class);
sSelectTab.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("Can't reflect into method TabLayout"
+ ".setScrollPosition(int, float, boolean, boolean)");
}
}
@SuppressWarnings("WeakerAccess")
static void setScrollPosition(TabLayout tabLayout, int position, float positionOffset,
boolean updateSelectedText, boolean updateIndicatorPosition) {
try {
if (sSetScrollPosition != null) {
sSetScrollPosition.invoke(tabLayout, position, positionOffset, updateSelectedText,
updateIndicatorPosition);
} else {
throwMethodNotFound(SET_SCROLL_POSITION_NAME);
}
} catch (Exception e) {
throwInvokeFailed(SET_SCROLL_POSITION_NAME);
}
}
@SuppressWarnings("WeakerAccess")
static void selectTab(TabLayout tabLayout, TabLayout.Tab tab, boolean updateIndicator) {
try {
if (sSelectTab != null) {
sSelectTab.invoke(tabLayout, tab, updateIndicator);
} else {
throwMethodNotFound(SELECT_TAB_NAME);
}
} catch (Exception e) {
throwInvokeFailed(SELECT_TAB_NAME);
}
}
private static void throwMethodNotFound(String method) {
throw new IllegalStateException("Method " + method + " not found");
}
private static void throwInvokeFailed(String method) {
throw new IllegalStateException("Couldn't invoke method " + method);
}
// endregion
/**
* A {@link TabLayout.OnTabSelectedListener} class which contains the necessary calls back to
* the provided {@link ViewPager2} so that the tab position is kept in sync.
*/
private static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
private final ViewPager2 mViewPager;
ViewPagerOnTabSelectedListener(ViewPager2 viewPager) {
this.mViewPager = viewPager;
}
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition(), true);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
// No-op
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// No-op
}
}
private class PagerAdapterObserver extends RecyclerView.AdapterDataObserver {
PagerAdapterObserver() {}
@Override
public void onChanged() {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
populateTabsFromPagerAdapter();
}
}
}
================================================
FILE: app/src/main/java/com/test/banner/viewholder/ImageHolder.java
================================================
package com.test.banner.viewholder;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class ImageHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public ImageHolder(@NonNull View view) {
super(view);
this.imageView = (ImageView) view;
}
}
================================================
FILE: app/src/main/java/com/test/banner/viewholder/ImageTitleHolder.java
================================================
package com.test.banner.viewholder;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
public class ImageTitleHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public TextView title;
public ImageTitleHolder(@NonNull View view) {
super(view);
imageView = view.findViewById(R.id.image);
title = view.findViewById(R.id.bannerTitle);
}
}
================================================
FILE: app/src/main/java/com/test/banner/viewholder/TitleHolder.java
================================================
package com.test.banner.viewholder;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.test.banner.R;
public class TitleHolder extends RecyclerView.ViewHolder {
public TextView title;
public TitleHolder(@NonNull View view) {
super(view);
title = view.findViewById(R.id.bannerTitle);
}
}
================================================
FILE: app/src/main/java/com/test/banner/viewholder/VideoHolder.java
================================================
package com.test.banner.viewholder;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.test.banner.R;
public class VideoHolder extends RecyclerView.ViewHolder {
public StandardGSYVideoPlayer player;
public VideoHolder(@NonNull View view) {
super(view);
player = view.findViewById(R.id.player);
}
}
================================================
FILE: app/src/main/res/drawable/background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#09000000"
android:endColor="#aa000000"
android:angle="270" />
</shape>
================================================
FILE: app/src/main/res/drawable/default_selecter.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/main_color" android:state_pressed="true"/>
<item android:drawable="@color/main_color" android:state_selected="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
================================================
FILE: app/src/main/res/drawable/green.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp" />
<padding
android:bottom="2dp"
android:left="6dp"
android:right="6dp"
android:top="2dp" />
<stroke android:color="@color/main_color" android:width="0.5dp"/>
</shape>
================================================
FILE: app/src/main/res/drawable/selected_radius.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/main_color" />
<corners android:radius="5dp" />
</shape>
================================================
FILE: app/src/main/res/drawable/unselected_radius.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#ffffff" />
<corners android:radius="5dp" />
</shape>
================================================
FILE: app/src/main/res/drawable/white.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#55ffffff" />
</shape>
================================================
FILE: app/src/main/res/layout/activity_constraint_layout_banner.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.ConstraintLayoutBannerActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:text="ConstraintLayout嵌套banner"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
================================================
FILE: app/src/main/res/layout/activity_gallery.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:banner="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.youth.banner.Banner
android:id="@+id/banner1"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_margin="10dp"
banner:banner_radius="5dp"
banner:banner_indicator_normal_color="@android:color/white"
banner:banner_indicator_selected_color="@color/colorPrimary" />
<com.youth.banner.Banner
android:id="@+id/banner2"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_margin="10dp"
banner:banner_radius="5dp"
banner:banner_indicator_normal_color="@android:color/white"
banner:banner_indicator_selected_color="@color/colorPrimary" />
<com.youth.banner.indicator.DrawableIndicator
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
banner:normal_drawable="@drawable/indicator_normal"
banner:selected_drawable="@drawable/indicator_selected"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:banner="http://schemas.android.com/apk/res-auto"
android:id="@+id/swipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f5f5f5">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_margin="10dp"
banner:banner_indicator_normal_color="@android:color/white"
banner:banner_indicator_selected_color="@color/colorPrimary"
banner:banner_radius="5dp"/>
<com.youth.banner.indicator.RoundLinesIndicator
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_below="@+id/banner"
android:layout_centerHorizontal="true"
android:visibility="gone" />
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/banner"
android:layout_marginTop="20dp">
<RelativeLayout
android:id="@+id/rl_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f5f5f5"
android:scrollbars="none">
<Button
android:id="@+id/style_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="图片" />
<Button
android:id="@+id/style_image_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/style_image"
android:text="图片+标题+指示器" />
<Button
android:id="@+id/style_image_title_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/style_image_title"
android:text="图片+标题+数字" />
<Button
android:id="@+id/style_multiple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/style_image"
android:text="多类型UI"
android:textAllCaps="false" />
<Button
android:id="@+id/style_net_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/style_image"
android:layout_toRightOf="@+id/style_multiple"
android:text="网络图片" />
<Button
android:id="@+id/change_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/style_net_image"
android:layout_below="@+id/style_image_title_num"
android:text="外部指示器" />
<Button
android:id="@+id/gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/change_indicator"
android:text="画廊,魅族效果,Drawable指示器"
android:textAllCaps="false" />
<Button
android:id="@+id/topLine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/gallery"
android:text="用banner实现类似淘宝头条的效果"
android:textAllCaps="false" />
<Button
android:id="@+id/rv_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/topLine"
android:text="RecyclerView嵌套banner"
android:textAllCaps="false" />
<Button
android:id="@+id/cl_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/rv_banner"
android:text="ConstraintLayout嵌套banner"
android:textAllCaps="false" />
<Button
android:id="@+id/vp_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/cl_banner"
android:text="viewpaer2+fragment+RecyclerView嵌套banner"
android:textAllCaps="false" />
<Button
android:id="@+id/banner_video"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/vp_banner"
android:text="仿淘宝商品详情banner"
android:textAllCaps="false" />
<Button
android:id="@+id/banner_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/banner_video"
android:text="测试在tv中,遥控切换banner"
android:textAllCaps="false" />
</RelativeLayout>
</androidx.core.widget.NestedScrollView>
</RelativeLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
================================================
FILE: app/src/main/res/layout/activity_recyclerview_banner.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RecyclerView+banner"
android:padding="10dp"
android:gravity="center"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/net_rv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
================================================
FILE: app/src/main/res/layout/activity_t_v.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.TVActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:text="TV中遥控控制banner切换,因为没有真机测试,所以不确定有没有问题,有测试环境的朋友可以多多反馈,或者修改哈"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="0dp"
android:layout_height="0dp"
app:banner_indicator_selected_color="@color/colorPrimary"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
================================================
FILE: app/src/main/res/layout/activity_tou_tiao.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.TouTiaoActivity">
<RelativeLayout
android:id="@+id/topLine"
android:layout_width="match_parent"
android:layout_height="65dp"
android:layout_below="@+id/tip2"
android:background="#ffffff"
android:layout_margin="5dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<ImageView
android:id="@+id/image_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/home_hotpoint"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_centerVertical="true"/>
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/image_top"
android:layout_toLeftOf="@+id/image_right"
android:layout_centerVertical="true"/>
<ImageView
android:id="@+id/image_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/home_right_arrow"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
================================================
FILE: app/src/main/res/layout/activity_video.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.VideoActivity">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="200dp"
app:banner_infinite_loop="false"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
================================================
FILE: app/src/main/res/layout/activity_vp2_fragment_recyclerview.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp2"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:titleEnabled="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="180dp"
android:orientation="vertical">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="180dp"/>
</LinearLayout>
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="40dp"
app:layout_collapseMode="pin">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical|center_horizontal"
android:gravity="center_vertical"
android:text="Banner"
android:textColor="#fff"
android:textStyle="bold"
android:textSize="20sp" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
app:tabSelectedTextColor="@color/colorPrimary"
app:tabIndicatorColor="@color/colorPrimary"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
================================================
FILE: app/src/main/res/layout/banner.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="10dp"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/banner_image.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
================================================
FILE: app/src/main/res/layout/banner_image_title.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/bannerTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#66000000"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:padding="10dp"
android:singleLine="true"
android:textColor="#ffffff"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
================================================
FILE: app/src/main/res/layout/banner_image_title_num.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<LinearLayout
android:id="@+id/titleView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:background="#44000000"
android:orientation="horizontal"
android:padding="5dp">
<TextView
android:id="@+id/bannerTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1000"
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:singleLine="true"
android:textColor="#ffffff" />
<TextView
android:id="@+id/numIndicator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="1/1"
android:textColor="#ffffff" />
</LinearLayout>
</RelativeLayout>
================================================
FILE: app/src/main/res/layout/banner_title.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/bannerTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#ffffff"
android:textSize="25dp"
android:gravity="center"
android:background="#5CB85C" />
</RelativeLayout>
================================================
FILE: app/src/main/res/layout/banner_video.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
android:id="@+id/player"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
================================================
FILE: app/src/main/res/layout/item.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardCornerRadius="4dp"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"
card_view:cardBackgroundColor="@color/main_color">
</androidx.cardview.widget.CardView>
================================================
FILE: app/src/main/res/layout/test.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="测试"
android:textColor="@color/colorPrimary"
android:textSize="20dp" />
</LinearLayout>
================================================
FILE: app/src/main/res/layout/top_line_item2.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:text="实现1号店热点效果"
android:textColor="#444444"
android:layout_marginBottom="10dp"
android:textSize="14sp" />
<TextView
android:id="@+id/source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:layout_below="@id/message"
android:layout_marginRight="10dp"
android:textColor="@color/main_color"
android:background="@drawable/green"
android:textSize="10dp"
android:text="1号店"/>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:textSize="13sp"
android:layout_toRightOf="@id/source"
android:layout_below="@id/message"
android:text="2020年1月23日"/>
</RelativeLayout>
================================================
FILE: app/src/main/res/values/arrays.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="url">
<item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic1xjab4j30ci08cjrv.jpg</item>
<item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic21363tj30ci08ct96.jpg</item>
<item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic259ohaj30ci08c74r.jpg</item>
<item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic2b16zuj30ci08cwf4.jpg</item>
<item>http://ww4.sinaimg.cn/large/006uZZy8jw1faic2e7vsaj30ci08cglz.jpg</item>
</array>
<array name="url1">
<item>http://img.zcool.cn/community/01700557a7f42f0000018c1bd6eb23.jpg</item>
</array>
<array name="url2">
<item>http://img.zcool.cn/community/01d28457d621800000018c1bb7877e.jpg</item>
<item>http://img.zcool.cn/community/01ae5656e1427f6ac72531cb72bac5.jpg</item>
</array>
<array name="url4">
<item>http://img.zcool.cn/community/01b72057a7e0790000018c1bf4fce0.png</item>
<item>http://img.zcool.cn/community/01fca557a7f5f90000012e7e9feea8.jpg</item>
<item>http://img.zcool.cn/community/01996b57a7f6020000018c1bedef97.jpg</item>
<item>http://img.zcool.cn/community/01700557a7f42f0000018c1bd6eb23.jpg</item>
</array>
<!-- http://588ku.com/image/daitengmandelitizi.html -->
<array name="test_num_url">
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f19cc0079.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1ac12d1d.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1bad97d1.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1c83c228.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1d53e3dd.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1e37fea9.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f1ef4d709.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f20b3ea10.jpg</item>
<item>http://bpic.588ku.com/element_origin_min_pic/00/00/05/115732f21927f8d.jpg</item>
</array>
<array name="title">
<item>51巅峰钜惠</item>
<item>十大星级品牌联盟,全场2折起</item>
<item>生命不是要超越别人,而是要超越自己。</item>
<item>己所不欲,勿施于人。——孔子</item>
<item>嗨购5折不要停</item>
</array>
<array name="demo_list">
<item>banner动画预览</item>
<item>banner内置样式预览</item>
<item>banner指示器位置设置预览</item>
<item>banner一些自定义样式方法预览</item>
<item>banner加载本地图片</item>
<item>banner自定义布局文件(这里通过修改ViewPager举一反三吧)</item>
<item>!!banner更多用法请看文档,这里就不一一列举了!</item>
</array>
<array name="anim">
<item>Default</item>
<item>Accordion</item>
<item>BackgroundToForeground</item>
<item>ForegroundToBackground</item>
<item>CubeIn</item>
<item>CubeOut</item>
<item>DepthPage</item>
<item>FlipHorizontal</item>
<item>FlipVertical</item>
<item>RotateDown</item>
<item>RotateUp</item>
<item>ScaleInOut</item>
<item>Stack</item>
<item>Tablet</item>
<item>ZoomIn</item>
<item>ZoomOut</item>
<item>ZoomOutSlide</item>
</array>
<string-array name="style">
<item>NOT_INDICATOR</item>
<item>CIRCLE_INDICATOR</item>
<item>NUM_INDICATOR</item>
<item>NUM_INDICATOR_TITLE</item>
<item>CIRCLE_INDICATOR_TITLE</item>
<item>CIRCLE_INDICATOR_TITLE_INSIDE</item>
</string-array>
<string-array name="indicator">
<item>LEFT</item>
<item>CENTER</item>
<item>RIGHT</item>
</string-array>
</resources>
================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">@color/main_color</color>
<color name="colorPrimaryDark">@color/main_color</color>
<color name="colorAccent">@color/main_color</color>
<color name="textColor">#BDBDBD</color>
<color name="main_color">#5CB85C</color>
</resources>
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">Banner</string>
</resources>
================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
================================================
FILE: app/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
================================================
FILE: banner/.gitignore
================================================
/build
================================================
FILE: banner/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
version = '2.2.3'
android {
compileSdk 33
defaultConfig {
minSdk 14
targetSdk 33
versionCode 202003
versionName version
consumerProguardFiles 'proguard-rules.pro'
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation "androidx.viewpager2:viewpager2:1.1.0-beta02"
}
task androidSourcesJar(type: Jar) {
archiveClassifier.set("sources")
from android.sourceSets.main.java.source
exclude "**/R.class"
exclude "**/BuildConfig.class"
}
publishing {
publications {
release(MavenPublication) {
// group id,发布后引用的依赖的 group id
groupId 'io.github.youth5201314'
// 发布后引用的依赖的 artifact id
artifactId 'banner'
// 发布的版本
version version
// 发布的 arr 的文件和源码文件
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
artifact androidSourcesJar
pom {
// 构件名称,可以自定义
name = 'banner'
// 构件描述
description = 'Android Banner 2.0 全新轮播控件,采用viewpager2为基础控件,支持AndroidX'
// 构件主页
url = 'https://github.com/youth5201314/banner'
// 许可证名称和地址
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
// 开发者信息
developers {
developer {
name = '春'
email = '1028729086@qq.com'
}
}
// 版本控制仓库地址
scm {
url = 'https://github.com/youth5201314/banner'
connection = 'scm:git:github.com/youth5201314/banner.git'
developerConnection = 'scm:git:ssh://git@github.com/youth5201314/banner.git'
}
}
}
}
repositories {
maven {
// 发布的位置,这里根据发布的版本区分了 SNAPSHOT 和最终版本两种情况
def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials {
// 这里就是之前在 issues.sonatype.org 注册的账号
username sonatypeUsername
password sonatypePassword
}
}
}
}
signing {
sign publishing.publications
}
================================================
FILE: banner/proguard-rules.pro
================================================
-dontwarn androidx.viewpager2.**
-keep class androidx.viewpager2.** {*;}
-dontwarn androidx.recyclerview.widget.RecyclerView
-keep class androidx.recyclerview.widget.RecyclerView{*;}
-dontwarn com.youth.banner.**
-keep class com.youth.banner.** {*;}
================================================
FILE: banner/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.youth.banner">
</manifest>
================================================
FILE: banner/src/main/java/com/youth/banner/Banner.java
================================================
package com.youth.banner;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.CompositePageTransformer;
import androidx.viewpager2.widget.MarginPageTransformer;
import androidx.viewpager2.widget.ViewPager2;
import com.youth.banner.adapter.BannerAdapter;
import com.youth.banner.config.BannerConfig;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.indicator.Indicator;
import com.youth.banner.listener.OnBannerListener;
import com.youth.banner.listener.OnPageChangeListener;
import com.youth.banner.transformer.MZScaleInTransformer;
import com.youth.banner.transformer.ScaleInTransformer;
import com.youth.banner.util.BannerLifecycleObserverAdapter;
import com.youth.banner.util.BannerUtils;
import com.youth.banner.util.BannerLifecycleObserver;
import com.youth.banner.util.LogUtils;
import com.youth.banner.util.ScrollSpeedManger;
import java.lang.annotation.Retention;
import java.lang.ref.WeakReference;
import java.util.List;
import static java.lang.annotation.RetentionPolicy.SOURCE;
public class Banner<T, BA extends BannerAdapter<T, ? extends RecyclerView.ViewHolder>> extends FrameLayout implements BannerLifecycleObserver {
public static final int INVALID_VALUE = -1;
private ViewPager2 mViewPager2;
private AutoLoopTask mLoopTask;
private OnPageChangeListener mOnPageChangeListener;
private BA mAdapter;
private Indicator mIndicator;
private CompositePageTransformer mCompositePageTransformer;
private BannerOnPageChangeCallback mPageChangeCallback;
// 是否允许无限轮播(即首尾直接切换)
private boolean mIsInfiniteLoop = BannerConfig.IS_INFINITE_LOOP;
// 是否自动轮播
private boolean mIsAutoLoop = BannerConfig.IS_AUTO_LOOP;
// 轮播切换间隔时间
private long mLoopTime = BannerConfig.LOOP_TIME;
// 轮播切换时间
private int mScrollTime = BannerConfig.SCROLL_TIME;
// 轮播开始位置
private int mStartPosition = 1;
// banner圆角半径,默认没有圆角
private float mBannerRadius = 0;
// banner圆角方向,如果一个都不设置,默认四个角全部圆角
private boolean mRoundTopLeft, mRoundTopRight, mRoundBottomLeft, mRoundBottomRight;
// 指示器相关配置
private int normalWidth = BannerConfig.INDICATOR_NORMAL_WIDTH;
private int selectedWidth = BannerConfig.INDICATOR_SELECTED_WIDTH;
private int normalColor = BannerConfig.INDICATOR_NORMAL_COLOR;
private int selectedColor = BannerConfig.INDICATOR_SELECTED_COLOR;
private int indicatorGravity = IndicatorConfig.Direction.CENTER;
private int indicatorSpace;
private int indicatorMargin;
private int indicatorMarginLeft;
private int indicatorMarginTop;
private int indicatorMarginRight;
private int indicatorMarginBottom;
private int indicatorHeight = BannerConfig.INDICATOR_HEIGHT;
private int indicatorRadius = BannerConfig.INDICATOR_RADIUS;
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private int mOrientation = HORIZONTAL;
// 滑动距离范围
private int mTouchSlop;
// 记录触摸的位置(主要用于解决事件冲突问题)
private float mStartX, mStartY;
// 记录viewpager2是否被拖动
private boolean mIsViewPager2Drag;
// 是否要拦截事件
private boolean isIntercept = true;
//绘制圆角视图
private Paint mRoundPaint;
private Paint mImagePaint;
@Retention(SOURCE)
@IntDef( {HORIZONTAL, VERTICAL})
public @interface Orientation {
}
public Banner(Context context) {
this(context, null);
}
public Banner(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Banner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
initTypedArray(context, attrs);
}
private void init(Context context) {
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop() / 2;
mCompositePageTransformer = new CompositePageTransformer();
mPageChangeCallback = new BannerOnPageChangeCallback();
mLoopTask = new AutoLoopTask(this);
mViewPager2 = new ViewPager2(context);
mViewPager2.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mViewPager2.setOffscreenPageLimit(2);
mViewPager2.registerOnPageChangeCallback(mPageChangeCallback);
mViewPager2.setPageTransformer(mCompositePageTransformer);
ScrollSpeedManger.reflectLayoutManager(this);
addView(mViewPager2);
mRoundPaint = new Paint();
mRoundPaint.setColor(Color.WHITE);
mRoundPaint.setAntiAlias(true);
mRoundPaint.setStyle(Paint.Style.FILL);
mRoundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mImagePaint = new Paint();
mImagePaint.setXfermode(null);
}
private void initTypedArray(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Banner);
mBannerRadius = a.getDimensionPixelSize(R.styleable.Banner_banner_radius, 0);
mLoopTime = a.getInt(R.styleable.Banner_banner_loop_time, BannerConfig.LOOP_TIME);
mIsAutoLoop = a.getBoolean(R.styleable.Banner_banner_auto_loop, BannerConfig.IS_AUTO_LOOP);
mIsInfiniteLoop = a.getBoolean(R.styleable.Banner_banner_infinite_loop, BannerConfig.IS_INFINITE_LOOP);
normalWidth = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_normal_width, BannerConfig.INDICATOR_NORMAL_WIDTH);
selectedWidth = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_selected_width, BannerConfig.INDICATOR_SELECTED_WIDTH);
normalColor = a.getColor(R.styleable.Banner_banner_indicator_normal_color, BannerConfig.INDICATOR_NORMAL_COLOR);
selectedColor = a.getColor(R.styleable.Banner_banner_indicator_selected_color, BannerConfig.INDICATOR_SELECTED_COLOR);
indicatorGravity = a.getInt(R.styleable.Banner_banner_indicator_gravity, IndicatorConfig.Direction.CENTER);
indicatorSpace = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_space, 0);
indicatorMargin = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_margin, 0);
indicatorMarginLeft = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginLeft, 0);
indicatorMarginTop = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginTop, 0);
indicatorMarginRight = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginRight, 0);
indicatorMarginBottom = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_marginBottom, 0);
indicatorHeight = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_height, BannerConfig.INDICATOR_HEIGHT);
indicatorRadius = a.getDimensionPixelSize(R.styleable.Banner_banner_indicator_radius, BannerConfig.INDICATOR_RADIUS);
mOrientation = a.getInt(R.styleable.Banner_banner_orientation, HORIZONTAL);
mRoundTopLeft = a.getBoolean(R.styleable.Banner_banner_round_top_left, false);
mRoundTopRight = a.getBoolean(R.styleable.Banner_banner_round_top_right, false);
mRoundBottomLeft = a.getBoolean(R.styleable.Banner_banner_round_bottom_left, false);
mRoundBottomRight = a.getBoolean(R.styleable.Banner_banner_round_bottom_right, false);
a.recycle();
}
setOrientation(mOrientation);
setInfiniteLoop();
}
private void initIndicatorAttr() {
if (indicatorMargin != 0) {
setIndicatorMargins(new IndicatorConfig.Margins(indicatorMargin));
} else if (indicatorMarginLeft != 0
|| indicatorMarginTop != 0
|| indicatorMarginRight != 0
|| indicatorMarginBottom != 0) {
setIndicatorMargins(new IndicatorConfig.Margins(
indicatorMarginLeft,
indicatorMarginTop,
indicatorMarginRight,
indicatorMarginBottom));
}
if (indicatorSpace > 0) {
setIndicatorSpace(indicatorSpace);
}
if (indicatorGravity != IndicatorConfig.Direction.CENTER) {
setIndicatorGravity(indicatorGravity);
}
if (normalWidth > 0) {
setIndicatorNormalWidth(normalWidth);
}
if (selectedWidth > 0) {
setIndicatorSelectedWidth(selectedWidth);
}
if (indicatorHeight > 0) {
setIndicatorHeight(indicatorHeight);
}
if (indicatorRadius > 0) {
setIndicatorRadius(indicatorRadius);
}
setIndicatorNormalColor(normalColor);
setIndicatorSelectedColor(selectedColor);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!getViewPager2().isUserInputEnabled()) {
return super.dispatchTouchEvent(ev);
}
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_OUTSIDE) {
start();
} else if (action == MotionEvent.ACTION_DOWN) {
stop();
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (!getViewPager2().isUserInputEnabled() || !isIntercept) {
return super.onInterceptTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = event.getX();
mStartY = event.getY();
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
float endX = event.getX();
float endY = event.getY();
float distanceX = Math.abs(endX - mStartX);
float distanceY = Math.abs(endY - mStartY);
if (getViewPager2().getOrientation() == HORIZONTAL) {
mIsViewPager2Drag = distanceX > mTouchSlop && distanceX > distanceY;
} else {
mIsViewPager2Drag = distanceY > mTouchSlop && distanceY > distanceX;
}
getParent().requestDisallowInterceptTouchEvent(mIsViewPager2Drag);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.onInterceptTouchEvent(event);
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (mBannerRadius > 0) {
canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), mImagePaint, Canvas.ALL_SAVE_FLAG);
super.dispatchDraw(canvas);
//绘制外圆环边框圆环
//默认四个角都设置
if (!mRoundTopRight && !mRoundTopLeft && !mRoundBottomRight && !mRoundBottomLeft) {
drawTopLeft(canvas);
drawTopRight(canvas);
drawBottomLeft(canvas);
drawBottomRight(canvas);
canvas.restore();
return;
}
if (mRoundTopLeft) {
drawTopLeft(canvas);
}
if (mRoundTopRight) {
drawTopRight(canvas);
}
if (mRoundBottomLeft) {
drawBottomLeft(canvas);
}
if (mRoundBottomRight) {
drawBottomRight(canvas);
}
canvas.restore();
} else {
super.dispatchDraw(canvas);
}
}
private void drawTopLeft(Canvas canvas) {
Path path = new Path();
path.moveTo(0, mBannerRadius);
path.lineTo(0, 0);
path.lineTo(mBannerRadius, 0);
path.arcTo(new RectF(0, 0, mBannerRadius * 2, mBannerRadius * 2), -90, -90);
path.close();
canvas.drawPath(path, mRoundPaint);
}
private void drawTopRight(Canvas canvas) {
int width = getWidth();
Path path = new Path();
path.moveTo(width - mBannerRadius, 0);
path.lineTo(width, 0);
path.lineTo(width, mBannerRadius);
path.arcTo(new RectF(width - 2 * mBannerRadius, 0, width, mBannerRadius * 2), 0, -90);
path.close();
canvas.drawPath(path, mRoundPaint);
}
private void drawBottomLeft(Canvas canvas) {
int height = getHeight();
Path path = new Path();
path.moveTo(0, height - mBannerRadius);
path.lineTo(0, height);
path.lineTo(mBannerRadius, height);
path.arcTo(new RectF(0, height - 2 * mBannerRadius, mBannerRadius * 2, height), 90, 90);
path.close();
canvas.drawPath(path, mRoundPaint);
}
private void drawBottomRight(Canvas canvas) {
int height = getHeight();
int width = getWidth();
Path path = new Path();
path.moveTo(width - mBannerRadius, height);
path.lineTo(width, height);
path.lineTo(width, height - mBannerRadius);
path.arcTo(new RectF(width - 2 * mBannerRadius, height - 2 * mBannerRadius, width, height), 0, 90);
path.close();
canvas.drawPath(path, mRoundPaint);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
start();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stop();
}
class BannerOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
private int mTempPosition = INVALID_VALUE;
private boolean isScrolled;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int realPosition = BannerUtils.getRealPosition(isInfiniteLoop(), position, getRealCount());
if (mOnPageChangeListener != null && realPosition == getCurrentItem() - 1) {
mOnPageChangeListener.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
}
if (getIndicator() != null && realPosition == getCurrentItem() - 1) {
getIndicator().onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
}
}
@Override
public void onPageSelected(int position) {
if (isScrolled) {
mTempPosition = position;
int realPosition = BannerUtils.getRealPosition(isInfiniteLoop(), position, getRealCount());
if (mOnPageChangeListener != null) {
mOnPageChangeListener.onPageSelected(realPosition);
}
if (getIndicator() != null) {
getIndicator().onPageSelected(realPosition);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
//手势滑动中,代码执行滑动中
if (state == ViewPager2.SCROLL_STATE_DRAGGING || state == ViewPager2.SCROLL_STATE_SETTLING) {
isScrolled = true;
} else if (state == ViewPager2.SCROLL_STATE_IDLE) {
//滑动闲置或滑动结束
isScrolled = false;
if (mTempPosition != INVALID_VALUE && mIsInfiniteLoop) {
if (mTempPosition == 0) {
setCurrentItem(getRealCount(), false);
} else if (mTempPosition == getItemCount() - 1) {
setCurrentItem(1, false);
}
}
}
if (mOnPageChangeListener != null) {
mOnPageChangeListener.onPageScrollStateChanged(state);
}
if (getIndicator() != null) {
getIndicator().onPageScrollStateChanged(state);
}
}
}
static class AutoLoopTask implements Runnable {
private final WeakReference<Banner> reference;
AutoLoopTask(Banner banner) {
this.reference = new WeakReference<>(banner);
}
@Override
public void run() {
Banner banner = reference.get();
if (banner != null && banner.mIsAutoLoop) {
int count = banner.getItemCount();
if (count == 0) {
return;
}
int next = (banner.getCurrentItem() + 1) % count;
banner.setCurrentItem(next);
banner.postDelayed(banner.mLoopTask, banner.mLoopTime);
}
}
}
private final RecyclerView.AdapterDataObserver mAdapterDataObserver = new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
if (getItemCount() <= 1) {
stop();
} else {
start();
}
setIndicatorPageChange();
}
};
private void initIndicator() {
if (getIndicator() == null || getAdapter() == null) {
return;
}
if (getIndicator().getIndicatorConfig().isAttachToBanner()) {
removeIndicator();
addView(getIndicator().getIndicatorView());
}
initIndicatorAttr();
setIndicatorPageChange();
}
private void setInfiniteLoop() {
// 当不支持无限循环时,要关闭自动轮播
if (!isInfiniteLoop()) {
isAutoLoop(false);
}
setStartPosition(isInfiniteLoop() ? mStartPosition : 0);
}
private void setRecyclerViewPadding(int itemPadding) {
setRecyclerViewPadding(itemPadding, itemPadding);
}
private void setRecyclerViewPadding(int leftItemPadding, int rightItemPadding) {
RecyclerView recyclerView = (RecyclerView) getViewPager2().getChildAt(0);
if (getViewPager2().getOrientation() == ViewPager2.ORIENTATION_VERTICAL) {
recyclerView.setPadding(mViewPager2.getPaddingLeft(), leftItemPadding, mViewPager2.getPaddingRight(), rightItemPadding);
} else {
recyclerView.setPadding(leftItemPadding, mViewPager2.getPaddingTop(), rightItemPadding, mViewPager2.getPaddingBottom());
}
recyclerView.setClipToPadding(false);
}
/**
* **********************************************************************
* ------------------------ 对外公开API ---------------------------------*
* **********************************************************************
*/
public int getCurrentItem() {
return getViewPager2().getCurrentItem();
}
public int getItemCount() {
if (getAdapter() != null) {
return getAdapter().getItemCount();
}
return 0;
}
public int getScrollTime() {
return mScrollTime;
}
public boolean isInfiniteLoop() {
return mIsInfiniteLoop;
}
public BannerAdapter getAdapter() {
return mAdapter;
}
public ViewPager2 getViewPager2() {
return mViewPager2;
}
public Indicator getIndicator() {
return mIndicator;
}
public IndicatorConfig getIndicatorConfig() {
if (getIndicator() != null) {
return getIndicator().getIndicatorConfig();
}
return null;
}
/**
* 返回banner真实总数
*/
public int getRealCount() {
if (getAdapter() != null) {
return getAdapter().getRealCount();
}
return 0;
}
//-----------------------------------------------------------------------------------------
/**
* 是否要拦截事件
* @param intercept
* @return
*/
public Banner setIntercept(boolean intercept) {
isIntercept = intercept;
return this;
}
/**
* 跳转到指定位置(最好在设置了数据后在调用,不然没有意义)
* @param position
* @return
*/
public Banner setCurrentItem(int position) {
return setCurrentItem(position, true);
}
/**
* 跳转到指定位置(最好在设置了数据后在调用,不然没有意义)
* @param position
* @param smoothScroll
* @return
*/
public Banner setCurrentItem(int position, boolean smoothScroll) {
getViewPager2().setCurrentItem(position, smoothScroll);
return this;
}
public Banner setIndicatorPageChange() {
if (getIndicator() != null) {
int realPosition = BannerUtils.getRealPosition(isInfiniteLoop(), getCurrentItem(), getRealCount());
getIndicator().onPageChanged(getRealCount(), realPosition);
}
return this;
}
public Banner removeIndicator() {
if (getIndicator() != null) {
removeView(getIndicator().getIndicatorView());
}
return this;
}
/**
* 设置开始的位置 (需要在setAdapter或者setDatas之前调用才有效哦)
*/
public Banner setStartPosition(int mStartPosition) {
this.mStartPosition = mStartPosition;
return this;
}
public int getStartPosition() {
return mStartPosition;
}
/**
* 禁止手动滑动
*
* @param enabled true 允许,false 禁止
*/
public Banner setUserInputEnabled(boolean enabled) {
getViewPager2().setUserInputEnabled(enabled);
return this;
}
/**
* 添加PageTransformer,可以组合效果
* {@link ViewPager2.PageTransformer}
* 如果找不到请导入implementation "androidx.viewpager2:viewpager2:1.0.0"
*/
public Banner addPageTransformer(@Nullable ViewPager2.PageTransformer transformer) {
mCompositePageTransformer.addTransformer(transformer);
return this;
}
/**
* 设置PageTransformer,和addPageTransformer不同,这个只支持一种transformer
*/
public Banner setPageTransformer(@Nullable ViewPager2.PageTransformer transformer) {
getViewPager2().setPageTransformer(transformer);
return this;
}
public Banner removeTransformer(ViewPager2.PageTransformer transformer) {
mCompositePageTransformer.removeTransformer(transformer);
return this;
}
/**
* 添加 ItemDecoration
*/
public Banner addItemDecoration(RecyclerView.ItemDecoration decor) {
getViewPager2().addItemDecoration(decor);
return this;
}
public Banner addItemDecoration(RecyclerView.ItemDecoration decor, int index) {
getViewPager2().addItemDecoration(decor, index);
return this;
}
/**
* 是否允许自动轮播
*
* @param isAutoLoop ture 允许,false 不允许
*/
public Banner isAutoLoop(boolean isAutoLoop) {
this.mIsAutoLoop = isAutoLoop;
return this;
}
/**
* 设置轮播间隔时间
*
* @param loopTime 时间(毫秒)
*/
public Banner setLoopTime(long loopTime) {
this.mLoopTime = loopTime;
return this;
}
/**
* 设置轮播滑动过程的时间
*/
public Banner setScrollTime(int scrollTime) {
this.mScrollTime = scrollTime;
return this;
}
/**
* 开始轮播
*/
public Banner start() {
if (mIsAutoLoop) {
stop();
postDelayed(mLoopTask, mLoopTime);
}
return this;
}
/**
* 停止轮播
*/
public Banner stop() {
if (mIsAutoLoop) {
removeCallbacks(mLoopTask);
}
return this;
}
/**
* 移除一些引用
*/
public void destroy() {
if (getViewPager2() != null && mPageChangeCallback != null) {
getViewPager2().unregisterOnPageChangeCallback(mPageChangeCallback);
mPageChangeCallback = null;
}
stop();
}
/**
* 设置banner的适配器
*/
public Banner setAdapter(BA adapter) {
if (adapter == null) {
throw new NullPointerException(getContext().getString(R.string.banner_adapter_null_error));
}
this.mAdapter = adapter;
if (!isInfiniteLoop()) {
getAdapter().setIncreaseCount(0);
}
getAdapter().registerAdapterDataObserver(mAdapterDataObserver);
mViewPager2.setAdapter(adapter);
setCurrentItem(mStartPosition, false);
initIndicator();
return this;
}
/**
* 设置banner的适配器
* @param adapter
* @param isInfiniteLoop 是否支持无限循环
* @return
*/
public Banner setAdapter(BA adapter,boolean isInfiniteLoop) {
mIsInfiniteLoop=isInfiniteLoop;
setInfiniteLoop();
setAdapter(adapter);
return this;
}
/**
* 重新设置banner数据,当然你也可以在你adapter中自己操作数据,不要过于局限在这个方法,举一反三哈
*
* @param datas 数据集合,当传null或者datas没有数据时,banner会变成空白的,请做好占位UI处理
*/
public Banner setDatas(List<T> datas) {
if (getAdapter() != null) {
getAdapter().setDatas(datas);
setCurrentItem(mStartPosition, false);
setIndicatorPageChange();
start();
}
return this;
}
/**
* 设置banner轮播方向
*
* @param orientation {@link Orientation}
*/
public Banner setOrientation(@Orientation int orientation) {
getViewPager2().setOrientation(orientation);
return this;
}
/**
* 改变最小滑动距离
*/
public Banner setTouchSlop(int mTouchSlop) {
this.mTouchSlop = mTouchSlop;
return this;
}
/**
* 设置点击事件
*/
public Banner setOnBannerListener(OnBannerListener<T> listener) {
if (getAdapter() != null) {
getAdapter().setOnBannerListener(listener);
}
return this;
}
/**
* 添加viewpager切换事件
* <p>
* 在viewpager2中切换事件{@link ViewPager2.OnPageChangeCallback}是一个抽象类,
* 为了方便使用习惯这里用的是和viewpager一样的{@link ViewPager.OnPageChangeListener}接口
* </p>
*/
public Banner addOnPageChangeListener(OnPageChangeListener pageListener) {
this.mOnPageChangeListener = pageListener;
return this;
}
/**
* 设置banner圆角
* <p>
* 默认没有圆角,需要取消圆角把半径设置为0即可
*
* @param radius 圆角半径
*/
public Banner setBannerRound(float radius) {
mBannerRadius = radius;
return this;
}
/**
* 设置banner圆角(第二种方式,和上面的方法不要同时使用),只支持5.0以上
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public Banner setBannerRound2(float radius) {
BannerUtils.setBannerRound(this, radius);
return this;
}
/**
* 为banner添加画廊效果
*
* @param itemWidth item左右展示的宽度,单位dp
* @param pageMargin 页面间距,单位dp
*/
public Banner setBannerGalleryEffect(int itemWidth, int pageMargin) {
return setBannerGalleryEffect(itemWidth, pageMargin, .85f);
}
/**
* 为banner添加画廊效果
*
* @param leftItemWidth item左展示的宽度,单位dp
* @param rightItemWidth item右展示的宽度,单位dp
* @param pageMargin 页面间距,单位dp
*/
public Banner setBannerGalleryEffect(int leftItemWidth, int rightItemWidth, int pageMargin) {
return setBannerGalleryEffect(leftItemWidth,rightItemWidth, pageMargin, .85f);
}
/**
* 为banner添加画廊效果
*
* @param itemWidth item左右展示的宽度,单位dp
* @param pageMargin 页面间距,单位dp
* @param scale 缩放[0-1],1代表不缩放
*/
public Banner setBannerGalleryEffect(int itemWidth, int pageMargin, float scale) {
return setBannerGalleryEffect(itemWidth, itemWidth, pageMargin, scale);
}
/**
* 为banner添加画廊效果
*
* @param leftItemWidth item左展示的宽度,单位dp
* @param rightItemWidth item右展示的宽度,单位dp
* @param pageMargin 页面间距,单位dp
* @param scale 缩放[0-1],1代表不缩放
*/
public Banner setBannerGalleryEffect(int leftItemWidth, int rightItemWidth, int pageMargin, float scale) {
if (pageMargin > 0) {
addPageTransformer(new MarginPageTransformer(BannerUtils.dp2px(pageMargin)));
}
if (scale < 1 && scale > 0) {
addPageTransformer(new ScaleInTransformer(scale));
}
setRecyclerViewPadding(leftItemWidth > 0 ? BannerUtils.dp2px(leftItemWidth + pageMargin) : 0,
rightItemWidth > 0 ? BannerUtils.dp2px(rightItemWidth + pageMargin) : 0);
return this;
}
/**
* 为banner添加魅族效果
*
* @param itemWidth item左右展示的宽度,单位dp
*/
public Banner setBannerGalleryMZ(int itemWidth) {
return setBannerGalleryMZ(itemWidth, .88f);
}
/**
* 为banner添加魅族效果
*
* @param itemWidth item左右展示的宽度,单位dp
* @param scale 缩放[0-1],1代表不缩放
*/
public Banner setBannerGalleryMZ(int itemWidth, float scale) {
if (scale < 1 && scale > 0) {
addPageTransformer(new MZScaleInTransformer(scale));
}
setRecyclerViewPadding(BannerUtils.dp2px(itemWidth));
return this;
}
/**
* **********************************************************************
* ------------------------ 指示器相关设置 --------------------------------*
* **********************************************************************
*/
/**
* 设置轮播指示器(显示在banner上)
*/
public Banner setIndicator(Indicator indicator) {
return setIndicator(indicator, true);
}
/**
* 设置轮播指示器(如果你的指示器写在布局文件中,attachToBanner传false)
*
* @param attachToBanner 是否将指示器添加到banner中,false 代表你可以将指示器通过布局放在任何位置
* 注意:设置为false后,内置的 setIndicatorGravity()和setIndicatorMargins() 方法将失效。
* 想改变可以自己调用系统提供的属性在布局文件中进行设置。具体可以参照demo
*/
public Banner setIndicator(Indicator indicator, boolean attachToBanner) {
removeIndicator();
indicator.getIndicatorConfig().setAttachToBanner(attachToBanner);
this.mIndicator = indicator;
initIndicator();
return this;
}
public Banner setIndicatorSelectedColor(@ColorInt int color) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setSelectedColor(color);
}
return this;
}
public Banner setIndicatorSelectedColorRes(@ColorRes int color) {
setIndicatorSelectedColor(ContextCompat.getColor(getContext(), color));
return this;
}
public Banner setIndicatorNormalColor(@ColorInt int color) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setNormalColor(color);
}
return this;
}
public Banner setIndicatorNormalColorRes(@ColorRes int color) {
setIndicatorNormalColor(ContextCompat.getColor(getContext(), color));
return this;
}
public Banner setIndicatorGravity(@IndicatorConfig.Direction int gravity) {
if (getIndicatorConfig() != null && getIndicatorConfig().isAttachToBanner()) {
getIndicatorConfig().setGravity(gravity);
getIndicator().getIndicatorView().postInvalidate();
}
return this;
}
public Banner setIndicatorSpace(int indicatorSpace) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setIndicatorSpace(indicatorSpace);
}
return this;
}
public Banner setIndicatorMargins(IndicatorConfig.Margins margins) {
if (getIndicatorConfig() != null && getIndicatorConfig().isAttachToBanner()) {
getIndicatorConfig().setMargins(margins);
getIndicator().getIndicatorView().requestLayout();
}
return this;
}
public Banner setIndicatorWidth(int normalWidth, int selectedWidth) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setNormalWidth(normalWidth);
getIndicatorConfig().setSelectedWidth(selectedWidth);
}
return this;
}
public Banner setIndicatorNormalWidth(int normalWidth) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setNormalWidth(normalWidth);
}
return this;
}
public Banner setIndicatorSelectedWidth(int selectedWidth) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setSelectedWidth(selectedWidth);
}
return this;
}
public Banner setIndicatorRadius(int indicatorRadius) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setRadius(indicatorRadius);
}
return this;
}
public Banner setIndicatorHeight(int indicatorHeight) {
if (getIndicatorConfig() != null) {
getIndicatorConfig().setHeight(indicatorHeight);
}
return this;
}
/**
* **********************************************************************
* ------------------------ 生命周期控制 --------------------------------*
* **********************************************************************
*/
public Banner addBannerLifecycleObserver(LifecycleOwner owner) {
if (owner != null) {
owner.getLifecycle().addObserver(new BannerLifecycleObserverAdapter(owner, this));
}
return this;
}
@Override
public void onStart(LifecycleOwner owner) {
start();
}
@Override
public void onStop(LifecycleOwner owner) {
stop();
}
@Override
public void onDestroy(LifecycleOwner owner) {
destroy();
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/adapter/BannerAdapter.java
================================================
package com.youth.banner.adapter;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.youth.banner.R;
import com.youth.banner.config.BannerConfig;
import com.youth.banner.holder.IViewHolder;
import com.youth.banner.listener.OnBannerListener;
import com.youth.banner.util.BannerUtils;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public abstract class BannerAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> implements IViewHolder<T, VH> {
protected List<T> mDatas = new ArrayList<>();
private OnBannerListener<T> mOnBannerListener;
private VH mViewHolder;
private int mIncreaseCount = BannerConfig.INCREASE_COUNT;
public BannerAdapter(List<T> datas) {
setDatas(datas);
}
/**
* 设置实体集合(可以在自己的adapter自定义,不一定非要使用)
*
* @param datas
*/
public void setDatas(List<T> datas) {
if (datas == null) {
datas = new ArrayList<>();
}
mDatas.clear();
mDatas.addAll(datas);
notifyDataSetChanged();
}
/**
* 获取指定的实体(可以在自己的adapter自定义,不一定非要使用)
*
* @param position 真实的position
* @return
*/
public T getData(int position) {
if (position > mDatas.size()-1) {
return null;
}
return mDatas.get(position);
}
/**
* 获取指定的实体(可以在自己的adapter自定义,不一定非要使用)
*
* @param position 这里传的position不是真实的,获取时转换了一次
* @return
*/
public T getRealData(int position) {
int realPosition = getRealPosition(position);
if (realPosition > mDatas.size()-1) {
return null;
}
return mDatas.get(realPosition);
}
@Override
public final void onBindViewHolder(@NonNull VH holder, int position) {
mViewHolder = holder;
int real = getRealPosition(position);
T data = mDatas.get(real);
holder.itemView.setTag(R.id.banner_data_key, data);
holder.itemView.setTag(R.id.banner_pos_key, real);
onBindView(holder, mDatas.get(real), real, getRealCount());
if (mOnBannerListener != null) {
holder.itemView.setOnClickListener(view -> mOnBannerListener.OnBannerClick(data, real));
}
}
@NonNull
@Override
@SuppressWarnings("unchecked")
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
VH vh = onCreateHolder(parent, viewType);
vh.itemView.setOnClickListener(v -> {
if (mOnBannerListener != null) {
T data = (T) vh.itemView.getTag(R.id.banner_data_key);
int real = (int) vh.itemView.getTag(R.id.banner_pos_key);
mOnBannerListener.OnBannerClick(data, real);
}
});
return vh;
}
@Override
public int getItemCount() {
return getRealCount() > 1 ? getRealCount() + mIncreaseCount : getRealCount();
}
public int getRealCount() {
return mDatas == null ? 0 : mDatas.size();
}
public int getRealPosition(int position) {
return BannerUtils.getRealPosition(mIncreaseCount == BannerConfig.INCREASE_COUNT, position, getRealCount());
}
public void setOnBannerListener(OnBannerListener<T> listener) {
this.mOnBannerListener = listener;
}
public VH getViewHolder() {
return mViewHolder;
}
public void setIncreaseCount(int increaseCount) {
this.mIncreaseCount = increaseCount;
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/adapter/BannerImageAdapter.java
================================================
package com.youth.banner.adapter;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.youth.banner.holder.BannerImageHolder;
import java.util.List;
/**
* 默认实现的图片适配器,图片加载需要自己实现
*/
public abstract class BannerImageAdapter<T> extends BannerAdapter<T, BannerImageHolder> {
public BannerImageAdapter(List<T> mData) {
super(mData);
}
@Override
public BannerImageHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
//注意,必须设置为match_parent,这个是viewpager2强制要求的
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(params);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return new BannerImageHolder(imageView);
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/config/BannerConfig.java
================================================
package com.youth.banner.config;
import com.youth.banner.util.BannerUtils;
/**
* 不忘初心
*
* ┌───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐ ┌┐ ┌┐ ┌┐
* │Esc│ │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│ └┘ └┘ └┘
* └───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐
* │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤
* │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │{ [│} ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │ │
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │
* │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│" '│ Enter │ │ 4 │ 5 │ 6 │ │
* ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ ┌───┐ ├───┼───┼───┼───┤
* │ Shift │ Z │ X │ C │ V │ B │ N │ M │< ,│> .│? /│ Shift │ │ ↑ │ │ 1 │ 2 │ 3 │ │
* ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││
* │ Ctrl│ │Alt │ Space │ Alt│ │ │Ctrl│ │ ← │ ↓ │ → │ │ 0 │ . │←─┘│
* └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘
*
* @author youth5201314/spring
* @date 2020/1/24
* banner 配置参数
*/
public class BannerConfig {
public static final boolean IS_AUTO_LOOP = true;
public static final boolean IS_INFINITE_LOOP = true;
public static final int LOOP_TIME = 3000;
public static final int SCROLL_TIME = 600;
public static final int INCREASE_COUNT = 2;
public static final int INDICATOR_NORMAL_COLOR = 0x88ffffff;
public static final int INDICATOR_SELECTED_COLOR = 0x88000000;
public static final int INDICATOR_NORMAL_WIDTH = (int) BannerUtils.dp2px(5);
public static final int INDICATOR_SELECTED_WIDTH = (int) BannerUtils.dp2px(7);
public static final int INDICATOR_SPACE = (int) BannerUtils.dp2px(5);
public static final int INDICATOR_MARGIN = (int) BannerUtils.dp2px(5);
public static final int INDICATOR_HEIGHT = (int) BannerUtils.dp2px(3);
public static final int INDICATOR_RADIUS = (int) BannerUtils.dp2px(3);
}
================================================
FILE: banner/src/main/java/com/youth/banner/config/IndicatorConfig.java
================================================
package com.youth.banner.config;
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class IndicatorConfig {
private int indicatorSize;
private int currentPosition;
private int gravity = Direction.CENTER;
private int indicatorSpace = BannerConfig.INDICATOR_SPACE;
private int normalWidth = BannerConfig.INDICATOR_NORMAL_WIDTH;
private int selectedWidth = BannerConfig.INDICATOR_SELECTED_WIDTH;
@ColorInt
private int normalColor = BannerConfig.INDICATOR_NORMAL_COLOR;
@ColorInt
private int selectedColor = BannerConfig.INDICATOR_SELECTED_COLOR;
private int radius = BannerConfig.INDICATOR_RADIUS;
private int height = BannerConfig.INDICATOR_HEIGHT;
private Margins margins;
//是将指示器添加到banner上
private boolean attachToBanner = true;
@IntDef({Direction.LEFT, Direction.CENTER, Direction.RIGHT})
@Retention(RetentionPolicy.SOURCE)
public @interface Direction {
int LEFT = 0;
int CENTER = 1;
int RIGHT = 2;
}
public static class Margins {
public int leftMargin;
public int topMargin;
public int rightMargin;
public int bottomMargin;
public Margins() {
this(BannerConfig.INDICATOR_MARGIN);
}
public Margins(int marginSize) {
this(marginSize, marginSize, marginSize, marginSize);
}
public Margins(int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
this.leftMargin = leftMargin;
this.topMargin = topMargin;
this.rightMargin = rightMargin;
this.bottomMargin = bottomMargin;
}
}
public Margins getMargins() {
if (margins == null) {
setMargins(new Margins());
}
return margins;
}
public IndicatorConfig setMargins(Margins margins) {
this.margins = margins;
return this;
}
public int getIndicatorSize() {
return indicatorSize;
}
public IndicatorConfig setIndicatorSize(int indicatorSize) {
this.indicatorSize = indicatorSize;
return this;
}
public int getNormalColor() {
return normalColor;
}
public IndicatorConfig setNormalColor(int normalColor) {
this.normalColor = normalColor;
return this;
}
public int getSelectedColor() {
return selectedColor;
}
public IndicatorConfig setSelectedColor(int selectedColor) {
this.selectedColor = selectedColor;
return this;
}
public int getIndicatorSpace() {
return indicatorSpace;
}
public IndicatorConfig setIndicatorSpace(int indicatorSpace) {
this.indicatorSpace = indicatorSpace;
return this;
}
public int getCurrentPosition() {
return currentPosition;
}
public IndicatorConfig setCurrentPosition(int currentPosition) {
this.currentPosition = currentPosition;
return this;
}
public int getNormalWidth() {
return normalWidth;
}
public IndicatorConfig setNormalWidth(int normalWidth) {
this.normalWidth = normalWidth;
return this;
}
public int getSelectedWidth() {
return selectedWidth;
}
public IndicatorConfig setSelectedWidth(int selectedWidth) {
this.selectedWidth = selectedWidth;
return this;
}
public int getGravity() {
return gravity;
}
public IndicatorConfig setGravity(@Direction int gravity) {
this.gravity = gravity;
return this;
}
public boolean isAttachToBanner() {
return attachToBanner;
}
public IndicatorConfig setAttachToBanner(boolean attachToBanner) {
this.attachToBanner = attachToBanner;
return this;
}
public int getRadius() {
return radius;
}
public IndicatorConfig setRadius(int radius) {
this.radius = radius;
return this;
}
public int getHeight() {
return height;
}
public IndicatorConfig setHeight(int height) {
this.height = height;
return this;
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/holder/BannerImageHolder.java
================================================
package com.youth.banner.holder;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public
class BannerImageHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public BannerImageHolder(@NonNull View view) {
super(view);
this.imageView = (ImageView) view;
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/holder/IViewHolder.java
================================================
package com.youth.banner.holder;
import android.view.ViewGroup;
public interface IViewHolder<T, VH> {
/**
* 创建ViewHolder
*
* @return XViewHolder
*/
VH onCreateHolder(ViewGroup parent, int viewType);
/**
* 绑定布局数据
*
* @param holder XViewHolder
* @param data 数据实体
* @param position 当前位置
* @param size 总数
*/
void onBindView(VH holder, T data, int position, int size);
}
================================================
FILE: banner/src/main/java/com/youth/banner/indicator/BaseIndicator.java
================================================
package com.youth.banner.indicator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.util.LogUtils;
public class BaseIndicator extends View implements Indicator {
protected IndicatorConfig config;
protected Paint mPaint;
protected float offset;
public BaseIndicator(Context context) {
this(context, null);
}
public BaseIndicator(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
config = new IndicatorConfig();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setColor(config.getNormalColor());
}
@NonNull
@Override
public View getIndicatorView() {
if (config.isAttachToBanner()) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
switch (config.getGravity()) {
case IndicatorConfig.Direction.LEFT:
layoutParams.gravity = Gravity.BOTTOM | Gravity.START;
break;
case IndicatorConfig.Direction.CENTER:
layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
break;
case IndicatorConfig.Direction.RIGHT:
layoutParams.gravity = Gravity.BOTTOM | Gravity.END;
break;
}
layoutParams.leftMargin = config.getMargins().leftMargin;
layoutParams.rightMargin = config.getMargins().rightMargin;
layoutParams.topMargin = config.getMargins().topMargin;
layoutParams.bottomMargin = config.getMargins().bottomMargin;
setLayoutParams(layoutParams);
}
return this;
}
@Override
public IndicatorConfig getIndicatorConfig() {
return config;
}
@Override
public void onPageChanged(int count, int currentPosition) {
config.setIndicatorSize(count);
config.setCurrentPosition(currentPosition);
requestLayout();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
offset = positionOffset;
invalidate();
}
@Override
public void onPageSelected(int position) {
config.setCurrentPosition(position);
invalidate();
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/indicator/CircleIndicator.java
================================================
package com.youth.banner.indicator;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
/**
* 圆形指示器
* 如果想要大小一样,可以将选中和默认设置成同样大小
*/
public class CircleIndicator extends BaseIndicator {
private int mNormalRadius;
private int mSelectedRadius;
private int maxRadius;
public CircleIndicator(Context context) {
this(context, null);
}
public CircleIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mNormalRadius = config.getNormalWidth() / 2;
mSelectedRadius = config.getSelectedWidth() / 2;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
mNormalRadius = config.getNormalWidth() / 2;
mSelectedRadius = config.getSelectedWidth() / 2;
//考虑当 选中和默认 的大小不一样的情况
maxRadius = Math.max(mSelectedRadius, mNormalRadius);
//间距*(总数-1)+选中宽度+默认宽度*(总数-1)
int width = (count - 1) * config.getIndicatorSpace() + config.getSelectedWidth() + config.getNormalWidth() * (count - 1);
setMeasuredDimension(width, Math.max(config.getNormalWidth(), config.getSelectedWidth()));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
float left = 0;
for (int i = 0; i < count; i++) {
mPaint.setColor(config.getCurrentPosition() == i ? config.getSelectedColor() : config.getNormalColor());
int indicatorWidth = config.getCurrentPosition() == i ? config.getSelectedWidth() : config.getNormalWidth();
int radius = config.getCurrentPosition() == i ? mSelectedRadius : mNormalRadius;
canvas.drawCircle(left + radius, maxRadius, radius, mPaint);
left += indicatorWidth + config.getIndicatorSpace();
}
// mPaint.setColor(config.getNormalColor());
// for (int i = 0; i < count; i++) {
// canvas.drawCircle(left + maxRadius, maxRadius, mNormalRadius, mPaint);
// left += config.getNormalWidth() + config.getIndicatorSpace();
// }
// mPaint.setColor(config.getSelectedColor());
// left = maxRadius + (config.getNormalWidth() + config.getIndicatorSpace()) * config.getCurrentPosition();
// canvas.drawCircle(left, maxRadius, mSelectedRadius, mPaint);
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/indicator/DrawableIndicator.java
================================================
package com.youth.banner.indicator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import com.youth.banner.R;
/**
* Drawable指示器
*/
public class DrawableIndicator extends BaseIndicator {
private Bitmap normalBitmap;
private Bitmap selectedBitmap;
/**
* 实例化Drawable指示器 ,也可以通过自定义属性设置
* @param context
* @param normalResId
* @param selectedResId
*/
public DrawableIndicator(Context context, @DrawableRes int normalResId, @DrawableRes int selectedResId) {
super(context);
normalBitmap = BitmapFactory.decodeResource(getResources(), normalResId);
selectedBitmap = BitmapFactory.decodeResource(getResources(), selectedResId);
}
public DrawableIndicator(Context context) {
this(context, null);
}
public DrawableIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawableIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableIndicator);
if (a != null) {
BitmapDrawable normal = (BitmapDrawable) a.getDrawable(R.styleable.DrawableIndicator_normal_drawable);
BitmapDrawable selected = (BitmapDrawable) a.getDrawable(R.styleable.DrawableIndicator_selected_drawable);
normalBitmap = normal.getBitmap();
selectedBitmap = selected.getBitmap();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
setMeasuredDimension(selectedBitmap.getWidth() * (count - 1) + selectedBitmap.getWidth() + config.getIndicatorSpace() * (count - 1),
Math.max(normalBitmap.getHeight(), selectedBitmap.getHeight()));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = config.getIndicatorSize();
if (count <= 1 || normalBitmap == null || selectedBitmap == null) {
return;
}
float left = 0;
for (int i = 0; i < count; i++) {
canvas.drawBitmap(config.getCurrentPosition() == i ? selectedBitmap : normalBitmap, left, 0, mPaint);
left += normalBitmap.getWidth() + config.getIndicatorSpace();
}
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/indicator/Indicator.java
================================================
package com.youth.banner.indicator;
import android.view.View;
import androidx.annotation.NonNull;
import com.youth.banner.config.IndicatorConfig;
import com.youth.banner.listener.OnPageChangeListener;
public interface Indicator extends OnPageChangeListener {
@NonNull
View getIndicatorView();
IndicatorConfig getIndicatorConfig();
void onPageChanged(int count, int currentPosition);
}
================================================
FILE: banner/src/main/java/com/youth/banner/indicator/RectangleIndicator.java
================================================
package com.youth.banner.indicator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.util.AttributeSet;
import com.youth.banner.config.BannerConfig;
/**
* 矩形(条形)指示器
* 1、可以设置选中和默认的宽度、指示器的圆角
* 2、如果需要正方形将圆角设置为0,可将宽度和高度设置为一样
* 3、如果不想选中时变长,可将选中的宽度和默认宽度设置为一样
*/
public class RectangleIndicator extends BaseIndicator {
RectF rectF;
public RectangleIndicator(Context context) {
this(context, null);
}
public RectangleIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RectangleIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
rectF = new RectF();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
//间距*(总数-1)+默认宽度*(总数-1)+选中宽度
int space = config.getIndicatorSpace() * (count - 1);
int normal = config.getNormalWidth() * (count - 1);
setMeasuredDimension(space + normal + config.getSelectedWidth(), config.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = config.getIndicatorSize();
if (count <= 1) {
return;
}
float left = 0;
for (int i = 0; i < count; i++) {
mPaint.setColor(config.getCurrentPosition() == i ? config.getSelectedColor() : config.getNormalColor());
int indicatorWidth = config.getCurrentPosition() == i ? config.getSelectedWidth() : config.getNormalWidth();
rectF.set(left, 0, left + indicatorWidth, config.getHeight());
left += indicatorWidth + config.getIndicatorSpace();
canvas.drawRoundRect(rectF, config.getRadius(), config.getRadius(), mPaint);
}
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/indicator/RoundLinesIndicator.java
================================================
package com.youth.banner.indicator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import com.youth.banner.util.BannerUtils;
public class RoundLinesIndicator extends BaseIndicator {
public RoundLinesIndicator(Context context) {
this(context, null);
}
public RoundLinesIndicator(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundLinesIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = config.getIndicatorSize();
if (count <= 1) return;
setMeasuredDimension((int) (config.getSelectedWidth() * count), config.getHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = config.getIndicatorSize();
if (count <= 1) return;
mPaint.setColor(config.getNormalColor());
RectF oval = new RectF(0, 0, canvas.getWidth(), config.getHeight());
canvas.drawRoundRect(oval, config.getRadius(), config.getRadius(), mPaint);
mPaint.setColor(config.getSelectedColor());
int left = config.getCurrentPosition() * config.getSelectedWidth();
RectF rectF = new RectF(left, 0, left + config.getSelectedWidth(), config.getHeight());
canvas.drawRoundRect(rectF, config.getRadius(), config.getRadius(), mPaint);
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/itemdecoration/MarginDecoration.java
================================================
package com.youth.banner.itemdecoration;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Px;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.youth.banner.util.BannerUtils;
public class MarginDecoration extends RecyclerView.ItemDecoration {
private int mMarginPx;
public MarginDecoration(@Px int margin) {
mMarginPx = margin;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent,
@NonNull RecyclerView.State state) {
LinearLayoutManager linearLayoutManager = requireLinearLayoutManager(parent);
if (linearLayoutManager.getOrientation() == LinearLayoutManager.VERTICAL) {
outRect.top = mMarginPx;
outRect.bottom = mMarginPx;
} else {
outRect.left = mMarginPx;
outRect.right = mMarginPx;
}
}
private LinearLayoutManager requireLinearLayoutManager(@NonNull RecyclerView parent) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
return (LinearLayoutManager) layoutManager;
}
throw new IllegalStateException("The layoutManager must be LinearLayoutManager");
}
}
================================================
FILE: banner/src/main/java/com/youth/banner/listener/OnBannerListener.java
================================================
package com.youth.banner.listener;
public interface OnBannerListener<T> {
/**
* 点击事件
*
* @param data 数据实体
* @param position 当前位置
*/
void OnBannerClick(T data, int position);
}
================================================
FILE: banner/src/main/java/com/youth/banner/listener/OnPageChangeListener.java
================================================
package com.youth.banner.listener;
import androidx.annotation.Px;
import androidx.viewpager2.widget.ViewPager2;
public interface OnPageChangeListener {
/**
* This method will be invoked when the current page is scrolled, either as part
* of a programmatically initiated smooth scroll or a user initiated touch scroll.
*
* @param position Position index of the first page currently being displayed.
* Page position+1 will be visible if positionOffset is nonzero.
* @param positionOffset Value from [0, 1) indicating the offset from the page at position.
* @param positionOffsetPixels Value in pixels indicating the offset from position.
*/
void onPageScrolled(int position, float positionOffset, @Px int positionOffsetPixels);
/**
* This method will be invoked when a new page becomes selected. Animation is not
* necessarily complete.
*
* @param position Position index of the new selected page.
*/
void onPageSelected(int position);
/**
gitextract_a7zjbpp5/
├── .gitignore
├── BannerExample.iml
├── LICENSE
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── test/
│ │ └── banner/
│ │ ├── MainActivity.java
│ │ ├── adapter/
│ │ │ ├── ImageAdapter.java
│ │ │ ├── ImageNetAdapter.java
│ │ │ ├── ImageTitleAdapter.java
│ │ │ ├── ImageTitleNumAdapter.java
│ │ │ ├── MultipleTypesAdapter.java
│ │ │ ├── MyRecyclerViewAdapter.java
│ │ │ └── TopLineAdapter.java
│ │ ├── bean/
│ │ │ └── DataBean.java
│ │ ├── indicator/
│ │ │ └── NumIndicator.java
│ │ ├── ui/
│ │ │ ├── BannerFragment.java
│ │ │ ├── BannerListFragment.java
│ │ │ ├── BlankFragment.java
│ │ │ ├── ConstraintLayoutBannerActivity.java
│ │ │ ├── GalleryActivity.java
│ │ │ ├── RecyclerViewBannerActivity.java
│ │ │ ├── TVActivity.java
│ │ │ ├── TouTiaoActivity.java
│ │ │ ├── VideoActivity.java
│ │ │ └── Vp2FragmentRecyclerviewActivity.java
│ │ ├── util/
│ │ │ ├── ParentRecyclerView.java
│ │ │ └── TabLayoutMediator.java
│ │ └── viewholder/
│ │ ├── ImageHolder.java
│ │ ├── ImageTitleHolder.java
│ │ ├── TitleHolder.java
│ │ └── VideoHolder.java
│ └── res/
│ ├── drawable/
│ │ ├── background.xml
│ │ ├── default_selecter.xml
│ │ ├── green.xml
│ │ ├── selected_radius.xml
│ │ ├── unselected_radius.xml
│ │ └── white.xml
│ ├── layout/
│ │ ├── activity_constraint_layout_banner.xml
│ │ ├── activity_gallery.xml
│ │ ├── activity_main.xml
│ │ ├── activity_recyclerview_banner.xml
│ │ ├── activity_t_v.xml
│ │ ├── activity_tou_tiao.xml
│ │ ├── activity_video.xml
│ │ ├── activity_vp2_fragment_recyclerview.xml
│ │ ├── banner.xml
│ │ ├── banner_image.xml
│ │ ├── banner_image_title.xml
│ │ ├── banner_image_title_num.xml
│ │ ├── banner_title.xml
│ │ ├── banner_video.xml
│ │ ├── item.xml
│ │ ├── test.xml
│ │ └── top_line_item2.xml
│ ├── values/
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-w820dp/
│ └── dimens.xml
├── banner/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── youth/
│ │ └── banner/
│ │ ├── Banner.java
│ │ ├── adapter/
│ │ │ ├── BannerAdapter.java
│ │ │ └── BannerImageAdapter.java
│ │ ├── config/
│ │ │ ├── BannerConfig.java
│ │ │ └── IndicatorConfig.java
│ │ ├── holder/
│ │ │ ├── BannerImageHolder.java
│ │ │ └── IViewHolder.java
│ │ ├── indicator/
│ │ │ ├── BaseIndicator.java
│ │ │ ├── CircleIndicator.java
│ │ │ ├── DrawableIndicator.java
│ │ │ ├── Indicator.java
│ │ │ ├── RectangleIndicator.java
│ │ │ └── RoundLinesIndicator.java
│ │ ├── itemdecoration/
│ │ │ └── MarginDecoration.java
│ │ ├── listener/
│ │ │ ├── OnBannerListener.java
│ │ │ └── OnPageChangeListener.java
│ │ ├── transformer/
│ │ │ ├── AlphaPageTransformer.java
│ │ │ ├── BasePageTransformer.java
│ │ │ ├── DepthPageTransformer.java
│ │ │ ├── MZScaleInTransformer.java
│ │ │ ├── RotateDownPageTransformer.java
│ │ │ ├── RotateUpPageTransformer.java
│ │ │ ├── RotateYTransformer.java
│ │ │ ├── ScaleInTransformer.java
│ │ │ └── ZoomOutPageTransformer.java
│ │ └── util/
│ │ ├── BannerLifecycleObserver.java
│ │ ├── BannerLifecycleObserverAdapter.java
│ │ ├── BannerUtils.java
│ │ ├── LogUtils.java
│ │ └── ScrollSpeedManger.java
│ └── res/
│ └── values/
│ ├── attr.xml
│ ├── ids.xml
│ └── strings.xml
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle
├── update_message.md
└── usekotlin/
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── com/
│ └── spring/
│ └── usekotlin/
│ └── ExampleInstrumentedTest.kt
├── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── spring/
│ │ └── usekotlin/
│ │ ├── ImageAdapter.kt
│ │ └── MainActivity.kt
│ └── res/
│ ├── layout/
│ │ └── activity_main.xml
│ └── values/
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
└── test/
└── java/
└── com/
└── spring/
└── usekotlin/
└── ExampleUnitTest.kt
SYMBOL INDEX (385 symbols across 56 files)
FILE: app/src/main/java/com/test/banner/MainActivity.java
class MainActivity (line 45) | public class MainActivity extends AppCompatActivity {
method onCreate (line 53) | @Override
method click (line 102) | @OnClick({R.id.style_image, R.id.style_image_title, R.id.style_image_t...
FILE: app/src/main/java/com/test/banner/adapter/ImageAdapter.java
class ImageAdapter (line 15) | public class ImageAdapter extends BannerAdapter<DataBean, ImageHolder> {
method ImageAdapter (line 17) | public ImageAdapter(List<DataBean> mDatas) {
method updateData (line 23) | public void updateData(List<DataBean> data) {
method onCreateHolder (line 32) | @Override
method onBindView (line 44) | @Override
FILE: app/src/main/java/com/test/banner/adapter/ImageNetAdapter.java
class ImageNetAdapter (line 34) | public class ImageNetAdapter extends BannerAdapter<DataBean, ImageHolder> {
method ImageNetAdapter (line 36) | public ImageNetAdapter(List<DataBean> mDatas) {
method onCreateHolder (line 40) | @Override
method onBindView (line 50) | @Override
FILE: app/src/main/java/com/test/banner/adapter/ImageTitleAdapter.java
class ImageTitleAdapter (line 19) | public class ImageTitleAdapter extends BannerAdapter<DataBean, ImageTitl...
method ImageTitleAdapter (line 21) | public ImageTitleAdapter(List<DataBean> mDatas) {
method onCreateHolder (line 25) | @Override
method onBindView (line 30) | @Override
FILE: app/src/main/java/com/test/banner/adapter/ImageTitleNumAdapter.java
class ImageTitleNumAdapter (line 21) | public class ImageTitleNumAdapter extends BannerAdapter<DataBean, ImageT...
method ImageTitleNumAdapter (line 23) | public ImageTitleNumAdapter(List<DataBean> mDatas) {
method onCreateHolder (line 29) | @Override
method onBindView (line 38) | @Override
class BannerViewHolder (line 47) | class BannerViewHolder extends RecyclerView.ViewHolder {
method BannerViewHolder (line 52) | public BannerViewHolder(@NonNull View view) {
FILE: app/src/main/java/com/test/banner/adapter/MultipleTypesAdapter.java
class MultipleTypesAdapter (line 25) | public class MultipleTypesAdapter extends BannerAdapter<DataBean, Recycl...
method MultipleTypesAdapter (line 29) | public MultipleTypesAdapter(Context context, List<DataBean> mDatas) {
method onCreateHolder (line 34) | @Override
method getItemViewType (line 47) | @Override
method onBindView (line 57) | @Override
method getVHMap (line 87) | public SparseArray<RecyclerView.ViewHolder> getVHMap() {
FILE: app/src/main/java/com/test/banner/adapter/MyRecyclerViewAdapter.java
class MyRecyclerViewAdapter (line 20) | public class MyRecyclerViewAdapter extends RecyclerView.Adapter {
method MyRecyclerViewAdapter (line 23) | public MyRecyclerViewAdapter(Context context) {
method onCreateViewHolder (line 27) | @NonNull
method onBindViewHolder (line 37) | @Override
method getItemViewType (line 51) | @Override
method getItemCount (line 60) | @Override
class MyViewHolder (line 90) | class MyViewHolder extends RecyclerView.ViewHolder {
method MyViewHolder (line 93) | public MyViewHolder(@NonNull View itemView) {
class MyBannerViewHolder (line 99) | class MyBannerViewHolder extends RecyclerView.ViewHolder {
method MyBannerViewHolder (line 102) | public MyBannerViewHolder(@NonNull View itemView) {
FILE: app/src/main/java/com/test/banner/adapter/TopLineAdapter.java
class TopLineAdapter (line 20) | public class TopLineAdapter extends BannerAdapter<DataBean, TopLineAdapt...
method TopLineAdapter (line 22) | public TopLineAdapter(List<DataBean> mDatas) {
method onCreateHolder (line 26) | @Override
method onBindView (line 31) | @Override
class TopLineHolder (line 43) | class TopLineHolder extends RecyclerView.ViewHolder {
method TopLineHolder (line 47) | public TopLineHolder(@NonNull View view) {
FILE: app/src/main/java/com/test/banner/bean/DataBean.java
class DataBean (line 9) | public class DataBean {
method DataBean (line 15) | public DataBean(Integer imageRes, String title, int viewType) {
method DataBean (line 21) | public DataBean(String imageUrl, String title, int viewType) {
method getTestData (line 27) | public static List<DataBean> getTestData() {
method getTestData2 (line 38) | public static List<DataBean> getTestData2() {
method getTestDataVideo (line 52) | public static List<DataBean> getTestDataVideo() {
method getTestData3 (line 63) | public static List<DataBean> getTestData3() {
method getVideos (line 73) | public static List<DataBean> getVideos() {
method getColors (line 85) | public static List<String> getColors(int size) {
method getRandColor (line 99) | public static String getRandColor() {
FILE: app/src/main/java/com/test/banner/indicator/NumIndicator.java
class NumIndicator (line 18) | public class NumIndicator extends BaseIndicator {
method NumIndicator (line 23) | public NumIndicator(Context context) {
method NumIndicator (line 27) | public NumIndicator(Context context, AttributeSet attrs) {
method NumIndicator (line 31) | public NumIndicator(Context context, AttributeSet attrs, int defStyleA...
method onMeasure (line 40) | @Override
method onDraw (line 50) | @Override
FILE: app/src/main/java/com/test/banner/ui/BannerFragment.java
class BannerFragment (line 22) | public class BannerFragment extends Fragment {
method newInstance (line 27) | public static Fragment newInstance() {
method onCreateView (line 31) | @Nullable
method onViewCreated (line 39) | @Override
method onStart (line 48) | @Override
method onStop (line 54) | @Override
FILE: app/src/main/java/com/test/banner/ui/BannerListFragment.java
class BannerListFragment (line 22) | public class BannerListFragment extends Fragment {
method newInstance (line 29) | public static Fragment newInstance(int i) {
method onCreateView (line 34) | @Nullable
method onViewCreated (line 42) | @Override
FILE: app/src/main/java/com/test/banner/ui/BlankFragment.java
class BlankFragment (line 29) | public class BlankFragment extends Fragment {
method newInstance (line 31) | public static Fragment newInstance() {
method onCreateView (line 35) | @Nullable
method onActivityCreated (line 41) | @Override
FILE: app/src/main/java/com/test/banner/ui/ConstraintLayoutBannerActivity.java
class ConstraintLayoutBannerActivity (line 23) | public class ConstraintLayoutBannerActivity extends AppCompatActivity {
method onCreate (line 28) | @Override
FILE: app/src/main/java/com/test/banner/ui/GalleryActivity.java
class GalleryActivity (line 20) | public class GalleryActivity extends AppCompatActivity {
method onCreate (line 29) | @Override
FILE: app/src/main/java/com/test/banner/ui/RecyclerViewBannerActivity.java
class RecyclerViewBannerActivity (line 18) | public class RecyclerViewBannerActivity extends AppCompatActivity {
method onCreate (line 22) | @Override
FILE: app/src/main/java/com/test/banner/ui/TVActivity.java
class TVActivity (line 19) | public class TVActivity extends AppCompatActivity {
method onCreate (line 25) | @Override
method onKeyDown (line 35) | @Override
FILE: app/src/main/java/com/test/banner/ui/TouTiaoActivity.java
class TouTiaoActivity (line 17) | public class TouTiaoActivity extends AppCompatActivity {
method onCreate (line 21) | @Override
FILE: app/src/main/java/com/test/banner/ui/VideoActivity.java
class VideoActivity (line 25) | public class VideoActivity extends AppCompatActivity {
method onCreate (line 30) | @Override
method stopVideo (line 59) | private void stopVideo(int position) {
method onPause (line 76) | @Override
method onResume (line 83) | @Override
method onDestroy (line 90) | @Override
method onBackPressed (line 96) | @Override
FILE: app/src/main/java/com/test/banner/ui/Vp2FragmentRecyclerviewActivity.java
class Vp2FragmentRecyclerviewActivity (line 21) | public class Vp2FragmentRecyclerviewActivity extends AppCompatActivity {
method onCreate (line 30) | @Override
FILE: app/src/main/java/com/test/banner/util/ParentRecyclerView.java
class ParentRecyclerView (line 11) | public class ParentRecyclerView extends RecyclerView {
method ParentRecyclerView (line 12) | public ParentRecyclerView(@NonNull Context context) {
method ParentRecyclerView (line 16) | public ParentRecyclerView(@NonNull Context context, @Nullable Attribut...
method ParentRecyclerView (line 20) | public ParentRecyclerView(@NonNull Context context, @Nullable Attribut...
method dispatchTouchEvent (line 26) | @Override
FILE: app/src/main/java/com/test/banner/util/TabLayoutMediator.java
class TabLayoutMediator (line 31) | @RestrictTo(LIBRARY_GROUP)
type OnConfigureTabCallback (line 48) | public interface OnConfigureTabCallback {
method onConfigureTab (line 57) | void onConfigureTab(@NonNull TabLayout.Tab tab, int position);
method TabLayoutMediator (line 68) | public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPa...
method TabLayoutMediator (line 83) | public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPa...
method attach (line 96) | public void attach() {
method detach (line 132) | public void detach() {
method populateTabsFromPagerAdapter (line 142) | @SuppressWarnings("WeakerAccess")
class TabLayoutOnPageChangeCallback (line 172) | private static class TabLayoutOnPageChangeCallback extends ViewPager2....
method TabLayoutOnPageChangeCallback (line 177) | TabLayoutOnPageChangeCallback(TabLayout tabLayout) {
method onPageScrollStateChanged (line 182) | @Override
method onPageScrolled (line 188) | @Override
method onPageSelected (line 205) | @Override
method reset (line 220) | void reset() {
method setScrollPosition (line 252) | @SuppressWarnings("WeakerAccess")
method selectTab (line 267) | @SuppressWarnings("WeakerAccess")
method throwMethodNotFound (line 280) | private static void throwMethodNotFound(String method) {
method throwInvokeFailed (line 284) | private static void throwInvokeFailed(String method) {
class ViewPagerOnTabSelectedListener (line 294) | private static class ViewPagerOnTabSelectedListener implements TabLayo...
method ViewPagerOnTabSelectedListener (line 297) | ViewPagerOnTabSelectedListener(ViewPager2 viewPager) {
method onTabSelected (line 301) | @Override
method onTabUnselected (line 306) | @Override
method onTabReselected (line 311) | @Override
class PagerAdapterObserver (line 317) | private class PagerAdapterObserver extends RecyclerView.AdapterDataObs...
method PagerAdapterObserver (line 318) | PagerAdapterObserver() {}
method onChanged (line 320) | @Override
method onItemRangeChanged (line 325) | @Override
method onItemRangeChanged (line 330) | @Override
method onItemRangeInserted (line 335) | @Override
method onItemRangeRemoved (line 340) | @Override
method onItemRangeMoved (line 345) | @Override
FILE: app/src/main/java/com/test/banner/viewholder/ImageHolder.java
class ImageHolder (line 9) | public class ImageHolder extends RecyclerView.ViewHolder {
method ImageHolder (line 12) | public ImageHolder(@NonNull View view) {
FILE: app/src/main/java/com/test/banner/viewholder/ImageTitleHolder.java
class ImageTitleHolder (line 12) | public class ImageTitleHolder extends RecyclerView.ViewHolder {
method ImageTitleHolder (line 16) | public ImageTitleHolder(@NonNull View view) {
FILE: app/src/main/java/com/test/banner/viewholder/TitleHolder.java
class TitleHolder (line 12) | public class TitleHolder extends RecyclerView.ViewHolder {
method TitleHolder (line 15) | public TitleHolder(@NonNull View view) {
FILE: app/src/main/java/com/test/banner/viewholder/VideoHolder.java
class VideoHolder (line 11) | public class VideoHolder extends RecyclerView.ViewHolder {
method VideoHolder (line 14) | public VideoHolder(@NonNull View view) {
FILE: banner/src/main/java/com/youth/banner/Banner.java
class Banner (line 54) | public class Banner<T, BA extends BannerAdapter<T, ? extends RecyclerVie...
method Banner (line 116) | public Banner(Context context) {
method Banner (line 120) | public Banner(Context context, AttributeSet attrs) {
method Banner (line 124) | public Banner(Context context, AttributeSet attrs, int defStyleAttr) {
method init (line 130) | private void init(Context context) {
method initTypedArray (line 152) | private void initTypedArray(Context context, AttributeSet attrs) {
method initIndicatorAttr (line 183) | private void initIndicatorAttr() {
method dispatchTouchEvent (line 219) | @Override
method onInterceptTouchEvent (line 236) | @Override
method dispatchDraw (line 267) | @Override
method drawTopLeft (line 300) | private void drawTopLeft(Canvas canvas) {
method drawTopRight (line 310) | private void drawTopRight(Canvas canvas) {
method drawBottomLeft (line 321) | private void drawBottomLeft(Canvas canvas) {
method drawBottomRight (line 332) | private void drawBottomRight(Canvas canvas) {
method onAttachedToWindow (line 344) | @Override
method onDetachedFromWindow (line 350) | @Override
class BannerOnPageChangeCallback (line 356) | class BannerOnPageChangeCallback extends ViewPager2.OnPageChangeCallba...
method onPageScrolled (line 360) | @Override
method onPageSelected (line 371) | @Override
method onPageScrollStateChanged (line 385) | @Override
class AutoLoopTask (line 411) | static class AutoLoopTask implements Runnable {
method AutoLoopTask (line 414) | AutoLoopTask(Banner banner) {
method run (line 418) | @Override
method onChanged (line 434) | @Override
method initIndicator (line 445) | private void initIndicator() {
method setInfiniteLoop (line 457) | private void setInfiniteLoop() {
method setRecyclerViewPadding (line 465) | private void setRecyclerViewPadding(int itemPadding) {
method setRecyclerViewPadding (line 469) | private void setRecyclerViewPadding(int leftItemPadding, int rightItem...
method getCurrentItem (line 486) | public int getCurrentItem() {
method getItemCount (line 490) | public int getItemCount() {
method getScrollTime (line 498) | public int getScrollTime() {
method isInfiniteLoop (line 502) | public boolean isInfiniteLoop() {
method getAdapter (line 506) | public BannerAdapter getAdapter() {
method getViewPager2 (line 510) | public ViewPager2 getViewPager2() {
method getIndicator (line 514) | public Indicator getIndicator() {
method getIndicatorConfig (line 518) | public IndicatorConfig getIndicatorConfig() {
method getRealCount (line 528) | public int getRealCount() {
method setIntercept (line 543) | public Banner setIntercept(boolean intercept) {
method setCurrentItem (line 553) | public Banner setCurrentItem(int position) {
method setCurrentItem (line 563) | public Banner setCurrentItem(int position, boolean smoothScroll) {
method setIndicatorPageChange (line 568) | public Banner setIndicatorPageChange() {
method removeIndicator (line 576) | public Banner removeIndicator() {
method setStartPosition (line 587) | public Banner setStartPosition(int mStartPosition) {
method getStartPosition (line 592) | public int getStartPosition() {
method setUserInputEnabled (line 601) | public Banner setUserInputEnabled(boolean enabled) {
method addPageTransformer (line 611) | public Banner addPageTransformer(@Nullable ViewPager2.PageTransformer ...
method setPageTransformer (line 619) | public Banner setPageTransformer(@Nullable ViewPager2.PageTransformer ...
method removeTransformer (line 624) | public Banner removeTransformer(ViewPager2.PageTransformer transformer) {
method addItemDecoration (line 632) | public Banner addItemDecoration(RecyclerView.ItemDecoration decor) {
method addItemDecoration (line 637) | public Banner addItemDecoration(RecyclerView.ItemDecoration decor, int...
method isAutoLoop (line 647) | public Banner isAutoLoop(boolean isAutoLoop) {
method setLoopTime (line 658) | public Banner setLoopTime(long loopTime) {
method setScrollTime (line 666) | public Banner setScrollTime(int scrollTime) {
method start (line 674) | public Banner start() {
method stop (line 685) | public Banner stop() {
method destroy (line 695) | public void destroy() {
method setAdapter (line 706) | public Banner setAdapter(BA adapter) {
method setAdapter (line 727) | public Banner setAdapter(BA adapter,boolean isInfiniteLoop) {
method setDatas (line 739) | public Banner setDatas(List<T> datas) {
method setOrientation (line 754) | public Banner setOrientation(@Orientation int orientation) {
method setTouchSlop (line 762) | public Banner setTouchSlop(int mTouchSlop) {
method setOnBannerListener (line 770) | public Banner setOnBannerListener(OnBannerListener<T> listener) {
method addOnPageChangeListener (line 784) | public Banner addOnPageChangeListener(OnPageChangeListener pageListene...
method setBannerRound (line 796) | public Banner setBannerRound(float radius) {
method setBannerRound2 (line 804) | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
method setBannerGalleryEffect (line 816) | public Banner setBannerGalleryEffect(int itemWidth, int pageMargin) {
method setBannerGalleryEffect (line 827) | public Banner setBannerGalleryEffect(int leftItemWidth, int rightItemW...
method setBannerGalleryEffect (line 838) | public Banner setBannerGalleryEffect(int itemWidth, int pageMargin, fl...
method setBannerGalleryEffect (line 850) | public Banner setBannerGalleryEffect(int leftItemWidth, int rightItemW...
method setBannerGalleryMZ (line 867) | public Banner setBannerGalleryMZ(int itemWidth) {
method setBannerGalleryMZ (line 877) | public Banner setBannerGalleryMZ(int itemWidth, float scale) {
method setIndicator (line 894) | public Banner setIndicator(Indicator indicator) {
method setIndicator (line 905) | public Banner setIndicator(Indicator indicator, boolean attachToBanner) {
method setIndicatorSelectedColor (line 914) | public Banner setIndicatorSelectedColor(@ColorInt int color) {
method setIndicatorSelectedColorRes (line 921) | public Banner setIndicatorSelectedColorRes(@ColorRes int color) {
method setIndicatorNormalColor (line 926) | public Banner setIndicatorNormalColor(@ColorInt int color) {
method setIndicatorNormalColorRes (line 933) | public Banner setIndicatorNormalColorRes(@ColorRes int color) {
method setIndicatorGravity (line 938) | public Banner setIndicatorGravity(@IndicatorConfig.Direction int gravi...
method setIndicatorSpace (line 946) | public Banner setIndicatorSpace(int indicatorSpace) {
method setIndicatorMargins (line 953) | public Banner setIndicatorMargins(IndicatorConfig.Margins margins) {
method setIndicatorWidth (line 961) | public Banner setIndicatorWidth(int normalWidth, int selectedWidth) {
method setIndicatorNormalWidth (line 969) | public Banner setIndicatorNormalWidth(int normalWidth) {
method setIndicatorSelectedWidth (line 976) | public Banner setIndicatorSelectedWidth(int selectedWidth) {
method setIndicatorRadius (line 983) | public Banner setIndicatorRadius(int indicatorRadius) {
method setIndicatorHeight (line 990) | public Banner setIndicatorHeight(int indicatorHeight) {
method addBannerLifecycleObserver (line 1003) | public Banner addBannerLifecycleObserver(LifecycleOwner owner) {
method onStart (line 1010) | @Override
method onStop (line 1015) | @Override
method onDestroy (line 1020) | @Override
FILE: banner/src/main/java/com/youth/banner/adapter/BannerAdapter.java
class BannerAdapter (line 21) | public abstract class BannerAdapter<T, VH extends RecyclerView.ViewHolde...
method BannerAdapter (line 27) | public BannerAdapter(List<T> datas) {
method setDatas (line 36) | public void setDatas(List<T> datas) {
method getData (line 51) | public T getData(int position) {
method getRealData (line 64) | public T getRealData(int position) {
method onBindViewHolder (line 73) | @Override
method onCreateViewHolder (line 86) | @NonNull
method getItemCount (line 101) | @Override
method getRealCount (line 106) | public int getRealCount() {
method getRealPosition (line 110) | public int getRealPosition(int position) {
method setOnBannerListener (line 114) | public void setOnBannerListener(OnBannerListener<T> listener) {
method getViewHolder (line 118) | public VH getViewHolder() {
method setIncreaseCount (line 122) | public void setIncreaseCount(int increaseCount) {
FILE: banner/src/main/java/com/youth/banner/adapter/BannerImageAdapter.java
class BannerImageAdapter (line 13) | public abstract class BannerImageAdapter<T> extends BannerAdapter<T, Ban...
method BannerImageAdapter (line 15) | public BannerImageAdapter(List<T> mData) {
method onCreateHolder (line 19) | @Override
FILE: banner/src/main/java/com/youth/banner/config/BannerConfig.java
class BannerConfig (line 27) | public class BannerConfig {
FILE: banner/src/main/java/com/youth/banner/config/IndicatorConfig.java
class IndicatorConfig (line 9) | public class IndicatorConfig {
class Margins (line 38) | public static class Margins {
method Margins (line 44) | public Margins() {
method Margins (line 48) | public Margins(int marginSize) {
method Margins (line 52) | public Margins(int leftMargin, int topMargin, int rightMargin, int b...
method getMargins (line 60) | public Margins getMargins() {
method setMargins (line 67) | public IndicatorConfig setMargins(Margins margins) {
method getIndicatorSize (line 72) | public int getIndicatorSize() {
method setIndicatorSize (line 76) | public IndicatorConfig setIndicatorSize(int indicatorSize) {
method getNormalColor (line 81) | public int getNormalColor() {
method setNormalColor (line 85) | public IndicatorConfig setNormalColor(int normalColor) {
method getSelectedColor (line 90) | public int getSelectedColor() {
method setSelectedColor (line 94) | public IndicatorConfig setSelectedColor(int selectedColor) {
method getIndicatorSpace (line 99) | public int getIndicatorSpace() {
method setIndicatorSpace (line 103) | public IndicatorConfig setIndicatorSpace(int indicatorSpace) {
method getCurrentPosition (line 108) | public int getCurrentPosition() {
method setCurrentPosition (line 112) | public IndicatorConfig setCurrentPosition(int currentPosition) {
method getNormalWidth (line 117) | public int getNormalWidth() {
method setNormalWidth (line 121) | public IndicatorConfig setNormalWidth(int normalWidth) {
method getSelectedWidth (line 126) | public int getSelectedWidth() {
method setSelectedWidth (line 130) | public IndicatorConfig setSelectedWidth(int selectedWidth) {
method getGravity (line 135) | public int getGravity() {
method setGravity (line 139) | public IndicatorConfig setGravity(@Direction int gravity) {
method isAttachToBanner (line 144) | public boolean isAttachToBanner() {
method setAttachToBanner (line 148) | public IndicatorConfig setAttachToBanner(boolean attachToBanner) {
method getRadius (line 153) | public int getRadius() {
method setRadius (line 157) | public IndicatorConfig setRadius(int radius) {
method getHeight (line 162) | public int getHeight() {
method setHeight (line 166) | public IndicatorConfig setHeight(int height) {
FILE: banner/src/main/java/com/youth/banner/holder/BannerImageHolder.java
class BannerImageHolder (line 9) | public
method BannerImageHolder (line 13) | public BannerImageHolder(@NonNull View view) {
FILE: banner/src/main/java/com/youth/banner/holder/IViewHolder.java
type IViewHolder (line 5) | public interface IViewHolder<T, VH> {
method onCreateHolder (line 12) | VH onCreateHolder(ViewGroup parent, int viewType);
method onBindView (line 22) | void onBindView(VH holder, T data, int position, int size);
FILE: banner/src/main/java/com/youth/banner/indicator/BaseIndicator.java
class BaseIndicator (line 20) | public class BaseIndicator extends View implements Indicator {
method BaseIndicator (line 25) | public BaseIndicator(Context context) {
method BaseIndicator (line 29) | public BaseIndicator(Context context, @Nullable AttributeSet attrs) {
method BaseIndicator (line 33) | public BaseIndicator(Context context, @Nullable AttributeSet attrs, in...
method getIndicatorView (line 42) | @NonNull
method getIndicatorConfig (line 68) | @Override
method onPageChanged (line 73) | @Override
method onPageScrolled (line 80) | @Override
method onPageSelected (line 87) | @Override
method onPageScrollStateChanged (line 93) | @Override
FILE: banner/src/main/java/com/youth/banner/indicator/CircleIndicator.java
class CircleIndicator (line 11) | public class CircleIndicator extends BaseIndicator {
method CircleIndicator (line 16) | public CircleIndicator(Context context) {
method CircleIndicator (line 20) | public CircleIndicator(Context context, AttributeSet attrs) {
method CircleIndicator (line 24) | public CircleIndicator(Context context, AttributeSet attrs, int defSty...
method onMeasure (line 30) | @Override
method onDraw (line 47) | @Override
FILE: banner/src/main/java/com/youth/banner/indicator/DrawableIndicator.java
class DrawableIndicator (line 22) | public class DrawableIndicator extends BaseIndicator {
method DrawableIndicator (line 32) | public DrawableIndicator(Context context, @DrawableRes int normalResId...
method DrawableIndicator (line 38) | public DrawableIndicator(Context context) {
method DrawableIndicator (line 42) | public DrawableIndicator(Context context, AttributeSet attrs) {
method DrawableIndicator (line 46) | public DrawableIndicator(Context context, AttributeSet attrs, int defS...
method onMeasure (line 57) | @Override
method onDraw (line 68) | @Override
FILE: banner/src/main/java/com/youth/banner/indicator/Indicator.java
type Indicator (line 10) | public interface Indicator extends OnPageChangeListener {
method getIndicatorView (line 11) | @NonNull
method getIndicatorConfig (line 14) | IndicatorConfig getIndicatorConfig();
method onPageChanged (line 16) | void onPageChanged(int count, int currentPosition);
FILE: banner/src/main/java/com/youth/banner/indicator/RectangleIndicator.java
class RectangleIndicator (line 16) | public class RectangleIndicator extends BaseIndicator {
method RectangleIndicator (line 19) | public RectangleIndicator(Context context) {
method RectangleIndicator (line 23) | public RectangleIndicator(Context context, AttributeSet attrs) {
method RectangleIndicator (line 27) | public RectangleIndicator(Context context, AttributeSet attrs, int def...
method onMeasure (line 32) | @Override
method onDraw (line 45) | @Override
FILE: banner/src/main/java/com/youth/banner/indicator/RoundLinesIndicator.java
class RoundLinesIndicator (line 13) | public class RoundLinesIndicator extends BaseIndicator {
method RoundLinesIndicator (line 15) | public RoundLinesIndicator(Context context) {
method RoundLinesIndicator (line 19) | public RoundLinesIndicator(Context context, @Nullable AttributeSet att...
method RoundLinesIndicator (line 23) | public RoundLinesIndicator(Context context, @Nullable AttributeSet att...
method onMeasure (line 28) | @Override
method onDraw (line 36) | @Override
FILE: banner/src/main/java/com/youth/banner/itemdecoration/MarginDecoration.java
class MarginDecoration (line 14) | public class MarginDecoration extends RecyclerView.ItemDecoration {
method MarginDecoration (line 17) | public MarginDecoration(@Px int margin) {
method getItemOffsets (line 21) | @Override
method requireLinearLayoutManager (line 34) | private LinearLayoutManager requireLinearLayoutManager(@NonNull Recycl...
FILE: banner/src/main/java/com/youth/banner/listener/OnBannerListener.java
type OnBannerListener (line 3) | public interface OnBannerListener<T> {
method OnBannerClick (line 11) | void OnBannerClick(T data, int position);
FILE: banner/src/main/java/com/youth/banner/listener/OnPageChangeListener.java
type OnPageChangeListener (line 7) | public interface OnPageChangeListener {
method onPageScrolled (line 17) | void onPageScrolled(int position, float positionOffset, @Px int positi...
method onPageSelected (line 25) | void onPageSelected(int position);
method onPageScrollStateChanged (line 35) | void onPageScrollStateChanged(@ViewPager2.ScrollState int state);
FILE: banner/src/main/java/com/youth/banner/transformer/AlphaPageTransformer.java
class AlphaPageTransformer (line 7) | public class AlphaPageTransformer extends BasePageTransformer {
method AlphaPageTransformer (line 11) | public AlphaPageTransformer() {
method AlphaPageTransformer (line 14) | public AlphaPageTransformer(float minAlpha) {
method transformPage (line 18) | @Override
FILE: banner/src/main/java/com/youth/banner/transformer/BasePageTransformer.java
class BasePageTransformer (line 5) | public abstract class BasePageTransformer implements ViewPager2.PageTran...
FILE: banner/src/main/java/com/youth/banner/transformer/DepthPageTransformer.java
class DepthPageTransformer (line 7) | public class DepthPageTransformer extends BasePageTransformer {
method DepthPageTransformer (line 11) | public DepthPageTransformer() {
method DepthPageTransformer (line 14) | public DepthPageTransformer(float minScale) {
method transformPage (line 18) | public void transformPage(View view, float position) {
FILE: banner/src/main/java/com/youth/banner/transformer/MZScaleInTransformer.java
class MZScaleInTransformer (line 13) | public class MZScaleInTransformer extends BasePageTransformer {
method MZScaleInTransformer (line 17) | public MZScaleInTransformer() {
method MZScaleInTransformer (line 20) | public MZScaleInTransformer(float minScale) {
method transformPage (line 24) | @Override
method requireViewPager (line 62) | private ViewPager2 requireViewPager(@NonNull View page) {
FILE: banner/src/main/java/com/youth/banner/transformer/RotateDownPageTransformer.java
class RotateDownPageTransformer (line 7) | public class RotateDownPageTransformer extends BasePageTransformer {
method RotateDownPageTransformer (line 11) | public RotateDownPageTransformer() {
method RotateDownPageTransformer (line 14) | public RotateDownPageTransformer(float maxRotate) {
method transformPage (line 18) | @Override
FILE: banner/src/main/java/com/youth/banner/transformer/RotateUpPageTransformer.java
class RotateUpPageTransformer (line 7) | public class RotateUpPageTransformer extends BasePageTransformer {
method RotateUpPageTransformer (line 11) | public RotateUpPageTransformer() {
method RotateUpPageTransformer (line 14) | public RotateUpPageTransformer(float maxRotate) {
method transformPage (line 18) | @Override
FILE: banner/src/main/java/com/youth/banner/transformer/RotateYTransformer.java
class RotateYTransformer (line 7) | public class RotateYTransformer extends BasePageTransformer {
method RotateYTransformer (line 11) | public RotateYTransformer() {
method RotateYTransformer (line 14) | public RotateYTransformer(float maxRotate) {
method transformPage (line 18) | @Override
FILE: banner/src/main/java/com/youth/banner/transformer/ScaleInTransformer.java
class ScaleInTransformer (line 12) | public class ScaleInTransformer extends BasePageTransformer {
method ScaleInTransformer (line 16) | public ScaleInTransformer() {
method ScaleInTransformer (line 19) | public ScaleInTransformer(float minScale) {
method transformPage (line 23) | @Override
FILE: banner/src/main/java/com/youth/banner/transformer/ZoomOutPageTransformer.java
class ZoomOutPageTransformer (line 8) | public class ZoomOutPageTransformer extends BasePageTransformer {
method ZoomOutPageTransformer (line 14) | public ZoomOutPageTransformer() {
method ZoomOutPageTransformer (line 17) | public ZoomOutPageTransformer(float minScale,float minAlpha ) {
method transformPage (line 22) | public void transformPage(View view, float position) {
FILE: banner/src/main/java/com/youth/banner/util/BannerLifecycleObserver.java
type BannerLifecycleObserver (line 6) | public interface BannerLifecycleObserver extends LifecycleObserver {
method onStop (line 8) | void onStop(LifecycleOwner owner);
method onStart (line 10) | void onStart(LifecycleOwner owner);
method onDestroy (line 12) | void onDestroy(LifecycleOwner owner);
FILE: banner/src/main/java/com/youth/banner/util/BannerLifecycleObserverAdapter.java
class BannerLifecycleObserverAdapter (line 8) | public class BannerLifecycleObserverAdapter implements LifecycleObserver {
method BannerLifecycleObserverAdapter (line 12) | public BannerLifecycleObserverAdapter(LifecycleOwner lifecycleOwner, B...
method onStart (line 17) | @OnLifecycleEvent(Lifecycle.Event.ON_START)
method onStop (line 23) | @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
method onDestroy (line 29) | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
FILE: banner/src/main/java/com/youth/banner/util/BannerUtils.java
class BannerUtils (line 16) | public class BannerUtils {
method getRealPosition (line 26) | public static int getRealPosition(boolean isIncrease, int position, in...
method getView (line 48) | public static View getView(@NonNull ViewGroup parent, @LayoutRes int l...
method dp2px (line 60) | public static int dp2px(float dp) {
method setBannerRound (line 70) | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
FILE: banner/src/main/java/com/youth/banner/util/LogUtils.java
class LogUtils (line 7) | public class LogUtils {
method d (line 12) | public static void d(String msg) {
method e (line 18) | public static void e(String msg) {
method i (line 24) | public static void i(String msg) {
method v (line 30) | public static void v( String msg) {
method w (line 36) | public static void w(String msg) {
FILE: banner/src/main/java/com/youth/banner/util/ScrollSpeedManger.java
class ScrollSpeedManger (line 16) | public class ScrollSpeedManger extends LinearLayoutManager {
method ScrollSpeedManger (line 19) | public ScrollSpeedManger(Banner banner, LinearLayoutManager linearLayo...
method smoothScrollToPosition (line 24) | @Override
method reflectLayoutManager (line 36) | public static void reflectLayoutManager(Banner banner) {
Condensed preview — 118 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (242K chars).
[
{
"path": ".gitignore",
"chars": 490,
"preview": "# 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# Generate"
},
{
"path": "BannerExample.iml",
"chars": 975,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"BannerExample\" external.linked.project.path=\""
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 10775,
"preview": "\r\n## Banner 2.0 全新升级\r\n> 只做一个可以自定义的轮播容器,不侵入UI ———— Banner 2.0\r\n\r\n```\r\n> 各位老铁反馈的问题我都有看,不是不解决,有时真的很难复现,\r\n> 如果能在提交问题时,有条件提供个"
},
{
"path": "app/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "app/build.gradle",
"chars": 1840,
"preview": "apply plugin: 'com.android.application'\n\nandroid {\n compileSdk 33\n\n defaultConfig {\n applicationId \"com.tes"
},
{
"path": "app/proguard-rules.pro",
"chars": 2210,
"preview": "#指定代码的压缩级别\n-optimizationpasses 5\n#包明不混合大小写\n-dontusemixedcaseclassnames\n#不去忽略非公共的库类\n-dontskipnonpubliclibraryclasses\n#优化 "
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 1289,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "app/src/main/java/com/test/banner/MainActivity.java",
"chars": 7765,
"preview": "package com.test.banner;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport and"
},
{
"path": "app/src/main/java/com/test/banner/adapter/ImageAdapter.java",
"chars": 1416,
"preview": "package com.test.banner.adapter;\n\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\n\nimport com.test.banne"
},
{
"path": "app/src/main/java/com/test/banner/adapter/ImageNetAdapter.java",
"chars": 2110,
"preview": "package com.test.banner.adapter;\n\nimport android.graphics.Bitmap;\nimport android.graphics.Outline;\nimport android.graphi"
},
{
"path": "app/src/main/java/com/test/banner/adapter/ImageTitleAdapter.java",
"chars": 995,
"preview": "package com.test.banner.adapter;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.View"
},
{
"path": "app/src/main/java/com/test/banner/adapter/ImageTitleNumAdapter.java",
"chars": 1892,
"preview": "package com.test.banner.adapter;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.View"
},
{
"path": "app/src/main/java/com/test/banner/adapter/MultipleTypesAdapter.java",
"chars": 3325,
"preview": "package com.test.banner.adapter;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.util.Spa"
},
{
"path": "app/src/main/java/com/test/banner/adapter/MyRecyclerViewAdapter.java",
"chars": 3537,
"preview": "package com.test.banner.adapter;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.util.Log"
},
{
"path": "app/src/main/java/com/test/banner/adapter/TopLineAdapter.java",
"chars": 1503,
"preview": "package com.test.banner.adapter;\n\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextVie"
},
{
"path": "app/src/main/java/com/test/banner/bean/DataBean.java",
"chars": 4455,
"preview": "package com.test.banner.bean;\n\nimport com.test.banner.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java"
},
{
"path": "app/src/main/java/com/test/banner/indicator/NumIndicator.java",
"chars": 1920,
"preview": "package com.test.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graph"
},
{
"path": "app/src/main/java/com/test/banner/ui/BannerFragment.java",
"chars": 1647,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimp"
},
{
"path": "app/src/main/java/com/test/banner/ui/BannerListFragment.java",
"chars": 1569,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimp"
},
{
"path": "app/src/main/java/com/test/banner/ui/BlankFragment.java",
"chars": 1844,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\n"
},
{
"path": "app/src/main/java/com/test/banner/ui/ConstraintLayoutBannerActivity.java",
"chars": 1504,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.KeyEvent;\n\nimport an"
},
{
"path": "app/src/main/java/com/test/banner/ui/GalleryActivity.java",
"chars": 1647,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.View;\n\nimport com.test.banner.R;\nimport com.t"
},
{
"path": "app/src/main/java/com/test/banner/ui/RecyclerViewBannerActivity.java",
"chars": 932,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport"
},
{
"path": "app/src/main/java/com/test/banner/ui/TVActivity.java",
"chars": 2183,
"preview": "package com.test.banner.ui;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport android.os.Bundle;\nimport android."
},
{
"path": "app/src/main/java/com/test/banner/ui/TouTiaoActivity.java",
"chars": 1215,
"preview": "package com.test.banner.ui;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport butterknife.BindView;\nimport butter"
},
{
"path": "app/src/main/java/com/test/banner/ui/VideoActivity.java",
"chars": 3128,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\nimport android.util.Log;\n\nimport com.shuyu.gsyvideoplayer.GSYVide"
},
{
"path": "app/src/main/java/com/test/banner/ui/Vp2FragmentRecyclerviewActivity.java",
"chars": 2043,
"preview": "package com.test.banner.ui;\n\nimport android.os.Bundle;\n\nimport com.google.android.material.tabs.TabLayout;\nimport com.te"
},
{
"path": "app/src/main/java/com/test/banner/util/ParentRecyclerView.java",
"chars": 1398,
"preview": "package com.test.banner.util;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.view.Mot"
},
{
"path": "app/src/main/java/com/test/banner/util/TabLayoutMediator.java",
"chars": 14220,
"preview": "package com.test.banner.util;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx."
},
{
"path": "app/src/main/java/com/test/banner/viewholder/ImageHolder.java",
"chars": 392,
"preview": "package com.test.banner.viewholder;\n\nimport android.view.View;\nimport android.widget.ImageView;\n\nimport androidx.annotat"
},
{
"path": "app/src/main/java/com/test/banner/viewholder/ImageTitleHolder.java",
"chars": 550,
"preview": "package com.test.banner.viewholder;\n\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.Te"
},
{
"path": "app/src/main/java/com/test/banner/viewholder/TitleHolder.java",
"chars": 457,
"preview": "package com.test.banner.viewholder;\n\nimport android.view.View;\nimport android.widget.ImageView;\nimport android.widget.Te"
},
{
"path": "app/src/main/java/com/test/banner/viewholder/VideoHolder.java",
"chars": 465,
"preview": "package com.test.banner.viewholder;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\nimport androidx.recy"
},
{
"path": "app/src/main/res/drawable/background.xml",
"chars": 224,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <gradient\n"
},
{
"path": "app/src/main/res/drawable/default_selecter.xml",
"chars": 335,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <item a"
},
{
"path": "app/src/main/res/drawable/green.xml",
"chars": 377,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:sha"
},
{
"path": "app/src/main/res/drawable/selected_radius.xml",
"chars": 224,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:sha"
},
{
"path": "app/src/main/res/drawable/unselected_radius.xml",
"chars": 214,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:sha"
},
{
"path": "app/src/main/res/drawable/white.xml",
"chars": 184,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:sha"
},
{
"path": "app/src/main/res/layout/activity_constraint_layout_banner.xml",
"chars": 1224,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas."
},
{
"path": "app/src/main/res/layout/activity_gallery.xml",
"chars": 1425,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout/activity_main.xml",
"chars": 6253,
"preview": "<androidx.swiperefreshlayout.widget.SwipeRefreshLayout\n xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout/activity_recyclerview_banner.xml",
"chars": 662,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/layout/activity_t_v.xml",
"chars": 1301,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas."
},
{
"path": "app/src/main/res/layout/activity_tou_tiao.xml",
"chars": 1942,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout\n xmlns:android=\"http://sche"
},
{
"path": "app/src/main/res/layout/activity_video.xml",
"chars": 667,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas."
},
{
"path": "app/src/main/res/layout/activity_vp2_fragment_recyclerview.xml",
"chars": 2609,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android=\"http://schema"
},
{
"path": "app/src/main/res/layout/banner.xml",
"chars": 449,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "app/src/main/res/layout/banner_image.xml",
"chars": 254,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ImageView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android"
},
{
"path": "app/src/main/res/layout/banner_image_title.xml",
"chars": 879,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n an"
},
{
"path": "app/src/main/res/layout/banner_image_title_num.xml",
"chars": 1476,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n an"
},
{
"path": "app/src/main/res/layout/banner_title.xml",
"chars": 495,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n an"
},
{
"path": "app/src/main/res/layout/banner_video.xml",
"chars": 393,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andro"
},
{
"path": "app/src/main/res/layout/item.xml",
"chars": 679,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.cardview.widget.CardView xmlns:android=\"http://schemas.android.com/apk/"
},
{
"path": "app/src/main/res/layout/test.xml",
"chars": 549,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/layout/top_line_item2.xml",
"chars": 1240,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n an"
},
{
"path": "app/src/main/res/values/arrays.xml",
"chars": 3750,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <array name=\"url\">\n <item>http://ww4.sinaimg.cn/large/006u"
},
{
"path": "app/src/main/res/values/colors.xml",
"chars": 330,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"colorPrimary\">@color/main_color</color>\n <color n"
},
{
"path": "app/src/main/res/values/dimens.xml",
"chars": 211,
"preview": "<resources>\n <!-- Default screen margins, per the Android Design guidelines. -->\n <dimen name=\"activity_horizontal"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 70,
"preview": "<resources>\n <string name=\"app_name\">Banner</string>\n\n</resources>\n"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 383,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "app/src/main/res/values-w820dp/dimens.xml",
"chars": 358,
"preview": "<resources>\n <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n (such as s"
},
{
"path": "banner/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "banner/build.gradle",
"chars": 2899,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'maven-publish'\napply plugin: 'signing'\n\nversion = '2.2.3'\n\nandroid {\n"
},
{
"path": "banner/proguard-rules.pro",
"chars": 251,
"preview": "-dontwarn androidx.viewpager2.**\n-keep class androidx.viewpager2.** {*;}\n-dontwarn androidx.recyclerview.widget.Recycler"
},
{
"path": "banner/src/main/AndroidManifest.xml",
"chars": 155,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "banner/src/main/java/com/youth/banner/Banner.java",
"chars": 33909,
"preview": "package com.youth.banner;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphic"
},
{
"path": "banner/src/main/java/com/youth/banner/adapter/BannerAdapter.java",
"chars": 3606,
"preview": "package com.youth.banner.adapter;\n\nimport android.view.ViewGroup;\n\nimport androidx.annotation.NonNull;\nimport androidx.r"
},
{
"path": "banner/src/main/java/com/youth/banner/adapter/BannerImageAdapter.java",
"chars": 924,
"preview": "package com.youth.banner.adapter;\n\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\n\nimport com.youth.ban"
},
{
"path": "banner/src/main/java/com/youth/banner/config/BannerConfig.java",
"chars": 2381,
"preview": "package com.youth.banner.config;\n\nimport com.youth.banner.util.BannerUtils;\n\n/**\n * 不忘初心\n *\n * ┌───┐ ┌───┬───┬───┬───┐"
},
{
"path": "banner/src/main/java/com/youth/banner/config/IndicatorConfig.java",
"chars": 4240,
"preview": "package com.youth.banner.config;\n\nimport androidx.annotation.ColorInt;\nimport androidx.annotation.IntDef;\n\nimport java.l"
},
{
"path": "banner/src/main/java/com/youth/banner/holder/BannerImageHolder.java",
"chars": 402,
"preview": "package com.youth.banner.holder;\n\nimport android.view.View;\nimport android.widget.ImageView;\n\nimport androidx.annotation"
},
{
"path": "banner/src/main/java/com/youth/banner/holder/IViewHolder.java",
"chars": 452,
"preview": "package com.youth.banner.holder;\n\nimport android.view.ViewGroup;\n\npublic interface IViewHolder<T, VH> {\n\n /**\n * "
},
{
"path": "banner/src/main/java/com/youth/banner/indicator/BaseIndicator.java",
"chars": 3104,
"preview": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.graph"
},
{
"path": "banner/src/main/java/com/youth/banner/indicator/CircleIndicator.java",
"chars": 2744,
"preview": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.util"
},
{
"path": "banner/src/main/java/com/youth/banner/indicator/DrawableIndicator.java",
"chars": 2846,
"preview": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport andro"
},
{
"path": "banner/src/main/java/com/youth/banner/indicator/Indicator.java",
"chars": 408,
"preview": "package com.youth.banner.indicator;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\nimport com.youth.ba"
},
{
"path": "banner/src/main/java/com/youth/banner/indicator/RectangleIndicator.java",
"chars": 2017,
"preview": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.grap"
},
{
"path": "banner/src/main/java/com/youth/banner/indicator/RoundLinesIndicator.java",
"chars": 1763,
"preview": "package com.youth.banner.indicator;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.grap"
},
{
"path": "banner/src/main/java/com/youth/banner/itemdecoration/MarginDecoration.java",
"chars": 1432,
"preview": "package com.youth.banner.itemdecoration;\n\nimport android.graphics.Rect;\nimport android.view.View;\n\nimport androidx.annot"
},
{
"path": "banner/src/main/java/com/youth/banner/listener/OnBannerListener.java",
"chars": 216,
"preview": "package com.youth.banner.listener;\n\npublic interface OnBannerListener<T> {\n\n /**\n * 点击事件\n *\n * @param dat"
},
{
"path": "banner/src/main/java/com/youth/banner/listener/OnPageChangeListener.java",
"chars": 1563,
"preview": "package com.youth.banner.listener;\n\nimport androidx.annotation.Px;\nimport androidx.viewpager2.widget.ViewPager2;\n\n\npubli"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/AlphaPageTransformer.java",
"chars": 1125,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class Alph"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/BasePageTransformer.java",
"chars": 225,
"preview": "package com.youth.banner.transformer;\n\nimport androidx.viewpager2.widget.ViewPager2;\n\npublic abstract class BasePageTran"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/DepthPageTransformer.java",
"chars": 1721,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.viewpager2.widget.ViewPager2;\n\npublic "
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/MZScaleInTransformer.java",
"chars": 2772,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\nimport android.view.ViewParent;\n\nimport androidx.annota"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/RotateDownPageTransformer.java",
"chars": 1544,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class Rota"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/RotateUpPageTransformer.java",
"chars": 1586,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class Rota"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/RotateYTransformer.java",
"chars": 1527,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.annotation.NonNull;\n\npublic class Rota"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/ScaleInTransformer.java",
"chars": 2016,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\nimport android.view.ViewParent;\n\nimport androidx.annota"
},
{
"path": "banner/src/main/java/com/youth/banner/transformer/ZoomOutPageTransformer.java",
"chars": 1886,
"preview": "package com.youth.banner.transformer;\n\nimport android.view.View;\n\nimport androidx.viewpager2.widget.ViewPager2;\n\n\npublic"
},
{
"path": "banner/src/main/java/com/youth/banner/util/BannerLifecycleObserver.java",
"chars": 315,
"preview": "package com.youth.banner.util;\n\nimport androidx.lifecycle.LifecycleObserver;\nimport androidx.lifecycle.LifecycleOwner;\n\n"
},
{
"path": "banner/src/main/java/com/youth/banner/util/BannerLifecycleObserverAdapter.java",
"chars": 1047,
"preview": "package com.youth.banner.util;\n\nimport androidx.lifecycle.Lifecycle;\nimport androidx.lifecycle.LifecycleObserver;\nimport"
},
{
"path": "banner/src/main/java/com/youth/banner/util/BannerUtils.java",
"chars": 2300,
"preview": "package com.youth.banner.util;\n\nimport android.content.res.Resources;\nimport android.graphics.Outline;\nimport android.os"
},
{
"path": "banner/src/main/java/com/youth/banner/util/LogUtils.java",
"chars": 765,
"preview": "package com.youth.banner.util;\n\nimport android.util.Log;\n\nimport com.youth.banner.BuildConfig;\n\npublic class LogUtils {\n"
},
{
"path": "banner/src/main/java/com/youth/banner/util/ScrollSpeedManger.java",
"chars": 3132,
"preview": "package com.youth.banner.util;\n\nimport androidx.recyclerview.widget.LinearLayoutManager;\nimport androidx.recyclerview.wi"
},
{
"path": "banner/src/main/res/values/attr.xml",
"chars": 2174,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <declare-styleable name=\"Banner\">\n <attr name=\"banner_loop"
},
{
"path": "banner/src/main/res/values/ids.xml",
"chars": 152,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <item name=\"banner_data_key\" type=\"id\"/>\n <item name=\"banner_p"
},
{
"path": "banner/src/main/res/values/strings.xml",
"chars": 203,
"preview": "<resources>\n <string name=\"indicator_color_error\">indicator color attribute : “@color/colorID or #000000”</string>\n "
},
{
"path": "build.gradle",
"chars": 1003,
"preview": "\nbuildscript {\n ext {\n kotlin_version = '1.7.0'\n }\n repositories {\n maven { url 'https://maven.al"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 200,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "settings.gradle",
"chars": 54,
"preview": "include ':app'\ninclude ':banner'\ninclude ':usekotlin'\n"
},
{
"path": "update_message.md",
"chars": 2648,
"preview": "\n## 更新说明\n#### v2.2.3\n * 修改adapter 数据相关操作方法\n * banner 去掉泛型返回\n * demo 添加更新数据注释\n * 更新viewpager2到beta2\n\n#### v2."
},
{
"path": "usekotlin/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "usekotlin/build.gradle",
"chars": 1361,
"preview": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\n\nandroi"
},
{
"path": "usekotlin/consumer-rules.pro",
"chars": 0,
"preview": ""
},
{
"path": "usekotlin/proguard-rules.pro",
"chars": 751,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "usekotlin/src/androidTest/java/com/spring/usekotlin/ExampleInstrumentedTest.kt",
"chars": 673,
"preview": "package com.spring.usekotlin\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport androidx.test.ext.junit.r"
},
{
"path": "usekotlin/src/main/AndroidManifest.xml",
"chars": 749,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "usekotlin/src/main/java/com/spring/usekotlin/ImageAdapter.kt",
"chars": 1198,
"preview": "package com.spring.usekotlin\n\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimp"
},
{
"path": "usekotlin/src/main/java/com/spring/usekotlin/MainActivity.kt",
"chars": 1936,
"preview": "package com.spring.usekotlin\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport com.bumpte"
},
{
"path": "usekotlin/src/main/res/layout/activity_main.xml",
"chars": 886,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout\n xmlns:android=\"http://sche"
},
{
"path": "usekotlin/src/main/res/values/colors.xml",
"chars": 330,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <color name=\"colorPrimary\">@color/main_color</color>\n <color n"
},
{
"path": "usekotlin/src/main/res/values/strings.xml",
"chars": 84,
"preview": "<resources>\n <string name=\"app_name\">Banner kotlin Example</string>\n</resources>\n"
},
{
"path": "usekotlin/src/main/res/values/styles.xml",
"chars": 383,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
},
{
"path": "usekotlin/src/test/java/com/spring/usekotlin/ExampleUnitTest.kt",
"chars": 345,
"preview": "package com.spring.usekotlin\n\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit test, which wi"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the youth5201314/banner GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 118 files (219.4 KB), approximately 57.3k tokens, and a symbol index with 385 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.