├── .gitignore
├── LICENSE
├── ReadMe.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── ryane
│ │ └── adplaybanner
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── ryane
│ │ │ └── adplaybanner
│ │ │ ├── MainActivity.java
│ │ │ └── MyApplication.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── ryane
│ └── adplaybanner
│ └── ExampleUnitTest.java
├── banner-lib
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── ryane
│ │ │ └── banner
│ │ │ ├── AdPageInfo.java
│ │ │ ├── AdPlayBanner.java
│ │ │ ├── ScrollerPager.java
│ │ │ ├── ScrollerPagerAdapter.java
│ │ │ ├── indicator
│ │ │ └── IndicatorManager.java
│ │ │ ├── loader
│ │ │ └── ImageLoaderManager.java
│ │ │ ├── scroller
│ │ │ └── AutoPlayScroller.java
│ │ │ ├── sort
│ │ │ └── QuickSort.java
│ │ │ ├── transformer
│ │ │ ├── FadeInFadeOutTransformer.java
│ │ │ ├── RotateDownTransformer.java
│ │ │ └── ZoomOutPageTransformer.java
│ │ │ ├── util
│ │ │ ├── ListUtils.java
│ │ │ └── OsUtil.java
│ │ │ └── view
│ │ │ ├── NumberView.java
│ │ │ ├── PointView.java
│ │ │ └── TitleView.java
│ └── res
│ │ ├── drawable
│ │ └── test.jpg
│ │ ├── layout
│ │ ├── view_number.xml
│ │ └── view_title.xml
│ │ └── values
│ │ ├── color.xml
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── ryane
│ └── banner
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .idea
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /captures
10 | .externalNativeBuild
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/ReadMe.md:
--------------------------------------------------------------------------------
1 | # AdPlayBanner #
2 |
3 | [AdPlayBanner](https://github.com/ryanlijianchang/AdPlayBanner)是一个Android平台基于ViewPager实现的轮播图插件,主要用以自动或者手动地播放轮播图,提供了Fresco、Picasso、Glide等图片加载方式供用户使用,以及多种图片切换动画,设置轮播时间,设置数据源顺序,提供不同分页指示器等功能,实现了一键式、灵活式的控件使用方式。下面是效果图:
4 |
5 | 
6 |
7 | 目前AdPlayBanner已经开源到了[Github](https://github.com/ryanlijianchang/AdPlayBanner)上面,大家可以在Github上面查看本控件的Demo,或者直接使用。
8 |
9 | 如果你想了解AdPlayBanner的实现思路,可以移步到[《手把手、脑把脑教你实现一个无限循环的轮播控件》](https://juejin.im/post/595cc6115188250d7e732180),里面已经把实现过程告诉大家,或者可以下载demo来自行理解。
10 |
11 | ## 一、使用方法 ##
12 |
13 | ### 1.添加依赖 ###
14 |
15 | #### bintray依赖 ####
16 |
17 | 如果使用bintray依赖,直接在模块目录下的`build.gradle`文件添加依赖:
18 |
19 | dependencies {
20 | compile 'com.ryane.banner:banner-lib:0.7'
21 | }
22 |
23 | #### jitpack依赖 ####
24 |
25 | 如果使用jitpack依赖,会需要操作多一步骤。
26 |
27 |
28 | 首先,在项目级别的`build.gradle`文件添加依赖:
29 |
30 | allprojects {
31 | repositories {
32 | ...
33 | maven { url 'https://jitpack.io' }
34 | }
35 | }
36 |
37 | 然后,在模块目录下的`build.gradle`文件添加依赖:
38 |
39 | dependencies {
40 | compile 'com.github.ryanlijianchang:AdPlayBanner:v0.7'
41 | }
42 |
43 | ### 2.在布局文件中添加控件 ###
44 |
45 | 在布局文件中添加AdPlayBanner控件,根据自己的需要设置高度,注意,控件需要在一个布局(可以是LinearLayout,RelativeLayout,FrameLayout等)之内。
46 |
47 |
51 |
52 | ### 3.在Activity中绑定控件 ###
53 |
54 | mAdPlayBanner = (AdPlayBanner) findViewById(R.id.game_banner);
55 |
56 | ### 4.添加网络权限 ###
57 |
58 | 由于加载的是网络图片,所以需要在Manifests文件中添加网络请求权限
59 |
60 |
61 |
62 | ### 5.初始化Fresco ###
63 |
64 | 默认使用Fresco加载图片,所以按照Fresco官方做法,需要在Application创建时初始化Fresco,常规做法如下:
65 |
66 | (1) 创建MyApplication类继承Application,然后在onCreate()方法中初始化Fresco:
67 |
68 | public class MyApplication extends Application {
69 | @Override
70 | public void onCreate() {
71 | super.onCreate();
72 | Fresco.initialize(this);
73 | }
74 | }
75 |
76 | (2) 在Manifests文件中标签中增加 `android:name="你的类名"`:
77 |
78 |
81 |
82 | ...
83 |
84 |
85 |
86 | 当然,如果你不使用Fresco加载,以上步骤可以跳过。
87 |
88 | ### 6.一键式使用 ###
89 |
90 | AdPlayBanner使用了Builder设计模式,所以可以通过一键式写法来直接装载AdPlayBanner,当然也可以使用常规写法。在使用之前需要先设置数据源,使用ArrayList来封装数据,而AdPageInfo是一个封装好的Bean类,封装如下:
91 |
92 | public class AdPageInfo implements Parcelable {
93 | public String title; // 广告标题
94 | public String picUrl; // 广告图片url
95 | public String clickUlr; // 图片点击url
96 | public int order; // 顺序
97 | }
98 |
99 | 在设置完数据源`mDatas`之后,使用Builder模式写法,一句话就可以使用AdPlayBanner了。**注意,`setUp()`方法必须在调用完所有API之后,最后调用**:
100 |
101 | mAdPlayBanner.setInfoList(mDatas).setUp();
102 |
103 | 当然,你也可以使用常规写法:
104 |
105 | mAdPlayBanner.setInfoList(mDatas);
106 | mAdPlayBanner.setUp();
107 |
108 | ### 7.关闭AdPlayBanner ###
109 |
110 | 在显示AdPlayBanner的页面生命周期到达onDestroy()时,建议调用`mAdPlayBanner.stop()`方法结束AdPlayBanner,避免内存泄漏。
111 |
112 | ----------
113 |
114 | ## 二、功能介绍 ##
115 |
116 | ### 1.自定义数据顺序 ###
117 |
118 | 在调用`setUp()`方法之前,我们需要设置数据源,每一页的数据使用`AdPageInfo`来封装,它里面就有一个int型变量`order`,我们通过给每一个`AdPageInfo`赋值order,AdPlayBanner就会**自动**按照order的大小来排序,如:
119 |
120 | 我们封装了三个数据到ArrayList里面,按顺序是图片1->图片2->图片3
121 |
122 | List mDatas = new ArrayList<>();
123 | AdPageInfo info1 = new AdPageInfo("图片1", "http://osjnd854m.bkt.clouddn.com/pic1_meitu_1.jpg", "链接1", 3);
124 | AdPageInfo info2 = new AdPageInfo("图片2", "http://osjnd854m.bkt.clouddn.com/pic1_meitu_2.jpg", "链接2", 2);
125 | AdPageInfo info3 = new AdPageInfo("图片3", "http://osjnd854m.bkt.clouddn.com/pic1_meitu_3.jpg", "链接3", 1);
126 | mDatas.add(info1);
127 | mDatas.add(info2);
128 | mDatas.add(info3);
129 |
130 | 装载之后运行,可见轮播顺序是按照order的顺序来播放:
131 |
132 | 
133 |
134 | ### 2.无限循环轮播 ###
135 |
136 | 很多轮播插件没有实现无限循环轮播这个功能, 而在AdPlayBanner上得到了实现,如下图可见,当我们无限循环滑动时,插件仍能正常运行:
137 |
138 | 
139 |
140 | ### 3.支持三种图片加载方式 ###
141 |
142 | 目前比较主流的Fresco、Picasso、Glide三种图片加载方式在AdPlayBanner中都支持,至于三者的区别我就不赘述了,默认是使用Fresco方式加载,具体调用方法`setImageLoadType(ImageLoaderType type)`,只需要将传入数据设置为:`FRESCO`、`GLIDE`、`PICASSO`其中一种即可,同样,也是可以通过代码一键式使用,例如使用Glide方式加载(其他加载方式使用类似),使用方法如下:
143 |
144 | mAdPlayBanner
145 | .setInfoList((ArrayList) mDatas)
146 | .setImageLoadType(Glide) // 设置Glide类型的图片加载方式
147 | .setUp();
148 |
149 | ### 4.支持多种ScaleType ###
150 |
151 | 在AdPlayBanner中,可以根据用户需要设置图片的ScaleType,具体效果和ImageView的ScaleType一致,默认是使用`FIT_XY`,但是在AdPlayBanner中比ImageView少了一种`MATRIX`类型,在AdPlayBanner中具体支持的ScaleType有如下:`FIT_XY`、`FIT_START`、`FIT_CENTER`、`FIT_END`、`CENTER`、`CENTER_CROP`、`CENTER_INSIDE`其中,具体调用方法`setImageViewScaleType(ScaleType scaleType)`,只需要将具体的ScaleType传入即可,同样,也是可以通过代码一键式使用,例如设置ScaleType为`FIT_START`(其他类似),使用方法如下:
152 |
153 | mAdPlayBanner
154 | .setInfoList((ArrayList) mDatas)
155 | .setImageViewScaleType(FIT_START) // 设置FIT_START类型的ScaleType
156 | .setUp();
157 |
158 | ### 5.支持不同页码指示器 ###
159 |
160 | 在AdPlayBanner中,提供了`数字型`、`点型`和`空型`页码指示器,用户可以通过调用`setIndicatorType(IndicatorType type)`,传入`NONE_INDICATOR`,`NUMBER_INDICATOR`,`POINT_INDICATOR`其中一种,即可显示对应的页码指示器,三种页码指示器对应效果如下:
161 |
162 | (1) `NONE_INDICATOR`:空型页码指示器
163 |
164 | 
165 |
166 | (2) `NUMBER_INDICATOR`:数字页码指示器
167 |
168 | 
169 |
170 | (3) `POINT_INDICATOR`:点型页码指示器
171 |
172 | 
173 |
174 | 使用方法也是非常简单,如我需要使用数字型页码指示器,使用方法如下:
175 |
176 | mAdPlayBanner
177 | .setInfoList((ArrayList) mDatas)
178 | .setIndicatorType(NUMBER_INDICATOR) //使用数字页码指示器
179 | .setUp();
180 |
181 | 此外,你也可以调用`setNumberViewColor(int normalColor, int selectedColor, int numberColor)`来修改数字型页码指示器的样式,`normalColor`为数字没选中时的背景颜色,`selectedColor`为数字选中时的背景颜色,`numberColor`为数字的字体颜色,例如我通过调用这个方法,把三个颜色都改变掉(注意:传入int型颜色必须ARGB8888的颜色类型,或者通过资源文件定义颜色再获取才有效),使用方法如下:
182 |
183 | mAdPlayBanner
184 | .setInfoList((ArrayList) mDatas)
185 | .setIndicatorType(NUMBER_INDICATOR) //使用数字页码指示器
186 | .setNumberViewColor(0xff00ffff, 0xffff3333, 0xff0000ff)
187 | .setUp();
188 |
189 | 得到如下效果:
190 |
191 | 
192 |
193 | ### 6.添加灵活性标题 ###
194 |
195 | 在AdPlayBanner中,只需要调用`addTitleView(TitleView mTitleView)`,就可以插入标题了,并且该标题的灵活性很强,可以根据用户需要修改标题的背景、位置、字体大小、padding、magin等,先上一个提供的默认效果:
196 |
197 | 
198 |
199 | 由于是使用了默认的效果,所以用法也是非常简单:
200 |
201 | mAdPlayBanner
202 | .setInfoList((ArrayList) mDatas)
203 | .setIndicatorType(POINT_INDICATOR) //使用数字页码指示器
204 | .addTitleView(TitleView.getDefaultTitleView(getApplicationContext())) // 使用默认标题
205 | .setUp();
206 |
207 | 我们可以看到我们通过调用`addTitleView(TitleView mTitleView)`,传入一个TitleView即可以生成标题,而上面是调用了AdPlayBanner提供的一个默认标题,当然,我们也说了这个标题的灵活性很强,就是我们可以设置TitleView的属性,我们来看一下TitleView提供了哪些API:
208 |
209 | - `TitleView setTitleColor(int color)`:设置标题字体颜色,传入color必须ARGB8888的颜色类型,或者通过资源文件定义颜色再获取才有效。
210 | - `setPosition(Gravity gravity)`:设置标题在AdPlayBanner中的位置,有`PARENT_TOP`,`PARENT_BOTTOM`,`PARENT_CENTER`三个取值,分别位于父布局顶部,父布局底部,父布局中间。
211 | - `setViewBackground(int color)`:设置标题的背景颜色,传入int型颜色必须ARGB8888的颜色类型,或者通过资源文件定义颜色再获取才有效。
212 | - `TitleView setTitleSize(int size)`:设置标题的字体大小,单位是sp。
213 | - `setTitleMargin(int left, int top, int right, int bottom)`:设置标题的四个方向margin值,单位是dp。
214 | - `setTitlePadding(int left, int top, int right, int bottom)`:设置标题的四个方向padding值,单位是dp。
215 |
216 | 同样,TitleView也是支持Builder模式的写法,例如我自定义一个TitleVIew并加到AdPlayBanner中,使用方法如下:
217 |
218 | mAdPlayBanner
219 | .setInfoList((ArrayList) mDatas)
220 | .setIndicatorType(POINT_INDICATOR) // 使用数字页码指示器
221 | .addTitleView(new TitleView(getApplicationContext()) // 创建新的TitleView
222 | .setPosition(PARENT_TOP)
223 | .setTitleColor(0xffffffff) // 设置字体颜色
224 | .setViewBackground(0x9944ff18) // 设置标题背景颜色
225 | .setTitleSize(18) // 设置字体大小
226 | .setTitleMargin(0,0,2,0) // 设置margin值
227 | .setTitlePadding(2,2,2,2)) // 设置padding值
228 | .setUp();
229 |
230 | 效果如下:
231 |
232 | 
233 |
234 |
235 | ### 7.支持多样式切换动画 ###
236 |
237 | 由于AdPlayBanner是基于ViewPager实现的,所以AdPlayBanner和ViewPager一样,同样支持自定义的切换动画,只需要通过调用`setPageTransformer(ViewPager.PageTransformer transformer)`方法,传入一个PageTransformer,即可改变它的切换样式,AdPlayBanner中提供了三种现成的切换方式:
238 |
239 | - `FadeInFadeOutTransformer`:淡入淡出效果
240 |
241 | 
242 |
243 | - `RotateDownTransformer`:旋转效果
244 |
245 | 
246 |
247 | - `ZoomOutPageTransformer`: 空间切换效果
248 |
249 | 
250 |
251 | 使用起来也是非常简单,例如使用ZoomOutPageTransformer切换效果:
252 |
253 | mAdPlayBanner
254 | .setInfoList((ArrayList) mDatas)
255 | .setIndicatorType(POINT_INDICATOR) // 使用数字页码指示器
256 | .setBannerBackground(0xff000000) // 设置背景颜色
257 | .setPageTransformer(new ZoomOutPageTransformer()) // 设置切换效果
258 | .setUp();
259 |
260 | 当然,你也可以自定义一个transformer实现ViewPager.PageTransformer接口,并重写`transformPage(View view, float position)`方法即可实现自定义的切换效果。
261 |
262 | ### 8.设置是否自动轮播 ###
263 |
264 | 通过调用`setAutoPlay(boolean autoPlay)`,传入boolean值控制是否自动播放的开关,传入true为自动,传入false为手动。
265 |
266 | ### 9.设置是否可以手动滑动 ###
267 |
268 | 通过调用`setCanScroll(boolean canScroll)`,传入boolean值控制是否可以手动滑动,传入true为可以,传入false为不可以。
269 |
270 | ### 10.设置自动滑动间隔时间 ###
271 |
272 | 通过调用`setInterval(int interval)`,传入int型的时间(单位ms),即可改变AdPlayBanner自动轮播时的切换时间。
273 |
274 | ### 11.设置点击事件监听器 ###
275 |
276 | AdPlayBanner支持点击事件监听,通过调用`setOnPageClickListener(OnPageClickListener l) `,传入OnPageClickListener,即可完成AdPlayBanner的点击监听,使用方法非常简单:
277 |
278 | mAdPlayBanner
279 | .setInfoList((ArrayList) mDatas)
280 | .setIndicatorType(POINT_INDICATOR) // 使用数字页码指示器
281 | .setOnPageClickListener(new AdPlayBanner.OnPageClickListener() {
282 | @Override
283 | public void onPageClick(AdPageInfo info, int postion) {
284 | // 点击操作
285 | }
286 | })
287 | .setUp();
288 |
289 | ### 12.关闭AdPlayBanner ###
290 |
291 | 在离开显示AdPlayBanner的页面时,建议调用`stop()`方法,避免内存泄漏。
292 |
293 | @Override
294 | protected void onDestroy() {
295 | if (mAdPlayBanner != null) {
296 | // 结束时需要调用stop释放资源
297 | mAdPlayBanner.stop();
298 | }
299 | super.onDestroy();
300 | }
301 |
302 | ## 三、API ##
303 |
304 | **AdPlayBanner:实现轮播效果的控件**
305 |
306 | AdPlayBanner | 解释 | 备注
307 | ----|------|----
308 | addTitleView(TitleView mTitleView) | 添加一个TitleView | 可以通过TitleView.getDefaultTitleView(Context context)来使用默认的TitleView或者通过new Title()的方式传入
309 | setBannerBackground(int color) | 设置AdPlayBanner的背景颜色 | 传入color必须ARGB8888的颜色类型,或者通过资源文件定义颜色再获取才有效
310 | setIndicatorType(IndicatorType type) | 设置页码指示器类型 | 传入`NONE_INDICATOR`,`NUMBER_INDICATOR`,`POINT_INDICATOR`其中一种
311 | setInterval(int interval) | 设置自动轮播时的切换时间 | 单位ms
312 | setImageLoadType(ImageLoaderType type) | 设置图片加载方式 | 传入`FRESCO`、`GLIDE`、`PICASSO`其中一种
313 | setPageTransformer(ViewPager.PageTransformer transformer) | 设置切换动画,如果不设置动画,设置为null | 提供了`FadeInFadeOutTransformer`,`RotateDownTransformer`,`ZoomOutPageTransformer`三种,也可以传入自定义的TransFormer
314 | setNumberViewColor(int normalColor, int selectedColor, int numberColor) | 设置数字页码的颜色 | normalColor 数字正常背景颜色,selectedColor 数字选中背景颜色,numberColor 数字字体颜色
315 | setOnPageClickListener(OnPageClickListener l) | 设置事件点击监听器 | 传入一个OnPageClickListener
316 | setImageViewScaleType(ScaleType scaleType) | 设置图片的ScaleType | 传入`FIT_XY`、`FIT_START`、`FIT_CENTER`、`FIT_END`、`CENTER`、`CENTER_CROP`、`CENTER_INSIDE`其中一种
317 | setAutoPlay(boolean autoPlay) | 设置是否自动播放 | 默认为true 自动播放,传入false为手动
318 | setCanScroll(boolean canScroll) | 设置是否可以手动滑动 | 默认为true可以,传入false为不可以
319 | setInfoList(ArrayList pageInfos) | 设置Banner的数据源 | 传入必须为AdPageInfo类型的ArrayList
320 | setOnPagerChangeListener(OnPagerChangeListener listener) | 设置滑动监听器 | 监听滑动状态
321 | setUp() | 装载AdPlayBanner | 必须在以上所有方法调用完之后才能调用
322 | stop() | 结束AdPlayBanner | 在离开显示AdPlayBanner页面时调用,避免内存泄漏
323 |
324 | **TitleView : 标题控件**
325 |
326 | TitleView | 解释 | 备注
327 | ----|------|----
328 | getDefaultTitleView(Context context) | 获取一个默认的TitleView | 传入一个Context
329 | setTitleSize(int size) | 设置字体大小 | 单位sp
330 | setTitleColor(int color) | 设置字体颜色 | 传入color必须ARGB8888的颜色类型,或者通过资源文件定义颜色再获取才有效
331 | setViewBackground(int color) | 设置标题背景 | 传入color必须ARGB8888的颜色类型,或者通过资源文件定义颜色再获取才有效
332 | setPosition(Gravity gravity) | 设置标题在Banner的位置 | 只能`PARENT_TOP`,`PARENT_BOTTOM`,`PARENT_CENTER`其中一个值
333 | setTitleMargin(int left, int top, int right, int bottom) | 设置标题的margin值 | 单位dp
334 | setTitlePadding(int left, int top, int right, int bottom) | 设置标题的padding值 | 单位dp
335 |
336 | **AdPageInfo:AdPlayView指定的数据源**
337 |
338 | AdPageInfo | 解释 | 备注
339 | ----|------|----
340 | AdPageInfo(String title, String picUrl, String clickUlr, int order) | 构造方法 |
341 | void setTitle(String title) | 设置标题 |
342 | String getTitle() | 获取标题 |
343 | void setPicUrl(String picUrl) | 设置图片源地址 |
344 | String getPicUrl() | 获取图片链接 |
345 | void setClickUlr(String clickUlr) | 设置点击事件地址 |
346 | String getClickUlr() | 获取点击事件链接 |
347 | void setOrder(int order) | 设置排序的优先级 | 设置了order,AdPlayBanner会根据order的大小由小到大排序
348 | int getOrder() | 获取排序优先级 |
349 |
350 | ## 四、版本特性 ##
351 |
352 | ### V0.7 ###
353 | 1. 支持最低API版本是14(即Android4.0)。
354 | 2. 代码优化。
355 |
356 | ### V0.6 ###
357 | 1. 增加`setOnPagerChangeListener(OnPagerChangeListener listener)`接口,监听当前位置。
358 |
359 | ### V0.5 ###
360 |
361 | 1. 增加`setCanScroll(boolean canScroll)`接口控制是否可以手动滑动。
362 |
363 | ### V0.4 ###
364 |
365 | 1. FIX BUG 多次刷新时数据源为空时造成的崩溃。
366 | 2. 代码、布局、性能优化。
367 | 3. gradle升级。
368 | 4. Fresco升级至V1.8(支持GIF、WebP);Picasso版本升级至V2.5.2;Glide是V4.0.0。
369 |
370 |
371 | ### V0.3 ###
372 |
373 | 1. 修复了静态变量造成的内存泄漏问题;
374 | 2. 提供手动结束Banner播放的接口;
375 |
376 | ### V0.2 ###
377 |
378 | 1. 支持定义数据顺序;
379 | 2. 无限循环轮播;
380 | 3. 支持Fresco、Glide、Picasso三种图片加载方式;
381 | 4. 支持多种ScaleType;
382 | 5. 支持点型、数字型、空型页码指示器;支持修改数字型页码器的样式;
383 | 6. 支持灵活性标题;支持修改标题的位置、字体大小、颜色、边距值等属性;
384 | 7. 支持多样式切换动画;
385 | 8. 支持设置自动轮播开关;
386 | 9. 自定义自动滑动间隔时间;
387 | 10. 提供点击事件监听器;
388 | 11. 支持修改AdPlayBanner的背景颜色;
389 |
390 | ### v0.1 ###
391 |
392 | 1. 基本框架搭建完成;
393 |
394 | ## 五、 Demo ##
395 |
396 | 如果大家在使用在仍然有问题,可以通过下载[Demo](https://github.com/ryanlijianchang/AdPlayBanner)来学习,当然,大家更可以通过查看源代码来学习如何自定义一个轮播控件。
397 |
398 | ## 六、后记 ##
399 |
400 | AdPlayBanner作为作者的第一个开源控件,作者也是非常用心认真地完成,这个过程也学习到很多东西,可能其中会遇到很多错误,所以希望大家可以多多包涵,然后把错误提到Issues里面,作者会在看到的第一时间进行修正。在后面的时间里,作者也会将更多的特性加到这个控件里面,所以希望大家可以加个star,以作为对作者的小小鼓励。 当然,如果你想第一时间联系到作者,不妨尝试以下联系方式:
401 |
402 |
403 | - Email:liji.anchang@163.com
404 | - CSDN:[http://blog.csdn.net/ljcitworld](http://blog.csdn.net/ljcitworld)
405 | - Github:[https://github.com/ryanlijianchang](https://github.com/ryanlijianchang)
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | defaultConfig {
6 | applicationId "com.ryane.adplaybanner"
7 | minSdkVersion 14
8 | targetSdkVersion 26
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
24 | exclude group: 'com.android.support', module: 'support-annotations'
25 | })
26 | implementation 'com.android.support:appcompat-v7:26.+'
27 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
28 | testImplementation 'junit:junit:4.12'
29 | compile project(path: ':banner-lib')
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/ryane/adplaybanner/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.ryane.adplaybanner;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.ryane.adplaybanner", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ryane/adplaybanner/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.ryane.adplaybanner;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.widget.Toast;
6 |
7 | import com.ryane.banner.AdPageInfo;
8 | import com.ryane.banner.AdPlayBanner;
9 | import com.ryane.banner.transformer.RotateDownTransformer;
10 | import com.ryane.banner.view.TitleView;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | import static com.ryane.banner.AdPlayBanner.ImageLoaderType.GLIDE;
16 | import static com.ryane.banner.AdPlayBanner.IndicatorType.NUMBER_INDICATOR;
17 | import static com.ryane.banner.AdPlayBanner.IndicatorType.POINT_INDICATOR;
18 | import static com.ryane.banner.view.TitleView.Gravity.PARENT_BOTTOM;
19 |
20 | /**
21 | * @author RyanLee
22 | */
23 | public class MainActivity extends AppCompatActivity {
24 | private AdPlayBanner mAdPlayBanner;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_main);
30 |
31 | List dataTest = new ArrayList<>();
32 | AdPageInfo info1 = new AdPageInfo("拜仁球场冠绝全球", "http://onq81n53u.bkt.clouddn.com/photo1.jpg", "http://www.bairen.com", 1);
33 | AdPageInfo info2 = new AdPageInfo("日落东单一起战斗", "http://onq81n53u.bkt.clouddn.com/photo2.jpg", "http://www.riluodongdan.com", 1);
34 | AdPageInfo info3 = new AdPageInfo("香港夜景流连忘返", "http://onq81n53u.bkt.clouddn.com/photo3333.jpg", "http://www.hongkong.com", 1);
35 | AdPageInfo info4 = new AdPageInfo("耐克大法绝顶天下", "http://7xrwkh.com1.z0.glb.clouddn.com/1.jpg", "http://www.nike.com", 1);
36 | dataTest.add(info1);
37 | dataTest.add(info2);
38 | dataTest.add(info3);
39 | dataTest.add(info4);
40 | mAdPlayBanner = findViewById(R.id.game_banner);
41 |
42 |
43 | mAdPlayBanner
44 | .setImageLoadType(GLIDE)
45 | .setOnPageClickListener(new AdPlayBanner.OnPageClickListener() {
46 | @Override
47 | public void onPageClick(AdPageInfo info, int position) {
48 | Toast.makeText(getApplicationContext(), "你点击了图片 " + info.getTitle() + "\n 跳转链接为:" + info.getClickUlr() + "\n 当前位置是:" + position + "\n 当前优先级是:" + info.getOrder(), Toast.LENGTH_SHORT).show();
49 | }
50 | })
51 | .setAutoPlay(true)
52 | .setIndicatorType(POINT_INDICATOR)
53 | .setNumberViewColor(0xcc00A600, 0xccea0000, 0xffffffff)
54 | .setInterval(3000)
55 | .setImageViewScaleType(AdPlayBanner.ScaleType.FIT_XY)
56 | .addTitleView(new TitleView(this).setPosition(PARENT_BOTTOM).setTitlePadding(5, 5, 5, 5).setTitleMargin(0, 0, 0, 25).setTitleSize(15).setViewBackground(0x55000000).setTitleColor(getResources().getColor(R.color.white)))
57 | //.addTitleView(TitleView.getDefaultTitleView(getApplicationContext()))
58 | .setBannerBackground(0xff565656)
59 | .setPageTransformer(new RotateDownTransformer())
60 | .setInfoList(dataTest)
61 | // 设置不可以手动滑动
62 | .setCanScroll(true)
63 | .setOnPagerChangeListener(new AdPlayBanner.OnPagerChangeListener() {
64 | @Override
65 | public void onPageSelected(int position) {
66 | }
67 |
68 | @Override
69 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
70 |
71 | }
72 |
73 | @Override
74 | public void onPageScrollStateChanged(int state) {
75 |
76 | }
77 | })
78 | .setUp();
79 | }
80 |
81 | @Override
82 | protected void onDestroy() {
83 | if (mAdPlayBanner != null) {
84 | // 结束时需要调用stop释放资源
85 | mAdPlayBanner.stop();
86 | }
87 | super.onDestroy();
88 |
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ryane/adplaybanner/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.ryane.adplaybanner;
2 |
3 | import android.app.Application;
4 |
5 | import com.facebook.drawee.backends.pipeline.Fresco;
6 |
7 | /**
8 | * Creator: lijianchang
9 | * Create Time: 2017/6/19.
10 | * Email: lijianchang@yy.com
11 | */
12 |
13 | public class MyApplication extends Application {
14 | @Override
15 | public void onCreate() {
16 | super.onCreate();
17 | Fresco.initialize(this);
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ryanlijianchang/AdPlayBanner/968603fa4ab81dc119aff0f6c9bb59ced159f60b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AdPlayBanner
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/ryane/adplaybanner/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.ryane.adplaybanner;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/banner-lib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/banner-lib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.jfrog.bintray'
3 | apply plugin: 'com.github.dcendents.android-maven'
4 |
5 | android {
6 | compileSdkVersion 26
7 |
8 | defaultConfig {
9 | minSdkVersion 14
10 | targetSdkVersion 26
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation 'com.android.support:appcompat-v7:26.+'
28 | implementation 'com.android.support:support-v4:26.+'
29 |
30 | compile 'com.squareup.picasso:picasso:2.5.2'
31 |
32 | compile 'com.facebook.fresco:fresco:1.8.0'
33 | // 支持 GIF 动图,需要添加
34 | compile 'com.facebook.fresco:animated-gif:1.8.0'
35 | // 支持 WebP (静态图+动图),需要添加
36 | compile 'com.facebook.fresco:animated-webp:1.8.0'
37 | compile 'com.facebook.fresco:webpsupport:1.8.0'
38 | // 仅支持 WebP 静态图,需要添加
39 | compile 'com.facebook.fresco:webpsupport:1.8.0'
40 |
41 | // Glide Start
42 | compile 'com.github.bumptech.glide:glide:4.0.0-RC0'
43 | annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC0'
44 | // Glide End
45 | testImplementation 'junit:junit:4.12'
46 | }
47 |
48 |
49 | //important
50 | task javadoc(type: Javadoc) {
51 | source = android.sourceSets.main.java.srcDirs
52 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
53 | }
54 | javadoc {
55 | options{
56 | encoding "UTF-8"
57 | charSet 'UTF-8'
58 | author true
59 | version true
60 | links "http://docs.oracle.com/javase/7/docs/api"
61 | }
62 | }
63 |
64 | version = "0.7"//发布的library的版本号,这个比较关键!!!
65 |
66 | def siteUrl = 'https://github.com/ryanlijianchang/AdPlayBanner' // 项目的主页(可随意,建议填library的github地址)
67 | def gitUrl = 'https://github.com/ryanlijianchang/AdPlayBanner' // Git仓库的url(可随意,建议填library的github地址)
68 | group = "com.ryane.banner" // 这里是groupId ,必须填写(建议填唯一的包名)
69 |
70 | install {
71 | repositories.mavenInstaller {
72 | // This generates POM.xml with proper parameters
73 | pom {
74 | project {
75 | packaging 'aar'
76 | // Add your description here
77 | name 'The library is a custom view about banner' //项目描述
78 | url siteUrl
79 | // Set your license
80 | licenses {
81 | license {
82 | name 'The Apache Software License, Version 2.0'
83 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
84 | }
85 | }
86 | developers {
87 | developer {
88 | id 'ryanlijianchang' //开发者的基本信息(建议填自己名称)
89 | name 'RyanLee' //开发者基本信息(建议填自己名称)
90 | email 'liji.anchang@163.com' //开发者基本信息(建议填自己名称)
91 | }
92 | }
93 | scm {
94 | connection gitUrl
95 | developerConnection gitUrl
96 | url siteUrl
97 | }
98 | }
99 | }
100 | }
101 | }
102 |
103 | task sourcesJar(type: Jar) {
104 | from android.sourceSets.main.java.srcDirs
105 | classifier = 'sources'
106 | }
107 | task javadocJar(type: Jar, dependsOn: javadoc) {
108 | classifier = 'javadoc'
109 | from javadoc.destinationDir
110 | }
111 | artifacts {
112 | archives javadocJar
113 | archives sourcesJar
114 | }
115 |
116 | //important 读取 local.properties 文件里面的 bintray.user和bintray.apikey
117 | Properties properties = new Properties()
118 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
119 |
120 | bintray {
121 | user = properties.getProperty("bintray.user") //读取 local.properties 文件里面的 bintray.user
122 | key = properties.getProperty("bintray.apikey")
123 |
124 | configurations = ['archives']
125 | pkg {
126 | repo = "maven"
127 | group = group
128 | name = "AdPlayBanner"//发布到JCenter上的项目名字,必须填写
129 | websiteUrl = siteUrl
130 | vcsUrl = gitUrl
131 | licenses = ["Apache-2.0"]
132 | publish = true
133 | }
134 | }
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/banner-lib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/banner-lib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/banner-lib/src/main/java/com/ryane/banner/AdPageInfo.java:
--------------------------------------------------------------------------------
1 | package com.ryane.banner;
2 |
3 | /**
4 | * Create Time: 2017/6/17.
5 | *
6 | * @author RyanLee
7 | */
8 |
9 | public class AdPageInfo {
10 | /**
11 | * 广告标题
12 | */
13 | private String title;
14 | /**
15 | * 广告图片url
16 | */
17 | private String picUrl;
18 | /**
19 | * 图片点击url
20 | */
21 | private String clickUlr;
22 | /**
23 | * 顺序
24 | */
25 | private int order;
26 |
27 | public AdPageInfo(String title, String picUrl, String clickUlr, int order) {
28 | this.title = title;
29 | this.picUrl = picUrl;
30 | this.clickUlr = clickUlr;
31 | this.order = order;
32 | }
33 |
34 | public String getTitle() {
35 | return title;
36 | }
37 |
38 | public void setTitle(String title) {
39 | this.title = title;
40 | }
41 |
42 | public String getPicUrl() {
43 | return picUrl;
44 | }
45 |
46 | public String getClickUlr() {
47 | return clickUlr;
48 | }
49 |
50 | public int getOrder() {
51 | return order;
52 | }
53 |
54 | @Override
55 | public String toString() {
56 | return "AdPageInfo{" +
57 | "title='" + title + '\'' +
58 | ", picUrl='" + picUrl + '\'' +
59 | ", clickUlr='" + clickUlr + '\'' +
60 | ", order=" + order +
61 | '}';
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/banner-lib/src/main/java/com/ryane/banner/AdPlayBanner.java:
--------------------------------------------------------------------------------
1 | package com.ryane.banner;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 | import android.widget.RelativeLayout;
7 |
8 | import com.ryane.banner.indicator.IndicatorManager;
9 | import com.ryane.banner.loader.ImageLoaderManager;
10 | import com.ryane.banner.sort.QuickSort;
11 | import com.ryane.banner.view.NumberView;
12 | import com.ryane.banner.view.TitleView;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * Create Time: 2017/6/17.
19 | * @author RyanLee
20 | */
21 |
22 | public class AdPlayBanner extends RelativeLayout {
23 | /**
24 | * 数据源
25 | */
26 | private List mDataList;
27 | /**
28 | * 滑动的ViewPager
29 | */
30 | private ScrollerPager mScrollerPager;
31 | /**
32 | * 标题控件
33 | */
34 | private TitleView mTitleView;
35 |
36 | private OnPagerChangeListener mPageChangeListener = null;
37 |
38 | public AdPlayBanner(Context context) {
39 | this(context, null);
40 | }
41 |
42 | public AdPlayBanner(Context context, AttributeSet attrs) {
43 | this(context, attrs, 0);
44 | }
45 |
46 | public AdPlayBanner(Context context, AttributeSet attrs, int defStyleAttr) {
47 | super(context, attrs, defStyleAttr);
48 | }
49 |
50 | /**
51 | * 初始化标题视图
52 | * @param mTitleView 标题的View
53 | * @return this
54 | */
55 | public AdPlayBanner addTitleView(TitleView mTitleView) {
56 | this.mTitleView = mTitleView;
57 | if (mScrollerPager != null) {
58 | mScrollerPager.setTitleView(mTitleView);
59 | }
60 | return this;
61 | }
62 |
63 | public AdPlayBanner setBannerBackground(int color) {
64 | setBackgroundColor(color);
65 | return this;
66 | }
67 |
68 | /**
69 | * 设置指示器类型
70 | *
71 | * @param type 指示器类型
72 | * @return this
73 | */
74 | public AdPlayBanner setIndicatorType(IndicatorType type) {
75 | IndicatorManager.getInstance().setIndicatorType(type);
76 | return this;
77 | }
78 |
79 | /**
80 | * 设置数据源
81 | * @param dataList 数据源
82 | * @return this
83 | */
84 | public AdPlayBanner setInfoList(List dataList) {
85 | if (null != dataList) {
86 | this.mDataList = QuickSort.quickSort(dataList, 0, dataList.size() - 1);
87 | } else {
88 | this.mDataList = new ArrayList<>();
89 | }
90 | return this;
91 | }
92 |
93 | /**
94 | * 设置自动滑动间隔时间
95 | * @param interval 间隔时间
96 | * @return this
97 | */
98 | public AdPlayBanner setInterval(int interval) {
99 | ScrollerPager.mInterval = interval;
100 | return this;
101 | }
102 |
103 | /**
104 | * 设置图片加载方式
105 | * @param type 加载方式
106 | * @return this
107 | */
108 | public AdPlayBanner setImageLoadType(ImageLoaderType type) {
109 | ImageLoaderManager.getInstance().setImageLoaderType(type);
110 | return this;
111 | }
112 |
113 | /**
114 | * 设置切换动画
115 | * 如果不设置动画,设置为null
116 | * @param transformer 切换动画
117 | * @return this
118 | */
119 | public AdPlayBanner setPageTransformer(ViewPager.PageTransformer transformer) {
120 | if (mScrollerPager != null) {
121 | mScrollerPager.setPageTransformer(true, transformer);
122 | } else {
123 | ScrollerPager.mTransformer = transformer;
124 | }
125 | return this;
126 | }
127 |
128 | /**
129 | * 设置数字页码的颜色
130 | *
131 | * @param normalColor 数字正常背景颜色
132 | * @param selectedColor 数字选中背景颜色
133 | * @param numberColor 数字字体颜色
134 | * @return this
135 | */
136 | public AdPlayBanner setNumberViewColor(int normalColor, int selectedColor, int numberColor) {
137 | if (mScrollerPager != null) {
138 | mScrollerPager.setNumberViewColor(normalColor, selectedColor, numberColor);
139 | } else {
140 | NumberView.mNumberViewNormalColor = normalColor;
141 | NumberView.mNumberViewSelectedColor = selectedColor;
142 | NumberView.mNumberTextColor = numberColor;
143 | }
144 | return this;
145 | }
146 |
147 | /**
148 | * 设置事件点击监听器
149 | * @param listener 点击监听器
150 | * @return this
151 | */
152 | public AdPlayBanner setOnPageClickListener(OnPageClickListener listener) {
153 | ImageLoaderManager.getInstance().setOnPageClickListener(listener);
154 | return this;
155 | }
156 |
157 | /**
158 | * 设置滑动监听
159 | * @param listener 滑动监听器
160 | * @return this
161 | */
162 | public AdPlayBanner setOnPagerChangeListener(OnPagerChangeListener listener) {
163 | if (mScrollerPager != null) {
164 | mScrollerPager.setmPageListener(listener);
165 | } else {
166 | mPageChangeListener = listener;
167 | }
168 | return this;
169 | }
170 |
171 | /**
172 | * 设置图片显示方式
173 | * @param scaleType 图片显示方式
174 | * @return this
175 | */
176 | public AdPlayBanner setImageViewScaleType(ScaleType scaleType) {
177 | ImageLoaderManager.getInstance().setScaleType(scaleType);
178 | return this;
179 | }
180 |
181 | /**
182 | * 设置是否自动播放
183 | * 默认为true 自动播放
184 | * @param autoPlay 自动播放
185 | * @return this
186 | */
187 | public AdPlayBanner setAutoPlay(boolean autoPlay) {
188 | ScrollerPager.mAutoPlay = autoPlay;
189 | return this;
190 | }
191 |
192 | /**
193 | * 设置是否可以手动滑动
194 | * @param canScroll 是否可以手动滑动
195 | * @return this
196 | */
197 | public AdPlayBanner setCanScroll(boolean canScroll) {
198 | ScrollerPager.canScroll = canScroll;
199 | return this;
200 | }
201 |
202 | /**
203 | * 装载AdPlayBanner
204 | */
205 | public void setUp() {
206 | mScrollerPager = new ScrollerPager(this, mTitleView, mDataList);
207 | if (mPageChangeListener != null) {
208 | mScrollerPager.setmPageListener(mPageChangeListener);
209 | }
210 | mScrollerPager.show();
211 | }
212 |
213 | /**
214 | * 停止播放
215 | */
216 | public void stop() {
217 | if (mScrollerPager == null) {
218 | return;
219 | }
220 | mScrollerPager.stop();
221 | // 清除所有的子view
222 | removeAllViews();
223 | }
224 |
225 | public interface OnPageClickListener {
226 | /**
227 | * 页面点击
228 | * @param info 数据
229 | * @param position 位置
230 | */
231 | void onPageClick(AdPageInfo info, int position);
232 | }
233 |
234 | public interface OnPagerChangeListener {
235 | void onPageSelected(final int position);
236 | void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
237 | void onPageScrollStateChanged(int state);
238 | }
239 |
240 |
241 | /**
242 | * 图片的ScaleType
243 | */
244 | public enum ScaleType {
245 | FIT_XY(1),
246 | FIT_START(2),
247 | FIT_CENTER(3),
248 | FIT_END(4),
249 | CENTER(5),
250 | CENTER_CROP(6),
251 | CENTER_INSIDE(7);
252 |
253 | ScaleType(int ni) {
254 | nativeInt = ni;
255 | }
256 |
257 | final int nativeInt;
258 | }
259 |
260 | /**
261 | * 图片加载方式
262 | */
263 | public enum ImageLoaderType {
264 | FRESCO(1),
265 | GLIDE(2),
266 | PICASSO(3);
267 |
268 | ImageLoaderType(int ni) {
269 | nativeInt = ni;
270 | }
271 |
272 | final int nativeInt;
273 | }
274 |
275 | /**
276 | * 指示器类型
277 | */
278 | public enum IndicatorType {
279 | /**
280 | * 空型页码指示器
281 | */
282 | NONE_INDICATOR(0),
283 | /**
284 | * 数字页码指示器
285 | */
286 | NUMBER_INDICATOR(1),
287 | /**
288 | * 点型页码指示器
289 | */
290 | POINT_INDICATOR(2);
291 |
292 | IndicatorType(int ni) {
293 | nativeInt = ni;
294 | }
295 |
296 | final int nativeInt;
297 | }
298 |
299 | }
300 |
--------------------------------------------------------------------------------
/banner-lib/src/main/java/com/ryane/banner/ScrollerPager.java:
--------------------------------------------------------------------------------
1 | package com.ryane.banner;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 | import android.os.Looper;
6 | import android.support.v4.content.ContextCompat;
7 | import android.support.v4.view.ViewPager;
8 | import android.util.AttributeSet;
9 | import android.util.TypedValue;
10 | import android.view.Gravity;
11 | import android.view.MotionEvent;
12 | import android.view.animation.LinearInterpolator;
13 | import android.widget.LinearLayout;
14 | import android.widget.RelativeLayout;
15 | import android.widget.Scroller;
16 |
17 | import com.ryane.banner.indicator.IndicatorManager;
18 | import com.ryane.banner.scroller.AutoPlayScroller;
19 | import com.ryane.banner.util.ListUtils;
20 | import com.ryane.banner.util.OsUtil;
21 | import com.ryane.banner.view.NumberView;
22 | import com.ryane.banner.view.PointView;
23 | import com.ryane.banner.view.TitleView;
24 |
25 | import java.lang.reflect.Field;
26 | import java.util.ArrayList;
27 | import java.util.List;
28 |
29 | import static com.ryane.banner.AdPlayBanner.IndicatorType.NUMBER_INDICATOR;
30 | import static com.ryane.banner.AdPlayBanner.IndicatorType.POINT_INDICATOR;
31 |
32 | /**
33 | * Create Time: 2017/6/17.
34 | * @author RyanLee
35 | */
36 |
37 | public class ScrollerPager extends ViewPager {
38 | /**
39 | * 父布局
40 | */
41 | private RelativeLayout mContainer;
42 | /**
43 | * 标题控件
44 | */
45 | private TitleView mTitleView;
46 | /**
47 | * 指示器控件
48 | */
49 | private LinearLayout mIndicator;
50 | /**
51 | * 数字指示器控件
52 | */
53 | private LinearLayout mPageNumberLayout;
54 | /**
55 | * 数据源
56 | */
57 | private List mDataList;
58 | /**
59 | * UI线程的Handler
60 | */
61 | private Handler mUIHandler = new Handler(Looper.myLooper());
62 | /**
63 | * 点型指示器
64 | */
65 | private PointView[] mPointViews = null;
66 | /**
67 | * 数字型指示器
68 | */
69 | private NumberView[] mNumberViews = null;
70 | /**
71 | * 点型指示器被选中的颜色
72 | */
73 | private final int POINT_VIEW_SELECTED_COLOR = ContextCompat.getColor(getContext(), R.color.point_selected_color);
74 | /**
75 | * 点型指示器默认的颜色
76 | */
77 | private final int POINT_VIEW_NORMAL_COLOR = ContextCompat.getColor(getContext(), R.color.point_normal_color);
78 | /**
79 | * 切换动画
80 | */
81 | public static ViewPager.PageTransformer mTransformer = null;
82 | /**
83 | * 是否自动播放
84 | */
85 | public static boolean mAutoPlay = true;
86 | /**
87 | * 是否可以手动滑动
88 | */
89 | public static boolean canScroll = true;
90 | /**
91 | * 间隔时间,默认2000ms
92 | */
93 | public static int mInterval = 2000;
94 | /**
95 | * 当前下标
96 | */
97 | private int mSelectedIndex = 0;
98 | /**
99 | * 滑动监听
100 | */
101 | private AdPlayBanner.OnPagerChangeListener mPageListener;
102 |
103 | public ScrollerPager(Context context) {
104 | this(context, null);
105 | }
106 |
107 | public ScrollerPager(Context context, AttributeSet attrs) {
108 | super(context, attrs);
109 | }
110 |
111 | public ScrollerPager(RelativeLayout mContainer, TitleView mTitleView, List infos) {
112 | super(mContainer.getContext());
113 |
114 | this.mContainer = mContainer;
115 | this.mTitleView = mTitleView;
116 |
117 | if (null != infos) {
118 | this.mDataList = infos;
119 | } else {
120 | this.mDataList = new ArrayList<>();
121 | }
122 |
123 | init();
124 | }
125 |
126 | /**
127 | * 初始化操作
128 | */
129 | private void init() {
130 | // 初始化Indicator
131 | initIndicator();
132 | // 初始化数字页码
133 | initPageNumber();
134 | // 初始化切换时间
135 | initScrollTime(new AutoPlayScroller(getContext(), new LinearInterpolator()));
136 | // 初始化切换动画
137 | initTransformer();
138 |
139 | // 初始化viewpager start
140 | ScrollerPagerAdapter adapter = new ScrollerPagerAdapter(getContext(), mDataList);
141 | setAdapter(adapter);
142 | addOnPageChangeListener(mOnPageChangeListener);
143 | // 初始化viewpager end
144 | }
145 |
146 | /**
147 | * 初始化Indicator
148 | */
149 | private void initIndicator() {
150 | // 如果是点型指示器
151 | if (IndicatorManager.getInstance().getIndicatorType() == POINT_INDICATOR) {
152 | mIndicator = new LinearLayout(getContext());
153 | mIndicator.setOrientation(LinearLayout.HORIZONTAL);
154 | mIndicator.setGravity(Gravity.CENTER);
155 |
156 | mIndicator.removeAllViews();
157 |
158 | mPointViews = new PointView[mDataList.size()];
159 |
160 | // 点的大小为5dp
161 | float pointSize = OsUtil.dpToPx(5);
162 |
163 | int size = mDataList.size();
164 | for (int i = 0; i 0) {
276 | mPointViews[rightPos].setPointViewColor(POINT_VIEW_SELECTED_COLOR);
277 | for (int i = 0; i < mPointViews.length; i++) {
278 | if (rightPos != i) {
279 | mPointViews[i].setPointViewColor(POINT_VIEW_NORMAL_COLOR);
280 | }
281 | }
282 | }
283 |
284 | if (IndicatorManager.getInstance().getIndicatorType() == NUMBER_INDICATOR && mPageNumberLayout != null && mNumberViews.length > 0) {
285 | mNumberViews[rightPos].setNumberViewColor(NumberView.mNumberViewSelectedColor);
286 | for (int i = 0; i < mNumberViews.length; i++) {
287 | if (rightPos != i) {
288 | mNumberViews[i].setNumberViewColor(NumberView.mNumberViewNormalColor);
289 | }
290 | }
291 | }
292 |
293 | }
294 |
295 | @Override
296 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
297 | if (mPageListener != null) {
298 | int pos = (mDataList == null || mDataList.size() == 0) ? 0 : position % mDataList.size();
299 | mPageListener.onPageScrolled(pos, positionOffset, positionOffsetPixels);
300 | }
301 | }
302 |
303 | @Override
304 | public void onPageScrollStateChanged(int state) {
305 | if (mPageListener != null) {
306 | mPageListener.onPageScrollStateChanged(state);
307 | }
308 | if (state == ViewPager.SCROLL_STATE_IDLE) {
309 | startAdvertPlay();
310 | }
311 | }
312 | };
313 |
314 | /**
315 | * 自动播放任务
316 | */
317 | private Runnable mImageTimmerTask = new Runnable() {
318 | @Override
319 | public void run() {
320 | if (mSelectedIndex == Integer.MAX_VALUE) {
321 | if (ListUtils.isEmpty(mDataList)) {
322 | return;
323 | }
324 | int rightPos = mSelectedIndex % mDataList.size();
325 | setCurrentItem(getInitPosition() + rightPos + 1, true);
326 | } else {
327 | setCurrentItem(mSelectedIndex + 1, true);
328 | }
329 | }
330 | };
331 |
332 | /**
333 | * 获取banner的初始位置
334 | *
335 | * @return banner的初始位置
336 | */
337 | private int getInitPosition() {
338 | if (ListUtils.isEmpty(mDataList)) {
339 | return 0;
340 | }
341 | int halfValue = Integer.MAX_VALUE / 2;
342 | int position = halfValue % mDataList.size();
343 | return halfValue - position;
344 | }
345 |
346 | /**
347 | * 设置数字页码的颜色
348 | *
349 | * @param normalColor 数字正常背景颜色
350 | * @param selectedColor 数字选中背景颜色
351 | * @param numberColor 数字字体颜色
352 | */
353 | public void setNumberViewColor(int normalColor, int selectedColor, int numberColor) {
354 | NumberView.mNumberViewNormalColor = normalColor;
355 | NumberView.mNumberViewSelectedColor = selectedColor;
356 | NumberView.mNumberTextColor = numberColor;
357 | initPageNumber();
358 | }
359 |
360 |
361 | public void setTitleView(TitleView mTitleView) {
362 | this.mTitleView = mTitleView;
363 | }
364 |
365 | /**
366 | * 设置切换动画
367 | */
368 | private void initTransformer() {
369 | if (mTransformer == null) {
370 | return;
371 | }
372 | setPageTransformer(true, mTransformer);
373 | }
374 |
375 | /**
376 | * 显示播放ScrollerPager
377 | */
378 | public void show() {
379 | mContainer.removeAllViews();
380 | if (null == mDataList || 0 == mDataList.size()) {
381 | stopAdvertPlay();
382 | mContainer.setVisibility(GONE);
383 | } else {
384 | addScrollerPager(); // 把ScrollerPager装载到外布局中
385 | addIndicatorView(); // 把IndicatorView装载到外布局中
386 | addPageNumberView();// 把PageNumberView装载到外布局
387 | addTitleView(); // 把TitleView装载到外布局中
388 |
389 | if (mDataList.size() == 1) {
390 | stopAdvertPlay();
391 | } else {
392 | startAdvertPlay();
393 | }
394 | mContainer.setVisibility(VISIBLE);
395 | // 设置初始化的位置
396 | setCurrentItem(getInitPosition());
397 | }
398 | }
399 |
400 | public void stop() {
401 | stopAdvertPlay();
402 | }
403 |
404 | /**
405 | * 装载ScrollerPager
406 | */
407 | private void addScrollerPager() {
408 | ViewPager.LayoutParams layoutParams = new ViewPager.LayoutParams();
409 | layoutParams.width = ViewPager.LayoutParams.MATCH_PARENT;
410 | layoutParams.height = ViewPager.LayoutParams.MATCH_PARENT;
411 | mContainer.addView(this, layoutParams);
412 | }
413 |
414 | /**
415 | * 装载PageNumberView
416 | */
417 | private void addPageNumberView() {
418 | if (IndicatorManager.getInstance().getIndicatorType() == NUMBER_INDICATOR && mPageNumberLayout != null) {
419 | RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
420 | layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
421 | layoutParams.bottomMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getContext().getResources().getDisplayMetrics());
422 | mContainer.addView(mPageNumberLayout, layoutParams);
423 | }
424 | }
425 |
426 | /**
427 | * 装载IndicatorView
428 | */
429 | private void addIndicatorView() {
430 | if (IndicatorManager.getInstance().getIndicatorType() == POINT_INDICATOR && mIndicator != null) {
431 | RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
432 | layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
433 | layoutParams.bottomMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getContext().getResources().getDisplayMetrics());
434 | mContainer.addView(mIndicator, layoutParams);
435 | }
436 | }
437 |
438 | /**
439 | * 装载TitleView
440 | */
441 | private void addTitleView() {
442 | if (mTitleView != null) {
443 | RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
444 | switch (mTitleView.gravity) {
445 | default:
446 | case PARENT_BOTTOM:
447 | layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
448 | break;
449 | case PARENT_TOP:
450 | layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
451 | break;
452 | case PARENT_CENTER:
453 | layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
454 | break;
455 | }
456 | layoutParams.topMargin = OsUtil.dpToPx(mTitleView.marginTop);
457 | layoutParams.bottomMargin = OsUtil.dpToPx(mTitleView.marginBottom);
458 | layoutParams.leftMargin = OsUtil.dpToPx(mTitleView.marginLeft);
459 | layoutParams.rightMargin = OsUtil.dpToPx(mTitleView.marginRight);
460 | mContainer.addView(mTitleView, layoutParams);
461 | }
462 | }
463 |
464 | @Override
465 | public boolean onInterceptTouchEvent(MotionEvent ev) {
466 | if (canScroll) {
467 | return super.onInterceptTouchEvent(ev);
468 | } else {
469 | return false;
470 | }
471 | }
472 |
473 | @Override
474 | public boolean onTouchEvent(MotionEvent ev) {
475 | switch (ev.getAction()) {
476 | case MotionEvent.ACTION_DOWN:
477 | // 如果点击
478 | performClick();
479 | stopAdvertPlay();
480 | break;
481 | case MotionEvent.ACTION_UP:
482 | startAdvertPlay();
483 | break;
484 | default:
485 | break;
486 | }
487 | return super.onTouchEvent(ev);
488 | }
489 |
490 | @Override
491 | public boolean performClick() {
492 | return super.performClick();
493 | }
494 |
495 | public void setmPageListener(AdPlayBanner.OnPagerChangeListener mPageListener) {
496 | this.mPageListener = mPageListener;
497 | }
498 | }
499 |
--------------------------------------------------------------------------------
/banner-lib/src/main/java/com/ryane/banner/ScrollerPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.ryane.banner;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.PagerAdapter;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.ryane.banner.loader.ImageLoaderManager;
9 | import com.ryane.banner.util.ListUtils;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * Create Time: 2017/6/17.
15 | *
16 | * @author RyanLee
17 | */
18 |
19 | class ScrollerPagerAdapter extends PagerAdapter {
20 | /**
21 | * 上下文
22 | */
23 | private Context mContext;
24 | /**
25 | * 数据源
26 | */
27 | private List mDataList;
28 |
29 |
30 | ScrollerPagerAdapter(Context context, List mDataList) {
31 | this.mContext = context;
32 | this.mDataList = mDataList;
33 | }
34 |
35 |
36 | @Override
37 | public int getCount() {
38 | if (!ListUtils.isEmpty(mDataList)) {
39 | // 当只有一张图片的时候,不可滑动
40 | if (mDataList.size() == 1) {
41 | return 1;
42 | } else {
43 | // 否则循环播放滑动
44 | return Integer.MAX_VALUE;
45 | }
46 | } else {
47 | return 0;
48 | }
49 | }
50 |
51 | @Override
52 | public Object instantiateItem(ViewGroup container, final int position) {
53 | if (!ListUtils.isEmpty(mDataList)) {
54 | return ImageLoaderManager.getInstance().initPageView(container, mContext, mDataList.get(position % mDataList.size()), position % mDataList.size());
55 | } else {
56 | return null;
57 | }
58 | }
59 |
60 | @Override
61 | public void destroyItem(ViewGroup container, int position, Object object) {
62 | ImageLoaderManager.getInstance().destroyPageView(container, object);
63 | }
64 |
65 | @Override
66 | public boolean isViewFromObject(View view, Object object) {
67 | return view == object;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/banner-lib/src/main/java/com/ryane/banner/indicator/IndicatorManager.java:
--------------------------------------------------------------------------------
1 | package com.ryane.banner.indicator;
2 |
3 | import com.ryane.banner.AdPlayBanner;
4 |
5 | import static com.ryane.banner.AdPlayBanner.IndicatorType.NONE_INDICATOR;
6 |
7 | /**
8 | * Create Time: 2017/7/1.
9 | * @author RyanLee
10 | */
11 |
12 | public class IndicatorManager {
13 |
14 |
15 | private static class SingletonHolder {
16 | private static final IndicatorManager INSTANCE = new IndicatorManager();
17 | }
18 |
19 | private IndicatorManager() {
20 | }
21 |
22 | public static IndicatorManager getInstance() {
23 | return IndicatorManager.SingletonHolder.INSTANCE;
24 | }
25 |
26 | private AdPlayBanner.IndicatorType mIndicatorType = NONE_INDICATOR;
27 |
28 | public void setIndicatorType(AdPlayBanner.IndicatorType indicatorType) {
29 | mIndicatorType = indicatorType;
30 | }
31 |
32 | public AdPlayBanner.IndicatorType getIndicatorType() {
33 | return mIndicatorType;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/banner-lib/src/main/java/com/ryane/banner/loader/ImageLoaderManager.java:
--------------------------------------------------------------------------------
1 | package com.ryane.banner.loader;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.ImageView;
9 |
10 | import com.bumptech.glide.Glide;
11 | import com.facebook.drawee.drawable.ScalingUtils;
12 | import com.facebook.drawee.generic.GenericDraweeHierarchy;
13 | import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
14 | import com.facebook.drawee.view.SimpleDraweeView;
15 | import com.ryane.banner.AdPageInfo;
16 | import com.ryane.banner.AdPlayBanner;
17 | import com.squareup.picasso.Picasso;
18 |
19 | import java.util.ArrayList;
20 |
21 | /**
22 | * Create Time: 2017/6/19.
23 | * @author RyanLee
24 | */
25 |
26 | public class ImageLoaderManager {
27 | /**
28 | * 图片加载方式,默认Fresco
29 | */
30 | private AdPlayBanner.ImageLoaderType mImageLoaderType = AdPlayBanner.ImageLoaderType.FRESCO;
31 |
32 | /**
33 | * 点击监听
34 | */
35 | private AdPlayBanner.OnPageClickListener mOnPageClickListener = null;
36 |
37 | /**
38 | * ScaleType,默认是FIT_XY
39 | */
40 | private AdPlayBanner.ScaleType mScaleType = AdPlayBanner.ScaleType.FIT_XY;
41 |
42 | /**
43 | * 图片的缓存集合
44 | */
45 | private final ArrayList