├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_CN.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── viewpager-1.0.0.aar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── example │ │ └── zhpan │ │ └── banner │ │ ├── App.java │ │ ├── activity │ │ ├── BaseCompatActivity.java │ │ ├── BaseDataActivity.kt │ │ ├── MainActivity.kt │ │ ├── WebViewActivity.java │ │ └── WelcomeActivity.kt │ │ ├── adapter │ │ ├── DataBindingSampleAdapter.kt │ │ ├── MultiViewTypesAdapter.java │ │ ├── SimpleAdapter.kt │ │ ├── ViewBindingSampleAdapter.kt │ │ └── others │ │ │ ├── AdapterFragmentPager.kt │ │ │ ├── ArticleAdapter.kt │ │ │ └── DataBindingAdapter.java │ │ ├── bean │ │ ├── ArticleWrapper.kt │ │ ├── CustomBean.kt │ │ └── DataWrapper.kt │ │ ├── fragment │ │ ├── BaseFragment.kt │ │ ├── EmptyFragment.java │ │ ├── HomeFragment.java │ │ ├── IndicatorFragment.java │ │ ├── OthersFragment.java │ │ └── PageFragment.kt │ │ ├── loading │ │ ├── LoadingDialog.java │ │ └── LoadingUtils.java │ │ ├── net │ │ ├── ApiService.java │ │ ├── BannerData.java │ │ ├── Constants.java │ │ ├── RetrofitGnerator.java │ │ ├── RxUtil.java │ │ ├── common │ │ │ ├── BasicResponse.java │ │ │ ├── Constants.java │ │ │ ├── ErrorCode.java │ │ │ ├── IdeaApi.java │ │ │ ├── LoadingTransformerCreator.java │ │ │ ├── ResponseObserver.java │ │ │ └── RetrofitUtils.java │ │ ├── converter │ │ │ ├── GsonConverterFactory.java │ │ │ ├── GsonRequestBodyConverter.java │ │ │ └── GsonResponseBodyConverter.java │ │ ├── exception │ │ │ ├── NoDataExceptionException.java │ │ │ ├── RemoteLoginExpiredException.java │ │ │ └── ServerResponseException.java │ │ ├── https │ │ │ ├── SafeHostnameVerifier.java │ │ │ └── SslContextFactory.java │ │ └── interceptor │ │ │ ├── HttpCacheInterceptor.java │ │ │ ├── HttpHeaderInterceptor.java │ │ │ └── LoggingInterceptor.java │ │ ├── recyclerview │ │ ├── listener │ │ │ └── ICustomClickListener.java │ │ ├── module │ │ │ └── RecyclerViewConfig.java │ │ └── ui │ │ │ ├── CustomAdapter.java │ │ │ └── CustomRecyclerView.java │ │ ├── transform │ │ ├── AccordionTransformer.java │ │ ├── BaseTransformer.java │ │ ├── DepthPageTransformer.kt │ │ ├── DepthScaleTransformer.kt │ │ ├── PageTransformerFactory.java │ │ ├── RotateTransformer.kt │ │ ├── RotateUpTransformer.java │ │ └── TransformerStyle.java │ │ └── view │ │ ├── CornerImageView.kt │ │ └── FigureIndicatorView.java │ └── res │ ├── drawable-anydpi │ └── ic_back.xml │ ├── drawable-hdpi │ └── ic_back.png │ ├── drawable-mdpi │ └── ic_back.png │ ├── drawable-xhdpi │ ├── creative_hover.png │ ├── creative_none.png │ ├── discover_hover.png │ ├── discover_none.png │ ├── home_hover.png │ ├── home_none.png │ ├── ic_back.png │ ├── mine_hover.png │ ├── mine_none.png │ └── tab4_selector.xml │ ├── drawable-xxhdpi │ ├── guide0.jpg │ ├── guide1.jpg │ ├── guide2.jpg │ ├── ic_back.png │ └── placeholder.jpg │ ├── drawable-xxxhdpi │ ├── advertise0.png │ ├── advertise1.png │ ├── advertise2.png │ ├── advertise3.png │ ├── advertise4.png │ ├── heart_empty.png │ ├── heart_red.png │ ├── ic_banner.png │ ├── ic_email.png │ ├── ic_indicator.png │ └── ic_qq_group.png │ ├── drawable │ ├── banner_indicator_focus.xml │ ├── banner_indicator_nornal.xml │ ├── bg_card0.xml │ ├── bg_card1.xml │ ├── bg_card2.xml │ ├── bg_card3.xml │ ├── bg_start.xml │ ├── tab1_selector.xml │ ├── tab2_selector.xml │ ├── tab3_selector.xml │ └── text_color_selector.xml │ ├── ezgif-3-b826de74b0.gif │ ├── layout │ ├── activity_main.xml │ ├── activity_webview.xml │ ├── activity_welcome.xml │ ├── fragment_empty.xml │ ├── fragment_find.xml │ ├── fragment_home.xml │ ├── fragment_indicator.xml │ ├── fragment_others.xml │ ├── item_article.xml │ ├── item_custom_view.xml │ ├── item_defalut_loadmore_view.xml │ ├── item_defalut_refresh_view.xml │ ├── item_head_foot_parent.xml │ ├── item_header_view.xml │ ├── item_home_banner.xml │ ├── item_line.xml │ ├── item_net_image.xml │ ├── item_new_type.xml │ ├── item_page_indicator.xml │ ├── item_slide_mode.xml │ ├── item_slide_model_data_binding.xml │ ├── item_view.xml │ ├── layout_loading_dialog.xml │ └── nav_header_main.xml │ ├── menu │ ├── indicator_slide_style_menu.xml │ ├── nav_menu.xml │ └── transformer_menu.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── raw │ ├── cabks.bks │ ├── capk.pkcs12 │ ├── loading2.json │ └── srca.cer │ ├── values-sw1024dp │ └── dimens.xml │ ├── values-sw1280dp │ └── dimens.xml │ ├── values-sw1365dp │ └── dimens.xml │ ├── values-sw384dp │ └── dimens.xml │ ├── values-sw392dp │ └── dimens.xml │ ├── values-sw400dp │ └── dimens.xml │ ├── values-sw410dp │ └── dimens.xml │ ├── values-sw411dp │ └── dimens.xml │ ├── values-sw432dp │ └── dimens.xml │ ├── values-sw480dp │ └── dimens.xml │ ├── values-sw533dp │ └── dimens.xml │ ├── values-sw592dp │ └── dimens.xml │ ├── values-sw600dp │ └── dimens.xml │ ├── values-sw640dp │ └── dimens.xml │ ├── values-sw662dp │ └── dimens.xml │ ├── values-sw720dp │ └── dimens.xml │ ├── values-sw768dp │ └── dimens.xml │ ├── values-sw800dp │ └── dimens.xml │ ├── values-sw811dp │ └── dimens.xml │ ├── values-sw820dp │ └── dimens.xml │ ├── values-sw960dp │ └── dimens.xml │ ├── values-sw961dp │ └── dimens.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── bannerview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zhpan │ │ └── bannerview │ │ ├── BannerViewPager.java │ │ ├── BaseBannerAdapter.java │ │ ├── BaseViewHolder.java │ │ ├── annotation │ │ ├── AIndicatorGravity.java │ │ ├── APageStyle.java │ │ └── Visibility.java │ │ ├── constants │ │ ├── IndicatorGravity.java │ │ └── PageStyle.java │ │ ├── indicator │ │ └── DrawableIndicator.kt │ │ ├── manager │ │ ├── AttributeController.java │ │ ├── BannerManager.java │ │ └── BannerOptions.java │ │ ├── provider │ │ ├── ReflectLayoutManager.java │ │ ├── RoundViewOutlineProvider.java │ │ ├── ScrollDurationManger.java │ │ └── ViewStyleSetter.java │ │ ├── transform │ │ ├── OverlapPageTransformer.kt │ │ └── ScaleInTransformer.java │ │ └── utils │ │ └── BannerUtils.java │ └── res │ ├── layout │ └── bvp_layout.xml │ └── values │ └── attrs.xml ├── build.gradle ├── codestyle └── codestyle.xml ├── git ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://github.com/zhpanvip/BannerViewPager#Sponsor'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | /app/release/output.json 10 | /app/release/app-release.apk 11 | /ideahttp/build/ 12 | /app/release/output-metadata.json 13 | /zoomlayout/build/ 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | android { 4 | compileSdkVersion 33 5 | defaultConfig { 6 | applicationId "com.example.zhpan.bannerviewpager" 7 | minSdkVersion 21 8 | targetSdkVersion 33 9 | versionCode 2 10 | versionName "3.5.10" 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | debuggable false 16 | minifyEnabled true 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | sourceSets { 22 | main { 23 | jniLibs.srcDirs = ['libs'] 24 | } 25 | } 26 | 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | 32 | viewBinding { 33 | enabled = true 34 | } 35 | dataBinding { 36 | //noinspection DataBindingWithoutKapt 37 | enabled = true 38 | } 39 | } 40 | 41 | repositories { 42 | flatDir { 43 | dirs 'libs' 44 | } 45 | } 46 | 47 | dependencies { 48 | implementation fileTree(include: ['*.jar'], dir: 'libs') 49 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 50 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 51 | androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', { 52 | exclude group: 'com.android.support', module: 'support-annotations' 53 | }) 54 | implementation "io.reactivex.rxjava2:rxjava:$rootProject.ext.rxjava2Version" 55 | implementation "com.squareup.retrofit2:retrofit:$rootProject.ext.retrofit2Version" 56 | implementation "com.squareup.retrofit2:converter-scalars:$rootProject.ext.retrofit2Version" 57 | implementation "com.squareup.retrofit2:converter-gson:$rootProject.ext.retrofit2Version" 58 | implementation "com.squareup.retrofit2:adapter-rxjava2:$rootProject.ext.retrofit2Version" 59 | implementation "com.trello.rxlifecycle2:rxlifecycle:$rootProject.ext.rxlifecycle" 60 | implementation "com.trello.rxlifecycle2:rxlifecycle-components:$rootProject.ext.rxlifecycle" 61 | implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 62 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' 63 | implementation 'com.squareup.okhttp3:logging-interceptor:4.8.1' 64 | 65 | implementation 'androidx.appcompat:appcompat:1.3.0' 66 | implementation 'androidx.recyclerview:recyclerview:1.2.1' 67 | implementation 'com.github.bumptech.glide:glide:4.11.0' 68 | implementation 'io.github.scwang90:refresh-layout-kernel:2.1.0' 69 | implementation 'io.github.scwang90:refresh-header-classics:2.1.0' 70 | implementation 'io.github.scwang90:refresh-header-material:2.1.0' 71 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10' 72 | implementation 'androidx.core:core-ktx:1.6.0' 73 | implementation 'androidx.cardview:cardview:1.0.0' 74 | implementation 'androidx.viewpager2:viewpager2:1.0.0' 75 | implementation 'io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.4' 76 | implementation 'com.google.android.material:material:1.3.0' 77 | implementation "androidx.navigation:navigation-fragment-ktx:2.3.5" 78 | implementation "androidx.navigation:navigation-ui-ktx:2.3.5" 79 | implementation 'com.tencent.bugly:crashreport:3.2.1' 80 | implementation 'com.google.android.material:material:1.3.0' 81 | implementation 'com.blankj:utilcodex:1.30.6' 82 | implementation 'com.airbnb.android:lottie:3.4.1' 83 | // implementation 'com.github.zhpanvip:bannerviewpager:3.5.6' 84 | implementation project(path: ':bannerview') 85 | } 86 | -------------------------------------------------------------------------------- /app/libs/viewpager-1.0.0.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/libs/viewpager-1.0.0.aar -------------------------------------------------------------------------------- /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\edianzu\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 | -keep class * extends androidx.fragment.app.Fragment { 20 | public void setUserVisibleHint(boolean); 21 | public void onHiddenChanged(boolean); 22 | public void onResume(); 23 | public void onPause(); 24 | } 25 | -keep public class * extends android.app.Activity 26 | -keep class com.example.zhpan.banner.bean.** { *; } 27 | -keep class com.example.zhpan.banner.net.** { *; } 28 | -keep class com.zhpan.idea.** { *; } 29 | -dontwarn com.tencent.bugly.** 30 | -keep public class com.tencent.bugly.**{*;} 31 | 32 | 33 | # For BannerViewPager 34 | -keep class androidx.recyclerview.widget.**{*;} 35 | -keep class androidx.viewpager2.widget.**{*;} -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/App.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner; 2 | 3 | import android.app.Application; 4 | import android.os.Debug; 5 | import android.os.Environment; 6 | 7 | import com.tencent.bugly.crashreport.CrashReport; 8 | import com.zhpan.bannerview.utils.BannerUtils; 9 | 10 | import java.io.File; 11 | 12 | /** 13 | *
14 |  *   Created by zhangpan on 2019-08-14.
15 |  *   Description:
16 |  *
17 |  * 
18 | */ 19 | public class App extends Application { 20 | 21 | @Override 22 | public void onCreate() { 23 | super.onCreate(); 24 | BannerUtils.setDebugMode(true); 25 | CrashReport.initCrashReport(getApplicationContext(), "69b176a2b6", true); 26 | // Debug.startMethodTracing(new File(Environment.getExternalStorageDirectory(), "test").getAbsolutePath()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/activity/BaseCompatActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.activity; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | 6 | import android.os.Bundle; 7 | 8 | import com.example.zhpan.banner.R; 9 | import com.scwang.smart.refresh.header.MaterialHeader; 10 | import com.scwang.smart.refresh.layout.SmartRefreshLayout; 11 | import com.scwang.smart.refresh.layout.api.RefreshLayout; 12 | import com.scwang.smart.refresh.layout.listener.OnRefreshListener; 13 | 14 | public class BaseCompatActivity extends AppCompatActivity implements OnRefreshListener { 15 | protected SmartRefreshLayout mRefreshLayout; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | } 21 | 22 | // 设置下拉刷新 23 | protected void setRefreshLayout(boolean isAutoRefresh) { 24 | mRefreshLayout = findViewById(R.id.swipe_refresh_layout); 25 | if (mRefreshLayout == null) return; 26 | if (needRefreshHeader()) { 27 | mRefreshLayout.setRefreshHeader(getRefreshHeader()); 28 | } 29 | mRefreshLayout.setEnableLoadMore(needLoadMore()); 30 | if (isAutoRefresh) { 31 | mRefreshLayout.post(new Runnable() { 32 | @Override 33 | public void run() { 34 | mRefreshLayout.autoRefresh(); 35 | } 36 | }); 37 | } 38 | mRefreshLayout.setOnRefreshListener(this); 39 | } 40 | 41 | // 是否需要上拉加载 42 | protected boolean needLoadMore() { 43 | return false; 44 | } 45 | 46 | // 是否需要添加刷新头部,如不需要可在子类中添加刷新头 47 | protected boolean needRefreshHeader() { 48 | return true; 49 | } 50 | 51 | // 获取刷新头 52 | protected MaterialHeader getRefreshHeader() { 53 | MaterialHeader materialHeader = new MaterialHeader(this); 54 | materialHeader.setColorSchemeResources(R.color.red); 55 | return materialHeader; 56 | } 57 | 58 | 59 | @Override public void onRefresh(@NonNull RefreshLayout refreshLayout) { 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/activity/BaseDataActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.activity 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | 5 | import android.os.Bundle 6 | 7 | import java.util.ArrayList 8 | 9 | abstract class BaseDataActivity : AppCompatActivity() { 10 | 11 | protected var mDrawableList: MutableList = ArrayList() 12 | 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | initData() 16 | } 17 | 18 | private fun initData() { 19 | for (i in 0..2) { 20 | val drawable = resources.getIdentifier("guide$i", "drawable", packageName) 21 | mDrawableList.add(drawable) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/activity/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.util.Log 7 | import androidx.appcompat.app.ActionBarDrawerToggle 8 | import androidx.appcompat.app.AppCompatActivity 9 | import androidx.viewpager2.widget.ViewPager2 10 | import com.example.zhpan.banner.R 11 | import com.example.zhpan.banner.adapter.others.AdapterFragmentPager 12 | import com.example.zhpan.banner.databinding.ActivityMainBinding 13 | import com.google.android.material.navigation.NavigationView 14 | 15 | class MainActivity : AppCompatActivity() { 16 | private lateinit var binding: ActivityMainBinding 17 | override fun onCreate(savedInstanceState: Bundle?) { 18 | super.onCreate(savedInstanceState) 19 | binding = ActivityMainBinding.inflate(layoutInflater) 20 | setContentView(binding.root) 21 | initView() 22 | initData() 23 | setListener() 24 | } 25 | 26 | override fun onResume() { 27 | super.onResume() 28 | val width = window.decorView.width 29 | val height = window.decorView.height 30 | Log.d("Main", "width = $width,height = $height") 31 | } 32 | 33 | private fun initView() { 34 | binding.toolbar.apply { 35 | title = getString(R.string.app_name) 36 | setSupportActionBar(binding.toolbar) 37 | } 38 | binding.drawerLayout.apply { 39 | val toggle = ActionBarDrawerToggle( 40 | this@MainActivity, 41 | this, 42 | binding.toolbar, R.string.navigation_drawer_open, 43 | R.string.navigation_drawer_close 44 | ) 45 | addDrawerListener(toggle) 46 | toggle.syncState() 47 | } 48 | binding.navView.apply { 49 | setNavigationItemSelectedListener(onDrawerNavigationItemSelectedListener) 50 | } 51 | } 52 | 53 | private fun initData() { 54 | with(binding.vpFragment) { 55 | adapter = AdapterFragmentPager(this@MainActivity) 56 | registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { 57 | override fun onPageSelected(position: Int) { 58 | super.onPageSelected(position) 59 | binding.rgTab.check(getCheckedId(position)) 60 | } 61 | }) 62 | } 63 | } 64 | 65 | private fun getCheckedId(position: Int): Int { 66 | return when (position) { 67 | 0 -> R.id.rb_home 68 | 1 -> R.id.rb_add 69 | 2 -> R.id.rb_find 70 | 3 -> R.id.rb_others 71 | else -> R.id.rb_home 72 | } 73 | } 74 | 75 | private fun setListener() { 76 | binding.rgTab.setOnCheckedChangeListener { _, checkedId -> 77 | when (checkedId) { 78 | R.id.rb_home -> binding.vpFragment.setCurrentItem(AdapterFragmentPager.PAGE_HOME, true) 79 | R.id.rb_add -> binding.vpFragment.setCurrentItem(AdapterFragmentPager.PAGE_FIND, true) 80 | R.id.rb_find -> binding.vpFragment.setCurrentItem( 81 | AdapterFragmentPager.PAGE_INDICATOR, 82 | true 83 | ) 84 | R.id.rb_others -> binding.vpFragment.setCurrentItem(AdapterFragmentPager.PAGE_OTHERS, true) 85 | } 86 | } 87 | } 88 | 89 | companion object { 90 | fun start(context: Context) { 91 | context.startActivity(Intent(context, MainActivity::class.java)) 92 | } 93 | } 94 | 95 | private val onDrawerNavigationItemSelectedListener = 96 | NavigationView.OnNavigationItemSelectedListener { item -> 97 | when (item.itemId) { 98 | R.id.nav_banner -> { 99 | WebViewActivity.start( 100 | this@MainActivity, getString(R.string.app_name), 101 | "https://github.com/zhpanvip/BannerViewPager" 102 | ) 103 | } 104 | 105 | R.id.nav_indicator -> { 106 | WebViewActivity.start( 107 | this@MainActivity, getString(R.string.indicator_name), 108 | "https://github.com/zhpanvip/ViewPagerIndicator" 109 | ) 110 | } 111 | } 112 | true 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/activity/WebViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.activity; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.pm.ApplicationInfo; 7 | import android.os.Bundle; 8 | import android.view.KeyEvent; 9 | import android.webkit.WebSettings; 10 | import android.webkit.WebView; 11 | import android.webkit.WebViewClient; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.appcompat.widget.Toolbar; 15 | 16 | import com.example.zhpan.banner.R; 17 | import com.scwang.smart.refresh.header.MaterialHeader; 18 | import com.scwang.smart.refresh.layout.api.RefreshLayout; 19 | 20 | /** 21 | * Created by zhpan on 2017/4/16. 22 | * Describe: 通用 WebView 考虑以后所有展示 WebView 的界面都从这个类继承 23 | */ 24 | @SuppressLint("SetJavaScriptEnabled") 25 | public class WebViewActivity extends BaseCompatActivity { 26 | 27 | protected static final String INTENT_KEY_TITLE = "title"; 28 | public static final String INTENT_KEY_URL = "url"; 29 | protected WebView mWebView; 30 | private String mTitle; 31 | private String mUrl; 32 | private Toolbar mToolbar; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_webview); 38 | initView(); 39 | initData(); 40 | initWebView(); 41 | } 42 | 43 | private void initView() { 44 | mToolbar = findViewById(R.id.toolbar); 45 | mWebView = findViewById(R.id.webView); 46 | mRefreshLayout = findViewById(R.id.swipe_refresh_layout); 47 | MaterialHeader materialHeader = findViewById(R.id.material_header); 48 | materialHeader.setColorSchemeColors(getResources().getColor(R.color.colorAccent)); 49 | } 50 | 51 | private void initData() { 52 | Intent intent = getIntent(); 53 | if (intent != null) { 54 | mTitle = intent.getStringExtra(INTENT_KEY_TITLE); 55 | mUrl = intent.getStringExtra(INTENT_KEY_URL); 56 | } 57 | mToolbar.setNavigationOnClickListener(v -> onBackPressed()); 58 | mToolbar.setTitle(mTitle); 59 | setRefreshLayout(true); 60 | } 61 | 62 | @Override 63 | protected boolean needRefreshHeader() { 64 | return false; 65 | } 66 | 67 | @Override 68 | public void onRefresh(@NonNull RefreshLayout refreshLayout) { 69 | super.onRefresh(refreshLayout); 70 | mWebView.clearHistory(); 71 | mWebView.reload(); 72 | } 73 | 74 | private void initWebView() { 75 | mWebView.setWebViewClient(new WebViewClient() { 76 | @Override 77 | public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) { 78 | return false; 79 | } 80 | }); 81 | // mWebView.setBackgroundColor(getResources().getColor(R.color.background)); 82 | WebSettings setting = mWebView.getSettings(); 83 | setting.setJavaScriptEnabled(true); 84 | setting.setDisplayZoomControls(false); 85 | setting.setSupportZoom(false); 86 | setting.setBuiltInZoomControls(false); 87 | // setting.setSavePassword(false); // 安全要求 88 | 89 | if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)) { 90 | WebView.setWebContentsDebuggingEnabled(true); 91 | } 92 | mWebView.setWebViewClient(new WebViewClient() { 93 | @Override 94 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 95 | view.loadUrl(url); 96 | return true; 97 | } 98 | 99 | @Override 100 | public void onPageFinished(WebView view, String url) { 101 | super.onPageFinished(view, url); 102 | mRefreshLayout.finishRefresh(); 103 | } 104 | }); 105 | mWebView.loadUrl(mUrl); 106 | } 107 | 108 | @Override 109 | public void onDestroy() { 110 | super.onDestroy(); 111 | if (mWebView != null) { 112 | mWebView.destroy(); 113 | } 114 | mWebView = null; 115 | } 116 | 117 | @Override 118 | public boolean onKeyDown(int keyCode, KeyEvent event) { 119 | //判断是否可以返回操作 120 | if (mWebView.canGoBack()) { 121 | mWebView.goBack(); 122 | return true; 123 | } else { 124 | finish(); 125 | return true; 126 | } 127 | } 128 | 129 | public static void start(@NonNull Context context, @NonNull String title, @NonNull String url) { 130 | Intent intent = new Intent(context, WebViewActivity.class); 131 | intent.putExtra(INTENT_KEY_TITLE, title); 132 | intent.putExtra(INTENT_KEY_URL, url); 133 | context.startActivity(intent); 134 | } 135 | 136 | public static void start(@NonNull Context context, @NonNull String url) { 137 | Intent intent = new Intent(context, WebViewActivity.class); 138 | intent.putExtra(INTENT_KEY_TITLE, ""); 139 | intent.putExtra(INTENT_KEY_URL, url); 140 | context.startActivity(intent); 141 | } 142 | 143 | public static void start(@NonNull Context context, Class baseActivity, 144 | @NonNull String url) { 145 | Intent intent = new Intent(context, baseActivity); 146 | intent.putExtra(INTENT_KEY_TITLE, ""); 147 | intent.putExtra(INTENT_KEY_URL, url); 148 | context.startActivity(intent); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/activity/WelcomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.activity 2 | 3 | import android.animation.AnimatorSet 4 | import android.animation.ObjectAnimator 5 | import android.os.Bundle 6 | import android.view.View 7 | import android.view.animation.DecelerateInterpolator 8 | import androidx.core.content.ContextCompat 9 | import androidx.viewpager2.widget.ViewPager2 10 | import com.blankj.utilcode.util.ToastUtils 11 | import com.example.zhpan.banner.R 12 | import com.example.zhpan.banner.adapter.SimpleAdapter 13 | import com.example.zhpan.banner.bean.CustomBean 14 | import com.example.zhpan.banner.databinding.ActivityWelcomeBinding 15 | import com.example.zhpan.banner.transform.PageTransformerFactory 16 | import com.zhpan.bannerview.BannerViewPager 17 | import com.example.zhpan.banner.transform.TransformerStyle 18 | import com.zhpan.bannerview.utils.BannerUtils 19 | import com.zhpan.indicator.enums.IndicatorSlideMode 20 | import java.util.* 21 | 22 | class WelcomeActivity : BaseDataActivity() { 23 | 24 | private lateinit var mViewPager: BannerViewPager 25 | private lateinit var binding: ActivityWelcomeBinding 26 | 27 | private val des = arrayOf("在这里\n你可以听到周围人的心声", "在这里\nTA会在下一秒遇见你", "在这里\n不再错过可以改变你一生的人") 28 | 29 | private val transforms = intArrayOf( 30 | TransformerStyle.NONE, 31 | TransformerStyle.ACCORDION, 32 | TransformerStyle.DEPTH, 33 | TransformerStyle.DEPTH_SCALE, 34 | TransformerStyle.ROTATE, 35 | TransformerStyle.SCALE_IN, 36 | TransformerStyle.ROTATE_UP 37 | ) 38 | 39 | private val data: List 40 | get() { 41 | val list = ArrayList() 42 | for (i in mDrawableList.indices) { 43 | val customBean = CustomBean() 44 | customBean.imageRes = mDrawableList[i] 45 | customBean.imageDescription = des[i] 46 | list.add(customBean) 47 | } 48 | return list 49 | } 50 | 51 | override fun onCreate(savedInstanceState: Bundle?) { 52 | super.onCreate(savedInstanceState) 53 | binding = ActivityWelcomeBinding.inflate(layoutInflater) 54 | setContentView(binding.root) 55 | setupViewPager() 56 | updateUI(0) 57 | } 58 | 59 | private fun setupViewPager() { 60 | mViewPager = findViewById(R.id.viewpager) 61 | mViewPager.apply { 62 | setCanLoop(false) 63 | setPageTransformer( 64 | PageTransformerFactory.createPageTransformer(transforms[Random().nextInt(7)]) 65 | ) 66 | setIndicatorMargin(0, 0, 0, resources.getDimensionPixelOffset(R.dimen.dp_100)) 67 | setIndicatorSliderGap( 68 | resources.getDimension(R.dimen.dp_10) 69 | .toInt() 70 | ) 71 | setIndicatorSlideMode(IndicatorSlideMode.SMOOTH) 72 | setIndicatorSliderRadius( 73 | resources.getDimension(R.dimen.dp_3) 74 | .toInt(), resources.getDimension(R.dimen.dp_4_5) 75 | .toInt() 76 | ) 77 | registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { 78 | override fun onPageSelected(position: Int) { 79 | BannerUtils.log("position:$position") 80 | updateUI(position) 81 | } 82 | }) 83 | adapter = SimpleAdapter().apply { 84 | mOnSubViewClickListener = object : SimpleAdapter.OnSubViewClickListener { 85 | override fun onViewClick( 86 | view: View?, 87 | position: Int 88 | ) { 89 | ToastUtils.showShort("Logo Clicked,position:$position") 90 | } 91 | } 92 | } 93 | setIndicatorSliderColor( 94 | ContextCompat.getColor(this@WelcomeActivity, R.color.white), 95 | ContextCompat.getColor(this@WelcomeActivity, R.color.white_alpha_75) 96 | ) 97 | } 98 | .create(data) 99 | } 100 | 101 | fun onClick(view: View) { 102 | MainActivity.start(this) 103 | finish() 104 | } 105 | 106 | private fun updateUI(position: Int) { 107 | binding.tvDescribe.text = des[position] 108 | val translationAnim = ObjectAnimator.ofFloat(binding.tvDescribe, "translationX", -120f, 0f) 109 | translationAnim.apply { 110 | duration = ANIMATION_DURATION.toLong() 111 | interpolator = DecelerateInterpolator() 112 | } 113 | val alphaAnimator = ObjectAnimator.ofFloat(binding.tvDescribe, "alpha", 0f, 1f) 114 | alphaAnimator.apply { 115 | duration = ANIMATION_DURATION.toLong() 116 | } 117 | val animatorSet = AnimatorSet() 118 | animatorSet.playTogether(translationAnim, alphaAnimator) 119 | animatorSet.start() 120 | 121 | if (position == mViewPager.data.size - 1 && binding.btnStart.visibility == View.GONE) { 122 | binding.btnStart.visibility = View.VISIBLE 123 | ObjectAnimator 124 | .ofFloat(binding.btnStart, "alpha", 0f, 1f) 125 | .setDuration(ANIMATION_DURATION.toLong()) 126 | .start() 127 | } else { 128 | binding.btnStart.visibility = View.GONE 129 | } 130 | } 131 | 132 | companion object { 133 | private const val ANIMATION_DURATION = 1300 134 | private const val MIN_SCALE = 0.9f 135 | private const val MIN_ALPHA = 0.7f 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/DataBindingSampleAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import com.zhpan.bannerview.BaseBannerAdapter 6 | import com.example.zhpan.banner.net.BannerData 7 | import androidx.databinding.DataBindingUtil 8 | import com.example.zhpan.banner.R.layout 9 | import com.example.zhpan.banner.databinding.ItemSlideModelDataBindingBinding 10 | import com.zhpan.bannerview.BaseViewHolder 11 | import java.lang.NullPointerException 12 | 13 | /** 14 | *
15 |  * Created by zhpan on 2020/4/5.
16 |  * Description:使用DataBinding示例
17 | 
* 18 | */ 19 | class DataBindingSampleAdapter : BaseBannerAdapter() { 20 | 21 | override fun createViewHolder( 22 | parent: ViewGroup, itemView: View, 23 | viewType: Int 24 | ): BaseViewHolder { 25 | val binding = DataBindingUtil.bind(itemView) 26 | ?: throw NullPointerException("binding is Null") 27 | return DataBindingViewHolder(binding) 28 | } 29 | 30 | override fun bindData( 31 | holder: BaseViewHolder?, 32 | data: BannerData?, 33 | position: Int, 34 | pageSize: Int 35 | ) { 36 | if (holder is DataBindingViewHolder) { 37 | holder.binding.bannerData = data 38 | } 39 | } 40 | 41 | override fun getLayoutId(viewType: Int): Int { 42 | return layout.item_slide_model_data_binding 43 | } 44 | } 45 | 46 | internal class DataBindingViewHolder(var binding: ItemSlideModelDataBindingBinding) : BaseViewHolder(binding.root) -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/MultiViewTypesAdapter.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter; 2 | 3 | import android.widget.ImageView; 4 | 5 | import com.bumptech.glide.Glide; 6 | import com.example.zhpan.banner.R; 7 | import com.example.zhpan.banner.net.BannerData; 8 | import com.zhpan.bannerview.BaseBannerAdapter; 9 | import com.zhpan.bannerview.BaseViewHolder; 10 | 11 | /** 12 | *
13 |  *   Created by zhpan on 2020/4/6.
14 |  *   Description:Sample of multiple view types .
15 |  * 
16 | */ 17 | public class MultiViewTypesAdapter extends BaseBannerAdapter { 18 | 19 | @Override 20 | protected void bindData(BaseViewHolder holder, BannerData data, int position, 21 | int pageSize) { 22 | if (getViewType(position) == BannerData.TYPE_NEW) { 23 | holder.setImageResource(R.id.image_view, data.getDrawable()); 24 | } else { 25 | ImageView imageView = holder.findViewById(R.id.banner_image); 26 | Glide.with(imageView) 27 | .load(data.getImagePath()) 28 | .placeholder(R.drawable.placeholder) 29 | .into(imageView); 30 | } 31 | } 32 | 33 | @Override 34 | public int getLayoutId(int viewType) { 35 | if (viewType == BannerData.TYPE_NEW) { 36 | return R.layout.item_new_type; 37 | } 38 | return R.layout.item_net_image; 39 | } 40 | 41 | @Override 42 | public int getViewType(int position) { 43 | return mList.get(position).getType(); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/SimpleAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter 2 | 3 | import android.animation.ObjectAnimator 4 | import android.view.View 5 | import android.widget.ImageView 6 | import com.example.zhpan.banner.R 7 | import com.example.zhpan.banner.bean.CustomBean 8 | import com.zhpan.bannerview.BaseBannerAdapter 9 | import com.zhpan.bannerview.BaseViewHolder 10 | 11 | /** 12 | *
13 |  * Created by zhpan on 2020/4/5.
14 |  * Description:
15 |  * 
16 | */ 17 | class SimpleAdapter : BaseBannerAdapter() { 18 | 19 | var mOnSubViewClickListener: OnSubViewClickListener? = null 20 | 21 | override fun bindData( 22 | holder: BaseViewHolder, 23 | data: CustomBean?, 24 | position: Int, 25 | pageSize: Int 26 | ) { 27 | val imageStart: ImageView = holder.findViewById(R.id.iv_logo) 28 | holder.setImageResource(R.id.banner_image, data!!.imageRes) 29 | holder.setOnClickListener(R.id.iv_logo) { view: View? -> 30 | if (null != mOnSubViewClickListener) mOnSubViewClickListener!!.onViewClick( 31 | view, holder.adapterPosition 32 | ) 33 | } 34 | val alphaAnimator = ObjectAnimator.ofFloat(imageStart, "alpha", 0f, 1f) 35 | alphaAnimator.duration = 1500 36 | alphaAnimator.start() 37 | } 38 | 39 | override fun getLayoutId(viewType: Int): Int { 40 | return R.layout.item_custom_view; 41 | } 42 | 43 | interface OnSubViewClickListener { 44 | fun onViewClick( 45 | view: View?, 46 | position: Int 47 | ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/ViewBindingSampleAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import com.example.zhpan.banner.R.layout 6 | import com.example.zhpan.banner.databinding.ItemSlideModeBinding 7 | import com.zhpan.bannerview.BaseBannerAdapter 8 | import com.zhpan.bannerview.BaseViewHolder 9 | 10 | /** 11 | * @author DBoy 12 | * @date 2020/12/11 13 | * Class 描述 : 使用ViewBinding示例 14 | */ 15 | class ViewBindingSampleAdapter(private val mRoundCorner: Int) : BaseBannerAdapter() { 16 | 17 | override fun createViewHolder( 18 | parent: ViewGroup, 19 | itemView: View, 20 | viewType: Int 21 | ): BaseViewHolder { 22 | return ViewBindingViewHolder(ItemSlideModeBinding.bind(itemView)) 23 | } 24 | 25 | override fun bindData(holder: BaseViewHolder, data: Int, position: Int, pageSize: Int) { 26 | if (holder is ViewBindingViewHolder) { 27 | holder.viewBinding.bannerImage.setRoundCorner(mRoundCorner) 28 | holder.viewBinding.bannerImage.setImageResource(data) 29 | } 30 | } 31 | 32 | override fun getLayoutId(viewType: Int): Int { 33 | return layout.item_slide_mode 34 | } 35 | } 36 | 37 | internal class ViewBindingViewHolder(var viewBinding: ItemSlideModeBinding) : 38 | BaseViewHolder(viewBinding.root) 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/others/AdapterFragmentPager.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter.others 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentActivity 5 | import androidx.viewpager2.adapter.FragmentStateAdapter 6 | import com.example.zhpan.banner.fragment.* 7 | 8 | /** 9 | *
10 |  * Created by zhangpan on 2019-12-05.
11 |  * Description: MainActivity Fragment Adapter.
12 | 
* 13 | */ 14 | class AdapterFragmentPager(fragmentActivity: FragmentActivity) : FragmentStateAdapter( 15 | fragmentActivity 16 | ) { 17 | 18 | override fun createFragment(position: Int): Fragment { 19 | return when (position) { 20 | PAGE_HOME -> HomeFragment.getInstance(); 21 | PAGE_FIND -> PageFragment.instance; 22 | PAGE_INDICATOR -> IndicatorFragment.getInstance(); 23 | PAGE_OTHERS -> OthersFragment.getInstance(); 24 | else -> EmptyFragment.getInstance(); 25 | } 26 | } 27 | 28 | override fun getItemCount(): Int { 29 | return 4 30 | } 31 | 32 | companion object { 33 | const val PAGE_HOME = 0 34 | const val PAGE_FIND = 1 35 | const val PAGE_INDICATOR = 2 36 | const val PAGE_OTHERS = 3 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/others/ArticleAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter.others 2 | 3 | import android.content.Context 4 | import android.content.res.Resources 5 | import androidx.recyclerview.widget.RecyclerView 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.TextView 10 | import androidx.appcompat.app.AppCompatActivity 11 | import androidx.core.content.ContextCompat 12 | import androidx.viewpager2.widget.ViewPager2 13 | 14 | import com.example.zhpan.banner.R 15 | import com.example.zhpan.banner.adapter.DataBindingSampleAdapter 16 | import com.example.zhpan.banner.bean.ArticleWrapper 17 | import com.example.zhpan.banner.net.BannerData 18 | import com.zhpan.bannerview.BannerViewPager 19 | import com.zhpan.bannerview.BaseViewHolder 20 | import com.zhpan.bannerview.constants.IndicatorGravity 21 | import com.zhpan.indicator.enums.IndicatorStyle 22 | 23 | import java.util.ArrayList 24 | 25 | /** 26 | * HomeFragment RecyclerView Adapter 27 | */ 28 | class ArticleAdapter( 29 | val context: Context, 30 | data: List 31 | ) : RecyclerView.Adapter() { 32 | private val mList = ArrayList() 33 | private val inflater: LayoutInflater 34 | 35 | init { 36 | this.mList.addAll(data) 37 | this.inflater = LayoutInflater.from(context) 38 | } 39 | 40 | override fun onCreateViewHolder( 41 | viewGroup: ViewGroup, 42 | itemType: Int 43 | ): RecyclerView.ViewHolder { 44 | if (itemType == 1001) { 45 | return BannerItemViewHolder(inflater.inflate(R.layout.item_home_banner, viewGroup, false)) 46 | } 47 | return ArticleViewHolder(inflater.inflate(R.layout.item_article, viewGroup, false)) 48 | } 49 | 50 | override fun onBindViewHolder( 51 | holder: RecyclerView.ViewHolder, 52 | i: Int 53 | ) { 54 | val article = mList[i] 55 | if (article.type == 1001 && holder is BannerItemViewHolder) { 56 | holder.bannerViewPager 57 | .refreshData(article.bannerData) 58 | } else if (holder is ArticleViewHolder) { 59 | holder.tvAuthor.text = article.author 60 | holder.tvTitle.text = article.title 61 | } 62 | } 63 | 64 | fun setData(list: List) { 65 | mList.clear() 66 | mList.addAll(list) 67 | notifyDataSetChanged() 68 | } 69 | 70 | override fun getItemViewType(position: Int): Int { 71 | return mList[position].type 72 | } 73 | 74 | override fun getItemCount(): Int { 75 | return mList.size 76 | } 77 | 78 | inner class ArticleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 79 | internal var tvTitle: TextView = itemView.findViewById(R.id.tv_title) 80 | internal var tvAuthor: TextView = itemView.findViewById(R.id.tv_auther) 81 | } 82 | 83 | inner class BannerItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 84 | var bannerViewPager: BannerViewPager = itemView.findViewById(R.id.banner_view3) 85 | var resources: Resources = itemView.context.resources 86 | 87 | init { 88 | if (context is AppCompatActivity) 89 | bannerViewPager.setCanLoop(false) 90 | .setOrientation(ViewPager2.ORIENTATION_VERTICAL) 91 | .setIndicatorGravity(IndicatorGravity.END) 92 | .setInterval(2000) 93 | .setAdapter(DataBindingSampleAdapter()) 94 | .registerLifecycleObserver(context.lifecycle) 95 | .create() 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/adapter/others/DataBindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.adapter.others; 2 | 3 | import android.widget.ImageView; 4 | 5 | import androidx.databinding.BindingAdapter; 6 | 7 | import com.bumptech.glide.Glide; 8 | 9 | /** 10 | *
11 |  *   Created by zhpan on 2020/7/18.
12 |  *   Description:
13 |  * 
14 | */ 15 | public class DataBindingAdapter { 16 | @BindingAdapter(value = { "url", "placeholder" }, requireAll = false) 17 | public static void bindUrl(ImageView imageView, String url, int placeholder) { 18 | Glide.with(imageView).load(url).error(placeholder).placeholder(placeholder).into(imageView); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/bean/ArticleWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.bean 2 | 3 | import com.example.zhpan.banner.net.BannerData 4 | 5 | class ArticleWrapper { 6 | 7 | var datas: List
? = null 8 | 9 | class Article { 10 | var title: String? = null 11 | 12 | var link: String? = null 13 | 14 | var author: String? = null 15 | 16 | var publishTime: Long = 0 17 | 18 | var type: Int = 0 19 | 20 | var bannerData: List? = null 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/bean/CustomBean.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.bean 2 | 3 | class CustomBean { 4 | 5 | var imageRes: Int = 0 6 | 7 | var imageDescription: String? = null 8 | 9 | var imgUrl: String? = null 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/bean/DataWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.bean 2 | 3 | import com.example.zhpan.banner.net.BannerData 4 | 5 | class DataWrapper( 6 | val articleList: List, 7 | val dataBeanList: List 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/fragment/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.fragment 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | 9 | import androidx.annotation.ColorInt 10 | import androidx.annotation.ColorRes 11 | import androidx.core.content.ContextCompat 12 | 13 | import com.trello.rxlifecycle2.components.support.RxFragment 14 | 15 | import java.util.ArrayList 16 | 17 | /** 18 | * MVC模式的Base fragment 19 | */ 20 | abstract class BaseFragment : RxFragment() { 21 | private var mDrawableList: MutableList = ArrayList() 22 | protected lateinit var mContext: Context 23 | 24 | private var mPictureList: MutableList = ArrayList() 25 | 26 | /** 27 | * 获取当前Activity的UI布局 28 | * 29 | * @return 布局id 30 | */ 31 | protected abstract val layout: Int 32 | 33 | override fun onAttach(context: Context) { 34 | super.onAttach(context) 35 | this.mContext = context.applicationContext 36 | } 37 | 38 | override fun onCreateView( 39 | inflater: LayoutInflater, 40 | container: ViewGroup?, 41 | savedInstanceState: Bundle? 42 | ): View? { 43 | val view = inflater.inflate(layout, container, false) 44 | initData(3) 45 | initTitle() 46 | initView(savedInstanceState, view) 47 | return view 48 | } 49 | 50 | protected fun getPicList(count: Int): MutableList { 51 | mPictureList.clear() 52 | for (i in 0..count) { 53 | val drawable = resources.getIdentifier("advertise$i", "drawable", mContext.packageName) 54 | mPictureList.add(drawable) 55 | } 56 | return mPictureList; 57 | } 58 | 59 | private fun initData(j: Int) { 60 | mDrawableList.clear() 61 | for (i in 0..j) { 62 | val drawable = resources.getIdentifier("bg_card$i", "drawable", mContext.packageName) 63 | mDrawableList.add(drawable) 64 | } 65 | } 66 | 67 | @ColorInt 68 | protected fun getColor(@ColorRes colorRes: Int): Int { 69 | return ContextCompat.getColor(requireContext(), colorRes) 70 | } 71 | 72 | /** 73 | * 初始化标题 74 | */ 75 | protected abstract fun initTitle() 76 | 77 | /** 78 | * 初始化数据 79 | */ 80 | protected abstract fun initView( 81 | savedInstanceState: Bundle?, 82 | view: View 83 | ) 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/fragment/EmptyFragment.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.os.Message; 5 | import android.view.View; 6 | 7 | import com.example.zhpan.banner.R; 8 | 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | /** 13 | * @author zhangpan 14 | * @date 2020/12/9 15 | */ 16 | public class EmptyFragment extends BaseFragment { 17 | 18 | @Override 19 | protected int getLayout() { 20 | return R.layout.fragment_empty; 21 | } 22 | 23 | @Override 24 | protected void initTitle() { 25 | 26 | } 27 | 28 | @Override 29 | protected void initView(@Nullable Bundle savedInstanceState, @NotNull View view) { 30 | 31 | } 32 | 33 | public static EmptyFragment getInstance() { 34 | return new EmptyFragment(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/loading/LoadingDialog.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.loading; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.widget.TextView; 7 | 8 | import com.airbnb.lottie.LottieAnimationView; 9 | import com.example.zhpan.banner.R; 10 | 11 | public class LoadingDialog extends Dialog { 12 | 13 | private final boolean cancelTouchOutside; 14 | private LottieAnimationView lottieAnimationView; 15 | private String message; 16 | private static final int KEY_NO_DIALOG_STYLE = -1; 17 | 18 | public LoadingDialog(Builder builder) { 19 | super(builder.context); 20 | cancelTouchOutside = builder.cancelTouchOutside; 21 | } 22 | 23 | private LoadingDialog(Builder builder, int themeResId) { 24 | super(builder.context, themeResId); 25 | cancelTouchOutside = builder.cancelTouchOutside; 26 | this.message = builder.message; 27 | } 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.layout_loading_dialog); 33 | TextView tvMessage = (TextView) findViewById(R.id.tv_loading); 34 | if (tvMessage != null) { 35 | tvMessage.setText(message); 36 | } 37 | setCanceledOnTouchOutside(cancelTouchOutside); 38 | } 39 | 40 | @Override 41 | public void onWindowFocusChanged(boolean hasFocus) { 42 | lottieAnimationView = findViewById(R.id.loadingImageView); 43 | lottieAnimationView.playAnimation(); 44 | } 45 | 46 | @Override 47 | protected void onStop() { 48 | super.onStop(); 49 | lottieAnimationView.pauseAnimation(); 50 | } 51 | 52 | public static final class Builder { 53 | Context context; 54 | private int themeResId = KEY_NO_DIALOG_STYLE; 55 | private String message; 56 | private boolean cancelTouchOutside; 57 | 58 | public Builder(Context context) { 59 | this.context = context; 60 | } 61 | 62 | /** 63 | * 设置主题 64 | * 65 | * @param themeResId theme res id 66 | * @return CustomProgressDialog.Builder 67 | */ 68 | public Builder setTheme(int themeResId) { 69 | this.themeResId = themeResId; 70 | return this; 71 | } 72 | 73 | public Builder setMessage(String message) { 74 | this.message = message; 75 | return this; 76 | } 77 | 78 | /** 79 | * 设置点击dialog外部是否取消dialog 80 | * 81 | * @param val 点击外部是否取消dialog 82 | * @return Builder 83 | */ 84 | public Builder cancelTouchOutside(boolean val) { 85 | cancelTouchOutside = val; 86 | return this; 87 | } 88 | 89 | public LoadingDialog build() { 90 | if (themeResId == KEY_NO_DIALOG_STYLE) { 91 | return new LoadingDialog(this); 92 | } else { 93 | return new LoadingDialog(this, themeResId); 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/loading/LoadingUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.loading; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import com.example.zhpan.banner.R; 7 | 8 | /** 9 | * Created by zhpan on 2017/5/26. 10 | */ 11 | public class LoadingUtils { 12 | 13 | private LoadingDialog mProgressDialog; 14 | 15 | /** 16 | * 显示带有文字的ProgressDialog 17 | */ 18 | public void showLoading(Context context, String msg) { 19 | if (context == null || context instanceof Activity && ((Activity) context).isFinishing()) { 20 | return; 21 | } 22 | 23 | if (mProgressDialog == null) { 24 | mProgressDialog = new LoadingDialog.Builder(context) 25 | .setTheme(R.style.ProgressDialogStyle) 26 | .setMessage(msg) 27 | .build(); 28 | } 29 | if (!mProgressDialog.isShowing()) { 30 | mProgressDialog.show(); 31 | } 32 | } 33 | 34 | /** 35 | * 显示ProgressDialog 36 | */ 37 | public void showLoading(Context context) { 38 | if (context == null || context instanceof Activity && ((Activity) context).isFinishing()) { 39 | return; 40 | } 41 | if (mProgressDialog == null) { 42 | mProgressDialog = new LoadingDialog.Builder(context) 43 | .setTheme(R.style.ProgressDialogStyle) 44 | .build(); 45 | } 46 | if (!mProgressDialog.isShowing()) { 47 | mProgressDialog.show(); 48 | } 49 | } 50 | 51 | /** 52 | * 取消ProgressDialog 53 | */ 54 | public void dismiss() { 55 | if (mProgressDialog != null && mProgressDialog.isShowing()) { 56 | mProgressDialog.dismiss(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net; 2 | 3 | import com.example.zhpan.banner.bean.ArticleWrapper; 4 | 5 | import java.util.List; 6 | 7 | import io.reactivex.Observable; 8 | import retrofit2.http.GET; 9 | import retrofit2.http.Headers; 10 | 11 | /** 12 | *
13 |  *   Created by zhangpan on 2019-08-14.
14 |  *   Description:
15 |  * 
16 | */ 17 | public interface ApiService { 18 | 19 | @Headers("Cache-Control: public, max-age=" + 3600) 20 | @GET("banner/json") 21 | Observable> getBannerData(); 22 | 23 | @Headers("Cache-Control: public, max-age=" + 3600) 24 | @GET("article/list/0/json") 25 | Observable getArticle(); 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/BannerData.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net; 2 | 3 | import androidx.annotation.DrawableRes; 4 | 5 | import com.example.zhpan.banner.R; 6 | 7 | /** 8 | *
  9 |  *   Created by zhangpan on 2019-08-14.
 10 |  *   Description:
 11 |  * 
12 | */ 13 | public class BannerData { 14 | 15 | /** 16 | * desc : 17 | * id : 20 18 | * imagePath : https://www.wanandroid.com/blogimgs/90c6cc12-742e-4c9f-b318-b912f163b8d0.png 19 | * isVisible : 1 20 | * order : 2 21 | * title : flutter 中文社区 22 | * type : 1 23 | * url : https://flutter.cn/ 24 | */ 25 | 26 | public static final int TYPE_NEW = 10000; 27 | 28 | private String desc; 29 | private int id; 30 | private String imagePath; 31 | private int isVisible; 32 | private int order; 33 | private String title; 34 | private int type; 35 | private String url; 36 | private int drawable; 37 | private @DrawableRes final int placeHolder = R.drawable.placeholder; 38 | 39 | public int getDrawable() { 40 | return drawable; 41 | } 42 | 43 | public void setDrawable(int drawable) { 44 | this.drawable = drawable; 45 | } 46 | 47 | public String getDesc() { 48 | return desc; 49 | } 50 | 51 | public void setDesc(String desc) { 52 | this.desc = desc; 53 | } 54 | 55 | public int getId() { 56 | return id; 57 | } 58 | 59 | public void setId(int id) { 60 | this.id = id; 61 | } 62 | 63 | public String getImagePath() { 64 | return imagePath; 65 | } 66 | 67 | public void setImagePath(String imagePath) { 68 | this.imagePath = imagePath; 69 | } 70 | 71 | public int getIsVisible() { 72 | return isVisible; 73 | } 74 | 75 | public void setIsVisible(int isVisible) { 76 | this.isVisible = isVisible; 77 | } 78 | 79 | public int getOrder() { 80 | return order; 81 | } 82 | 83 | public void setOrder(int order) { 84 | this.order = order; 85 | } 86 | 87 | public String getTitle() { 88 | return title; 89 | } 90 | 91 | public void setTitle(String title) { 92 | this.title = title; 93 | } 94 | 95 | public int getType() { 96 | return type; 97 | } 98 | 99 | public void setType(int type) { 100 | this.type = type; 101 | } 102 | 103 | public String getUrl() { 104 | return url; 105 | } 106 | 107 | public void setUrl(String url) { 108 | this.url = url; 109 | } 110 | 111 | public @DrawableRes 112 | int getPlaceHolder() { 113 | return placeHolder; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/Constants.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net; 2 | 3 | /** 4 | *
 5 |  *   Created by zhangpan on 2019-08-14.
 6 |  *   Description:
 7 |  * 
8 | */ 9 | public interface Constants { 10 | String BASE_URL = "https://www.wanandroid.com/"; 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/RetrofitGnerator.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net; 2 | 3 | import com.example.zhpan.banner.net.common.IdeaApi; 4 | 5 | /** 6 | *
 7 |  *   Created by zhangpan on 2019-08-14.
 8 |  *   Description:
 9 |  * 
10 | */ 11 | public class RetrofitGnerator { 12 | private static ApiService mApiservice; 13 | 14 | public static ApiService getApiSerVice() { 15 | if (mApiservice == null) { 16 | mApiservice = IdeaApi.getApiService(ApiService.class, Constants.BASE_URL); 17 | } 18 | return mApiservice; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/RxUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net; 2 | 3 | import com.example.zhpan.banner.net.common.LoadingTransformerCreator; 4 | import com.trello.rxlifecycle2.android.ActivityEvent; 5 | import com.trello.rxlifecycle2.android.FragmentEvent; 6 | import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; 7 | import com.trello.rxlifecycle2.components.support.RxFragment; 8 | 9 | import io.reactivex.Observable; 10 | import io.reactivex.ObservableTransformer; 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | @SuppressWarnings("unused") 15 | public class RxUtil { 16 | 17 | /** 18 | * 统一线程处理 19 | * 20 | * @return ObservableTransformer 21 | */ 22 | public static ObservableTransformer rxSchedulerHelper( 23 | final RxAppCompatActivity activity, final boolean showLoading) { //compose简化线程 24 | return observable -> { 25 | Observable compose = observable.subscribeOn(Schedulers.io()) 26 | .observeOn(AndroidSchedulers.mainThread()) 27 | .compose(activity.bindUntilEvent(ActivityEvent.DESTROY)); 28 | if (showLoading) { 29 | return compose.compose(LoadingTransformerCreator.applyLoading(activity)); 30 | } else { 31 | return compose; 32 | } 33 | }; 34 | } 35 | 36 | /** 37 | * 统一线程处理 38 | * 39 | * @return ObservableTransformer 40 | */ 41 | public static ObservableTransformer rxSchedulerHelper(final RxFragment fragment, 42 | final boolean showLoading) { 43 | return observable -> { 44 | Observable compose = observable.subscribeOn(Schedulers.io()) 45 | .observeOn(AndroidSchedulers.mainThread()) 46 | .compose(fragment.bindUntilEvent(FragmentEvent.DESTROY)); 47 | if (showLoading) { 48 | return compose.compose(LoadingTransformerCreator.applyLoading(fragment.getActivity())); 49 | } else { 50 | return compose; 51 | } 52 | }; 53 | } 54 | 55 | /** 56 | * 统一线程处理 57 | * 58 | * @return ObservableTransformer 59 | */ 60 | public static ObservableTransformer rxSchedulerHelper() { //compose简化线程 61 | return observable -> observable.subscribeOn(Schedulers.io()) 62 | .observeOn(AndroidSchedulers.mainThread()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/BasicResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.common; 2 | 3 | /** 4 | * 5 | */ 6 | public class BasicResponse { 7 | 8 | private int errorCode; 9 | private String errorMsg; 10 | private T data; 11 | 12 | public T getData() { 13 | return data; 14 | } 15 | 16 | public void setData(T results) { 17 | this.data = results; 18 | } 19 | 20 | public int getErrorCode() { 21 | return errorCode; 22 | } 23 | 24 | public void setCode(int code) { 25 | this.errorCode = code; 26 | } 27 | 28 | public String getErrorMsg() { 29 | return errorMsg; 30 | } 31 | 32 | public void setErrorMsg(String message) { 33 | this.errorMsg = message; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/Constants.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.common; 2 | 3 | /** 4 | * Created by zhpan on 2018/2/1. 5 | */ 6 | 7 | public interface Constants { 8 | /** 9 | * 网络请求超时时间毫秒 10 | */ 11 | int DEFAULT_TIMEOUT = 20000; 12 | String IP = "202.108.22.59"; 13 | String HOST = "http://gank.io/"; 14 | String API_SERVER_URL = HOST + "api/data/"; 15 | String DOWNLOAD_URL = "http://www.oitsme.com/download/oitsme.apk"; 16 | /// String API_SERVER_URL = HOST + PORT+"iocm/app/"; 17 | // String API_SERVER_URL = "https://www.12306.cn/mormhweb/"; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/ErrorCode.java: -------------------------------------------------------------------------------- 1 | 2 | package com.example.zhpan.banner.net.common; 3 | 4 | import androidx.annotation.StringRes; 5 | 6 | import com.blankj.utilcode.util.Utils; 7 | import com.example.zhpan.banner.R; 8 | 9 | /** 10 | * Created by zhpan on 2018/3/27. 11 | */ 12 | public class ErrorCode { 13 | /** 14 | * request success 15 | */ 16 | public static final int SUCCESS = 0; 17 | /** 18 | * Wrong verify code 19 | */ 20 | public static final int VERIFY_CODE_ERROR = 110011; 21 | /** 22 | * Verify code is invalid 23 | */ 24 | public static final int VERIFY_CODE_EXPIRED = 110010; 25 | /** 26 | * User is not register 27 | */ 28 | public static final int ACCOUNT_NOT_REGISTER = 110009; 29 | /** 30 | * Wrong password or username 31 | */ 32 | public static final int PASSWORD_ERROR = 110012; 33 | 34 | /** 35 | * Wrong old password 36 | */ 37 | public static final int OLD_PASSWORD_ERROR = 110015; 38 | 39 | public static final int USER_REGISTERED = 110006; 40 | 41 | public static final int PARAMS_ERROR = 19999; 42 | /** 43 | * 异地登录 44 | */ 45 | public static final int REMOTE_LOGIN = 91011; 46 | 47 | /** 48 | * get error message with error code 49 | * 50 | * @param errorCode error code 51 | * @return error message 52 | */ 53 | public static String getErrorMessage(int errorCode) { 54 | String message; 55 | switch (errorCode) { 56 | case VERIFY_CODE_ERROR: 57 | message = getString(R.string.verify_code_error); 58 | break; 59 | case VERIFY_CODE_EXPIRED: 60 | message = getString(R.string.verify_code_expired); 61 | break; 62 | case ACCOUNT_NOT_REGISTER: 63 | message = getString(R.string.not_register); 64 | break; 65 | case PASSWORD_ERROR: 66 | message = getString(R.string.wrong_pwd_username); 67 | break; 68 | case USER_REGISTERED: 69 | message = getString(R.string.user_registered); 70 | break; 71 | case OLD_PASSWORD_ERROR: 72 | message = getString(R.string.wrong_password); 73 | break; 74 | case PARAMS_ERROR: 75 | message = getString(R.string.parameters_exception); 76 | break; 77 | case REMOTE_LOGIN: 78 | message = getString(R.string.remote_login); 79 | break; 80 | default: 81 | message = getString(R.string.request_error) + errorCode; 82 | break; 83 | } 84 | return message; 85 | } 86 | 87 | private static String getString(@StringRes int resId) { 88 | return Utils.getApp().getString(resId); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/IdeaApi.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.common; 2 | 3 | import retrofit2.Retrofit; 4 | 5 | /** 6 | * Created by zhpan on 2017/4/1. 7 | */ 8 | 9 | public class IdeaApi { 10 | public static T getApiService(Class cls, String baseUrl) { 11 | Retrofit retrofit = RetrofitUtils.getRetrofitBuilder(baseUrl).build(); 12 | return retrofit.create(cls); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/LoadingTransformerCreator.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.common; 2 | 3 | import android.app.Activity; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.example.zhpan.banner.loading.LoadingUtils; 8 | 9 | import io.reactivex.CompletableTransformer; 10 | import io.reactivex.ObservableTransformer; 11 | import io.reactivex.disposables.Disposable; 12 | import io.reactivex.functions.Consumer; 13 | 14 | /** 15 | * Created by zhpan on 2018/3/22. 16 | */ 17 | public class LoadingTransformerCreator { 18 | 19 | public static ObservableTransformer applyLoading( 20 | @NonNull final Activity activity, String msg) { 21 | final LoadingUtils dialogUtils = new LoadingUtils(); 22 | dialogUtils.showLoading(activity, msg); 23 | return upstream -> upstream.doOnSubscribe(disposable -> { 24 | }).doOnTerminate(dialogUtils::dismiss) 25 | .doOnSubscribe((Consumer) disposable -> { 26 | }); 27 | } 28 | 29 | public static ObservableTransformer applyLoading( 30 | @NonNull final Activity activity) { 31 | return applyLoading(activity, ""); 32 | } 33 | 34 | public static CompletableTransformer applyLoadingForCompletable( 35 | @NonNull final Activity activity) { 36 | return applyLoadingForCompletable(activity, ""); 37 | } 38 | 39 | public static CompletableTransformer applyLoadingForCompletable( 40 | @NonNull final Activity activity, String msg) { 41 | final LoadingUtils dialogUtils = new LoadingUtils(); 42 | dialogUtils.showLoading(activity, msg); 43 | return upstream -> upstream.doOnSubscribe(disposable -> { 44 | 45 | }).doOnTerminate(dialogUtils::dismiss) 46 | .doOnSubscribe((Consumer) disposable -> { 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/ResponseObserver.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.common; 2 | 3 | import android.widget.Toast; 4 | 5 | import com.blankj.utilcode.util.LogUtils; 6 | import com.blankj.utilcode.util.ToastUtils; 7 | import com.example.zhpan.banner.R; 8 | import com.google.gson.JsonParseException; 9 | import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; 10 | import com.example.zhpan.banner.net.exception.NoDataExceptionException; 11 | import com.example.zhpan.banner.net.exception.ServerResponseException; 12 | 13 | import org.json.JSONException; 14 | 15 | import java.io.InterruptedIOException; 16 | import java.net.ConnectException; 17 | import java.net.UnknownHostException; 18 | import java.text.ParseException; 19 | 20 | import io.reactivex.Observer; 21 | import io.reactivex.disposables.Disposable; 22 | 23 | /** 24 | * Created by zhpan on 2017/4/18. 25 | */ 26 | 27 | public abstract class ResponseObserver implements Observer { 28 | @Override 29 | public void onSubscribe(Disposable d) { 30 | 31 | } 32 | 33 | @Override 34 | public void onNext(T response) { 35 | onSuccess(response); 36 | onFinish(); 37 | } 38 | 39 | @Override 40 | public void onError(Throwable e) { 41 | LogUtils.e("Retrofit", e.getMessage()); 42 | if (e instanceof HttpException) { // HTTP错误 43 | onException(ExceptionReason.BAD_NETWORK); 44 | } else if (e instanceof ConnectException 45 | || e instanceof UnknownHostException) { // 连接错误 46 | onException(ExceptionReason.CONNECT_ERROR); 47 | } else if (e instanceof InterruptedIOException) { // 连接超时 48 | onException(ExceptionReason.CONNECT_TIMEOUT); 49 | } else if (e instanceof JsonParseException 50 | || e instanceof JSONException 51 | || e instanceof ParseException) { // 解析错误 52 | onException(ExceptionReason.PARSE_ERROR); 53 | } else if (e instanceof ServerResponseException) { 54 | onFail(e.getMessage()); 55 | } else if (e instanceof NoDataExceptionException) { 56 | onSuccess(null); 57 | } else { 58 | onException(ExceptionReason.UNKNOWN_ERROR); 59 | } 60 | onFinish(); 61 | } 62 | 63 | @Override 64 | public void onComplete() { 65 | } 66 | 67 | /** 68 | * 请求成功 69 | * 70 | * @param response 服务器返回的数据 71 | */ 72 | abstract public void onSuccess(T response); 73 | 74 | /** 75 | * 服务器返回数据,但响应码不为200 76 | * 77 | */ 78 | /** 79 | * 服务器返回数据,但响应码不为1000 80 | */ 81 | public void onFail(String message) { 82 | ToastUtils.showShort(message); 83 | } 84 | 85 | public void onFinish() { 86 | } 87 | 88 | /** 89 | * 请求异常 90 | */ 91 | public void onException(ExceptionReason reason) { 92 | switch (reason) { 93 | case CONNECT_ERROR: 94 | ToastUtils.showShort(R.string.connect_error, Toast.LENGTH_SHORT); 95 | break; 96 | 97 | case CONNECT_TIMEOUT: 98 | ToastUtils.showShort(R.string.connect_timeout, Toast.LENGTH_SHORT); 99 | break; 100 | 101 | case BAD_NETWORK: 102 | ToastUtils.showShort(R.string.bad_network, Toast.LENGTH_SHORT); 103 | break; 104 | 105 | case PARSE_ERROR: 106 | ToastUtils.showShort(R.string.parse_error, Toast.LENGTH_SHORT); 107 | break; 108 | 109 | case UNKNOWN_ERROR: 110 | default: 111 | ToastUtils.showShort(R.string.unknown_error, Toast.LENGTH_SHORT); 112 | break; 113 | } 114 | } 115 | 116 | /** 117 | * 请求网络失败原因 118 | */ 119 | public enum ExceptionReason { 120 | /** 121 | * 解析数据失败 122 | */ 123 | PARSE_ERROR, 124 | /** 125 | * 网络问题 126 | */ 127 | BAD_NETWORK, 128 | /** 129 | * 连接错误 130 | */ 131 | CONNECT_ERROR, 132 | /** 133 | * 连接超时 134 | */ 135 | CONNECT_TIMEOUT, 136 | /** 137 | * 未知错误 138 | */ 139 | UNKNOWN_ERROR, 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/common/RetrofitUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.common; 2 | 3 | import com.blankj.utilcode.util.Utils; 4 | import com.google.gson.Gson; 5 | import com.google.gson.GsonBuilder; 6 | import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 7 | import com.example.zhpan.banner.net.converter.GsonConverterFactory; 8 | import com.example.zhpan.banner.net.interceptor.HttpCacheInterceptor; 9 | import com.example.zhpan.banner.net.interceptor.HttpHeaderInterceptor; 10 | import com.example.zhpan.banner.net.interceptor.LoggingInterceptor; 11 | 12 | import java.io.File; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | import okhttp3.Cache; 16 | import okhttp3.OkHttpClient; 17 | import retrofit2.Retrofit; 18 | 19 | /** 20 | * Created by zhpan on 2018/3/21. 21 | */ 22 | 23 | public class RetrofitUtils { 24 | public static OkHttpClient.Builder getOkHttpClientBuilder() { 25 | File cacheFile = new File(Utils.getApp().getCacheDir(), "cache"); 26 | Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb 27 | 28 | return new OkHttpClient.Builder() 29 | .readTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS) 30 | .connectTimeout(Constants.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS) 31 | .addInterceptor(new LoggingInterceptor()) 32 | .addInterceptor(new HttpHeaderInterceptor()) 33 | .addNetworkInterceptor(new HttpCacheInterceptor()) 34 | // .sslSocketFactory(SslContextFactory.getSSLSocketFactoryForTwoWay()) // https认证 如果要使用https且为自定义证书 可以去掉这两行注释,并自行配制证书。 35 | // .hostnameVerifier(new SafeHostnameVerifier()) 36 | .cache(cache); 37 | } 38 | 39 | public static Retrofit.Builder getRetrofitBuilder(String baseUrl) { 40 | Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").serializeNulls().create(); 41 | OkHttpClient okHttpClient = getOkHttpClientBuilder().build(); 42 | return new Retrofit.Builder() 43 | .client(okHttpClient) 44 | .addConverterFactory(GsonConverterFactory.create(gson)) 45 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 46 | .baseUrl(baseUrl); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/converter/GsonConverterFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.zhpan.banner.net.converter; 18 | 19 | import com.google.gson.Gson; 20 | import com.google.gson.TypeAdapter; 21 | import com.google.gson.reflect.TypeToken; 22 | import com.example.zhpan.banner.net.common.BasicResponse; 23 | 24 | import java.lang.annotation.Annotation; 25 | import java.lang.reflect.ParameterizedType; 26 | import java.lang.reflect.Type; 27 | 28 | import okhttp3.RequestBody; 29 | import okhttp3.ResponseBody; 30 | import retrofit2.Converter; 31 | import retrofit2.Retrofit; 32 | 33 | /** 34 | * A {@linkplain Converter.Factory converter} which uses Gson for JSON. 35 | *

36 | * Because Gson is so flexible in the types it supports, this converter assumes that it can handle 37 | * all types. If you are mixing JSON serialization with something else (such as protocol buffers), 38 | * you must {@linkplain Retrofit.Builder#addConverterFactory(Converter.Factory) add this instance} 39 | * last to allow the other converters a chance to see their types. 40 | */ 41 | public final class GsonConverterFactory extends Converter.Factory { 42 | /** 43 | * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and 44 | * decoding from JSON (when no charset is specified by a header) will use UTF-8. 45 | */ 46 | public static GsonConverterFactory create() { 47 | return create(new Gson()); 48 | } 49 | 50 | /** 51 | * Create an instance using {@code gson} for conversion. Encoding to JSON and 52 | * decoding from JSON (when no charset is specified by a header) will use UTF-8. 53 | */ 54 | public static GsonConverterFactory create(Gson gson) { 55 | return new GsonConverterFactory(gson); 56 | } 57 | 58 | private final Gson gson; 59 | 60 | private GsonConverterFactory(Gson gson) { 61 | if (gson == null) throw new NullPointerException("gson == null"); 62 | this.gson = gson; 63 | } 64 | 65 | @Override 66 | public Converter responseBodyConverter(final Type type, Annotation[] annotations, 67 | Retrofit retrofit) { 68 | Type newType = new ParameterizedType() { 69 | @Override 70 | public Type[] getActualTypeArguments() { 71 | return new Type[] { type }; 72 | } 73 | 74 | @Override 75 | public Type getOwnerType() { 76 | return null; 77 | } 78 | 79 | @Override 80 | public Type getRawType() { 81 | return BasicResponse.class; 82 | } 83 | }; 84 | TypeAdapter adapter = gson.getAdapter(TypeToken.get(newType)); 85 | return new GsonResponseBodyConverter<>(adapter); 86 | } 87 | 88 | @Override 89 | public Converter requestBodyConverter(Type type, 90 | Annotation[] parameterAnnotations, 91 | Annotation[] methodAnnotations, Retrofit retrofit) { 92 | TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); 93 | return new GsonRequestBodyConverter<>(gson, adapter); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/converter/GsonRequestBodyConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.zhpan.banner.net.converter; 18 | 19 | import com.google.gson.Gson; 20 | import com.google.gson.TypeAdapter; 21 | import com.google.gson.stream.JsonWriter; 22 | 23 | import java.io.IOException; 24 | import java.io.OutputStreamWriter; 25 | import java.io.Writer; 26 | import java.nio.charset.Charset; 27 | 28 | import okhttp3.MediaType; 29 | import okhttp3.RequestBody; 30 | import okio.Buffer; 31 | import retrofit2.Converter; 32 | 33 | final class GsonRequestBodyConverter implements Converter { 34 | private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); 35 | private static final Charset UTF_8 = Charset.forName("UTF-8"); 36 | 37 | private final Gson gson; 38 | private final TypeAdapter adapter; 39 | 40 | GsonRequestBodyConverter(Gson gson, TypeAdapter adapter) { 41 | this.gson = gson; 42 | this.adapter = adapter; 43 | } 44 | 45 | @Override 46 | public RequestBody convert(T value) throws IOException { 47 | Buffer buffer = new Buffer(); 48 | Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); 49 | JsonWriter jsonWriter = gson.newJsonWriter(writer); 50 | adapter.write(jsonWriter, value); 51 | jsonWriter.close(); 52 | return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/converter/GsonResponseBodyConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.zhpan.banner.net.converter; 18 | 19 | import com.google.gson.TypeAdapter; 20 | import com.example.zhpan.banner.net.common.BasicResponse; 21 | import com.example.zhpan.banner.net.common.ErrorCode; 22 | import com.example.zhpan.banner.net.exception.NoDataExceptionException; 23 | import com.example.zhpan.banner.net.exception.RemoteLoginExpiredException; 24 | import com.example.zhpan.banner.net.exception.ServerResponseException; 25 | 26 | import java.io.IOException; 27 | 28 | import okhttp3.ResponseBody; 29 | import retrofit2.Converter; 30 | 31 | import static com.example.zhpan.banner.net.common.ErrorCode.REMOTE_LOGIN; 32 | import static com.example.zhpan.banner.net.common.ErrorCode.SUCCESS; 33 | 34 | final class GsonResponseBodyConverter implements Converter { 35 | 36 | private final TypeAdapter adapter; 37 | 38 | GsonResponseBodyConverter(TypeAdapter adapter) { 39 | this.adapter = adapter; 40 | } 41 | 42 | @Override 43 | public Object convert(ResponseBody value) throws IOException { 44 | try { 45 | BasicResponse response = (BasicResponse) adapter.fromJson(value.charStream()); 46 | if (response.getErrorCode() == ErrorCode.SUCCESS) { 47 | if (response.getData() != null) { 48 | return response.getData(); 49 | } else { 50 | throw new NoDataExceptionException(); 51 | } 52 | } else if (response.getErrorCode() == REMOTE_LOGIN) { 53 | throw new RemoteLoginExpiredException(response.getErrorCode(), response.getErrorMsg()); 54 | } else if (response.getErrorCode() != SUCCESS) { 55 | throw new ServerResponseException(response.getErrorCode(), response.getErrorMsg()); 56 | } 57 | /*if (response.isError()) { 58 | // 特定 API 的错误,在相应的 DefaultObserver 的 onError 的方法中进行处理 59 | throw new ServerResponseException(response.getCode(), response.getMessage()); 60 | } else if (!response.isError()) { 61 | if (response.getResults() != null) 62 | return response.getResults(); 63 | else throw new NoDataExceptionException(); 64 | }*/ 65 | } finally { 66 | value.close(); 67 | } 68 | return null; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/exception/NoDataExceptionException.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.exception; 2 | 3 | /** 4 | * 服务器返回的异常 5 | */ 6 | public class NoDataExceptionException extends RuntimeException { 7 | public NoDataExceptionException() { 8 | super("服务器没有返回对应的Data数据", new Throwable("Server error")); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/exception/RemoteLoginExpiredException.java: -------------------------------------------------------------------------------- 1 | 2 | package com.example.zhpan.banner.net.exception; 3 | 4 | import com.example.zhpan.banner.net.common.ErrorCode; 5 | 6 | /** 7 | * Created by zhpan on 2018/3/27. 8 | */ 9 | public class RemoteLoginExpiredException extends RuntimeException { 10 | private int errorCode; 11 | 12 | public RemoteLoginExpiredException(int errorCode, String cause) { 13 | super(ErrorCode.getErrorMessage(errorCode), new Throwable(cause)); 14 | this.errorCode = errorCode; 15 | } 16 | 17 | public int getErrorCode() { 18 | return errorCode; 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/exception/ServerResponseException.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.exception; 2 | 3 | import com.example.zhpan.banner.net.common.ErrorCode; 4 | 5 | /** 6 | * 服务器返回的异常 7 | */ 8 | public class ServerResponseException extends RuntimeException { 9 | 10 | private int errorCode; 11 | 12 | public ServerResponseException(int errorCode, String cause) { 13 | super(ErrorCode.getErrorMessage(errorCode), new Throwable(cause)); 14 | this.errorCode = errorCode; 15 | } 16 | 17 | public int getErrorCode() { 18 | return errorCode; 19 | } 20 | 21 | public void setErrorCode(int errorCode) { 22 | this.errorCode = errorCode; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/https/SafeHostnameVerifier.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.https; 2 | 3 | import com.example.zhpan.banner.net.common.Constants; 4 | 5 | import javax.net.ssl.HostnameVerifier; 6 | import javax.net.ssl.SSLSession; 7 | 8 | /** 9 | * Created by zhpan on 2018/3/21. 10 | */ 11 | 12 | public class SafeHostnameVerifier implements HostnameVerifier { 13 | @Override 14 | public boolean verify(String hostname, SSLSession session) { 15 | if (Constants.IP.equals(hostname)) {//校验hostname是否正确,如果正确则建立连接 16 | return true; 17 | } 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/https/SslContextFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.https; 2 | 3 | import com.blankj.utilcode.util.Utils; 4 | import com.example.zhpan.banner.R; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.security.KeyStore; 9 | import java.security.SecureRandom; 10 | import java.security.cert.CertificateFactory; 11 | 12 | import javax.net.ssl.KeyManagerFactory; 13 | import javax.net.ssl.SSLContext; 14 | import javax.net.ssl.SSLSocketFactory; 15 | import javax.net.ssl.TrustManagerFactory; 16 | 17 | /** 18 | * Created by zhpan on 2018/1/25. 19 | */ 20 | public class SslContextFactory { 21 | private static final String CLIENT_AGREEMENT = "TLS";//使用协议 22 | private static final String CLIENT_TRUST_MANAGER = "X.509"; 23 | private static final String CLIENT_TRUST_KEYSTORE = "BKS"; 24 | private static final String CLIENT_TRUST_KEY = "PKCS12"; 25 | private static final String CLIENT_TRUST_PROVIDER = "BC"; 26 | public static String TRUST_CA_PWD = "Huawei@123"; 27 | public static String SELF_CERT_PWD = "IoM@1234"; 28 | 29 | /** 30 | * 单项认证 31 | */ 32 | public static SSLSocketFactory getSSLSocketFactoryForOneWay(InputStream... certificates) { 33 | try { 34 | CertificateFactory certificateFactory = 35 | CertificateFactory.getInstance(CLIENT_TRUST_MANAGER, CLIENT_TRUST_PROVIDER); 36 | KeyStore keyStore = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE); 37 | keyStore.load(null); 38 | int index = 0; 39 | for (InputStream certificate : certificates) { 40 | String certificateAlias = Integer.toString(index++); 41 | keyStore.setCertificateEntry(certificateAlias, 42 | certificateFactory.generateCertificate(certificate)); 43 | try { 44 | if (certificate != null) { 45 | certificate.close(); 46 | } 47 | } catch (IOException e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | 52 | SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT); 53 | 54 | TrustManagerFactory trustManagerFactory = 55 | TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 56 | 57 | trustManagerFactory.init(keyStore); 58 | sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); 59 | return sslContext.getSocketFactory(); 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | return null; 64 | } 65 | 66 | /** 67 | * 双向认证 68 | * 69 | * @return SSLSocketFactory 70 | */ 71 | public static SSLSocketFactory getSSLSocketFactoryForTwoWay() { 72 | try { 73 | InputStream certificate = Utils.getApp().getResources().openRawResource(R.raw.capk); 74 | // CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC"); 75 | KeyStore keyStore = KeyStore.getInstance(CLIENT_TRUST_KEY); 76 | keyStore.load(certificate, SELF_CERT_PWD.toCharArray()); 77 | KeyManagerFactory kmf = 78 | KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 79 | kmf.init(keyStore, SELF_CERT_PWD.toCharArray()); 80 | 81 | try { 82 | if (certificate != null) { 83 | certificate.close(); 84 | } 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | } 88 | 89 | //初始化keystore 90 | KeyStore clientKeyStore = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE); 91 | clientKeyStore.load(Utils.getApp().getResources().openRawResource(R.raw.cabks), 92 | TRUST_CA_PWD.toCharArray()); 93 | 94 | SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT); 95 | TrustManagerFactory trustManagerFactory = TrustManagerFactory. 96 | getInstance(TrustManagerFactory.getDefaultAlgorithm()); 97 | 98 | trustManagerFactory.init(clientKeyStore); 99 | 100 | KeyManagerFactory keyManagerFactory = 101 | KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 102 | keyManagerFactory.init(clientKeyStore, SELF_CERT_PWD.toCharArray()); 103 | 104 | sslContext.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), 105 | new SecureRandom()); 106 | return sslContext.getSocketFactory(); 107 | } catch (Exception e) { 108 | e.printStackTrace(); 109 | } 110 | return null; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/interceptor/HttpCacheInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.interceptor; 2 | 3 | import com.blankj.utilcode.util.LogUtils; 4 | import com.blankj.utilcode.util.NetworkUtils; 5 | 6 | import java.io.IOException; 7 | 8 | import okhttp3.CacheControl; 9 | import okhttp3.Interceptor; 10 | import okhttp3.Request; 11 | import okhttp3.Response; 12 | 13 | /** 14 | * Created by zhpan on 2018/3/21. 15 | */ 16 | 17 | public class HttpCacheInterceptor implements Interceptor { 18 | // 配置缓存的拦截器 19 | @Override 20 | public Response intercept(Chain chain) throws IOException { 21 | Request request = chain.request(); 22 | if (!NetworkUtils.isConnected()) { //没网强制从缓存读取 23 | request = request.newBuilder() 24 | .cacheControl(CacheControl.FORCE_CACHE) 25 | .build(); 26 | LogUtils.d("Okhttp", "no network"); 27 | } 28 | 29 | Response originalResponse = chain.proceed(request); 30 | if (NetworkUtils.isConnected()) { 31 | //有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置 32 | String cacheControl = request.cacheControl().toString(); 33 | 34 | return originalResponse.newBuilder() 35 | .header("Cache-Control", cacheControl) 36 | .removeHeader("Pragma") 37 | .build(); 38 | } else { 39 | return originalResponse.newBuilder() 40 | .header("Cache-Control", "public, only-if-cached, max-stale=2419200") 41 | .removeHeader("Pragma") 42 | .build(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/interceptor/HttpHeaderInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.interceptor; 2 | 3 | import java.io.IOException; 4 | 5 | import okhttp3.Interceptor; 6 | import okhttp3.Request; 7 | import okhttp3.Response; 8 | 9 | /** 10 | * Created by zhpan on 2018/3/21. 11 | */ 12 | 13 | public class HttpHeaderInterceptor implements Interceptor { 14 | @Override 15 | public Response intercept(Chain chain) throws IOException { 16 | // 配置请求头 17 | String accessToken = "token"; 18 | String tokenType = "tokenType"; 19 | Request request = chain.request().newBuilder() 20 | .header("app_key", "appId") 21 | .header("Authorization", tokenType + " " + accessToken) 22 | .header("Content-Type", "application/json") 23 | .addHeader("Connection", "close") 24 | .addHeader("Accept-Encoding", "identity") 25 | .build(); 26 | return chain.proceed(request); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/net/interceptor/LoggingInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.net.interceptor; 2 | 3 | import com.blankj.utilcode.util.LogUtils; 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.Interceptor; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | import okhttp3.ResponseBody; 11 | 12 | /** 13 | * Created by zhpan on 2018/4/20. 14 | */ 15 | 16 | public class LoggingInterceptor implements Interceptor { 17 | @Override 18 | public Response intercept(Interceptor.Chain chain) throws IOException { 19 | //这个chain里面包含了request和response,所以你要什么都可以从这里拿 20 | Request request = chain.request(); 21 | 22 | long t1 = System.nanoTime();//请求发起的时间 23 | 24 | LogUtils.e(String.format("请求URL------%s on %s%n请求头------%s", 25 | request.url(), chain.connection(), request.headers())); 26 | Response response = chain.proceed(request); 27 | 28 | long t2 = System.nanoTime();//收到响应的时间 29 | 30 | //这里不能直接使用response.body().string()的方式输出日志 31 | //因为response.body().string()之后,response中的流会被关闭,程序会报错,我们需要创建出一 32 | //个新的response给应用层处理 33 | ResponseBody responseBody = response.peekBody(1024 * 1024); 34 | 35 | LogUtils.e(String.format("响应URL-------: %s %n响应数据------%s 请求用时--------%.1fms%n%s", 36 | response.request().url(), 37 | responseBody.string(), 38 | (t2 - t1) / 1e6d, 39 | response.headers())); 40 | 41 | return response; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/recyclerview/listener/ICustomClickListener.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.recyclerview.listener; 2 | 3 | import android.view.View; 4 | 5 | public interface ICustomClickListener { 6 | void onClick(View view, int position, int type, Object... data); 7 | 8 | void onLongClick(View view, int position, int type, Object... data); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/recyclerview/module/RecyclerViewConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.recyclerview.module; 2 | 3 | import android.view.View; 4 | 5 | public class RecyclerViewConfig { 6 | public static final String HEADVIEW = "_head_"; 7 | public static final String FOOTVIEW = "_foot_"; 8 | public static final int HEADVIEW_TYPE = 100000; 9 | public static final int FOOTVIEW_TYPE = 100001; 10 | private int type; // 100000 代表头部 100001 代表尾部 11 | private int view; 12 | private String tag; 13 | private View contentView; 14 | private boolean isCache; //是否需要缓存 15 | 16 | public boolean isCache() { 17 | return isCache; 18 | } 19 | 20 | public void setCache(boolean cache) { 21 | isCache = cache; 22 | } 23 | 24 | public View getContentView() { 25 | return contentView; 26 | } 27 | 28 | public void setContentView(View contentView) { 29 | this.contentView = contentView; 30 | } 31 | 32 | public int getType() { 33 | return type; 34 | } 35 | 36 | public void setType(int type) { 37 | this.type = type; 38 | } 39 | 40 | public int getView() { 41 | return view; 42 | } 43 | 44 | public void setView(int view) { 45 | this.view = view; 46 | } 47 | 48 | public String getTag() { 49 | return tag; 50 | } 51 | 52 | public void setTag(String tag) { 53 | this.tag = tag; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/AccordionTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.zhpan.banner.transform; 18 | 19 | import android.view.View; 20 | 21 | public class AccordionTransformer extends BaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | view.setPivotX(position < 0 ? 0 : view.getWidth()); 26 | view.setScaleX(position < 0 ? 1f + position : 1f - position); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/BaseTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.zhpan.banner.transform; 18 | 19 | import android.view.View; 20 | 21 | import androidx.viewpager2.widget.ViewPager2; 22 | 23 | public abstract class BaseTransformer implements ViewPager2.PageTransformer { 24 | 25 | /** 26 | * Called each {@link #transformPage(View, float)}. 27 | * 28 | * @param page Apply the transformation to this page 29 | * @param position Position of page relative to the current front-and-center position of the 30 | * pager. 0 is front and 31 | * center. 1 is one full page position to the right, and -1 is one page position to the left. 32 | */ 33 | protected abstract void onTransform(View page, float position); 34 | 35 | /** 36 | * Apply a property transformation to the given page. For most use cases, this method should not 37 | * be overridden. 38 | * Instead use {@link #transformPage(View, float)} to perform typical transformations. 39 | * 40 | * @param page Apply the transformation to this page 41 | * @param position Position of page relative to the current front-and-center position of the 42 | * pager. 0 is front and 43 | * center. 1 is one full page position to the right, and -1 is one page position to the left. 44 | */ 45 | @Override 46 | public void transformPage(View page, float position) { 47 | onPreTransform(page, position); 48 | onTransform(page, position); 49 | onPostTransform(page, position); 50 | } 51 | 52 | /** 53 | * If the position offset of a fragment is less than negative one or greater than one, returning 54 | * true will set the 55 | * fragment alpha to 0f. Otherwise fragment alpha is always defaulted to 1f. 56 | */ 57 | protected boolean hideOffscreenPages() { 58 | return true; 59 | } 60 | 61 | /** 62 | * Indicates if the default animations of the view pager should be used. 63 | */ 64 | protected boolean isPagingEnabled() { 65 | return false; 66 | } 67 | 68 | /** 69 | * Called each {@link #transformPage(View, float)} before {{@link #onTransform(View, float)}. 70 | *

71 | * The default implementation attempts to reset all view properties. This is useful when toggling 72 | * transforms that do 73 | * not modify the same page properties. For instance changing from a transformation that applies 74 | * rotation to a 75 | * transformation that fades can inadvertently leave a fragment stuck with a rotation or with some 76 | * degree of applied 77 | * alpha. 78 | * 79 | * @param page Apply the transformation to this page 80 | * @param position Position of page relative to the current front-and-center position of the 81 | * pager. 0 is front and 82 | * center. 1 is one full page position to the right, and -1 is one page position to the left. 83 | */ 84 | protected void onPreTransform(View page, float position) { 85 | final float width = page.getWidth(); 86 | 87 | page.setRotationX(0); 88 | page.setRotationY(0); 89 | page.setRotation(0); 90 | page.setScaleX(1); 91 | page.setScaleY(1); 92 | page.setPivotX(0); 93 | page.setPivotY(0); 94 | page.setTranslationY(0); 95 | page.setTranslationX(isPagingEnabled() ? 0f : -width * position); 96 | 97 | if (hideOffscreenPages()) { 98 | page.setAlpha(position <= -1f || position >= 1f ? 0f : 1f); 99 | // page.setEnabled(false); 100 | } else { 101 | // page.setEnabled(true); 102 | page.setAlpha(1f); 103 | } 104 | } 105 | 106 | /** 107 | * Called each {@link #transformPage(View, float)} after {@link #onTransform(View, float)}. 108 | * 109 | * @param page Apply the transformation to this page 110 | * @param position Position of page relative to the current front-and-center position of the 111 | * pager. 0 is front and 112 | * center. 1 is one full page position to the right, and -1 is one page position to the left. 113 | */ 114 | protected void onPostTransform(View page, float position) { 115 | } 116 | 117 | /** 118 | * Same as { Math#min(double, double)} without double casting, zero closest to infinity handling, 119 | * or NaN support. 120 | */ 121 | protected static final float min(float val, float min) { 122 | return val < min ? min : val; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/DepthPageTransformer.kt: -------------------------------------------------------------------------------- 1 | 2 | package com.example.zhpan.banner.transform 3 | 4 | import android.view.View 5 | import androidx.viewpager2.widget.ViewPager2 6 | 7 | class DepthPageTransformer : ViewPager2.PageTransformer { 8 | 9 | override fun transformPage(page: View, position: Float) { 10 | page.also { 11 | if (kotlin.math.abs(position) >= 1f) { 12 | it.alpha = 0f 13 | return@transformPage 14 | } 15 | if (position > 0) { 16 | it.alpha = 1 - position 17 | val scale = 1f - position / 4f 18 | it.scaleX = scale 19 | it.scaleY = scale 20 | it.translationX = -it.width * position 21 | it.translationZ = -1f 22 | } else { 23 | it.alpha = 1f 24 | it.scaleX = 1f 25 | it.scaleY = 1f 26 | it.translationX = 0f 27 | it.translationZ = 0f 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/DepthScaleTransformer.kt: -------------------------------------------------------------------------------- 1 | 2 | package com.example.zhpan.banner.transform 3 | 4 | import android.view.View 5 | import androidx.viewpager2.widget.ViewPager2 6 | 7 | class DepthScaleTransformer : ViewPager2.PageTransformer { 8 | 9 | companion object { 10 | private const val MIN_SCALE = 0.9f 11 | private const val MIN_ALPHA = 0.7f 12 | } 13 | 14 | override fun transformPage(page: View, position: Float) { 15 | page.also { 16 | if (kotlin.math.abs(position) >= 1f) { 17 | it.alpha = 0f 18 | return@transformPage 19 | } 20 | val scale = (1 - kotlin.math.abs(position) / 2).coerceAtLeast(MIN_SCALE) 21 | it.scaleX = scale 22 | it.scaleY = scale 23 | it.alpha = (1 - kotlin.math.abs(position)).coerceAtLeast(MIN_ALPHA) 24 | it.translationX = (1 - scale) * it.width / 2 * if (position > 0) -1 else 1 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/PageTransformerFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.transform; 2 | 3 | import androidx.viewpager2.widget.ViewPager2; 4 | 5 | import com.zhpan.bannerview.transform.ScaleInTransformer; 6 | 7 | import static com.example.zhpan.banner.transform.TransformerStyle.ACCORDION; 8 | import static com.example.zhpan.banner.transform.TransformerStyle.DEPTH; 9 | import static com.example.zhpan.banner.transform.TransformerStyle.DEPTH_SCALE; 10 | import static com.example.zhpan.banner.transform.TransformerStyle.ROTATE; 11 | import static com.example.zhpan.banner.transform.TransformerStyle.ROTATE_UP; 12 | import static com.example.zhpan.banner.transform.TransformerStyle.SCALE_IN; 13 | 14 | public class PageTransformerFactory { 15 | 16 | public static ViewPager2.PageTransformer createPageTransformer(int transformerStyle) { 17 | ViewPager2.PageTransformer transformer = null; 18 | switch (transformerStyle) { 19 | case DEPTH: 20 | transformer = new DepthPageTransformer(); 21 | break; 22 | case ROTATE: 23 | transformer = new RotateTransformer(); 24 | break; 25 | case ROTATE_UP: 26 | transformer = new RotateUpTransformer(); 27 | break; 28 | case DEPTH_SCALE: 29 | transformer = new DepthScaleTransformer(); 30 | break; 31 | case ACCORDION: 32 | transformer = new AccordionTransformer(); 33 | break; 34 | case SCALE_IN: 35 | transformer = new ScaleInTransformer(ScaleInTransformer.DEFAULT_MIN_SCALE, false); 36 | break; 37 | } 38 | return transformer; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/RotateTransformer.kt: -------------------------------------------------------------------------------- 1 | 2 | package com.example.zhpan.banner.transform 3 | 4 | import android.view.View 5 | import androidx.viewpager2.widget.ViewPager2 6 | import kotlin.math.abs 7 | 8 | class RotateTransformer : ViewPager2.PageTransformer { 9 | override fun transformPage(page: View, position: Float) { 10 | page.also { 11 | if (abs(position) >= 1f) { 12 | it.alpha = 0f 13 | return@transformPage 14 | } 15 | val scale = (1 - abs(position)).coerceAtLeast(MIN_SCALE) 16 | it.scaleX = scale 17 | it.scaleY = scale 18 | it.alpha = 1f 19 | it.translationX = (1 - scale) * it.width / 2 * if (position > 0) -1 else 1 20 | it.translationZ = if (scale == MIN_SCALE) -1f else 0f 21 | it.rotation = -position * 45 22 | } 23 | } 24 | 25 | companion object{ 26 | private const val MIN_SCALE = 0.5f 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/RotateUpTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.zhpan.banner.transform; 18 | 19 | import android.view.View; 20 | 21 | public class RotateUpTransformer extends BaseTransformer { 22 | 23 | private static final float ROT_MOD = -15f; 24 | 25 | @Override 26 | protected void onTransform(View view, float position) { 27 | final float width = view.getWidth(); 28 | final float rotation = ROT_MOD * position; 29 | 30 | view.setPivotX(width * 0.5f); 31 | view.setPivotY(0f); 32 | view.setTranslationX(0f); 33 | view.setRotation(rotation); 34 | } 35 | 36 | @Override 37 | protected boolean isPagingEnabled() { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/transform/TransformerStyle.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.transform; 2 | 3 | public interface TransformerStyle { 4 | int NONE = 0; 5 | int DEPTH = 1; 6 | int DEPTH_SCALE = 2; 7 | int ACCORDION = 3; 8 | int ROTATE = 4; 9 | int ROTATE_UP=5; 10 | int SCALE_IN = 6; 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/view/CornerImageView.kt: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | 6 | import androidx.appcompat.widget.AppCompatImageView 7 | import com.zhpan.bannerview.provider.ViewStyleSetter 8 | 9 | class CornerImageView @JvmOverloads constructor( 10 | context: Context, 11 | attrs: AttributeSet? = null, 12 | defStyleAttr: Int = 0 13 | ) : AppCompatImageView(context, attrs, defStyleAttr) { 14 | 15 | fun setRoundCorner(radius: Int) { 16 | ViewStyleSetter.applyRoundCorner(this, radius.toFloat()) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/zhpan/banner/view/FigureIndicatorView.java: -------------------------------------------------------------------------------- 1 | package com.example.zhpan.banner.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.util.AttributeSet; 8 | 9 | import androidx.annotation.ColorInt; 10 | import androidx.annotation.Nullable; 11 | 12 | import com.zhpan.bannerview.utils.BannerUtils; 13 | import com.zhpan.indicator.base.BaseIndicatorView; 14 | 15 | /** 16 | *

17 |  *   Created by zhangpan on 2019-10-18.
18 |  *   Description:
19 |  * 
20 | */ 21 | public class FigureIndicatorView extends BaseIndicatorView { 22 | 23 | private int radius = BannerUtils.dp2px(20); 24 | 25 | private int backgroundColor = Color.parseColor("#88FF5252"); 26 | 27 | private int textColor = Color.WHITE; 28 | 29 | private int textSize = BannerUtils.dp2px(13); 30 | 31 | private Paint mPaint; 32 | 33 | public FigureIndicatorView(Context context) { 34 | this(context, null); 35 | } 36 | 37 | public FigureIndicatorView(Context context, @Nullable AttributeSet attrs) { 38 | this(context, attrs, 0); 39 | } 40 | 41 | public FigureIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 42 | super(context, attrs, defStyleAttr); 43 | mPaint = new Paint(); 44 | } 45 | 46 | @Override 47 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 48 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 49 | setMeasuredDimension(2 * radius, 2 * radius); 50 | } 51 | 52 | @Override 53 | protected void onDraw(Canvas canvas) { 54 | super.onDraw(canvas); 55 | if (getPageSize() > 1) { 56 | mPaint.setColor(backgroundColor); 57 | canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mPaint); 58 | mPaint.setColor(textColor); 59 | mPaint.setTextSize(textSize); 60 | String text = getCurrentPosition() + 1 + "/" + getPageSize(); 61 | int textWidth = (int) mPaint.measureText(text); 62 | Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt(); 63 | int baseline = (getMeasuredHeight() - fontMetricsInt.bottom + fontMetricsInt.top) / 2 64 | - fontMetricsInt.top; 65 | canvas.drawText(text, (getWidth() - textWidth) / 2f, baseline, mPaint); 66 | } 67 | } 68 | 69 | public void setRadius(int radius) { 70 | this.radius = radius; 71 | } 72 | 73 | @Override 74 | public void setBackgroundColor(@ColorInt int backgroundColor) { 75 | this.backgroundColor = backgroundColor; 76 | } 77 | 78 | public void setTextSize(int textSize) { 79 | this.textSize = textSize; 80 | } 81 | 82 | public void setTextColor(int textColor) { 83 | this.textColor = textColor; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_back.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-hdpi/ic_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-mdpi/ic_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/creative_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/creative_hover.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/creative_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/creative_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/discover_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/discover_hover.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/discover_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/discover_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/home_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/home_hover.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/home_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/home_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/ic_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/mine_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/mine_hover.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/mine_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xhdpi/mine_none.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/tab4_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/guide0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxhdpi/guide0.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/guide1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxhdpi/guide1.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/guide2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxhdpi/guide2.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxhdpi/ic_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxhdpi/placeholder.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/advertise0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/advertise0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/advertise1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/advertise1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/advertise2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/advertise2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/advertise3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/advertise3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/advertise4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/advertise4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/heart_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/heart_empty.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/heart_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/heart_red.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/ic_banner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/ic_email.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/ic_indicator.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_qq_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/drawable-xxxhdpi/ic_qq_group.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/banner_indicator_focus.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/banner_indicator_nornal.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_card0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_card1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_card2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_card3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_start.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab1_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab2_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab3_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/text_color_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/ezgif-3-b826de74b0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/ezgif-3-b826de74b0.gif -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | 27 | 28 | 33 | 34 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_welcome.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 22 | 23 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 21 | 22 | 26 | 27 | 31 | 32 | 33 | 40 | 41 | 51 | 52 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 20 | 21 | 25 | 26 | 36 | 37 | 43 | 44 | 52 | 53 | 61 | 62 | 70 | 71 | 72 | 73 | 74 | 84 | 85 | 91 | 92 | 101 | 102 | 110 | 111 | 119 | 120 | 128 | 129 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_article.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_custom_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_defalut_loadmore_view.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_defalut_refresh_view.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_head_foot_parent.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_header_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_home_banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_net_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_new_type.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_page_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_slide_mode.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_slide_model_data_binding.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_loading_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | 19 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 22 | 23 | 24 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/menu/indicator_slide_style_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/nav_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 12 | 13 | 17 | 18 | 22 | 23 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/menu/transformer_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 15 | 20 | 21 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/raw/cabks.bks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/raw/cabks.bks -------------------------------------------------------------------------------- /app/src/main/res/raw/capk.pkcs12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/raw/capk.pkcs12 -------------------------------------------------------------------------------- /app/src/main/res/raw/loading2.json: -------------------------------------------------------------------------------- 1 | {"v":"4.10.1","fr":30,"ip":0,"op":41,"w":300,"h":300,"nm":"合成 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[180,156.5,0],"e":[100,156.5,0],"to":[-13.3333330154419,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":19,"s":[100,156.5,0],"e":[180,156.5,0],"to":[0,0,0],"ti":[-13.3333330154419,0,0]},{"t":40}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[40.916,40.916],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.184,0.482,0.906,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[4.534,-3.114],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[100,156.5,0],"e":[180,156.5,0],"to":[13.3333330154419,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":19,"s":[180,156.5,0],"e":[100,156.5,0],"to":[0,0,0],"ti":[13.3333330154419,0,0]},{"t":40}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[40.916,40.916],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.145097994337,0.847059003045,0.654901960784,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[4.534,-3.114],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0}]} -------------------------------------------------------------------------------- /app/src/main/res/raw/srca.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/app/src/main/res/raw/srca.cer -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #5187f4 4 | #5187f4 5 | #D81B60 6 | 7 | #FF5252 8 | 9 | #88FF5252 10 | #FFFFFF 11 | #BFFFFFFF 12 | #6FFFFFFF 13 | 14 | #000000 15 | #000000 16 | #DCDCDC 17 | 18 | #FF4C39 19 | #935656 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BannerViewPager 3 | Open navigation drawer 4 | Close navigation drawer 5 | Jump to random position smoothly 6 | Start Now 7 | guide 8 | NORMAL 9 | SMOOTH 10 | image description 11 | Home 12 | Page 13 | Indicator 14 | Others 15 | Page Style: 16 | Indicator Style: 17 | Custom Style 18 | Indicator Slide Mode 19 | About ViewPagerIndicator 20 | 60902509 21 | About BannerViewPager 22 | ViewPagerIndicator 23 | zhpanvip@outlook.com 24 | Add Data 25 | Remove Item 26 | Insert Item 27 | 28 | 29 | 网络连接失败,请检查网络 30 | 连接超时,请稍后再试 31 | 服务器异常 32 | 解析服务器响应数据失败 33 | 未知错误 34 | 服务器返回数据失败 35 | 36 | Failed to request server,error code: 37 | Parameter exception 38 | 输入验证码有误 39 | 验证码已过期 40 | 该账户还未注册 41 | 用户名或密码错误 42 | 该账户已存在 43 | 密码错误 44 | 您的账号已在其它设备上登录,如非本人操作,请及时修改密码! 45 | More Page Styles: 46 | 下一个 47 | 上一个 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 | 25 | 26 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /bannerview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /bannerview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | android { 4 | compileSdkVersion 28 5 | 6 | defaultConfig { 7 | minSdkVersion 19 8 | } 9 | 10 | buildTypes { 11 | release { 12 | minifyEnabled false 13 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 14 | } 15 | } 16 | } 17 | 18 | dependencies { 19 | implementation 'androidx.viewpager2:viewpager2:1.0.0' 20 | api 'com.github.zhpanvip:viewpagerindicator:1.2.3' 21 | // api project(path: ':indicator') 22 | } 23 | -------------------------------------------------------------------------------- /bannerview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /bannerview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/BaseBannerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview; 18 | 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | 23 | import androidx.annotation.LayoutRes; 24 | import androidx.annotation.NonNull; 25 | import androidx.recyclerview.widget.RecyclerView; 26 | 27 | import com.zhpan.bannerview.utils.BannerUtils; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | /** 33 | * Created by zhpan on 2017/3/28. 34 | */ 35 | public abstract class BaseBannerAdapter extends RecyclerView.Adapter> { 36 | protected List mList = new ArrayList<>(); 37 | private boolean isCanLoop; 38 | public static final int MAX_VALUE = 1000; 39 | private PageClickListener mPageClickListener; 40 | 41 | @NonNull 42 | @Override 43 | public final BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 44 | View itemView = 45 | LayoutInflater.from(parent.getContext()).inflate(getLayoutId(viewType), parent, false); 46 | BaseViewHolder viewHolder = createViewHolder(parent, itemView, viewType); 47 | itemView.setOnClickListener(clickedView -> { 48 | int adapterPosition = viewHolder.getAdapterPosition(); 49 | if (mPageClickListener != null && adapterPosition != RecyclerView.NO_POSITION) { 50 | int realPosition = 51 | BannerUtils.getRealPosition(adapterPosition, getListSize()); 52 | mPageClickListener.onPageClick(clickedView, realPosition, adapterPosition); 53 | } 54 | }); 55 | return viewHolder; 56 | } 57 | 58 | @Override 59 | public final void onBindViewHolder(@NonNull BaseViewHolder holder, final int position) { 60 | int realPosition = BannerUtils.getRealPosition(position, getListSize()); 61 | bindData(holder, mList.get(realPosition), realPosition, getListSize()); 62 | } 63 | 64 | @Override 65 | public final int getItemViewType(int position) { 66 | int realPosition = BannerUtils.getRealPosition(position, getListSize()); 67 | return getViewType(realPosition); 68 | } 69 | 70 | @Override 71 | public final int getItemCount() { 72 | if (isCanLoop && getListSize() > 1) { 73 | return MAX_VALUE; 74 | } else { 75 | return getListSize(); 76 | } 77 | } 78 | 79 | List getData() { 80 | return mList; 81 | } 82 | 83 | void setData(List list) { 84 | if (null != list) { 85 | mList.clear(); 86 | mList.addAll(list); 87 | } 88 | } 89 | 90 | void setCanLoop(boolean canLoop) { 91 | isCanLoop = canLoop; 92 | } 93 | 94 | void setPageClickListener(PageClickListener pageClickListener) { 95 | mPageClickListener = pageClickListener; 96 | } 97 | 98 | int getListSize() { 99 | return mList.size(); 100 | } 101 | 102 | protected int getViewType(int position) { 103 | return 0; 104 | } 105 | 106 | public boolean isCanLoop() { 107 | return isCanLoop; 108 | } 109 | 110 | /** 111 | * Generally,subclasses do not need to override this method,Unless you want to use a custom ViewHolder. 112 | * 113 | * This method called by {@link #onCreateViewHolder(ViewGroup, int)} to create a default {@link 114 | * BaseViewHolder} 115 | * 116 | * @param parent The ViewGroup into which the new View will be added after it is bound to 117 | * an adapter position. 118 | * @param itemView Item View. 119 | * @param viewType The view type of the new View. 120 | * @return ViewHolder extends {@link BaseViewHolder}. 121 | */ 122 | public BaseViewHolder createViewHolder(@NonNull ViewGroup parent, View itemView, 123 | int viewType) { 124 | return new BaseViewHolder<>(itemView); 125 | } 126 | 127 | /** 128 | * @param holder The ViewHolder which should be updated to represent the contents of the 129 | * item at the given position in the data set. 130 | * @param data Current item data. 131 | * @param position Current item position. 132 | * @param pageSize Page size of BVP,equals {@link BaseBannerAdapter#getListSize()}. 133 | */ 134 | protected abstract void bindData(BaseViewHolder holder, T data, int position, int pageSize); 135 | 136 | /** 137 | * @param viewType The view type of the new View. 138 | * @return The item view layout. 139 | */ 140 | public abstract @LayoutRes 141 | int getLayoutId(int viewType); 142 | 143 | interface PageClickListener { 144 | void onPageClick(View clickedView, int realPosition, int adapterPosition); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/BaseViewHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.zhpan.bannerview; 17 | 18 | import android.graphics.Bitmap; 19 | import android.graphics.drawable.Drawable; 20 | import android.util.SparseArray; 21 | import android.view.View; 22 | import android.widget.ImageView; 23 | import android.widget.TextView; 24 | 25 | import androidx.annotation.ColorInt; 26 | import androidx.annotation.ColorRes; 27 | import androidx.annotation.DrawableRes; 28 | import androidx.annotation.IdRes; 29 | import androidx.annotation.NonNull; 30 | import androidx.annotation.StringRes; 31 | import androidx.core.content.ContextCompat; 32 | import androidx.recyclerview.widget.RecyclerView; 33 | 34 | import com.zhpan.bannerview.annotation.Visibility; 35 | 36 | /** 37 | *
 38 |  *   Created by zhpan on 2020/4/5.
 39 |  *   Attention:Don't use {@link RecyclerView.ViewHolder#getAdapterPosition}
 40 |  *   method to get position,this method will return a fake position.
 41 |  * 
42 | */ 43 | @SuppressWarnings("unused") 44 | public class BaseViewHolder extends RecyclerView.ViewHolder { 45 | 46 | private final SparseArray mViews = new SparseArray<>(); 47 | 48 | public BaseViewHolder(@NonNull View itemView) { 49 | super(itemView); 50 | } 51 | 52 | /** 53 | * @deprecated bind data in adapter please. 54 | */ 55 | @Deprecated 56 | public void bindData(T data, int position, int pageSize) { 57 | } 58 | 59 | @SuppressWarnings("unchecked") 60 | public V findViewById(int viewId) { 61 | View view = mViews.get(viewId); 62 | if (view == null) { 63 | view = itemView.findViewById(viewId); 64 | mViews.put(viewId, view); 65 | } 66 | return (V) view; 67 | } 68 | 69 | public void setText(int viewId, CharSequence text) { 70 | View view = findViewById(viewId); 71 | if (view instanceof TextView) { 72 | ((TextView) view).setText(text); 73 | } 74 | } 75 | 76 | public void setText(int viewId, @StringRes int textId) { 77 | View view = findViewById(viewId); 78 | if (view instanceof TextView) { 79 | ((TextView) view).setText(textId); 80 | } 81 | } 82 | 83 | public void setTextColor(int viewId, @ColorInt int colorId) { 84 | View view = findViewById(viewId); 85 | if (view instanceof TextView) { 86 | ((TextView) view).setTextColor(colorId); 87 | } 88 | } 89 | 90 | public void setTextColorRes(@IdRes int viewId, @ColorRes int colorRes) { 91 | View view = findViewById(viewId); 92 | if (view instanceof TextView) { 93 | ((TextView) view).setTextColor(ContextCompat.getColor(itemView.getContext(), colorRes)); 94 | } 95 | } 96 | 97 | public void setOnClickListener(int viewId, View.OnClickListener clickListener) { 98 | findViewById(viewId).setOnClickListener(clickListener); 99 | } 100 | 101 | public void setBackgroundResource(int viewId, @DrawableRes int resId) { 102 | findViewById(viewId).setBackgroundResource(resId); 103 | } 104 | 105 | public void setBackgroundColor(int viewId, @ColorInt int colorId) { 106 | findViewById(viewId).setBackgroundColor(colorId); 107 | } 108 | 109 | public void setImageResource(@IdRes int viewId, @DrawableRes int resId) { 110 | View view = findViewById(viewId); 111 | if (view instanceof ImageView) { 112 | ((ImageView) view).setImageResource(resId); 113 | } 114 | } 115 | 116 | public void setImageDrawable(@IdRes int viewId, Drawable drawable) { 117 | View view = findViewById(viewId); 118 | if (view instanceof ImageView) { 119 | ((ImageView) view).setImageDrawable(drawable); 120 | } 121 | } 122 | 123 | public void setImageBitmap(@IdRes int viewId, Bitmap bitmap) { 124 | ImageView view = findViewById(viewId); 125 | view.setImageBitmap(bitmap); 126 | } 127 | 128 | public void setVisibility(@IdRes int resId, @Visibility int visibility) { 129 | findViewById(resId).setVisibility(visibility); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/annotation/AIndicatorGravity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.annotation; 18 | 19 | import androidx.annotation.IntDef; 20 | 21 | import java.lang.annotation.ElementType; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.annotation.Target; 25 | 26 | import static com.zhpan.bannerview.constants.IndicatorGravity.CENTER; 27 | import static com.zhpan.bannerview.constants.IndicatorGravity.END; 28 | import static com.zhpan.bannerview.constants.IndicatorGravity.START; 29 | 30 | /** 31 | *
32 |  *   Created by zhangpan on 2019-10-18.
33 |  *   Description:指示器显示位置
34 |  * 
35 | */ 36 | @IntDef({ CENTER, START, END }) 37 | @Retention(RetentionPolicy.SOURCE) 38 | @Target(ElementType.PARAMETER) 39 | public @interface AIndicatorGravity { 40 | 41 | } 42 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/annotation/APageStyle.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.annotation; 18 | 19 | import androidx.annotation.IntDef; 20 | 21 | import java.lang.annotation.ElementType; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.annotation.Target; 25 | 26 | import static com.zhpan.bannerview.constants.PageStyle.MULTI_PAGE; 27 | import static com.zhpan.bannerview.constants.PageStyle.MULTI_PAGE_OVERLAP; 28 | import static com.zhpan.bannerview.constants.PageStyle.MULTI_PAGE_SCALE; 29 | import static com.zhpan.bannerview.constants.PageStyle.NORMAL; 30 | 31 | /** 32 | *
33 |  *   Created by zhangpan on 2019-11-06.
34 |  *   Description:
35 |  * 
36 | */ 37 | @IntDef({ NORMAL, MULTI_PAGE, MULTI_PAGE_OVERLAP, MULTI_PAGE_SCALE }) 38 | @Retention(RetentionPolicy.SOURCE) 39 | @Target(ElementType.PARAMETER) 40 | public @interface APageStyle { 41 | } 42 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/annotation/Visibility.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.annotation; 18 | 19 | import android.view.View; 20 | 21 | import androidx.annotation.IntDef; 22 | 23 | import java.lang.annotation.ElementType; 24 | import java.lang.annotation.Retention; 25 | import java.lang.annotation.RetentionPolicy; 26 | import java.lang.annotation.Target; 27 | 28 | /** 29 | *
30 |  *   Created by zhangpan on 2019-11-12.
31 |  * 
32 | */ 33 | @IntDef({ View.VISIBLE, View.INVISIBLE, View.GONE }) 34 | @Retention(RetentionPolicy.SOURCE) 35 | @Target(ElementType.PARAMETER) 36 | public @interface Visibility { 37 | 38 | } 39 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/constants/IndicatorGravity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.constants; 18 | 19 | /** 20 | *
21 |  *   Created by zhangpan on 2019-10-18.
22 |  *   Description:
23 |  * 
24 | */ 25 | public interface IndicatorGravity { 26 | int CENTER = 0; 27 | int START = 1 << 1; 28 | int END = 1 << 2; 29 | } 30 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/constants/PageStyle.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.constants; 18 | 19 | /** 20 | *
21 |  *   Created by zhangpan on 2019-10-18.
22 |  *   Description:
23 |  * 
24 | */ 25 | public interface PageStyle { 26 | 27 | int NORMAL = 0; 28 | /** 29 | * @deprecated please use {@link com.zhpan.bannerview.BannerViewPager#setRevealWidth(int)} instead. 30 | */ 31 | @Deprecated 32 | int MULTI_PAGE = 1 << 1; 33 | /** 34 | * Requires Api Version >= 21 35 | */ 36 | int MULTI_PAGE_OVERLAP = 1 << 2; 37 | 38 | int MULTI_PAGE_SCALE = 1 << 3; 39 | } 40 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/manager/AttributeController.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.manager; 18 | 19 | import android.content.Context; 20 | import android.content.res.TypedArray; 21 | import android.graphics.Color; 22 | import android.util.AttributeSet; 23 | 24 | import androidx.annotation.NonNull; 25 | import androidx.annotation.Nullable; 26 | 27 | import com.zhpan.bannerview.R; 28 | import com.zhpan.bannerview.utils.BannerUtils; 29 | 30 | import static com.zhpan.bannerview.manager.BannerOptions.DEFAULT_REVEAL_WIDTH; 31 | 32 | /** 33 | *
 34 |  *   Created by zhpan on 2019/11/20.
 35 |  *   Description:初始化xml的自定义属性
 36 |  * 
37 | */ 38 | public class AttributeController { 39 | 40 | private final BannerOptions mBannerOptions; 41 | 42 | public AttributeController(BannerOptions bannerOptions) { 43 | mBannerOptions = bannerOptions; 44 | } 45 | 46 | public void init(@NonNull Context context, @Nullable AttributeSet attrs) { 47 | if (attrs != null) { 48 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerViewPager); 49 | initBannerAttrs(typedArray); 50 | initIndicatorAttrs(typedArray); 51 | typedArray.recycle(); 52 | } 53 | } 54 | 55 | private void initIndicatorAttrs(TypedArray typedArray) { 56 | int indicatorCheckedColor = 57 | typedArray.getColor(R.styleable.BannerViewPager_bvp_indicator_checked_color, 58 | Color.parseColor("#8C18171C")); 59 | int indicatorNormalColor = 60 | typedArray.getColor(R.styleable.BannerViewPager_bvp_indicator_normal_color, 61 | Color.parseColor("#8C6C6D72")); 62 | int normalIndicatorWidth = 63 | (int) typedArray.getDimension(R.styleable.BannerViewPager_bvp_indicator_radius, 64 | BannerUtils.dp2px(8)); 65 | int indicatorGravity = typedArray.getInt(R.styleable.BannerViewPager_bvp_indicator_gravity, 0); 66 | int indicatorStyle = typedArray.getInt(R.styleable.BannerViewPager_bvp_indicator_style, 0); 67 | int indicatorSlideMode = 68 | typedArray.getInt(R.styleable.BannerViewPager_bvp_indicator_slide_mode, 0); 69 | int indicatorVisibility = 70 | typedArray.getInt(R.styleable.BannerViewPager_bvp_indicator_visibility, 0); 71 | mBannerOptions.setIndicatorSliderColor(indicatorNormalColor, indicatorCheckedColor); 72 | mBannerOptions.setIndicatorSliderWidth(normalIndicatorWidth, normalIndicatorWidth); 73 | mBannerOptions.setIndicatorGravity(indicatorGravity); 74 | mBannerOptions.setIndicatorStyle(indicatorStyle); 75 | mBannerOptions.setIndicatorSlideMode(indicatorSlideMode); 76 | mBannerOptions.setIndicatorVisibility(indicatorVisibility); 77 | mBannerOptions.setIndicatorGap(normalIndicatorWidth); 78 | mBannerOptions.setIndicatorHeight(normalIndicatorWidth / 2); 79 | } 80 | 81 | private void initBannerAttrs(TypedArray typedArray) { 82 | int interval = typedArray.getInteger(R.styleable.BannerViewPager_bvp_interval, 3000); 83 | boolean isAutoPlay = typedArray.getBoolean(R.styleable.BannerViewPager_bvp_auto_play, true); 84 | boolean isCanLoop = typedArray.getBoolean(R.styleable.BannerViewPager_bvp_can_loop, true); 85 | int pageMargin = (int) typedArray.getDimension(R.styleable.BannerViewPager_bvp_page_margin, 0); 86 | int roundCorner = 87 | (int) typedArray.getDimension(R.styleable.BannerViewPager_bvp_round_corner, 0); 88 | int revealWidth = (int) typedArray.getDimension(R.styleable.BannerViewPager_bvp_reveal_width, 89 | DEFAULT_REVEAL_WIDTH); 90 | int pageStyle = typedArray.getInt(R.styleable.BannerViewPager_bvp_page_style, 0); 91 | int scrollDuration = typedArray.getInt(R.styleable.BannerViewPager_bvp_scroll_duration, 0); 92 | mBannerOptions.setInterval(interval); 93 | mBannerOptions.setAutoPlay(isAutoPlay); 94 | mBannerOptions.setCanLoop(isCanLoop); 95 | mBannerOptions.setPageMargin(pageMargin); 96 | mBannerOptions.setRoundRectRadius(roundCorner); 97 | mBannerOptions.setRightRevealWidth(revealWidth); 98 | mBannerOptions.setLeftRevealWidth(revealWidth); 99 | mBannerOptions.setPageStyle(pageStyle); 100 | mBannerOptions.setScrollDuration(scrollDuration); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/manager/BannerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.manager; 18 | 19 | import android.content.Context; 20 | import android.os.Build; 21 | import android.util.AttributeSet; 22 | 23 | import androidx.annotation.NonNull; 24 | import androidx.viewpager2.widget.CompositePageTransformer; 25 | import androidx.viewpager2.widget.MarginPageTransformer; 26 | import androidx.viewpager2.widget.ViewPager2; 27 | 28 | import com.zhpan.bannerview.transform.OverlapPageTransformer; 29 | import com.zhpan.bannerview.transform.ScaleInTransformer; 30 | 31 | /** 32 | *
 33 |  *   Created by zhpan on 2019/11/20.
 34 |  *   Description:
 35 |  * 
36 | */ 37 | public class BannerManager { 38 | 39 | private BannerOptions mBannerOptions; 40 | 41 | private final AttributeController mAttributeController; 42 | 43 | private final CompositePageTransformer mCompositePageTransformer; 44 | 45 | private MarginPageTransformer mMarginPageTransformer; 46 | 47 | private ViewPager2.PageTransformer mDefaultPageTransformer; 48 | 49 | public BannerManager() { 50 | mBannerOptions = new BannerOptions(); 51 | mAttributeController = new AttributeController(mBannerOptions); 52 | mCompositePageTransformer = new CompositePageTransformer(); 53 | } 54 | 55 | public BannerOptions getBannerOptions() { 56 | if (mBannerOptions == null) { 57 | mBannerOptions = new BannerOptions(); 58 | } 59 | return mBannerOptions; 60 | } 61 | 62 | public void initAttrs(Context context, AttributeSet attrs) { 63 | mAttributeController.init(context, attrs); 64 | } 65 | 66 | public CompositePageTransformer getCompositePageTransformer() { 67 | return mCompositePageTransformer; 68 | } 69 | 70 | public void addTransformer(@NonNull ViewPager2.PageTransformer transformer) { 71 | mCompositePageTransformer.addTransformer(transformer); 72 | } 73 | 74 | public void removeTransformer(@NonNull ViewPager2.PageTransformer transformer) { 75 | mCompositePageTransformer.removeTransformer(transformer); 76 | } 77 | 78 | public void removeMarginPageTransformer() { 79 | if (mMarginPageTransformer != null) { 80 | mCompositePageTransformer.removeTransformer(mMarginPageTransformer); 81 | } 82 | } 83 | 84 | public void removeDefaultPageTransformer() { 85 | if (mDefaultPageTransformer != null) { 86 | mCompositePageTransformer.removeTransformer(mDefaultPageTransformer); 87 | } 88 | } 89 | 90 | public void setPageMargin(int pageMargin) { 91 | mBannerOptions.setPageMargin(pageMargin); 92 | } 93 | 94 | public void createMarginTransformer() { 95 | removeMarginPageTransformer(); 96 | mMarginPageTransformer = new MarginPageTransformer(mBannerOptions.getPageMargin()); 97 | mCompositePageTransformer.addTransformer(mMarginPageTransformer); 98 | } 99 | 100 | public void setMultiPageStyle(boolean overlap, float scale) { 101 | removeDefaultPageTransformer(); 102 | if (overlap && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 103 | mDefaultPageTransformer = new OverlapPageTransformer(mBannerOptions 104 | .getOrientation(), scale, 0f, 1, 0); 105 | } else { 106 | mDefaultPageTransformer = new ScaleInTransformer(scale, mBannerOptions.isRtl()); 107 | } 108 | mCompositePageTransformer.addTransformer(mDefaultPageTransformer); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/provider/ReflectLayoutManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.provider; 18 | 19 | import androidx.recyclerview.widget.LinearLayoutManager; 20 | import androidx.recyclerview.widget.RecyclerView; 21 | import androidx.viewpager2.widget.ViewPager2; 22 | 23 | import java.lang.reflect.Field; 24 | 25 | /** 26 | * 通过反射修改页面滑动的时间 27 | * Thanks:https://github.com/zguop/banner/blob/master/pager2banner/src/main/java/com/to/aboomy/pager2banner/Banner.java 28 | */ 29 | public class ReflectLayoutManager { 30 | 31 | public static void reflectLayoutManager(ViewPager2 viewPager2, int scrollDuration) { 32 | try { 33 | RecyclerView recyclerView = (RecyclerView) viewPager2.getChildAt(0); 34 | recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER); 35 | LinearLayoutManager linearLayoutManager = 36 | (LinearLayoutManager) recyclerView.getLayoutManager(); 37 | if (linearLayoutManager == null) { 38 | return; 39 | } 40 | ScrollDurationManger scrollDurationManger = 41 | new ScrollDurationManger(viewPager2, scrollDuration, linearLayoutManager); 42 | recyclerView.setLayoutManager(scrollDurationManger); 43 | 44 | Field mRecyclerField = RecyclerView.LayoutManager.class.getDeclaredField("mRecyclerView"); 45 | mRecyclerField.setAccessible(true); 46 | mRecyclerField.set(linearLayoutManager, recyclerView); 47 | Field layoutMangerField = ViewPager2.class.getDeclaredField("mLayoutManager"); 48 | layoutMangerField.setAccessible(true); 49 | layoutMangerField.set(viewPager2, scrollDurationManger); 50 | 51 | Field pageTransformerAdapterField = 52 | ViewPager2.class.getDeclaredField("mPageTransformerAdapter"); 53 | pageTransformerAdapterField.setAccessible(true); 54 | Object mPageTransformerAdapter = pageTransformerAdapterField.get(viewPager2); 55 | if (mPageTransformerAdapter != null) { 56 | Class aClass = mPageTransformerAdapter.getClass(); 57 | Field layoutManager = aClass.getDeclaredField("mLayoutManager"); 58 | layoutManager.setAccessible(true); 59 | layoutManager.set(mPageTransformerAdapter, scrollDurationManger); 60 | } 61 | Field scrollEventAdapterField = ViewPager2.class.getDeclaredField("mScrollEventAdapter"); 62 | scrollEventAdapterField.setAccessible(true); 63 | Object mScrollEventAdapter = scrollEventAdapterField.get(viewPager2); 64 | if (mScrollEventAdapter != null) { 65 | Class aClass = mScrollEventAdapter.getClass(); 66 | Field layoutManager = aClass.getDeclaredField("mLayoutManager"); 67 | layoutManager.setAccessible(true); 68 | layoutManager.set(mScrollEventAdapter, scrollDurationManger); 69 | } 70 | } catch (NoSuchFieldException | IllegalAccessException e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/provider/RoundViewOutlineProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.provider; 18 | 19 | import android.annotation.TargetApi; 20 | import android.graphics.Outline; 21 | import android.graphics.Rect; 22 | import android.os.Build; 23 | import android.view.View; 24 | import android.view.ViewOutlineProvider; 25 | 26 | /** 27 | *
28 |  *   Created by zhangpan on 2018/12/26.
29 |  *   Description:圆角效果
30 |  * 
31 | */ 32 | 33 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 34 | public class RoundViewOutlineProvider extends ViewOutlineProvider { 35 | /** 36 | * 圆角弧度 37 | */ 38 | private final float mRadius; 39 | 40 | public RoundViewOutlineProvider(float radius) { 41 | this.mRadius = radius; 42 | } 43 | 44 | @Override 45 | public void getOutline(View view, Outline outline) { 46 | // 绘制区域 47 | Rect selfRect = new Rect(0, 0, view.getWidth(), view.getHeight()); 48 | outline.setRoundRect(selfRect, mRadius); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/provider/ScrollDurationManger.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package com.zhpan.bannerview.provider; 18 | 19 | import android.graphics.Rect; 20 | import android.os.Bundle; 21 | import android.view.View; 22 | 23 | import androidx.annotation.NonNull; 24 | import androidx.annotation.Nullable; 25 | import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; 26 | import androidx.recyclerview.widget.LinearLayoutManager; 27 | import androidx.recyclerview.widget.LinearSmoothScroller; 28 | import androidx.recyclerview.widget.RecyclerView; 29 | import androidx.viewpager2.widget.ViewPager2; 30 | 31 | import com.zhpan.bannerview.utils.BannerUtils; 32 | 33 | import java.lang.reflect.InvocationTargetException; 34 | import java.lang.reflect.Method; 35 | 36 | /** 37 | * @author zhangpan 38 | * @date 2020/12/21 39 | */ 40 | public class ScrollDurationManger extends LinearLayoutManager { 41 | private final LinearLayoutManager mParent; 42 | private final int scrollDuration; 43 | 44 | public ScrollDurationManger(ViewPager2 viewPager2, int scrollDuration, 45 | LinearLayoutManager linearLayoutManager) { 46 | super(viewPager2.getContext(), linearLayoutManager.getOrientation(), false); 47 | this.scrollDuration = scrollDuration; 48 | mParent = linearLayoutManager; 49 | } 50 | 51 | @Override 52 | public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, 53 | int position) { 54 | LinearSmoothScroller linearSmoothScroller = 55 | new LinearSmoothScroller(recyclerView.getContext()) { 56 | @Override 57 | protected int calculateTimeForDeceleration(int dx) { 58 | return scrollDuration; 59 | } 60 | }; 61 | linearSmoothScroller.setTargetPosition(position); 62 | startSmoothScroll(linearSmoothScroller); 63 | } 64 | 65 | @Override 66 | public boolean performAccessibilityAction(@NonNull RecyclerView.Recycler recycler, 67 | @NonNull RecyclerView.State state, int action, @Nullable Bundle args) { 68 | return mParent.performAccessibilityAction(recycler, state, action, args); 69 | } 70 | 71 | @Override 72 | public void onInitializeAccessibilityNodeInfo(@NonNull RecyclerView.Recycler recycler, 73 | @NonNull RecyclerView.State state, @NonNull AccessibilityNodeInfoCompat info) { 74 | mParent.onInitializeAccessibilityNodeInfo(recycler, state, info); 75 | } 76 | 77 | @Override 78 | protected void calculateExtraLayoutSpace(@NonNull RecyclerView.State state, 79 | @NonNull int[] extraLayoutSpace) { 80 | try { 81 | Method method = mParent.getClass() 82 | .getDeclaredMethod("calculateExtraLayoutSpace", 83 | state.getClass(), extraLayoutSpace.getClass()); 84 | method.setAccessible(true); 85 | method.invoke(mParent, state, extraLayoutSpace); 86 | } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 87 | e.printStackTrace(); 88 | BannerUtils.log(e.getMessage()); 89 | } 90 | } 91 | 92 | @Override 93 | public boolean requestChildRectangleOnScreen(@NonNull RecyclerView parent, 94 | @NonNull View child, @NonNull Rect rect, boolean immediate, 95 | boolean focusedChildVisible) { 96 | return false; // users should use setCurrentItem instead 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/provider/ViewStyleSetter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.zhpan.bannerview.provider; 17 | 18 | import android.os.Build; 19 | import androidx.annotation.RequiresApi; 20 | import android.view.View; 21 | 22 | /** 23 | *
24 |  *   Created by zhangpan on 2018/12/26.
25 |  *   Description:为View设置圆角,支持View及ViewGroup,适用Android 5.1及以上系统。
26 |  * 
27 | */ 28 | public class ViewStyleSetter { 29 | 30 | /** 31 | * 为View设置圆角效果 32 | * 33 | * @param radius 圆角半径 34 | */ 35 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 36 | public static void applyRoundCorner(View target, float radius) { 37 | if (target == null) { 38 | return; 39 | } 40 | target.setClipToOutline(true);// 用outline裁剪内容区域 41 | target.setOutlineProvider(new RoundViewOutlineProvider(radius)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/transform/OverlapPageTransformer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.zhpan.bannerview.transform 17 | 18 | import android.os.Build 19 | import android.view.View 20 | import androidx.annotation.RequiresApi 21 | import androidx.viewpager2.widget.ViewPager2 22 | import com.zhpan.indicator.utils.IndicatorUtils 23 | import kotlin.math.abs 24 | import kotlin.math.max 25 | 26 | /** 27 | * @param: gives veiwpager2 orientation 28 | * Source from:https://github.com/KoderLabs/finite-cover-flow/blob/dev/lib/src/main/java/com/saeed/finiteflow/lib/OverlapSliderTransformer.kt 29 | */ 30 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 31 | class OverlapPageTransformer( 32 | private val orientation: Int, 33 | private val minScale: Float = 0f, 34 | private val unSelectedItemRotation: Float = 0f, 35 | private val unSelectedItemAlpha: Float = 0f, 36 | private val itemGap: Float = 0f 37 | ) : ViewPager2.PageTransformer { 38 | 39 | init { 40 | require(minScale in 0f..1f) { "minScale value should be between 1.0 to 0.0" } 41 | require( 42 | unSelectedItemAlpha in 0f..1f 43 | ) { "unSelectedItemAlpha value should be between 1.0 to 0.0" } 44 | } 45 | 46 | private var scalingValue = 0.2f 47 | 48 | override fun transformPage( 49 | page: View, 50 | position: Float 51 | ) { 52 | page.apply { 53 | scalingValue = if (minScale >= 0.8) { 54 | 0.2f 55 | } else if (minScale >= 0.6) { 56 | 0.3f 57 | } else { 58 | 0.4f 59 | } 60 | elevation = -abs(position) 61 | val delta = max(1f - abs(position * (1 - 0.5f)), 0.5f) 62 | 63 | if (unSelectedItemRotation != 0f) { 64 | val rotation = 65 | (1 - delta) * if (position > 0) unSelectedItemRotation else -unSelectedItemRotation 66 | 67 | rotationY = rotation 68 | } 69 | 70 | val scaleDelta = abs(position * scalingValue) 71 | val scale = max(1f - scaleDelta, minScale) 72 | 73 | scaleX = scale 74 | scaleY = scale 75 | 76 | val dp2px = IndicatorUtils.dp2px((itemGap.toInt() / 2).toFloat()) 77 | when (orientation) { 78 | ViewPager2.ORIENTATION_HORIZONTAL -> { 79 | translationX = 80 | position * dp2px + 81 | if (position > 0) { 82 | (-width * (1f - scale)) 83 | } else { 84 | (width * (1f - scale)) 85 | } 86 | } 87 | ViewPager2.ORIENTATION_VERTICAL -> { 88 | translationY = position * dp2px + 89 | if (position > 0) { 90 | (-width * (1f - scale)) 91 | } else { 92 | (width * (1f - scale)) 93 | } 94 | } 95 | else -> throw IllegalArgumentException( 96 | "Gives correct orientation value, ViewPager2.ORIENTATION_HORIZONTAL or ViewPager2.ORIENTATION_VERTICAL" 97 | ) 98 | } 99 | 100 | if (unSelectedItemAlpha != 1f) { 101 | alpha = when { 102 | position >= -1f && position <= 1f -> { // (0, 1] 103 | // page move from right to center. 104 | 0.5f + ((1 - abs(position)) * 0.5f) 105 | } 106 | else -> { 107 | 0.5f / abs(position * position) 108 | } 109 | } 110 | } 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/transform/ScaleInTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.zhpan.bannerview.transform; 17 | 18 | import android.view.View; 19 | 20 | import androidx.viewpager2.widget.ViewPager2; 21 | 22 | public class ScaleInTransformer implements ViewPager2.PageTransformer { 23 | 24 | private static final float DEFAULT_CENTER = 0.5f; 25 | public static final float DEFAULT_MIN_SCALE = 0.85f; 26 | private final float mMinScale; 27 | 28 | private final boolean mIsRtl; 29 | 30 | public ScaleInTransformer(float minScale, boolean isRtl) { 31 | mMinScale = minScale; 32 | mIsRtl = isRtl; 33 | } 34 | 35 | @Override 36 | public void transformPage(View view, float position) { 37 | if (mIsRtl) { 38 | position = -position; 39 | } 40 | int pageWidth = view.getWidth(); 41 | int pageHeight = view.getHeight(); 42 | 43 | view.setPivotY(pageHeight / 2f); 44 | view.setPivotX(pageWidth / 2f); 45 | if (position < -1) { 46 | // This page is way off-screen to the left. 47 | view.setScaleX(mMinScale); 48 | view.setScaleY(mMinScale); 49 | view.setPivotX(pageWidth); 50 | } else if (position <= 1) { 51 | // Modify the default slide transition to shrink the page as well 52 | if (position < 0) { 53 | float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale; 54 | view.setScaleX(scaleFactor); 55 | view.setScaleY(scaleFactor); 56 | view.setPivotX(pageWidth * (DEFAULT_CENTER + (DEFAULT_CENTER * -position))); 57 | } else { 58 | float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale; 59 | view.setScaleX(scaleFactor); 60 | view.setScaleY(scaleFactor); 61 | view.setPivotX(pageWidth * ((1 - position) * DEFAULT_CENTER)); 62 | } 63 | } else { 64 | view.setPivotX(0); 65 | view.setScaleX(mMinScale); 66 | view.setScaleY(mMinScale); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /bannerview/src/main/java/com/zhpan/bannerview/utils/BannerUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 zhpanvip The BannerViewPager Open Source Project 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package com.zhpan.bannerview.utils; 17 | 18 | import android.content.res.Resources; 19 | import android.util.Log; 20 | 21 | import com.zhpan.bannerview.BaseBannerAdapter; 22 | 23 | import static com.zhpan.bannerview.BaseBannerAdapter.MAX_VALUE; 24 | 25 | /** 26 | *
27 |  *   Created by zhangpan on 2019-08-14.
28 |  *   Description:
29 |  * 
30 | */ 31 | public class BannerUtils { 32 | 33 | private static boolean debugMode = false; 34 | 35 | private static final String TAG = "BVP"; 36 | 37 | public static void setDebugMode(boolean isDebug) { 38 | debugMode = isDebug; 39 | } 40 | 41 | public static boolean isDebugMode() { 42 | return debugMode; 43 | } 44 | 45 | public static int dp2px(float dpValue) { 46 | return (int) (0.5F + dpValue * Resources.getSystem().getDisplayMetrics().density); 47 | } 48 | 49 | public static void log(String tag, String msg) { 50 | if (isDebugMode()) { 51 | Log.e(tag, msg); 52 | } 53 | } 54 | 55 | public static void log(String msg) { 56 | if (isDebugMode()) { 57 | log(TAG, msg); 58 | } 59 | } 60 | 61 | /** 62 | * 在循环模式下{@link com.zhpan.bannerview.BannerViewPager}会初始化一个item为 63 | * {@link BaseBannerAdapter#MAX_VALUE}的ViewPager2,并将当前position设置为ViewPager2 64 | * 的中间位置,因此,此时的position需要通过该方法进行转换为真实的position。 65 | * 66 | * @param position 当前position 67 | * @param pageSize 轮播图页面数 68 | * @return 真实的position 69 | */ 70 | public static int getRealPosition(int position, int pageSize) { 71 | if (pageSize == 0) { 72 | return 0; 73 | } 74 | return (position + pageSize) % pageSize; 75 | } 76 | 77 | /** 78 | * @param pageSize 轮播图页面数 79 | * @return 轮播图初始位置 80 | */ 81 | public static int getOriginalPosition(int pageSize) { 82 | return MAX_VALUE / 2 - ((MAX_VALUE / 2) % pageSize); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /bannerview/src/main/res/layout/bvp_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | 19 | -------------------------------------------------------------------------------- /bannerview/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | /> 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.9.0' 5 | repositories { 6 | mavenCentral() 7 | google() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.1.2' 11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | mavenCentral() 19 | google() 20 | maven { url "https://www.jitpack.io" } 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | 28 | ext { 29 | compileSdkVersion=27 30 | buildToolsVersion = '28.0.0' 31 | targetSdkVersion = 26 32 | minSdkVersion = 16 33 | releaseVersionCode = 1 34 | releaseVersionName = '1.0.0' 35 | 36 | rxjava2Version = '2.2.12' 37 | retrofit2Version = '2.5.0' 38 | rxlifecycle='2.2.1' 39 | gsonVersion = '2.8.0' 40 | butterknifeVersion = '8.5.1' 41 | } 42 | -------------------------------------------------------------------------------- /git: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/git -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | android.enableJetifier=true 13 | android.useAndroidX=true 14 | org.gradle.jvmargs=-Xmx1536m 15 | 16 | # When configured, Gradle will run in incubating parallel mode. 17 | # This option should only be used with decoupled projects. More details, visit 18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 19 | # org.gradle.parallel=true 20 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhpanvip/BannerViewPager/e57de09eeef4ee5cb458853543ebef272a1fdb10/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Apr 11 17:35:28 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':bannerview' 2 | //include "indicator" 3 | //project(':indicator').projectDir = file('../viewpagerindicator/indicator') --------------------------------------------------------------------------------