├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── GIF.gif ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── nanchen │ │ └── cheerbanner │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── nanchen │ │ │ └── cheerbanner │ │ │ └── MainActivity.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 │ └── nanchen │ └── cheerbanner │ └── ExampleUnitTest.java ├── banner ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── nanchen │ │ └── banner │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── nanchen │ │ │ └── banner │ │ │ ├── BannerConfig.java │ │ │ ├── BannerEntity.java │ │ │ ├── BannerLayout.java │ │ │ ├── BannerLine.java │ │ │ ├── BannerPagerAdapter.java │ │ │ ├── BannerView.java │ │ │ └── OnBannerClickListener.java │ └── res │ │ ├── layout │ │ ├── layout_banner.xml │ │ └── view_banner.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── nanchen │ └── 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 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /GIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/GIF.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CheerBanner 2 | CheerBanner:不止是图片,这是一款支持任意控件轮播的Banner控件,支持触摸暂停,任意定义高度。 3 | 4 | ## 为什么出现这个? 5 | 6 | - 当前现有的轮子大多数只支持图片轮播,但在生活中却会存在其他控件显示的需求,这部分轮子很缺乏。 7 | - 我这不是一个库,只是一个抛砖引玉的实现参考,感兴趣的可以 clone 查看。 8 | - 之前修改 [banner](https://github.com/youth5201314/banner), 但会出现布局错误和闪屏问题 9 | - 所以有了它。 10 | 11 | ## 效果图
12 | ![](https://github.com/nanchen2251/CheerBanner/blob/master/GIF.gif) 13 | 14 | #### ⊙开源不易,希望给个 star 或者 fork 奖励 15 | #### ⊙拥抱开源:https://github.com/nanchen2251/ 16 | #### ⊙交流群(拒绝无脑问):118116509 Android神技侧漏交流群( 点击图标即可加入 )
17 | ## 特点 18 | 1、支持自动轮播
19 | 2、支持触摸暂停轮播
20 | 3、支持更改高度不改变布局(不会出现 [banner](https://github.com/youth5201314/banner) 的改变高度出现布局错位)
21 | 4、支持自定义任意控件轮播(不会出现 [banner](https://github.com/youth5201314/banner) 的第一个闪屏问题)
22 | 23 | 24 | ### 关于作者 25 |    南尘
26 |    四川成都
27 |    [其它开源](https://github.com/nanchen2251/)
28 |    [个人博客](https://nanchen2251.github.io/)
29 |    [简书](http://www.jianshu.com/u/f690947ed5a6)
30 |    [博客园](http://www.cnblogs.com/liushilin/)
31 |    交流群:118116509
32 |    欢迎投稿(关注)我的唯一公众号,公众号搜索 nanchen 或者扫描下方二维码:
33 |    ![](http://images2015.cnblogs.com/blog/845964/201707/845964-20170718083641599-1963842541.jpg) 34 |     35 | #### 有码走遍天下 无码寸步难行(引自网络) 36 | 37 | > 1024 - 梦想,永不止步! 38 | 爱编程 不爱Bug 39 | 爱加班 不爱黑眼圈 40 | 固执 但不偏执 41 | 疯狂 但不疯癫 42 | 生活里的菜鸟 43 | 工作中的大神 44 | 身怀宝藏,一心憧憬星辰大海 45 | 追求极致,目标始于高山之巅 46 | 一群怀揣好奇,梦想改变世界的孩子 47 | 一群追日逐浪,正在改变世界的极客 48 | 你们用最美的语言,诠释着科技的力量 49 | 你们用极速的创新,引领着时代的变迁 50 | 51 | ------至所有正在努力奋斗的程序猿们!加油!! 52 | 53 | ## Licenses 54 | ``` 55 | Copyright 2017 nanchen(刘世麟) 56 | 57 | Licensed under the Apache License, Version 2.0 (the "License"); 58 | you may not use this file except in compliance with the License. 59 | You may obtain a copy of the License at 60 | 61 | http://www.apache.org/licenses/LICENSE-2.0 62 | 63 | Unless required by applicable law or agreed to in writing, software 64 | distributed under the License is distributed on an "AS IS" BASIS, 65 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 66 | See the License for the specific language governing permissions and 67 | limitations under the License. 68 | ``` 69 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.nanchen.cheerbanner" 8 | minSdkVersion 11 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:25.3.1' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 29 | testCompile 'junit:junit:4.12' 30 | compile 'com.android.support:recyclerview-v7:25.3.1' 31 | compile 'com.github.bumptech.glide:glide:3.7.0' 32 | compile project(':banner') 33 | } 34 | -------------------------------------------------------------------------------- /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 D:\Users\50323\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/nanchen/cheerbanner/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.cheerbanner; 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.nanchen.cheerbanner", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/nanchen/cheerbanner/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.cheerbanner; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.nanchen.banner.BannerEntity; 9 | import com.nanchen.banner.BannerView; 10 | import com.nanchen.banner.OnBannerClickListener; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class MainActivity extends AppCompatActivity { 16 | 17 | private BannerView mBannerView; 18 | private TextView mTextView; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | mBannerView = (BannerView) findViewById(R.id.banner); 25 | mTextView = (TextView) findViewById(R.id.textView); 26 | final List entities = new ArrayList<>(); 27 | entities.add(new BannerEntity(1, "https://github.com/nanchen2251", "webView")); 28 | entities.add(new BannerEntity(0, "http://img.zcool.cn/community/01700557a7f42f0000018c1bd6eb23.jpg", "image")); 29 | entities.add(new BannerEntity(2, "https://github.com/nanchen2251", "custom")); 30 | mBannerView.setEntities(entities); 31 | 32 | mBannerView.setOnBannerClickListener(new OnBannerClickListener() { 33 | @Override 34 | public void onClick(int position) { 35 | if (mTextView.getVisibility() == View.VISIBLE){ 36 | mTextView.setVisibility(View.GONE); 37 | }else{ 38 | mTextView.setVisibility(View.VISIBLE); 39 | } 40 | } 41 | }); 42 | } 43 | 44 | //如果你需要考虑更好的体验,可以这么操作 45 | @Override 46 | protected void onStart() { 47 | super.onStart(); 48 | //开始轮播 49 | mBannerView.startAutoScroll(); 50 | } 51 | 52 | @Override 53 | protected void onStop() { 54 | super.onStop(); 55 | //结束轮播 56 | mBannerView.stopAutoScroll(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanchen2251/CheerBanner/c79336117ce415cee665078c6d62ebe00f61806a/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 | CheerBanner 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/nanchen/cheerbanner/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.cheerbanner; 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/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /banner/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 11 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | compile fileTree(dir: 'libs', include: ['*.jar']) 26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 27 | exclude group: 'com.android.support', module: 'support-annotations' 28 | }) 29 | compile 'com.android.support:appcompat-v7:25.3.1' 30 | testCompile 'junit:junit:4.12' 31 | compile 'com.github.bumptech.glide:glide:3.7.0' 32 | } 33 | -------------------------------------------------------------------------------- /banner/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 D:\Users\50323\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/src/androidTest/java/com/nanchen/banner/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 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.nanchen.banner.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /banner/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/BannerConfig.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 2 | 3 | /** 4 | * Author: nanchen 5 | * Email: liushilin520@foxmail.com 6 | * Date: 2017-08-30 9:22 7 | */ 8 | 9 | public class BannerConfig { 10 | public static final int TYPE_IMAGE = 0; 11 | public static final int TYPE_WEB = 1; 12 | public static final int TYPE_OTHER = 2; 13 | } 14 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/BannerEntity.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 2 | 3 | /** 4 | * Author: nanchen 5 | * Email: liushilin520@foxmail.com 6 | * Date: 2017-08-30 9:16 7 | */ 8 | 9 | public class BannerEntity { 10 | public int type; // 显示样式,你可以自定义 N 种样式 11 | public String url; // 地址,可以是图片或者网址或者其他 12 | public String title; // 显示轮播的标题 13 | 14 | public BannerEntity(int type, String url, String title) { 15 | this.type = type; 16 | this.url = url; 17 | this.title = title; 18 | } 19 | 20 | public BannerEntity() { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/BannerLayout.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.AttrRes; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.text.TextUtils; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | import android.webkit.WebChromeClient; 11 | import android.webkit.WebSettings; 12 | import android.webkit.WebView; 13 | import android.webkit.WebViewClient; 14 | import android.widget.Button; 15 | import android.widget.FrameLayout; 16 | import android.widget.ImageView; 17 | import android.widget.LinearLayout; 18 | import android.widget.TextView; 19 | 20 | import com.bumptech.glide.Glide; 21 | 22 | import java.util.Locale; 23 | 24 | /** 25 | * BannerLayout 其他布局继承自这里 26 | *

27 | * Author: nanchen 28 | * Email: liushilin520@foxmail.com 29 | * Date: 2017-08-30 9:24 30 | */ 31 | 32 | public class BannerLayout extends FrameLayout { 33 | private ImageView mImageView; 34 | private TextView mTvBannerTitle; 35 | private WebView mWebView; 36 | private LinearLayout mLinearLayout; 37 | private Button mButton; 38 | private TextView mTextView; 39 | private int flag = 0; 40 | 41 | public BannerLayout(@NonNull Context context) { 42 | this(context, null); 43 | } 44 | 45 | public BannerLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 46 | this(context, attrs, 0); 47 | } 48 | 49 | public BannerLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { 50 | super(context, attrs, defStyleAttr); 51 | View.inflate(getContext(), R.layout.layout_banner, this); 52 | mImageView = (ImageView) this.findViewById(R.id.imageView); 53 | mTvBannerTitle = (TextView) this.findViewById(R.id.tv_banner_title); 54 | mWebView = (WebView) findViewById(R.id.webView); 55 | mLinearLayout = (LinearLayout) findViewById(R.id.ll_mine); 56 | mButton = (Button) findViewById(R.id.btn); 57 | mTextView = (TextView) findViewById(R.id.text); 58 | } 59 | 60 | public void setEntity(BannerEntity entity) { 61 | if (entity.type == 0){ 62 | mImageView.setVisibility(View.VISIBLE); 63 | mWebView.setVisibility(View.GONE); 64 | mLinearLayout.setVisibility(View.GONE); 65 | Glide.with(getContext().getApplicationContext()).load(entity.url).centerCrop().crossFade().into(mImageView); 66 | }else if (entity.type == 1){ 67 | mImageView.setVisibility(View.GONE); 68 | mWebView.setVisibility(View.VISIBLE); 69 | mLinearLayout.setVisibility(View.GONE); 70 | 71 | WebSettings settings = mWebView.getSettings(); 72 | settings.setLoadWithOverviewMode(true); 73 | settings.setJavaScriptEnabled(true); 74 | settings.setAppCacheEnabled(true); 75 | settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); 76 | settings.setSupportZoom(true); 77 | mWebView.setWebViewClient(new WebViewClient()); 78 | mWebView.setWebChromeClient(new WebChromeClient()); 79 | mWebView.loadUrl(entity.url); 80 | }else{ 81 | mImageView.setVisibility(View.GONE); 82 | mWebView.setVisibility(View.GONE); 83 | mLinearLayout.setVisibility(View.VISIBLE); 84 | mButton.setOnClickListener(new OnClickListener() { 85 | @Override 86 | public void onClick(View v) { 87 | mTextView.setText(String.format(Locale.CHINA,"按钮已点击:%d",++flag)); 88 | } 89 | }); 90 | } 91 | if (!TextUtils.isEmpty(entity.title)) { 92 | mTvBannerTitle.setText(entity.title); 93 | } else { 94 | mTvBannerTitle.setVisibility(GONE); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/BannerLine.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.support.v4.content.ContextCompat; 7 | import android.util.AttributeSet; 8 | import android.util.DisplayMetrics; 9 | import android.view.View; 10 | 11 | /** 12 | * banner底部的指示线,后期加入其他样式,比如原点型。 13 | * 14 | * Author: nanchen 15 | * Email: liushilin520@foxmail.com 16 | * Date: 2017-08-30 9:17 17 | */ 18 | 19 | public class BannerLine extends View { 20 | 21 | private Paint mPaint; 22 | private float mWidth; 23 | private int mPageSize; 24 | private float mPageWidth = 0f; 25 | private int mPosition; 26 | private float mPositionOffset; 27 | private int mLineColor = ContextCompat.getColor(getContext(), R.color.banner_blue); 28 | 29 | public BannerLine(Context context) { 30 | this(context, null); 31 | } 32 | 33 | public BannerLine(Context context, AttributeSet attrs) { 34 | this(context, attrs, 0); 35 | } 36 | 37 | public BannerLine(Context context, AttributeSet attrs, int defStyleAttr) { 38 | super(context, attrs, defStyleAttr); 39 | DisplayMetrics dm = getResources().getDisplayMetrics(); 40 | mWidth = dm.widthPixels; 41 | mPaint = new Paint(); 42 | mPaint.setColor(mLineColor); 43 | mPaint.setAntiAlias(true); 44 | mPaint.setStrokeWidth(1000f); 45 | } 46 | 47 | @Override 48 | protected void onDraw(Canvas canvas) { 49 | if (mPosition == 0) { 50 | canvas.drawLine((mPageSize - 3) * mPageWidth + mPageWidth * mPositionOffset, 0, (mPageSize - 2) * mPageWidth + mPageWidth * mPositionOffset, 0, mPaint); 51 | canvas.drawLine(0, 0, mPageWidth * mPositionOffset, 0, mPaint); 52 | } else if (mPosition == mPageSize - 2) { 53 | canvas.drawLine((mPosition - 1) * mPageWidth + mPageWidth * mPositionOffset, 0, mPosition * mPageWidth + mPageWidth * mPositionOffset, 0, mPaint); 54 | canvas.drawLine(0, 0, mPageWidth * mPositionOffset, 0, mPaint); 55 | } else { 56 | canvas.drawLine((mPosition - 1) * mPageWidth + mPageWidth * mPositionOffset, 0, mPosition * mPageWidth + mPageWidth * mPositionOffset, 0, mPaint); 57 | } 58 | 59 | } 60 | 61 | public void setPageWidth(int pageSize) { 62 | mPageSize = pageSize; 63 | calcPageWidth(); 64 | } 65 | 66 | private void calcPageWidth() { 67 | this.mPageWidth = this.mWidth / (this.mPageSize - 2); 68 | } 69 | 70 | public void setPageScrolled(int position, float positionOffset) { 71 | mPosition = position; 72 | mPositionOffset = positionOffset; 73 | invalidate(); 74 | } 75 | 76 | public void setLineColor(int lineColor) { 77 | mLineColor = lineColor; 78 | mPaint.setColor(mLineColor); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/BannerPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.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 java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * Author: nanchen 13 | * Email: liushilin520@foxmail.com 14 | * Date: 2017-08-30 9:36 15 | */ 16 | 17 | public class BannerPagerAdapter extends PagerAdapter { 18 | 19 | private Context mContext; 20 | private List mEntities = new ArrayList<>(); 21 | private List mLayouts = new ArrayList<>(); 22 | private OnBannerClickListener mClickListener; 23 | 24 | public BannerPagerAdapter(Context context, List entities) { 25 | mContext = context; 26 | this.mEntities = entities; 27 | setLayouts(); 28 | } 29 | 30 | private void setLayouts() { 31 | for (BannerEntity entity : mEntities) { 32 | BannerLayout layout = new BannerLayout(mContext); 33 | layout.setEntity(entity); 34 | mLayouts.add(layout); 35 | } 36 | } 37 | 38 | @Override 39 | public int getCount() { 40 | return mLayouts.size(); 41 | } 42 | 43 | @Override 44 | public boolean isViewFromObject(View view, Object object) { 45 | return view == object; 46 | } 47 | 48 | @Override 49 | public Object instantiateItem(ViewGroup container, final int position) { 50 | BannerLayout bannerLayout = mLayouts.get(position); 51 | bannerLayout.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | if (mClickListener != null) { 55 | mClickListener.onClick(position - 1); 56 | } 57 | } 58 | }); 59 | container.addView(bannerLayout, 0); 60 | return mLayouts.get(position); 61 | } 62 | 63 | @Override 64 | public void destroyItem(ViewGroup container, int position, Object object) { 65 | container.removeView(mLayouts.get(position)); 66 | } 67 | 68 | @Override 69 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 70 | super.setPrimaryItem(container, position, object); 71 | } 72 | 73 | public void setOnBannerClickListener(OnBannerClickListener clickListener) { 74 | this.mClickListener = clickListener; 75 | } 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/BannerView.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.os.Handler; 7 | import android.os.Message; 8 | import android.support.v4.content.ContextCompat; 9 | import android.support.v4.view.ViewPager; 10 | import android.util.AttributeSet; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | import android.widget.FrameLayout; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Timer; 18 | import java.util.TimerTask; 19 | 20 | /** 21 | * Author: nanchen 22 | * Email: liushilin520@foxmail.com 23 | * Date: 2017-08-30 9:36 24 | */ 25 | 26 | public class BannerView extends FrameLayout { 27 | private long mAutoScrollDelay = 3000; 28 | private Timer mAutoScrollTimer; 29 | private ViewPager mVpBanner; 30 | private BannerLine mLine; 31 | private List mEntities = new ArrayList<>(); 32 | private BannerPagerAdapter mAdapter; 33 | private Handler mMainHandler; 34 | private int currentIdx = 0; 35 | private Timer mTimer = null; 36 | 37 | 38 | @Override 39 | public boolean dispatchTouchEvent(MotionEvent ev) { 40 | int action = ev.getAction(); 41 | if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL 42 | || action == MotionEvent.ACTION_OUTSIDE) { 43 | startAutoScroll(); 44 | } else if (action == MotionEvent.ACTION_DOWN) { 45 | stopAutoScroll(); 46 | } 47 | return super.dispatchTouchEvent(ev); 48 | } 49 | 50 | public BannerView(Context context) { 51 | this(context, null); 52 | } 53 | 54 | public BannerView(Context context, AttributeSet attrs) { 55 | this(context, attrs, 0); 56 | } 57 | 58 | public BannerView(Context context, AttributeSet attrs, int defStyleAttr) { 59 | super(context, attrs, defStyleAttr); 60 | View.inflate(getContext(), R.layout.view_banner, this); 61 | mVpBanner = (ViewPager) this.findViewById(R.id.vp_banner); 62 | mLine = (BannerLine) this.findViewById(R.id.line); 63 | TypedArray typeArray = context.obtainStyledAttributes(attrs, 64 | R.styleable.BannerView); 65 | int lineColor = typeArray.getColor(R.styleable.BannerView_banner_line_color, 66 | ContextCompat.getColor(getContext(), R.color.banner_blue)); 67 | typeArray.recycle(); 68 | mLine.setLineColor(lineColor); 69 | mMainHandler = new Handler(context.getMainLooper()); 70 | } 71 | 72 | public void setEntities(List entities) { 73 | addExtraPage(entities); 74 | showBanner(); 75 | } 76 | 77 | private void addExtraPage(List entities) { 78 | mEntities.clear(); 79 | mEntities.add(entities.get(entities.size() - 1)); 80 | mEntities.addAll(entities); 81 | mEntities.add(entities.get(0)); 82 | } 83 | 84 | private void showBanner() { 85 | mLine.setPageWidth(mEntities.size()); 86 | mAdapter = new BannerPagerAdapter(getContext(), mEntities); 87 | mVpBanner.setAdapter(mAdapter); 88 | mVpBanner.setCurrentItem(1, true); 89 | currentIdx = 1; 90 | mVpBanner.clearOnPageChangeListeners(); 91 | mVpBanner.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 92 | @Override 93 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 94 | mLine.setPageScrolled(position, positionOffset); 95 | currentIdx = position; 96 | if (positionOffsetPixels == 0.0) { 97 | setViewPagerItemPosition(position); 98 | } 99 | } 100 | 101 | @Override 102 | public void onPageSelected(int position) { 103 | 104 | } 105 | 106 | @Override 107 | public void onPageScrollStateChanged(int state) { 108 | 109 | } 110 | }); 111 | } 112 | 113 | /** 114 | * set auto scroll time 115 | */ 116 | public void setAutoScroll(long time) { 117 | if (this.mTimer != null) { 118 | this.mTimer.cancel(); 119 | this.mTimer = null; 120 | } 121 | this.mTimer = new Timer("Banner Scroller Timer"); 122 | TimerTask scrollerTask = new TimerTask() { 123 | @Override 124 | public void run() { 125 | mHandler.sendMessage(new Message()); 126 | } 127 | }; 128 | this.mTimer.schedule(scrollerTask, time, time); 129 | } 130 | 131 | @SuppressLint("HandlerLeak") 132 | private Handler mHandler = new Handler() { 133 | @Override 134 | public void handleMessage(Message msg) { 135 | super.handleMessage(msg); 136 | if (currentIdx >= mEntities.size()) { 137 | currentIdx = 0; 138 | } 139 | mVpBanner.setCurrentItem(currentIdx, true); 140 | currentIdx++; 141 | } 142 | }; 143 | 144 | private void setViewPagerItemPosition(int position) { 145 | if (position == mEntities.size() - 1) { 146 | mVpBanner.setCurrentItem(1, false); 147 | } else if (position == 0) { 148 | mVpBanner.setCurrentItem(mEntities.size() - 2, false); 149 | } else { 150 | mVpBanner.setCurrentItem(position); 151 | } 152 | } 153 | 154 | private void nextScroll() { 155 | int position = mVpBanner.getCurrentItem(); 156 | mLine.setPageScrolled(position + 1, 0); 157 | setViewPagerItemPosition(position + 1); 158 | } 159 | 160 | public void startAutoScroll() { 161 | mAutoScrollTimer = new Timer(); 162 | mAutoScrollTimer.schedule(new TimerTask() { 163 | @Override 164 | public void run() { 165 | mMainHandler.post(new Runnable() { 166 | @Override 167 | public void run() { 168 | nextScroll(); 169 | } 170 | }); 171 | } 172 | }, mAutoScrollDelay, mAutoScrollDelay); 173 | } 174 | 175 | public void stopAutoScroll() { 176 | mAutoScrollTimer.cancel(); 177 | } 178 | 179 | public void setAutoScrollDelay(long delay) { 180 | this.mAutoScrollDelay = delay; 181 | } 182 | 183 | public void setOnBannerClickListener(OnBannerClickListener clickListener) { 184 | if (mAdapter != null) { 185 | mAdapter.setOnBannerClickListener(clickListener); 186 | } 187 | } 188 | 189 | } 190 | 191 | -------------------------------------------------------------------------------- /banner/src/main/java/com/nanchen/banner/OnBannerClickListener.java: -------------------------------------------------------------------------------- 1 | package com.nanchen.banner; 2 | 3 | /** 4 | * Author: nanchen 5 | * Email: liushilin520@foxmail.com 6 | * Date: 2017-08-30 9:35 7 | */ 8 | 9 | public interface OnBannerClickListener { 10 | void onClick(int position); 11 | } 12 | -------------------------------------------------------------------------------- /banner/src/main/res/layout/layout_banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | 25 | 26 | 32 | 33 |