├── .gitignore
├── .idea
├── .gitignore
├── .name
├── compiler.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jarRepositories.xml
└── misc.xml
├── LICENSE
├── Label_README.md
├── README.md
├── TAB_README.md
├── TAB_README3_0.md
├── appx
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── zhengsr
│ │ └── tabhelper
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── zhengsr
│ │ │ └── tabhelper
│ │ │ ├── App.java
│ │ │ ├── CommonUtils.java
│ │ │ ├── MainActivity.java
│ │ │ ├── activity
│ │ │ ├── BaseActivity.java
│ │ │ ├── CountActivity.java
│ │ │ ├── LabelActivity.java
│ │ │ ├── LabelShowMoreActivity.java
│ │ │ ├── NetTestActivity.java
│ │ │ ├── TabActivity.java
│ │ │ ├── TabNoViewPagerActivity.java
│ │ │ └── VerticalTabActivity.java
│ │ │ ├── bean
│ │ │ ├── ArticleData.java
│ │ │ ├── BaseResponse.java
│ │ │ ├── NaviBean.java
│ │ │ ├── NaviChildrenBean.java
│ │ │ ├── PageDataInfo.java
│ │ │ └── SystematicBean.java
│ │ │ ├── fragment
│ │ │ ├── BaseFragment.java
│ │ │ ├── CusFragment.java
│ │ │ ├── RecyclerFragment.java
│ │ │ └── TestFragment.java
│ │ │ ├── rx
│ │ │ ├── HttpCreate.java
│ │ │ └── HttpServerApi.java
│ │ │ └── utils
│ │ │ └── RxUtils.java
│ └── res
│ │ ├── color
│ │ └── color_selector.xml
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── ic_launcher_background.xml
│ │ ├── select_tag.xml
│ │ ├── shape_bg.xml
│ │ ├── shape_red_radius.xml
│ │ ├── shape_round.xml
│ │ ├── shape_round_ff.xml
│ │ ├── shape_round_trans.xml
│ │ ├── shape_search.xml
│ │ ├── shape_search_select.xml
│ │ └── shape_showmore.xml
│ │ ├── layout
│ │ ├── activity_count.xml
│ │ ├── activity_label.xml
│ │ ├── activity_label_show_more.xml
│ │ ├── activity_main.xml
│ │ ├── activity_net_test.xml
│ │ ├── activity_tab.xml
│ │ ├── activity_tab_no_view_pager.xml
│ │ ├── activity_vertical_tab.xml
│ │ ├── handup.xml
│ │ ├── item_article_recy_layout.xml
│ │ ├── item_color_msg.xml
│ │ ├── item_msg.xml
│ │ ├── item_navi_detail.xml
│ │ ├── item_search_layout.xml
│ │ ├── item_tab.xml
│ │ ├── item_tab_text.xml
│ │ ├── item_test.xml
│ │ ├── item_text_width_match.xml
│ │ ├── item_textview.xml
│ │ ├── item_textview_navi.xml
│ │ ├── recycler_layout.xml
│ │ ├── show_more.xml
│ │ ├── tab_text_layout.xml
│ │ └── test_fragment.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── bg_man.jpg
│ │ ├── delete.png
│ │ ├── handup.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── more.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── zhengsr
│ └── tabhelper
│ └── ExampleUnitTest.java
├── build.gradle
├── gif
├── alipay.jpg
├── label.gif
├── label_showmore.gif
├── tab_click.gif
├── tab_vertical.gif
├── tab_viewpager.gif
├── tab_visual_count.png
└── wechat.png
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── tablibx
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── com
│ └── zhengsr
│ └── tablib
│ └── ExampleInstrumentedTest.java
├── main
├── AndroidManifest.xml
├── java
│ └── com
│ │ └── zhengsr
│ │ └── tablib
│ │ ├── FlowConstants.java
│ │ ├── bean
│ │ ├── BaseLabelItem.java
│ │ ├── LabelBean.java
│ │ ├── TabBean.java
│ │ ├── TabConfig.java
│ │ ├── TabTypeEvaluator.java
│ │ ├── TabValue.java
│ │ └── TextConfig.java
│ │ ├── callback
│ │ ├── FlowListener.java
│ │ └── FlowListenerAdapter.java
│ │ ├── utils
│ │ ├── AttrsUtils.java
│ │ ├── DisplayUtil.java
│ │ └── ViewPagerHelperUtils.java
│ │ └── view
│ │ ├── TabColorTextView.java
│ │ ├── action
│ │ ├── BViewPager.java
│ │ ├── BaseAction.java
│ │ ├── BaseVpAction.java
│ │ ├── ColorAction.java
│ │ ├── RectAction.java
│ │ ├── ResAction.java
│ │ ├── RoundAction.java
│ │ └── TriAction.java
│ │ ├── adapter
│ │ ├── BaseFlowAdapter.java
│ │ ├── LabelFlowAdapter.java
│ │ ├── TabFlowAdapter.java
│ │ └── TemplateAdapter.java
│ │ └── flow
│ │ ├── LabelFlowLayout.java
│ │ ├── TabFlowLayout.java
│ │ ├── TabVpFlowLayout.java
│ │ └── base
│ │ ├── AbsFlowLayout.java
│ │ ├── FlowLayout.java
│ │ └── ScrollFlowLayout.java
└── res
│ └── values
│ ├── attrs.xml
│ └── strings.xml
└── test
└── java
└── com
└── zhengsr
└── tablib
└── ExampleUnitTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
86 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | TabHelper
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.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 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FlowHelper
2 | FlowHelper 可以帮助您迅速构建Tab,比如热搜、搜索记录、与ViewPager搭配的工具类;
3 |
4 | **注意注意注意!!!**
5 | **提问题的时候,请遵循以下标准**
6 |
7 | - **现象: 操作步骤,应用场景**
8 | - **对应代码: 贴图或者贴代码**
9 | - **机型或版本: 可选**
10 |
11 | **后面对描述不清的问题,不予理会,精力有限,感谢理解**
12 |
13 | **具体原理可参考着四篇文章:**
14 |
15 | **如果你也想自己写一个,可以参考以下几篇文章**
16 |
17 | [实现一个可定制化的TabFlowLayout(一) -- 测量与布局](https://blog.csdn.net/u011418943/article/details/103804677)
18 |
19 | [实现一个可定制化的TabFlowLayout(二) -- 实现滚动和平滑过渡](https://blog.csdn.net/u011418943/article/details/103807920)
20 |
21 | [实现一个可定制化的TabFlowLayout(三) -- 动态数据添加与常用接口封装](https://blog.csdn.net/u011418943/article/details/103817967)
22 |
23 | [实现一个可定制化的TabFlowLayout(四) -- 与ViewPager 结合,实现炫酷效果](https://blog.csdn.net/u011418943/article/details/103851359)
24 |
25 | [实现一个可定制化的TabFlowLayout -- 原理篇](https://juejin.im/post/5e365f52f265da3e3d511d65)
26 |
27 | [实现一个可定制化的TabFlowLayout -- 说明文档](https://juejin.im/post/5e2f9dc7e51d4558836e3f99)
28 |
29 |
30 | [FlowLayout 和 Recyclerview 实现双联表联动](https://blog.csdn.net/u011418943/article/details/104083568)
31 |
32 | 如果您也想快速实现 **Banner 轮播图**,可以使用这个库 https://github.com/LillteZheng/ViewPagerHelper
33 |
34 | **工程实际使用 - 玩Android 客户端 : https://github.com/LillteZheng/WanAndroid**
35 |
36 |
37 | [](https://jitpack.io/#LillteZheng/FlowHelper)
38 | 
39 | 
40 | [](https://blog.csdn.net/u011418943)
41 |
42 | ## 使用
43 | 在buid.gradle (新版as在setting.gradle)
44 | ```
45 | allprojects {
46 | repositories {
47 | ...
48 | maven { url 'https://jitpack.io' }
49 |
50 | }
51 | }
52 | ```
53 |
54 |
55 | **如果你的工程的是androidx且想支持ViewPager2,可以关联tablibx库**
56 | ```
57 | implementation 'com.github.LillteZheng:FlowHelper:v2.3'
58 | ```
59 | **support可以关联以下连接,请尽快切到androidx,support包不再维护**
60 | ```
61 | implementation 'com.github.LillteZheng.FlowHelper:tablib:v1.29'
62 | ```
63 |
64 |
65 | **不一定有时间处理,如果工程有不满足或bug,可以修改后提mr**
66 |
67 |
68 | ## TabFlowLayout 效果图
69 |
70 |
71 |
72 | 没有结合ViewPager |
73 | 结合ViewPager |
74 |
75 |
76 |  |
77 |  |
78 |
79 |
80 |
81 |
82 |
83 |
84 | 竖直效果 |
85 |
86 |
87 |  |
88 |
89 |
90 |
91 |
92 | **目前TabFlowLayout 支持以下效果:**
93 | - **矩形**
94 | - **三角形**
95 | - **圆角**
96 | - **shape 或者 bitmap 等资源**
97 | - **自定义功能**
98 | - **放大Item效果,与上述效果可共用**
99 | - **颜色渐变效果,需要使用 TabColorTextView 控件,与上述效果可共用,只支持有viewpager 的情况**
100 | - **竖直效果,需要设置 tab_orientation = vertical**
101 | - **宽度均分**
102 |
103 | [TabFlowLayout 使用说明](https://github.com/LillteZheng/FlowHelper/blob/feature_3.0/TAB_README3_0.md)
104 |
105 | ## LabelFlowLayout 效果图
106 |
107 |
108 |
109 | LabelFlowLayout |
110 | LabelFlowLayout 显示更多 |
111 |
112 |
113 |  |
114 |  |
115 |
116 |
117 |
118 |
119 |
120 | **LabelFlowLayout 支持以下效果:**
121 | - **单选**
122 | - **多选**
123 | - **长按**
124 | - **显示更多**
125 | - **收起**
126 |
127 |
128 | [LabelFlowLayout 使用说明](https://github.com/LillteZheng/FlowHelper/blob/master/Label_README.md)
129 |
130 |
131 | **其实TabFlowLayout也可以支持底部导航栏,但其实没必要,可以参考这个库 https://github.com/LillteZheng/CusBottomHelper**
132 |
133 |
134 |
135 | 底部凸起 |
136 | 结合ViewPager |
137 |
138 |
139 |  |
140 |  |
141 |
142 |
143 |
144 |
145 |
146 | ## 版本信息:
147 | - v2.5 : 修复TabLabelLayout 在调用 resetStatus,第一个无法点击的问题。并增加 BaseLabelItem,Bean 类继承它,可实现换行
148 | - v2.3 : 修改TabVpFlowLayout 快速点击时,TabColorTextView 还有残留,和 tab 没有转移过去的问题
149 | - v2.0 : 内置部分控件,减少接入成本,并优化一些bug,和关闭demo ,viewpager 内存泄露的问题
150 | - v1.37 : 增加 tab_width_equals_text ,让 rect 根据 text 的长度变化,修复 TabColorTextView 加粗不起作用的问题
151 | - v1.32 : 修复res和round,tab_margin_x 不起作用的问题
152 | - v1.30 : 重构分离了ViewPager和非ViewPager的情况,并处理数据增加减少时,notifyDataChange()导致布局混乱的问题
153 | - v1.291: 修复notifyDataChange部分场景不起作用的问题,小重构了参数配置
154 | - v1.29 : 修复添加了tabWidth,round和res第一次不起作用的问题
155 | - v1.28 : 1. 修复底部条跳动的问题;2. 修复TabColorText不能设置padding的问题
156 | - v1.27 : 修复 tab_color 不起作用的问题
157 | - v1.26 : 增加 ViewPager2
158 | ....
159 |
160 | ## QQ群
161 | 为方便大家交流,创建了一个qq群,群号216618259
162 |
163 |
164 |
165 |
166 | ## 如果该项目对您有帮助,赞赏一下吧 ^_^
167 |
168 |
169 |
170 |
171 |
172 | 赞赏名单 |
173 | 方式 |
174 |
175 |
176 | *头 |
177 | 微信 |
178 |
179 |
180 | *变 |
181 | 微信 |
182 |
183 |
184 |
185 |
186 |
187 | ## 参考
188 |
189 | 本工程参考以下优秀项目:
190 |
191 | [鸿洋的 flowLayout](https://github.com/hongyangAndroid/FlowLayout)
192 |
193 | [Flyco的 TabLayout](https://github.com/H07000223/FlycoTabLayout)
194 |
195 |
196 |
197 |
198 |
--------------------------------------------------------------------------------
/appx/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/appx/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 |
6 | defaultConfig {
7 | applicationId "com.zhengsr.tabhelper"
8 | minSdkVersion 19
9 | targetSdkVersion 29
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14 | }
15 |
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(dir: "libs", include: ["*.jar"])
26 | implementation 'androidx.appcompat:appcompat:1.2.0'
27 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
28 | testImplementation 'junit:junit:4.12'
29 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
31 |
32 | implementation project(path: ':tablibx')
33 | //implementation 'com.github.LillteZheng:FlowHelper:v1.34'
34 | implementation 'me.yokeyword:fragmentationx:1.0.2'
35 | implementation 'androidx.cardview:cardview:1.0.0'
36 | implementation 'androidx.viewpager2:viewpager2:1.0.0'
37 | implementation 'com.squareup.retrofit2:retrofit:2.5.0'
38 | implementation 'com.squareup.retrofit2:converter-scalars:2.5.0'
39 |
40 | implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
41 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
42 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
43 | implementation 'com.alibaba:fastjson:1.1.71.android'
44 | implementation 'org.ligboy.retrofit2:converter-fastjson-android:2.1.0'
45 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
46 | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
47 | implementation 'com.github.weikaiyun.SFragmentation:fragmentation:1.8.4'
48 | }
49 |
--------------------------------------------------------------------------------
/appx/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
--------------------------------------------------------------------------------
/appx/src/androidTest/java/com/zhengsr/tabhelper/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.exceedshare.appx", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/appx/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/App.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper;
2 |
3 | import android.app.Application;
4 |
5 | import com.weikaiyun.fragmentation.Fragmentation;
6 |
7 | /**
8 | * @author by zhengshaorui 2022/2/26
9 | * describe:
10 | */
11 | public class App extends Application {
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 | Fragmentation.builder() // 设置 栈视图 模式为 (默认)悬浮球模式 SHAKE: 摇一摇唤出 NONE:隐藏, 仅在Debug环境生效
16 | .stackViewMode(Fragmentation.BUBBLE)
17 | .debug(BuildConfig.DEBUG) // 实际场景建议.debug(BuildConfig.DEBUG)
18 | .animation(R.anim.v_fragment_enter, R.anim.v_fragment_pop_exit, R.anim.v_fragment_pop_enter, R.anim.v_fragment_exit) //设置默认动画
19 | .install();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/CommonUtils.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper;
2 |
3 | import android.graphics.Color;
4 | import android.graphics.drawable.Drawable;
5 | import android.graphics.drawable.GradientDrawable;
6 |
7 | import java.util.Random;
8 |
9 | /**
10 | * @author by zhengshaorui on 2019/10/8
11 | * Describe:
12 | */
13 | public class CommonUtils {
14 | /**
15 | * Tab colors
16 | */
17 | public static final int[] TAB_COLORS = new int[]{
18 | Color.parseColor("#90C5F0"),
19 | Color.parseColor("#91CED5"),
20 | Color.parseColor("#F88F55"),
21 | Color.parseColor("#C0AFD0"),
22 | Color.parseColor("#E78F8F"),
23 | Color.parseColor("#67CCB7"),
24 | Color.parseColor("#F6BC7E"),
25 | Color.parseColor("#3399ff")
26 | };
27 | public static int randomTagColor() {
28 | int randomNum = new Random().nextInt();
29 | int position = randomNum % TAB_COLORS.length;
30 | if (position < 0) {
31 | position = -position;
32 | }
33 | return TAB_COLORS[position];
34 | }
35 |
36 | public static Drawable getColorDrawable(int radius){
37 | GradientDrawable drawable = new GradientDrawable();
38 | drawable.setColor(randomTagColor());
39 | drawable.setCornerRadius(radius);
40 | return drawable;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import androidx.fragment.app.Fragment;
10 | import androidx.fragment.app.FragmentManager;
11 | import androidx.fragment.app.FragmentPagerAdapter;
12 | import androidx.viewpager.widget.ViewPager;
13 |
14 | import com.zhengsr.tabhelper.activity.BaseActivity;
15 | import com.zhengsr.tabhelper.activity.CountActivity;
16 | import com.zhengsr.tabhelper.activity.LabelActivity;
17 | import com.zhengsr.tabhelper.activity.LabelShowMoreActivity;
18 | import com.zhengsr.tabhelper.activity.NetTestActivity;
19 | import com.zhengsr.tabhelper.activity.TabActivity;
20 | import com.zhengsr.tabhelper.activity.TabNoViewPagerActivity;
21 | import com.zhengsr.tabhelper.activity.VerticalTabActivity;
22 | import com.zhengsr.tabhelper.fragment.TestFragment;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | public class MainActivity extends BaseActivity {
28 | private List mFragments = new ArrayList<>();
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_main);
33 | TextView textView = findViewById(R.id.text);
34 | textView.setTextColor(getResources().getColor(R.color.color_selector));
35 | }
36 |
37 |
38 | public void tablayout(View view) {
39 | startActivity(new Intent(this, TabActivity.class));
40 | }
41 |
42 | public void tablayout2(View view) {
43 | startActivity(new Intent(this, TabNoViewPagerActivity.class));
44 | }
45 | public void tab_count(View view) {
46 | startActivity(new Intent(this, CountActivity.class));
47 | }
48 |
49 | public void labelflow(View view) {
50 | startActivity(new Intent(this, LabelActivity.class));
51 | }
52 |
53 | public void tablayout3(View view) {
54 | startActivity(new Intent(this, NetTestActivity.class));
55 | }
56 |
57 | public void tablayout4(View view) {
58 | startActivity(new Intent(this,VerticalTabActivity.class));
59 | }
60 |
61 | public void labelflowshomore(View view) {
62 | startActivity(new Intent(this, LabelShowMoreActivity.class));
63 | }
64 |
65 | /**
66 | * viewpager adapter
67 | */
68 | class CusAdapter extends FragmentPagerAdapter {
69 |
70 | public CusAdapter(FragmentManager fm) {
71 | super(fm);
72 | }
73 |
74 | @Override
75 | public Fragment getItem(int position) {
76 | return mFragments.get(position);
77 | }
78 |
79 | @Override
80 | public int getCount() {
81 | return mFragments.size();
82 | }
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/activity/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.activity;
2 |
3 | import me.yokeyword.fragmentation.SupportActivity;
4 |
5 | /**
6 | * @author by zhengshaorui 2022/2/26
7 | * describe:
8 | */
9 | public class BaseActivity extends SupportActivity {
10 | }
11 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/activity/CountActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.activity;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import androidx.fragment.app.Fragment;
10 | import androidx.fragment.app.FragmentActivity;
11 | import androidx.viewpager2.adapter.FragmentStateAdapter;
12 | import androidx.viewpager2.widget.ViewPager2;
13 |
14 | import com.zhengsr.tabhelper.R;
15 | import com.zhengsr.tabhelper.fragment.CusFragment;
16 | import com.zhengsr.tablib.view.adapter.TabFlowAdapter;
17 | import com.zhengsr.tablib.view.flow.TabVpFlowLayout;
18 |
19 | import java.util.ArrayList;
20 | import java.util.Arrays;
21 | import java.util.List;
22 |
23 | /**
24 | * @author by zhengshaorui 2021/4/22 16:31
25 | * describe:
26 | */
27 | public class CountActivity extends BaseActivity {
28 | private List mTitle = new ArrayList<>(Arrays.asList("test1","test2"));
29 | private List mFragments = new ArrayList<>();
30 | private ViewPager2 mViewPager;
31 | @Override
32 | protected void onCreate(@Nullable Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.activity_count);
35 | mViewPager = findViewById(R.id.viewpager2);
36 | for (String s : mTitle) {
37 | mFragments.add(CusFragment.newInStance(s));
38 | }
39 | mViewPager.setAdapter(new CusAdapter2(this));
40 | rectFlow();
41 | }
42 |
43 | private void rectFlow(){
44 | final TabVpFlowLayout flowLayout = findViewById(R.id.rectflow);
45 | // flowLayout.setViewPager(mViewPager,R.id.item_text,getResources().getColor(R.color.unselect),Color.WHITE);
46 | flowLayout.setViewPager(mViewPager);
47 | flowLayout.setAdapter(new TabFlowAdapter(mTitle));
48 |
49 |
50 |
51 |
52 | }
53 |
54 | class CusAdapter2 extends FragmentStateAdapter {
55 |
56 | public CusAdapter2(@NonNull FragmentActivity fragmentActivity) {
57 | super(fragmentActivity);
58 | }
59 |
60 | @NonNull
61 | @Override
62 | public Fragment createFragment(int position) {
63 | return mFragments.get(position);
64 | }
65 |
66 | @Override
67 | public int getItemCount() {
68 | return mFragments.size();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/activity/LabelActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.activity;
2 |
3 | import android.graphics.Color;
4 | import android.icu.text.CaseMap;
5 | import android.os.Bundle;
6 | import android.service.quicksettings.Tile;
7 | import android.view.View;
8 | import android.widget.Toast;
9 |
10 | import androidx.appcompat.app.AppCompatActivity;
11 |
12 | import com.zhengsr.tabhelper.CommonUtils;
13 | import com.zhengsr.tabhelper.R;
14 | import com.zhengsr.tablib.bean.BaseLabelItem;
15 | import com.zhengsr.tablib.view.adapter.LabelFlowAdapter;
16 | import com.zhengsr.tablib.view.flow.LabelFlowLayout;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Arrays;
20 | import java.util.List;
21 |
22 | public class LabelActivity extends BaseActivity {
23 | private List mTitle = new ArrayList<>(Arrays.asList("新闻", "娱乐", "学习", "测试后", "新闻", "娱乐", "学习"));
24 | private List mTitle2 = new ArrayList<>(Arrays.asList("Life is like an ocean Only strong willed ".split(" ")));
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_label);
30 | singleFlow();
31 | searchFlow();
32 | multiFlow();
33 | canLongFlow();
34 | }
35 |
36 | private void singleFlow() {
37 | LabelFlowLayout flowLayout = findViewById(R.id.singleflow);
38 | List datas = new ArrayList();
39 | for (int i = 0; i < 20; i++) {
40 | SingleBean bean = new SingleBean();
41 | bean.name = "测试 " + i;
42 | if (i == 0 || i == 3 || i == 10) {
43 | bean.isHeader = true;
44 | bean.name = "Header";
45 | }
46 | datas.add(bean);
47 | }
48 | final LabelFlowAdapter adapter;
49 | flowLayout.setAdapter(adapter = new LabelFlowAdapter(R.layout.item_textview, datas) {
50 | @Override
51 | public void bindView(View view, SingleBean data, int position) {
52 | setText(view, R.id.item_text, data.name)
53 | .setTextColor(view, R.id.item_text, getResources().getColor(R.color.unselect));
54 | }
55 |
56 |
57 | @Override
58 | public void onItemSelectState(View view, boolean isSelected) {
59 | super.onItemSelectState(view, isSelected);
60 | if (isSelected) {
61 | setTextColor(view, R.id.item_text, Color.BLACK);
62 | } else {
63 | setTextColor(view, R.id.item_text, getResources().getColor(R.color.unselect));
64 | }
65 | }
66 | });
67 |
68 | findViewById(R.id.update).setOnClickListener(new View.OnClickListener() {
69 | @Override
70 | public void onClick(View view) {
71 | mTitle.clear();
72 | mTitle.addAll(mTitle2);
73 | adapter.notifyDataChanged();
74 | }
75 | });
76 |
77 | // flowLayout.setSelects(6);
78 |
79 | }
80 |
81 | class SingleBean extends BaseLabelItem {
82 | public String name;
83 | }
84 |
85 | private void searchFlow() {
86 | LabelFlowLayout flowLayout = findViewById(R.id.search_flow);
87 | flowLayout.setAdapter(new LabelFlowAdapter(R.layout.item_textview, mTitle) {
88 | @Override
89 | public void bindView(View view, String data, int position) {
90 | setText(view, R.id.item_text, data)
91 | .setTextColor(view, R.id.item_text, Color.WHITE);
92 | view.setBackground(CommonUtils.getColorDrawable(10));
93 | }
94 | });
95 |
96 | }
97 |
98 | private void multiFlow() {
99 | LabelFlowLayout flowLayout = findViewById(R.id.multiflow);
100 | flowLayout.setMaxSelectCount(3);
101 | flowLayout.setAdapter(new LabelFlowAdapter(R.layout.item_textview, mTitle2) {
102 | @Override
103 | public void bindView(View view, String data, int position) {
104 | setText(view, R.id.item_text, data);
105 | }
106 |
107 |
108 | @Override
109 | public void onReachMaxCount(List ids, int count) {
110 | super.onReachMaxCount(ids, count);
111 | Toast.makeText(LabelActivity.this, "最多只能选中 " + count + " 个" + " 已选中坐标: " + ids, Toast.LENGTH_SHORT).show();
112 | }
113 |
114 |
115 | });
116 |
117 | //选中默认数据
118 | flowLayout.setSelects(2, 3, 5);
119 |
120 | }
121 |
122 | private void canLongFlow() {
123 | LabelFlowLayout flowLayout = findViewById(R.id.longflow);
124 | flowLayout.setAdapter(new LabelFlowAdapter(R.layout.item_search_layout, mTitle2) {
125 | @Override
126 | public void bindView(View view, String data, int position) {
127 | setText(view, R.id.search_msg_tv, data)
128 | .addChildrenClick(view, R.id.search_delete_iv, position);
129 | }
130 |
131 | @Override
132 | public void onItemSelectState(View view, boolean isSelected) {
133 | super.onItemSelectState(view, isSelected);
134 | if (!isSelected) {
135 | view.setBackgroundResource(R.drawable.shape_search);
136 | setVisible(view, R.id.search_delete_iv, false);
137 | }
138 | }
139 |
140 | @Override
141 | public void onItemClick(View view, String data, int position) {
142 | super.onItemClick(view, data, position);
143 | Toast.makeText(LabelActivity.this, "点击了: " + data, Toast.LENGTH_SHORT).show();
144 | }
145 |
146 | @Override
147 | public void onItemChildClick(View childView, int position) {
148 | super.onItemChildClick(childView, position);
149 | if (childView.getId() == R.id.search_delete_iv) {
150 | mTitle2.remove(position);
151 | notifyDataChanged();
152 | }
153 | }
154 |
155 | @Override
156 | public boolean onItemLongClick(View view, int position) {
157 | /**
158 | * 置所有view 的 select 为 false
159 | */
160 | resetStatus();
161 | view.setBackgroundResource(R.drawable.shape_search_select);
162 | setVisible(view, R.id.search_delete_iv, true);
163 | return super.onItemLongClick(view, position);
164 | }
165 |
166 |
167 | });
168 | }
169 |
170 |
171 | public void test(View view) {
172 |
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/activity/LabelShowMoreActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.activity;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Toast;
7 |
8 | import androidx.appcompat.app.AppCompatActivity;
9 |
10 | import com.zhengsr.tabhelper.R;
11 | import com.zhengsr.tablib.bean.LabelBean;
12 | import com.zhengsr.tablib.view.adapter.LabelFlowAdapter;
13 | import com.zhengsr.tablib.view.flow.LabelFlowLayout;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.List;
18 |
19 | public class LabelShowMoreActivity extends BaseActivity {
20 |
21 | private List mTitle = new ArrayList<>(Arrays.asList("Life is like an ocean Only strong willed people can reach the other side ".split(" ")));
22 |
23 | @Override
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | setContentView(R.layout.activity_label_show_more);
27 |
28 | LabelFlowLayout flowLayout = findViewById(R.id.labelflow);
29 |
30 | //自定义属性
31 | LabelBean bean = new LabelBean();
32 | bean.showLines = 2;
33 | bean.showMoreLayoutId = R.layout.show_more;
34 | bean.showMoreColor = Color.WHITE;
35 | bean.handUpLayoutId = R.layout.handup;
36 |
37 | flowLayout.setLabelBean(bean);
38 | flowLayout.setAdapter(new LabelFlowAdapter(R.layout.item_textview,mTitle) {
39 | @Override
40 | public void bindView(View view, String data, int position) {
41 | setDefaultText(view,data)
42 | .setDefaultTextColor(view, Color.BLACK);
43 | }
44 | @Override
45 | public void onItemSelectState(View view, boolean isSelected) {
46 | super.onItemSelectState(view, isSelected);
47 | if (isSelected){
48 | setDefaultTextColor(view, getResources().getColor(R.color.colorPrimary));
49 | }else{
50 | setDefaultTextColor(view,Color.BLACK);
51 | }
52 | }
53 |
54 | @Override
55 | public void onShowMoreClick(View view) {
56 | super.onShowMoreClick(view);
57 | Toast.makeText(LabelShowMoreActivity.this, "显示全部", Toast.LENGTH_SHORT).show();
58 | }
59 |
60 | @Override
61 | public void onHandUpClick(View view) {
62 | super.onHandUpClick(view);
63 | Toast.makeText(LabelShowMoreActivity.this, "收起", Toast.LENGTH_SHORT).show();
64 | }
65 | });
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/activity/NetTestActivity.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.activity;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 |
8 | import androidx.fragment.app.Fragment;
9 | import androidx.fragment.app.FragmentManager;
10 | import androidx.fragment.app.FragmentPagerAdapter;
11 | import androidx.viewpager.widget.ViewPager;
12 |
13 | import com.zhengsr.tabhelper.R;
14 | import com.zhengsr.tabhelper.bean.BaseResponse;
15 | import com.zhengsr.tabhelper.bean.NaviChildrenBean;
16 | import com.zhengsr.tabhelper.bean.SystematicBean;
17 | import com.zhengsr.tabhelper.fragment.RecyclerFragment;
18 | import com.zhengsr.tabhelper.rx.HttpCreate;
19 | import com.zhengsr.tablib.bean.TabConfig;
20 | import com.zhengsr.tablib.view.adapter.TabFlowAdapter;
21 | import com.zhengsr.tablib.view.flow.TabVpFlowLayout;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | import io.reactivex.android.schedulers.AndroidSchedulers;
27 | import io.reactivex.observers.ResourceObserver;
28 | import io.reactivex.schedulers.Schedulers;
29 | import me.yokeyword.fragmentation.SupportActivity;
30 |
31 | public class NetTestActivity extends BaseActivity {
32 | private static final String TAG = "NetTestActivity";
33 | private ViewPager mViewPager;
34 |
35 | @SuppressLint("CheckResult")
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.activity_net_test);
40 |
41 | final TabVpFlowLayout flowLayout = findViewById(R.id.tabflow);
42 | mViewPager = findViewById(R.id.viewpager);
43 |
44 | mViewPager.setOffscreenPageLimit(3);
45 | final List titles = new ArrayList<>();
46 | final List fragments = new ArrayList<>();
47 |
48 |
49 | final TabFlowAdapter adapter ;
50 |
51 |
52 | TabConfig config = new TabConfig.Builder()
53 | .setViewPager(mViewPager)
54 | .setTextId(R.id.item_text)
55 | .setDefaultPos(2)
56 | .setVisibleCount(4)
57 | .build();
58 |
59 | flowLayout.setAdapter(config,adapter = new TabFlowAdapter(R.layout.item_tab,titles) {
60 |
61 | @Override
62 | public void bindView(View view, String data, int position) {
63 | setDefaultText(view,data);
64 | }
65 | });
66 |
67 |
68 | HttpCreate.getServer().getTreeKnowledge()
69 | .subscribeOn(Schedulers.io())
70 | .observeOn(AndroidSchedulers.mainThread())
71 | .subscribeWith(new ResourceObserver>>() {
72 | @Override
73 | public void onNext(BaseResponse> baseResponse) {
74 | List data = baseResponse.getData();
75 | // 可以通过 page 获取不同的参数
76 | int page = 1;
77 | for (NaviChildrenBean child : data.get(page).getChildren()) {
78 | String title = child.getName().replaceAll("&","和");
79 | titles.add(title);
80 | fragments.add(RecyclerFragment.newInstance(child));
81 | }
82 | mViewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(),fragments));
83 | //刷新数据
84 | // adapter.notifyDataChanged();
85 | adapter.notifyDataChanged();
86 | }
87 |
88 | @Override
89 | public void onError(Throwable e) {
90 | Log.d(TAG, "zsr - onError: "+e);
91 | }
92 |
93 | @Override
94 | public void onComplete() {
95 |
96 | }
97 | });
98 |
99 |
100 |
101 |
102 | }
103 |
104 | public void test(View view) {
105 | recreate();
106 | }
107 |
108 | class ViewPagerAdapter extends FragmentPagerAdapter {
109 | List fragments;
110 | public ViewPagerAdapter(FragmentManager fm, List fragments) {
111 | super(fm);
112 | this.fragments = fragments;
113 | }
114 |
115 | @Override
116 | public Fragment getItem(int i) {
117 | return fragments.get(i);
118 | }
119 |
120 | @Override
121 | public int getCount() {
122 | return fragments.size();
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/bean/BaseResponse.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.bean;
2 |
3 | public class BaseResponse {
4 | //自行去定义
5 | public static final int SUCCESS = 0;
6 | private T data;
7 | private int errorCode;
8 | private String errorMsg;
9 |
10 | public T getData() {
11 | return data;
12 | }
13 |
14 | public int getErrorCode() {
15 | return errorCode;
16 | }
17 |
18 | public String getErrorMsg() {
19 | return errorMsg;
20 | }
21 |
22 | public void setData(T data) {
23 | this.data = data;
24 | }
25 |
26 | public void setErrorCode(int errorCode) {
27 | this.errorCode = errorCode;
28 | }
29 |
30 | public void setErrorMsg(String errorMsg) {
31 | this.errorMsg = errorMsg;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return "BaseResponse{" +
37 | "data=" + data +
38 | ", errorCode=" + errorCode +
39 | ", errorMsg='" + errorMsg + '\'' +
40 | '}';
41 | }
42 | }
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/bean/NaviChildrenBean.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.bean;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | /**
7 | * @author by zhengshaorui on 2019/10/8
8 | * Describe:
9 | */
10 | public class NaviChildrenBean implements Serializable {
11 | /**
12 | * children : []
13 | * courseId : 13
14 | * id : 60
15 | * name : Android Studio相关
16 | * order : 1000
17 | * parentChapterId : 150
18 | * userControlSetTop : false
19 | * visible : 1
20 | */
21 |
22 | private int courseId;
23 | private int id;
24 | private String name;
25 | private int order;
26 | private int parentChapterId;
27 | private boolean userControlSetTop;
28 | private int visible;
29 | private List> children;
30 |
31 | public int getCourseId() {
32 | return courseId;
33 | }
34 |
35 | public void setCourseId(int courseId) {
36 | this.courseId = courseId;
37 | }
38 |
39 | public int getId() {
40 | return id;
41 | }
42 |
43 | public void setId(int id) {
44 | this.id = id;
45 | }
46 |
47 | public String getName() {
48 | return name;
49 | }
50 |
51 | public void setName(String name) {
52 | this.name = name;
53 | }
54 |
55 | public int getOrder() {
56 | return order;
57 | }
58 |
59 | public void setOrder(int order) {
60 | this.order = order;
61 | }
62 |
63 | public int getParentChapterId() {
64 | return parentChapterId;
65 | }
66 |
67 | public void setParentChapterId(int parentChapterId) {
68 | this.parentChapterId = parentChapterId;
69 | }
70 |
71 | public boolean isUserControlSetTop() {
72 | return userControlSetTop;
73 | }
74 |
75 | public void setUserControlSetTop(boolean userControlSetTop) {
76 | this.userControlSetTop = userControlSetTop;
77 | }
78 |
79 | public int getVisible() {
80 | return visible;
81 | }
82 |
83 | public void setVisible(int visible) {
84 | this.visible = visible;
85 | }
86 |
87 | public List> getChildren() {
88 | return children;
89 | }
90 |
91 | public void setChildren(List> children) {
92 | this.children = children;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/bean/PageDataInfo.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.bean;
2 |
3 | /**
4 | * @author by zhengshaorui on 2019/10/8
5 | * Describe:
6 | */
7 | public class PageDataInfo {
8 | /**
9 | * curPage : 1
10 | * datas : []
11 | * offset : 0
12 | * over : false
13 | * pageCount : 377
14 | * size : 20
15 | * total : 7522
16 | */
17 | private int curPage;
18 | private int offset;
19 | private boolean over;
20 | private int pageCount;
21 | private int size;
22 | private int total;
23 | private T datas;
24 |
25 | public int getCurPage() {
26 | return curPage;
27 | }
28 |
29 | public void setCurPage(int curPage) {
30 | this.curPage = curPage;
31 | }
32 |
33 | public int getOffset() {
34 | return offset;
35 | }
36 |
37 | public void setOffset(int offset) {
38 | this.offset = offset;
39 | }
40 |
41 | public boolean isOver() {
42 | return over;
43 | }
44 |
45 | public void setOver(boolean over) {
46 | this.over = over;
47 | }
48 |
49 | public int getPageCount() {
50 | return pageCount;
51 | }
52 |
53 | public void setPageCount(int pageCount) {
54 | this.pageCount = pageCount;
55 | }
56 |
57 | public int getSize() {
58 | return size;
59 | }
60 |
61 | public void setSize(int size) {
62 | this.size = size;
63 | }
64 |
65 | public int getTotal() {
66 | return total;
67 | }
68 |
69 | public void setTotal(int total) {
70 | this.total = total;
71 | }
72 |
73 | public T getDatas() {
74 | return datas;
75 | }
76 |
77 | public void setDatas(T datas) {
78 | this.datas = datas;
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/bean/SystematicBean.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.bean;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | /**
7 | * @author by zhengshaorui on 2019/10/8
8 | * Describe:
9 | */
10 | public class SystematicBean implements Serializable {
11 |
12 | /**
13 | * children : [{"children":[],"courseId":13,"id":60,"name":"Android Studio相关","order":1000,"parentChapterId":150,"userControlSetTop":false,"visible":1},{"children":[],"courseId":13,"id":169,"name":"gradle","order":1001,"parentChapterId":150,"userControlSetTop":false,"visible":1},{"children":[],"courseId":13,"id":269,"name":"官方发布","order":1002,"parentChapterId":150,"userControlSetTop":false,"visible":1}]
14 | * courseId : 13
15 | * id : 150
16 | * name : 开发环境
17 | * order : 1
18 | * parentChapterId : 0
19 | * userControlSetTop : false
20 | * visible : 1
21 | */
22 |
23 | private int courseId;
24 | private int id;
25 | private String name;
26 | private int order;
27 | private int parentChapterId;
28 | private boolean userControlSetTop;
29 | private int visible;
30 | private List children;
31 | /**
32 | * 拿到所有child的字符
33 | */
34 | public String childAppendString;
35 |
36 | public int getCourseId() {
37 | return courseId;
38 | }
39 |
40 | public void setCourseId(int courseId) {
41 | this.courseId = courseId;
42 | }
43 |
44 | public int getId() {
45 | return id;
46 | }
47 |
48 | public void setId(int id) {
49 | this.id = id;
50 | }
51 |
52 | public String getName() {
53 | return name;
54 | }
55 |
56 | public void setName(String name) {
57 | this.name = name;
58 | }
59 |
60 | public int getOrder() {
61 | return order;
62 | }
63 |
64 | public void setOrder(int order) {
65 | this.order = order;
66 | }
67 |
68 | public int getParentChapterId() {
69 | return parentChapterId;
70 | }
71 |
72 | public void setParentChapterId(int parentChapterId) {
73 | this.parentChapterId = parentChapterId;
74 | }
75 |
76 | public boolean isUserControlSetTop() {
77 | return userControlSetTop;
78 | }
79 |
80 | public void setUserControlSetTop(boolean userControlSetTop) {
81 | this.userControlSetTop = userControlSetTop;
82 | }
83 |
84 | public int getVisible() {
85 | return visible;
86 | }
87 |
88 | public void setVisible(int visible) {
89 | this.visible = visible;
90 | }
91 |
92 | public List getChildren() {
93 | return children;
94 | }
95 |
96 | public void setChildren(List children) {
97 | this.children = children;
98 | }
99 |
100 |
101 | @Override
102 | public String toString() {
103 | return "SystematicBean{" +
104 | "courseId=" + courseId +
105 | ", id=" + id +
106 | ", name='" + name + '\'' +
107 | ", order=" + order +
108 | ", parentChapterId=" + parentChapterId +
109 | ", userControlSetTop=" + userControlSetTop +
110 | ", visible=" + visible +
111 | ", children=" + children +
112 | ", childAppendString='" + childAppendString + '\'' +
113 | '}';
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/fragment/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.annotation.Nullable;
10 |
11 | import me.yokeyword.fragmentation.SupportFragment;
12 |
13 | /**
14 | * @author by zhengshaorui 2022/2/26
15 | * describe:
16 | */
17 | public abstract class BaseFragment extends SupportFragment {
18 |
19 | @Nullable
20 | @Override
21 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
22 | View view;
23 | if (getLayoutId() != -1) {
24 | view = inflater.inflate(getLayoutId(), container, false);
25 | initView(view);
26 | }else{
27 | view = getContentView();
28 | }
29 | return view;
30 | }
31 |
32 | @Override
33 | public void onLazyInitView(@Nullable Bundle savedInstanceState) {
34 | super.onLazyInitView(savedInstanceState);
35 | initData();
36 | }
37 |
38 | protected void initData() {
39 | }
40 |
41 | ;
42 |
43 | protected void initView(View view) {
44 | }
45 |
46 |
47 |
48 | public View getContentView(){
49 | return null;
50 | }
51 | public int getLayoutId() {
52 | return -1;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/fragment/CusFragment.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.fragment;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.view.Gravity;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 |
11 | import androidx.annotation.Nullable;
12 | import androidx.fragment.app.Fragment;
13 |
14 | /**
15 | * Created by Administrator on 2017/11/10.
16 | */
17 |
18 | public class CusFragment extends BaseFragment {
19 |
20 | public static final String ARGUMENT = "argument";
21 | private String mTitle;
22 |
23 | @Override
24 | public View getContentView() {
25 | Bundle bundle = getArguments();
26 |
27 | TextView textView = new TextView(getActivity());
28 | if (bundle != null){
29 | textView.setText(bundle.getString(ARGUMENT));
30 | }else{
31 | textView.setText("nothing here");
32 | }
33 | textView.setTextSize(30);
34 | textView.setGravity(Gravity.CENTER);
35 | textView.setTextColor(Color.BLACK);
36 | return textView;
37 | }
38 |
39 |
40 |
41 | /**
42 | * 弄一个静态工厂的方法调用 用于传参
43 | * @param key
44 | * @return
45 | */
46 | public static CusFragment newInStance(String key){
47 | CusFragment fragment = new CusFragment();
48 | Bundle bundle = new Bundle();
49 | bundle.putString(ARGUMENT,key);
50 | fragment.setArguments(bundle);
51 | return fragment;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/fragment/RecyclerFragment.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.text.TextUtils;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.recyclerview.widget.LinearLayoutManager;
12 | import androidx.recyclerview.widget.RecyclerView;
13 |
14 | import com.chad.library.adapter.base.BaseQuickAdapter;
15 | import com.chad.library.adapter.base.viewholder.BaseViewHolder;
16 | import com.zhengsr.tabhelper.R;
17 | import com.zhengsr.tabhelper.bean.ArticleData;
18 | import com.zhengsr.tabhelper.bean.BaseResponse;
19 | import com.zhengsr.tabhelper.bean.NaviChildrenBean;
20 | import com.zhengsr.tabhelper.bean.PageDataInfo;
21 | import com.zhengsr.tabhelper.rx.HttpCreate;
22 | import com.zhengsr.tabhelper.utils.RxUtils;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | import io.reactivex.Observer;
28 | import io.reactivex.disposables.Disposable;
29 | import me.yokeyword.fragmentation.SupportFragment;
30 |
31 | /**
32 | * @author by zhengshaorui on 2019/10/8
33 | * Describe:
34 | */
35 | public class RecyclerFragment extends BaseFragment {
36 | private static final String TAG = "RecyclerFragment";
37 | private NaviChildrenBean mBean;
38 | private ArticleAdapter mAdapter;
39 | private List mArticleBeans = new ArrayList<>();
40 | public static RecyclerFragment newInstance(NaviChildrenBean bean) {
41 |
42 | Bundle args = new Bundle();
43 | args.putSerializable("bean",bean);
44 | RecyclerFragment fragment = new RecyclerFragment();
45 | fragment.setArguments(args);
46 | return fragment;
47 | }
48 |
49 | @Override
50 | public int getLayoutId() {
51 | return R.layout.recycler_layout;
52 | }
53 | @Override
54 | public void initView(View view) {
55 | Bundle arguments = getArguments();
56 | mBean = (NaviChildrenBean) arguments.getSerializable("bean");
57 |
58 | RecyclerView recyclerView = view.findViewById(R.id.recycler);
59 | LinearLayoutManager manager = new LinearLayoutManager(getContext());
60 | recyclerView.setLayoutManager(manager);
61 | mAdapter = new ArticleAdapter(R.layout.item_article_recy_layout, mArticleBeans);
62 | recyclerView.setAdapter(mAdapter);
63 |
64 |
65 |
66 |
67 | }
68 |
69 | @Override
70 | protected void initData() {
71 | super.initData();
72 | HttpCreate.getServer().getSystematicDetail(0,mBean.getId())
73 | .compose(RxUtils.>>>rxScheduers())
74 | .subscribe(new Observer>>>() {
75 | @Override
76 | public void onSubscribe(Disposable d) {
77 |
78 | }
79 |
80 | @Override
81 | public void onNext(BaseResponse>> pageDataInfoBaseResponse) {
82 | PageDataInfo> data = pageDataInfoBaseResponse.getData();
83 | List datas = data.getDatas();
84 | mAdapter.setNewData(datas);
85 | }
86 |
87 | @Override
88 | public void onError(Throwable e) {
89 |
90 | }
91 |
92 | @Override
93 | public void onComplete() {
94 |
95 | }
96 | });
97 | }
98 |
99 |
100 |
101 |
102 |
103 | public class ArticleAdapter extends BaseQuickAdapter {
104 |
105 | private boolean isCollected = false;
106 |
107 | public ArticleAdapter(int layoutResId, @Nullable List data) {
108 | super(layoutResId, data);
109 | }
110 |
111 | public void setCollected(boolean collected) {
112 | isCollected = collected;
113 | }
114 |
115 |
116 |
117 | @Override
118 | protected void convert(BaseViewHolder helper, ArticleData item) {
119 | String msg;
120 | if (!TextUtils.isEmpty(item.getSuperChapterName())){
121 | msg = item.getSuperChapterName()+"/"+item.getChapterName();
122 | }else{
123 | msg = item.getChapterName();
124 | }
125 | String author = (item.getAuthor() != null && item.getAuthor().length() > 0) ? item.getAuthor():item.getShareUser();
126 | helper.setText(R.id.item_article_author,author)
127 | .setText(R.id.item_article_chapat, msg)
128 | .setText(R.id.item_article_title,item.getTitle())
129 | .setText(R.id.item_article_time,item.getNiceDate());
130 |
131 | }
132 |
133 |
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/fragment/TestFragment.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import androidx.annotation.Nullable;
9 | import androidx.fragment.app.Fragment;
10 |
11 | import com.zhengsr.tabhelper.R;
12 | import com.zhengsr.tablib.view.adapter.TabFlowAdapter;
13 | import com.zhengsr.tablib.view.flow.TabFlowLayout;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.List;
18 |
19 | /**
20 | * Created by Administrator on 2017/11/10.
21 | */
22 |
23 | public class TestFragment extends BaseFragment {
24 |
25 | public static final String ARGUMENT = "argument";
26 | private List mTitle = new ArrayList<>(Arrays.asList("Life is like an ocean Only strong willed people can reach the other side".split(" ")));
27 |
28 |
29 | @Override
30 | public int getLayoutId() {
31 | return R.layout.test_fragment;
32 | }
33 |
34 | @Override
35 | protected void initView(View view) {
36 | super.initView(view);
37 | TabFlowLayout tabFlowLayout = view.findViewById(R.id.tabflow);
38 | tabFlowLayout.setAdapter(new TabFlowAdapter(R.layout.item_msg,mTitle) {
39 | @Override
40 | public void bindView(View view, String data, int position) {
41 | setDefaultText(view,data);
42 | }
43 |
44 |
45 | });
46 | }
47 |
48 | /**
49 | * 弄一个静态工厂的方法调用 用于传参
50 | * @return
51 | */
52 | public static TestFragment newInStance(){
53 | TestFragment fragment = new TestFragment();
54 | Bundle bundle = new Bundle();
55 | fragment.setArguments(bundle);
56 | return fragment;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/rx/HttpCreate.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.rx;
2 |
3 |
4 | import java.util.concurrent.TimeUnit;
5 |
6 | import okhttp3.OkHttpClient;
7 | import retrofit2.Retrofit;
8 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
9 | import retrofit2.converter.fastjson.FastJsonConverterFactory;
10 | import retrofit2.converter.scalars.ScalarsConverterFactory;
11 |
12 | /**
13 | * @author by zhengshaorui on 2019/10/9
14 | * Describe: 网络生成类
15 | */
16 | public class HttpCreate {
17 |
18 | public static HttpServerApi getServer(){
19 | Retrofit retrofit = new Retrofit.Builder()
20 | //这里采用这个,因为有多个baseurl
21 | .baseUrl("https://www.wanandroid.com/")
22 | //转字符串
23 | .addConverterFactory(ScalarsConverterFactory.create())
24 | //fastjson
25 | .addConverterFactory(FastJsonConverterFactory.create())
26 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
27 | .client(OkHttpHolder.BUILDER)
28 | .build();
29 | return retrofit.create(HttpServerApi.class);
30 | }
31 |
32 | /**
33 | * 配置okhttp3 client
34 | */
35 |
36 | private static class OkHttpHolder{
37 | static OkHttpClient BUILDER = new OkHttpClient.Builder()
38 | .connectTimeout(10, TimeUnit.SECONDS)
39 | .build();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/rx/HttpServerApi.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.rx;
2 |
3 |
4 | import com.zhengsr.tabhelper.bean.ArticleData;
5 | import com.zhengsr.tabhelper.bean.BaseResponse;
6 | import com.zhengsr.tabhelper.bean.NaviBean;
7 | import com.zhengsr.tabhelper.bean.PageDataInfo;
8 | import com.zhengsr.tabhelper.bean.SystematicBean;
9 |
10 | import java.util.List;
11 |
12 | import io.reactivex.Observable;
13 | import retrofit2.http.GET;
14 | import retrofit2.http.Path;
15 | import retrofit2.http.Query;
16 | import retrofit2.http.Url;
17 |
18 | /**
19 | * @author by zhengshaorui on 2019/10/9
20 | * Describe: 统一网络服务接口类
21 | */
22 | public interface HttpServerApi {
23 | @GET
24 | Observable getJson(@Url String url);
25 |
26 |
27 |
28 | /**
29 | * 获取体系
30 | * https://www.wanandroid.com/tree/json
31 | */
32 | @GET("tree/json")
33 | Observable>> getTreeKnowledge();
34 |
35 | /**
36 | * 获取系列的具体内容
37 | * https://www.wanandroid.com/article/list/0/json?cid=60
38 | *
39 | */
40 | @GET("article/list/{page}/json")
41 | Observable>>> getSystematicDetail(@Path("page") int page, @Query("cid") int cid);
42 |
43 |
44 |
45 |
46 | /**
47 | * https://www.wanandroid.com/navi/json
48 | * 获取导航数据
49 | */
50 | @GET("navi/json")
51 | Observable>> getNaviData();
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/appx/src/main/java/com/zhengsr/tabhelper/utils/RxUtils.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper.utils;
2 |
3 |
4 | import org.reactivestreams.Publisher;
5 |
6 | import io.reactivex.Flowable;
7 | import io.reactivex.FlowableTransformer;
8 | import io.reactivex.Observable;
9 | import io.reactivex.ObservableEmitter;
10 | import io.reactivex.ObservableOnSubscribe;
11 | import io.reactivex.ObservableSource;
12 | import io.reactivex.ObservableTransformer;
13 | import io.reactivex.android.schedulers.AndroidSchedulers;
14 | import io.reactivex.schedulers.Schedulers;
15 |
16 | /**
17 | * @author by zhengshaorui on 2019/10/9
18 | * Describe:
19 | */
20 | public class RxUtils {
21 | /**
22 | * 封装线程调度
23 | * @param
24 | * @return
25 | */
26 | public static ObservableTransformer rxScheduers(){
27 | return new ObservableTransformer(){
28 |
29 | @Override
30 | public ObservableSource apply(Observable upstream) {
31 | return upstream.subscribeOn(Schedulers.io())
32 | .observeOn(AndroidSchedulers.mainThread());
33 | }
34 | };
35 | }
36 |
37 |
38 | public static FlowableTransformer flScheduers(){
39 | return new FlowableTransformer() {
40 | @Override
41 | public Publisher apply(Flowable upstream) {
42 | return upstream.subscribeOn(Schedulers.io())
43 | .observeOn(AndroidSchedulers.mainThread());
44 | }
45 | };
46 | }
47 |
48 |
49 |
50 |
51 | /**
52 | * 得到 Observable
53 | * @param 指定的泛型类型
54 | * @return Observable
55 | */
56 | private static Observable createData(final T t) {
57 | return Observable.create(new ObservableOnSubscribe() {
58 | @Override
59 | public void subscribe(ObservableEmitter emitter) throws Exception {
60 | emitter.onNext(t);
61 | emitter.onComplete();
62 | }
63 | });
64 | }
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/appx/src/main/res/color/color_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/select_tag.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_red_radius.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_round_ff.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_round_trans.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_search_select.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/appx/src/main/res/drawable/shape_showmore.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_count.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
30 |
31 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_label.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
17 |
25 |
26 |
32 |
33 |
38 |
39 |
46 |
47 |
54 |
55 |
56 |
63 |
64 |
71 |
72 |
80 |
81 |
89 |
90 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_label_show_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
19 |
20 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
24 |
25 |
31 |
32 |
38 |
39 |
45 |
46 |
52 |
53 |
59 |
60 |
66 |
67 |
68 |
69 |
70 |
71 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_net_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
28 |
29 |
30 |
31 |
38 |
39 |
40 |
46 |
47 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
20 |
37 |
45 |
55 |
63 |
64 |
76 |
84 |
85 |
99 |
100 |
108 |
114 |
115 |
123 |
124 |
134 |
135 |
143 |
144 |
157 |
158 |
159 |
165 |
166 |
167 |
168 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_tab_no_view_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
40 |
41 |
60 |
61 |
80 |
81 |
99 |
100 |
112 |
113 |
135 |
136 |
137 |
138 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/activity_vertical_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
26 |
27 |
35 |
36 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/handup.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
15 |
16 |
22 |
23 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_article_recy_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
34 |
35 |
52 |
53 |
66 |
67 |
83 |
84 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_color_msg.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
26 |
27 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_msg.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
24 |
25 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_navi_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
31 |
32 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_search_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
24 |
25 |
39 |
40 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_tab_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_text_width_match.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_textview.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/item_textview_navi.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/recycler_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/show_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
15 |
16 |
22 |
23 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/tab_text_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
--------------------------------------------------------------------------------
/appx/src/main/res/layout/test_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
21 |
22 |
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xhdpi/bg_man.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xhdpi/bg_man.jpg
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xhdpi/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xhdpi/delete.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xhdpi/handup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xhdpi/handup.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xhdpi/more.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xhdpi/more.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/appx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/appx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/appx/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 | #ffffff
7 | #b0f1ffff
8 | #b01a1a1a
9 | #000000
10 | #323232
11 | #15000000
12 |
13 |
--------------------------------------------------------------------------------
/appx/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TabHelper
3 |
4 |
--------------------------------------------------------------------------------
/appx/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/appx/src/test/java/com/zhengsr/tabhelper/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tabhelper;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | kotlin_version = '1.3.72'
6 | }
7 | repositories {
8 | jcenter()
9 | google()
10 |
11 | }
12 | dependencies {
13 | classpath 'com.android.tools.build:gradle:4.0.0'
14 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | jcenter()
24 | google()
25 | maven { url 'https://jitpack.io' }
26 |
27 | }
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/gif/alipay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/alipay.jpg
--------------------------------------------------------------------------------
/gif/label.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/label.gif
--------------------------------------------------------------------------------
/gif/label_showmore.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/label_showmore.gif
--------------------------------------------------------------------------------
/gif/tab_click.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/tab_click.gif
--------------------------------------------------------------------------------
/gif/tab_vertical.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/tab_vertical.gif
--------------------------------------------------------------------------------
/gif/tab_viewpager.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/tab_viewpager.gif
--------------------------------------------------------------------------------
/gif/tab_visual_count.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/tab_visual_count.png
--------------------------------------------------------------------------------
/gif/wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gif/wechat.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 | android.useAndroidX=true
16 | # Automatically convert third-party libraries to use AndroidX
17 | android.enableJetifier=false
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jan 02 11:41:40 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-6.5-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':appx'
2 | include ':tablibx'
3 | rootProject.name='TabHelper'
4 |
--------------------------------------------------------------------------------
/tablibx/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/tablibx/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | group='com.github.LillteZheng'
4 | android {
5 | compileSdkVersion 29
6 |
7 | defaultConfig {
8 | minSdkVersion 19
9 | targetSdkVersion 29
10 | versionCode 2
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | consumerProguardFiles "consumer-rules.pro"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: "libs", include: ["*.jar"])
27 | implementation 'androidx.appcompat:appcompat:1.2.0'
28 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
29 | testImplementation 'junit:junit:4.12'
30 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
32 | compileOnly 'androidx.viewpager2:viewpager2:1.0.0'
33 |
34 | }
--------------------------------------------------------------------------------
/tablibx/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LillteZheng/FlowHelper/812eef08f33fe5948412115f20f5e5f402a5f4e5/tablibx/consumer-rules.pro
--------------------------------------------------------------------------------
/tablibx/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
--------------------------------------------------------------------------------
/tablibx/src/androidTest/java/com/zhengsr/tablib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 | assertEquals("com.exceedshare.tablibx.test", appContext.getPackageName());
24 | }
25 | }
--------------------------------------------------------------------------------
/tablibx/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 | /
5 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/FlowConstants.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib;
2 |
3 | /**
4 | * @author by zhengshaorui on 2019/10/8
5 | * Describe:
6 | */
7 | public class FlowConstants {
8 | /**
9 | * 矩形
10 | */
11 | public static final int RECT = 0;
12 | /**
13 | * 三角形
14 | */
15 | public static final int TRI = 1;
16 | /**
17 | * 圆角
18 | */
19 | public static final int ROUND = 2;
20 | /**
21 | * 颜色
22 | */
23 | public static final int COLOR = 3;
24 | /**
25 | * 资源
26 | */
27 | public static final int RES = 4;
28 |
29 | /**
30 | * 竖向
31 | */
32 | public static final int VERTICAL = 1;
33 | /**
34 | * 横向
35 | */
36 | public static final int HORIZONTATAL = 2;
37 |
38 | /**
39 | * 左边
40 | */
41 | public static final int LEFT = 1;
42 | /**
43 | * 右边
44 | */
45 | public static final int RIGHT = 2;
46 | /**
47 | * 普通类型的 textview
48 | */
49 | public static final int NORMALTEXT = 1;
50 | /**
51 | * {@link com.zhengsr.tablib.view.TabColorTextView}
52 | */
53 | public static final int COLORTEXT = 2;
54 |
55 | public static final int COLOR_ILLEGAL = -2;
56 | }
57 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/BaseLabelItem.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | /**
4 | * @author by zhengshaorui 2023/3/29
5 | * describe:Label
6 | */
7 | public class BaseLabelItem {
8 | public boolean isHeader;
9 | }
10 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/LabelBean.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | import com.zhengsr.tablib.FlowConstants;
4 |
5 | /**
6 | * @auther by zhengshaorui on 2020/2/1
7 | * describe:
8 | */
9 | public class LabelBean {
10 |
11 | /**
12 | * 多选最大个数
13 | */
14 | public int maxSelectCount =1;
15 | /**
16 | * 是否超过控件高度,自动滚动,默认为true
17 | */
18 | public boolean isAutoScroll = true;
19 | /**
20 | * 支持最多显示的行数,默认显示全部
21 | */
22 | public int showLines = -1;
23 |
24 | /**
25 | * 显示更多的layoutId
26 | */
27 | public int showMoreLayoutId = -1;
28 |
29 | /**
30 | * 显示更多的背景色,建议与主布局的背景色一直
31 | */
32 | public int showMoreColor = FlowConstants.COLOR_ILLEGAL;
33 |
34 | /**
35 | * 收起的 layoutId
36 | */
37 | public int handUpLayoutId = -1;
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/TabBean.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | import androidx.annotation.ColorInt;
4 | import androidx.annotation.ColorRes;
5 |
6 | import com.zhengsr.tablib.FlowConstants;
7 |
8 | /**
9 | * @auther by zhengshaorui on 2020/1/9
10 | * describe: 用来配置tab的bean
11 | */
12 | public class TabBean {
13 | /**
14 | * tab 类型,rect、tri、round、res、color、cus
15 | */
16 | public int tabType = -1;
17 | /**
18 | * tab 的颜色
19 | */
20 | public int tabColor = FlowConstants.COLOR_ILLEGAL;
21 | /**
22 | * tab 的宽度
23 | */
24 | public int tabWidth = -1;
25 | /**
26 | * tab 的高度
27 | */
28 | public int tabHeight = -1;
29 | /**
30 | * type选择 round 时的圆角大小
31 | */
32 | public int tabRoundSize = -1;
33 | /**
34 | * margin 的左上右下
35 | */
36 | public int tabMarginLeft = -1;
37 | public int tabMarginTop = -1;
38 | public int tabMarginRight = -1;
39 | public int tabMarginBottom = -1;
40 | /**
41 | * 点击的切换速度,当没有viewpager 时,相当于滑动速度
42 | */
43 | public int tabClickAnimTime = -1;
44 | /**
45 | * type 为 res时,你要关联的resouce,比如 bitmap、shape等
46 | */
47 | public int tabItemRes = -1;
48 |
49 | /**
50 | * 是否自动放大缩小的效果
51 | */
52 | public boolean autoScale = false;
53 |
54 | /**
55 | * 放大倍数
56 | */
57 | public float scaleFactor = 1;
58 |
59 | /**
60 | * TabFlow 的方向, FlowConstants.VERTICAL 竖向,FlowConstants.HORIZONTAL 横向
61 | */
62 | public int tabOrientation = FlowConstants.HORIZONTATAL;
63 |
64 | /**
65 | * tab 为 rect 或者 tri 的时候,左边还是在右边,也使用 flowConstants
66 | */
67 | public int actionOrientation = -1;
68 |
69 | /**
70 | * 是否自动滚动
71 | */
72 | public boolean isAutoScroll = true;
73 |
74 | /**
75 | * 可视个数
76 | */
77 | public int visualCount = -1;
78 |
79 |
80 | /**
81 | * tab 的宽度是否跟随text的宽度大小,只对 rect 有用
82 | */
83 | public boolean tabWidthEqualsText = true;
84 |
85 | /**
86 | * tab 默认的textview,normal 或者 color
87 | */
88 | public int textType = 1;
89 |
90 | /**
91 | * textview 的颜色值
92 | */
93 | @ColorInt
94 | public int selectedColor = FlowConstants.COLOR_ILLEGAL;
95 | @ColorInt
96 | public int unSelectedColor = FlowConstants.COLOR_ILLEGAL;
97 |
98 | @Override
99 | public String toString() {
100 | return "TabBean{" +
101 | "tabType=" + tabType +
102 | ", tabColor=" + tabColor +
103 | ", tabWidth=" + tabWidth +
104 | ", tabHeight=" + tabHeight +
105 | ", tabRoundSize=" + tabRoundSize +
106 | ", tabMarginLeft=" + tabMarginLeft +
107 | ", tabMarginTop=" + tabMarginTop +
108 | ", tabMarginRight=" + tabMarginRight +
109 | ", tabMarginBottom=" + tabMarginBottom +
110 | ", tabClickAnimTime=" + tabClickAnimTime +
111 | ", tabItemRes=" + tabItemRes +
112 | ", autoScale=" + autoScale +
113 | ", scaleFactor=" + scaleFactor +
114 | ", tabOrientation=" + tabOrientation +
115 | ", actionOrientation=" + actionOrientation +
116 | ", isAutoScroll=" + isAutoScroll +
117 | ", visualCount=" + visualCount +
118 | ", tabWidthEqualsText=" + tabWidthEqualsText +
119 | ", textType=" + textType +
120 | '}';
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/TabConfig.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | import android.graphics.Rect;
4 | import android.widget.TextView;
5 |
6 | import androidx.annotation.ColorInt;
7 | import androidx.annotation.IdRes;
8 | import androidx.viewpager.widget.ViewPager;
9 | import androidx.viewpager2.widget.ViewPager2;
10 |
11 | import com.zhengsr.tablib.FlowConstants;
12 | import com.zhengsr.tablib.view.TabColorTextView;
13 |
14 | /**
15 | * @author by zhengshaorui 2021/5/21 08:53
16 | * describe:TabFlowLayout 配置类
17 | */
18 | public class TabConfig {
19 | private Builder builder;
20 | private TabConfig(Builder builder){
21 | this.builder = builder;
22 | }
23 |
24 | public int getTextId() {
25 | return builder.textId;
26 | }
27 |
28 | public ViewPager2 getViewPager2() {
29 | return builder.viewpager2;
30 | }
31 |
32 | public int getUnSelectColor() {
33 | return builder.unSelectColor;
34 | }
35 |
36 | public int getDefaultPos() {
37 | return builder.defaultPos;
38 | }
39 |
40 | public int getSelectedColor() {
41 | return builder.selectedColor;
42 | }
43 |
44 | public ViewPager getViewPager() {
45 | return builder.viewPager;
46 | }
47 |
48 | public int getVisibleCount() {
49 | return builder.visibleCount;
50 | }
51 |
52 | public TextConfig getTextConfig(){
53 | return builder.textConfig;
54 | }
55 |
56 | public Builder getBuilder() {
57 | return builder;
58 | }
59 |
60 | public boolean isUseColorText(){
61 | return builder.useColorText;
62 | }
63 | @Override
64 | public String toString() {
65 | return "TabConfig{" +
66 | "builder=" + builder.toString() +
67 | '}';
68 | }
69 |
70 | public static class Builder{
71 | private int textId = -1;
72 | private int unSelectColor = FlowConstants.COLOR_ILLEGAL;
73 | private int defaultPos;
74 | private int selectedColor = FlowConstants.COLOR_ILLEGAL;
75 | private ViewPager viewPager;
76 | private ViewPager2 viewpager2;
77 | private int visibleCount=-1;
78 | private boolean useColorText;
79 | private TextConfig textConfig;
80 | public Builder setViewPager(ViewPager viewPager){
81 | this.viewPager = viewPager;
82 | return this;
83 | }
84 |
85 |
86 | public Builder setViewpager(ViewPager2 viewpager2){
87 | this. viewpager2 = viewpager2;
88 | return this;
89 | }
90 |
91 | public Builder setDefaultPos(int defaultPos){
92 | this.defaultPos = defaultPos;
93 | return this;
94 | }
95 |
96 | /**
97 | * 若设置了layout,不设置id,不会有颜色变化
98 | * @param textId TextView 的id
99 | */
100 | public Builder setTextId(@IdRes int textId){
101 | this.textId = textId;
102 | return this;
103 | }
104 |
105 | public Builder setSelectedColor(@ColorInt int selectedColor){
106 | this.selectedColor = selectedColor;
107 | return this;
108 | }
109 | public Builder setUnSelectColor(@ColorInt int unSelectColor){
110 | this.unSelectColor = unSelectColor;
111 | return this;
112 | }
113 |
114 | /**
115 | * 可见可数
116 | */
117 | public Builder setVisibleCount(int visibleCount){
118 | this.visibleCount = visibleCount;
119 | return this;
120 | }
121 |
122 |
123 | /**
124 | * 不设置 layout ,默认 TextView 的大小
125 | * @param type {@link FlowConstants#NORMALTEXT} 或者 {@link FlowConstants#COLORTEXT}
126 | * @return
127 | */
128 | public Builder setDefaultTextType(int type) {
129 | useColorText = type == FlowConstants.COLORTEXT;
130 | return this;
131 | }
132 |
133 | /**
134 | * 设置 TextView 的通用属性
135 | * @param config
136 | * @return
137 | */
138 | public Builder setTextConfig(TextConfig config) {
139 | this.textConfig = config;
140 | return this;
141 | }
142 |
143 |
144 | public TabConfig build(){
145 | //判断参数
146 | if (viewpager2 != null && viewPager != null){
147 | throw new IllegalArgumentException("you cannot set ViewPager and ViewPager2");
148 | }
149 |
150 | return new TabConfig(this);
151 | }
152 |
153 | @Override
154 | public String toString() {
155 | return "Builder{" +
156 | "textId=" + textId +
157 | ", unSelectColor=" + unSelectColor +
158 | ", defaultPos=" + defaultPos +
159 | ", selectedColor=" + selectedColor +
160 | ", viewPager=" + viewPager +
161 | ", viewpager2=" + viewpager2 +
162 | ", visibleCount=" + visibleCount +
163 | '}';
164 | }
165 | }
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/TabTypeEvaluator.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | import android.animation.TypeEvaluator;
4 |
5 | /**
6 | * 自定义 TypeEvaluator
7 | */
8 | public class TabTypeEvaluator implements TypeEvaluator {
9 | // PointF pointF = new PointF();
10 | TabValue value = new TabValue();
11 |
12 | @Override
13 | public TabValue evaluate(float fraction, TabValue startValue, TabValue endValue) {
14 | //这里都采用匀速
15 | value.left = startValue.left + fraction * (endValue.left - startValue.left);
16 | value.top = startValue.top + fraction * (endValue.top - startValue.top);
17 | value.bottom = startValue.bottom + fraction * (endValue.bottom - startValue.bottom);
18 | value.right = startValue.right + fraction * (endValue.right - startValue.right);
19 | return value;
20 | }
21 | }
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/TabValue.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | import android.graphics.RectF;
4 |
5 | public class TabValue {
6 | public float left;
7 | public float top;
8 | public float right;
9 | public float bottom;
10 |
11 | public TabValue(float left, float right) {
12 | this.left = left;
13 | this.right = right;
14 | }
15 |
16 | public TabValue() {
17 | }
18 | public float width(){
19 | return right - left;
20 | }
21 |
22 | @Override
23 | public String toString() {
24 | return "TabValue{" +
25 | "left=" + left +
26 | ", top=" + top +
27 | ", right=" + right +
28 | ", bottom=" + bottom +
29 | '}';
30 | }
31 |
32 | public RectF valueToRect(){
33 | return new RectF(left,top,right,bottom);
34 | }
35 |
36 | public TabValue rectToValue(RectF rectF){
37 | left = rectF.left;
38 | top = rectF.top;
39 | right = rectF.right;
40 | bottom = rectF.bottom;
41 | return this;
42 | }
43 | }
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/bean/TextConfig.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.bean;
2 |
3 | import android.graphics.Rect;
4 | import android.graphics.Typeface;
5 |
6 | import androidx.annotation.ColorInt;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * @author by zhengshaorui 2022/3/1
13 | * describe:用于配置 TextView 相关的一些属性
14 | */
15 | public class TextConfig {
16 | private Rect rect;
17 | private List list;
18 | private float size = 0;
19 | public TextConfig setPadding(int l,int t,int r,int b){
20 | if (rect == null) {
21 | rect = new Rect();
22 | }
23 | rect.set(l,t,r,b);
24 | return this;
25 | }
26 | public TextConfig setTypeface(Typeface tf){
27 | if (list == null) {
28 | list = new ArrayList<>();
29 | }
30 | list.add(tf);
31 | return this;
32 | }
33 | public TextConfig setTextSize(float size){
34 | this.size = size;
35 | return this;
36 | }
37 |
38 |
39 | public Rect getPadding() {
40 | return rect;
41 | }
42 |
43 | public List getTypefaces() {
44 | return list;
45 | }
46 |
47 | public float getTextSize() {
48 | return size;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/callback/FlowListener.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.callback;
2 |
3 | /**
4 | * @author by zhengshaorui on 2019/10/8
5 | * Describe:
6 | */
7 | public interface FlowListener {
8 | void notifyDataChanged();
9 | void resetAllTextColor(int viewId, int color);
10 | void pagerClickChangeColor(int viewId, int unSelectedColor, int selectedColor);
11 | }
12 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/callback/FlowListenerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.callback;
2 |
3 | /**
4 | * @author by zhengshaorui on 2019/10/8
5 | * Describe:
6 | */
7 | public abstract class FlowListenerAdapter {
8 |
9 | public abstract void notifyDataChanged();
10 |
11 | public void resetAllTextColor(int viewId,int color) { }
12 |
13 | public abstract void resetAllStatus();
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/utils/AttrsUtils.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.utils;
2 |
3 | import android.content.res.TypedArray;
4 | import android.graphics.Color;
5 |
6 | import com.zhengsr.tablib.FlowConstants;
7 | import com.zhengsr.tablib.R;
8 | import com.zhengsr.tablib.bean.TabBean;
9 |
10 | /**
11 | * @author by zhengshaorui 2020/8/29 11:17
12 | * describe:自定义属性转换类
13 | */
14 | public class AttrsUtils {
15 | private static final String TAG = "AttrsUtils";
16 | /**
17 | * 获取TabBean的自定义数据
18 | * @param ta
19 | * @return
20 | */
21 |
22 | public static TabBean getTabBean(TypedArray ta){
23 | TabBean bean = new TabBean();
24 |
25 | bean.tabType = ta.getInteger(R.styleable.AbsFlowLayout_tab_type, -1);
26 | bean.tabColor = ta.getColor(R.styleable.AbsFlowLayout_tab_color, FlowConstants.COLOR_ILLEGAL);
27 | bean.tabWidth = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_width, -1);
28 | bean.tabHeight = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_height, -1);
29 |
30 | bean.tabRoundSize = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_round_size,-1);
31 |
32 | bean.tabMarginLeft = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_margin_l, 0);
33 | bean.tabMarginTop = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_margin_t, 0);
34 | bean.tabMarginRight = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_margin_r, 0);
35 | bean.tabMarginBottom = ta.getDimensionPixelSize(R.styleable.AbsFlowLayout_tab_margin_b, 0);
36 |
37 | bean.tabItemRes = ta.getResourceId(R.styleable.AbsFlowLayout_tab_item_res,-1);
38 | bean.tabClickAnimTime = ta.getInt(R.styleable.AbsFlowLayout_tab_click_animTime, 300);
39 | bean.autoScale = ta.getBoolean(R.styleable.AbsFlowLayout_tab_item_autoScale, false);
40 | bean.scaleFactor = ta.getFloat(R.styleable.AbsFlowLayout_tab_scale_factor, 1);
41 |
42 | bean.tabOrientation = ta.getInteger(R.styleable.AbsFlowLayout_tab_orientation, FlowConstants.HORIZONTATAL);
43 | bean.actionOrientation = ta.getInteger(R.styleable.AbsFlowLayout_tab_action_orientaion,-1);
44 | bean.isAutoScroll = ta.getBoolean(R.styleable.AbsFlowLayout_tab_isAutoScroll, true);
45 | bean.visualCount = ta.getInteger(R.styleable.AbsFlowLayout_tab_visual_count, -1);
46 | bean.tabWidthEqualsText = ta.getBoolean(R.styleable.AbsFlowLayout_tab_width_equals_text,true);
47 | bean.textType = ta.getInteger(R.styleable.AbsFlowLayout_tab_default_textType,1);
48 | bean.selectedColor = ta.getInteger(R.styleable.AbsFlowLayout_tab_text_select_color,FlowConstants.COLOR_ILLEGAL);
49 | bean.unSelectedColor = ta.getInteger(R.styleable.AbsFlowLayout_tab_text_unselect_color,FlowConstants.COLOR_ILLEGAL);
50 | return bean;
51 | }
52 |
53 |
54 | /**
55 | * 对比数据,xml的数据会被用户的覆盖
56 | * @param xmlBean
57 | * @param userBean
58 | * @return
59 | */
60 | public static TabBean diffTabBean(TabBean xmlBean,TabBean userBean){
61 | //todo 是有有工具帮忙优化?
62 | if (userBean.tabType != -1){
63 | xmlBean.tabType = userBean.tabType;
64 | }
65 | if (userBean.tabColor != FlowConstants.COLOR_ILLEGAL){
66 | xmlBean.tabColor = userBean.tabColor;
67 | }
68 | if (userBean.tabWidth != -1){
69 | xmlBean.tabWidth = userBean.tabWidth;
70 | }
71 |
72 | if (userBean.tabHeight != -1){
73 | xmlBean.tabHeight = userBean.tabHeight;
74 | }
75 |
76 | if (userBean.tabRoundSize != -1){
77 | xmlBean.tabRoundSize = userBean.tabRoundSize;
78 | }
79 | if (userBean.tabMarginLeft != -1){
80 | xmlBean.tabMarginLeft = userBean.tabMarginLeft;
81 | }
82 | if (userBean.tabMarginTop != -1){
83 | xmlBean.tabMarginTop = userBean.tabMarginTop;
84 | }
85 | if (userBean.tabMarginRight != -1){
86 | xmlBean.tabMarginRight = userBean.tabMarginRight;
87 | }
88 | if (userBean.tabMarginBottom != -1){
89 | xmlBean.tabMarginBottom = userBean.tabMarginBottom;
90 | }
91 |
92 |
93 | if (userBean.tabClickAnimTime != -1){
94 | xmlBean.tabClickAnimTime = userBean.tabClickAnimTime;
95 | }
96 | if (userBean.tabItemRes != -1){
97 | xmlBean.tabItemRes = userBean.tabItemRes;
98 | }
99 | if (userBean.autoScale){
100 | xmlBean.autoScale = true;
101 | }
102 |
103 | if (userBean.scaleFactor != 1){
104 | xmlBean.scaleFactor = userBean.scaleFactor;
105 | }
106 | if (userBean.tabOrientation != FlowConstants.HORIZONTATAL){
107 | xmlBean.tabOrientation = userBean.tabOrientation;
108 | }
109 | if (userBean.actionOrientation != -1){
110 | xmlBean.actionOrientation = userBean.actionOrientation;
111 | }
112 |
113 | if (!userBean.isAutoScroll){
114 | xmlBean.isAutoScroll = false;
115 | }
116 |
117 | if (userBean.visualCount != -1){
118 | xmlBean.visualCount = userBean.visualCount;
119 | }
120 |
121 | if (userBean.unSelectedColor != FlowConstants.COLOR_ILLEGAL) {
122 | xmlBean.unSelectedColor = userBean.unSelectedColor;
123 | }
124 |
125 | if (userBean.selectedColor != FlowConstants.COLOR_ILLEGAL) {
126 | xmlBean.selectedColor = userBean.selectedColor;
127 | }
128 |
129 | if (userBean.textType != FlowConstants.NORMALTEXT) {
130 | xmlBean.textType = userBean.textType;
131 | }
132 | return xmlBean;
133 | }
134 |
135 |
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/utils/DisplayUtil.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.utils;
2 |
3 | import android.content.Context;
4 |
5 | public class DisplayUtil {
6 |
7 | /**
8 | * px传dp,dip,保证尺寸大小不变
9 | * @param context
10 | * @param pxValue
11 | * @return
12 | */
13 | public static int px2dip(Context context, float pxValue){
14 | final float scale = context.getResources().getDisplayMetrics().density;
15 | return (int)(pxValue/scale+0.5f);
16 | }
17 |
18 | /**
19 | * dip,dp传px,保证尺寸大小不变
20 | * @param context
21 | * @param dipValue
22 | * @return
23 | */
24 | public static int dip2px(Context context,float dipValue){
25 | final float scale = context.getResources().getDisplayMetrics().density;
26 | return (int)(dipValue*scale+0.5f);
27 | }
28 |
29 | /**
30 | * px转sp,保证文字大小不变
31 | * @param context
32 | * @param pxValue
33 | * @return
34 | */
35 | public static int px2sp(Context context,float pxValue){
36 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
37 | return (int)(pxValue/fontScale + 0.5f);
38 | }
39 |
40 | /**
41 | * sp转px,保证文字大小不变
42 | * @param context
43 | * @param spValue
44 | * @return
45 | */
46 | public static int sp2px(Context context,float spValue){
47 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
48 | return (int)(spValue*fontScale + 0.5f);
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/utils/ViewPagerHelperUtils.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.utils;
2 |
3 | import android.content.Context;
4 | import android.widget.Scroller;
5 |
6 | import androidx.recyclerview.widget.LinearLayoutManager;
7 | import androidx.recyclerview.widget.LinearSmoothScroller;
8 | import androidx.recyclerview.widget.RecyclerView;
9 | import androidx.viewpager.widget.ViewPager;
10 | import androidx.viewpager2.widget.ViewPager2;
11 |
12 | import java.lang.reflect.Field;
13 |
14 | /**
15 | * Created by zhengshaorui on 2017/11/5.
16 | * csdn: http://blog.csdn.net/u011418943
17 | */
18 |
19 | public class ViewPagerHelperUtils {
20 | public static final int LOOP_COUNT = 5000;
21 | public static final int LOOP_TAIL_MODE = 0x1001;
22 |
23 | public static final int LOOP_MODE = 0x1002;
24 | public static final int GLIDE_MODE = 0x1002;
25 |
26 | public static final int VIEWPAGER_DATA_URL = 0x2002;
27 | public static final int VIEWPAGER_DATA_RES = 0x2003;
28 | public static final int VIEWPAGER_DATA_VIEW = 0x2004;
29 |
30 |
31 |
32 | /**
33 | * 设置viewpager 之间的切换速度
34 | */
35 | public static void initSwitchTime(Context context, ViewPager viewPager, int time){
36 | try {
37 | Field field = ViewPager.class.getDeclaredField("mScroller");
38 | field.setAccessible(true);
39 | field.set(viewPager,new ViewPagerScroller(context,time));
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | }
43 | }
44 |
45 | static class ViewPagerScroller extends Scroller {
46 | int time;
47 | public ViewPagerScroller(Context context, int time) {
48 | super(context);
49 | this.time = time;
50 | }
51 |
52 | /*@Override
53 | public void startScroll(int startX, int startY, int dx, int dy) {
54 | super.startScroll(startX, startY, dx, time);
55 | }
56 | */
57 | @Override
58 | public void startScroll(int startX, int startY, int dx, int dy, int duration) {
59 | super.startScroll(startX, startY, dx, dy, time);
60 | }
61 | }
62 |
63 |
64 | public static void initSwitchTime(Context context, ViewPager2 viewPager2, int time) {
65 | try {
66 | //控制切换速度,采用反射方。法方法只会调用一次,替换掉内部的RecyclerView的LinearLayoutManager
67 | RecyclerView recyclerView = (RecyclerView) viewPager2.getChildAt(0);
68 | recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
69 | ProxyLayoutManger proxyLayoutManger = new ProxyLayoutManger(context, viewPager2.getOrientation(),time);
70 | recyclerView.setLayoutManager(proxyLayoutManger);
71 |
72 | Field LayoutMangerField = ViewPager2.class.getDeclaredField("mLayoutManager");
73 | LayoutMangerField.setAccessible(true);
74 | LayoutMangerField.set(viewPager2, proxyLayoutManger);
75 |
76 | Field pageTransformerAdapterField = ViewPager2.class.getDeclaredField("mPageTransformerAdapter");
77 | pageTransformerAdapterField.setAccessible(true);
78 | Object mPageTransformerAdapter = pageTransformerAdapterField.get(viewPager2);
79 | if (mPageTransformerAdapter != null) {
80 | Class> aClass = mPageTransformerAdapter.getClass();
81 | Field layoutManager = aClass.getDeclaredField("mLayoutManager");
82 | layoutManager.setAccessible(true);
83 | layoutManager.set(mPageTransformerAdapter, proxyLayoutManger);
84 | }
85 | Field scrollEventAdapterField = ViewPager2.class.getDeclaredField("mScrollEventAdapter");
86 | scrollEventAdapterField.setAccessible(true);
87 | Object mScrollEventAdapter = scrollEventAdapterField.get(viewPager2);
88 | if (mScrollEventAdapter != null) {
89 | Class> aClass = mScrollEventAdapter.getClass();
90 | Field layoutManager = aClass.getDeclaredField("mLayoutManager");
91 | layoutManager.setAccessible(true);
92 | layoutManager.set(mScrollEventAdapter, proxyLayoutManger);
93 | }
94 | } catch (NoSuchFieldException e) {
95 | e.printStackTrace();
96 | } catch (IllegalAccessException e) {
97 | e.printStackTrace();
98 | }
99 | }
100 |
101 | private static class ProxyLayoutManger extends LinearLayoutManager {
102 |
103 | int time;
104 | ProxyLayoutManger(Context context, int orientation,int time) {
105 | super(context, orientation, false);
106 | this.time = time;
107 | }
108 |
109 | @Override
110 | public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
111 | LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
112 | @Override
113 | protected int calculateTimeForDeceleration(int dx) {
114 | return (int) (time * (1 - .3356));
115 | }
116 | };
117 | linearSmoothScroller.setTargetPosition(position);
118 | startSmoothScroll(linearSmoothScroller);
119 | }
120 | }
121 |
122 | public static int getViewPageClickItem(ViewPager viewPager){
123 | if (viewPager != null) {
124 | try {
125 | Class> zClass = viewPager.getClass();
126 | Field mCurItem = zClass.getDeclaredField("mCurItem");
127 | mCurItem.setAccessible(true);
128 | return mCurItem.getInt(viewPager);
129 | } catch (Exception e) {
130 | e.printStackTrace();
131 | }
132 | }
133 | return 0;
134 | }
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/TabColorTextView.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Typeface;
9 | import android.util.AttributeSet;
10 | import android.util.Log;
11 | import android.view.Gravity;
12 |
13 | import androidx.annotation.NonNull;
14 | import androidx.appcompat.widget.AppCompatTextView;
15 |
16 | import com.zhengsr.tablib.R;
17 |
18 |
19 | /**
20 | * @author by zhengshaorui on 2019/10/8
21 | * csdn: http://blog.csdn.net/u011418943
22 | * Describe: 颜色渐变类
23 | */
24 |
25 | public class TabColorTextView extends AppCompatTextView {
26 | private static final String TAG = "ColorTextView";
27 | /**
28 | * const
29 | */
30 | public static final int DEC_LEFT = 1;
31 | public static final int DEC_RIGHT = 2;
32 |
33 | private Paint mPaint;
34 | /**
35 | * attrs
36 | */
37 | private int mWidth,mHeight;
38 | private int mDefaultColor ;
39 | private int mChangeColor ;
40 | private int mDecection = DEC_LEFT;
41 |
42 | private boolean isUseUserColor = false;
43 | public TabColorTextView(Context context) {
44 | this(context,null);
45 | }
46 |
47 | public TabColorTextView(Context context, AttributeSet attrs) {
48 | this(context, attrs,0);
49 |
50 | setIncludeFontPadding(false);
51 |
52 | }
53 |
54 | public TabColorTextView(Context context, AttributeSet attrs, int defStyleAttr) {
55 | super(context, attrs, defStyleAttr);
56 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TabColorTextView);
57 | mDefaultColor = ta.getColor(R.styleable.TabColorTextView_colortext_default_color, Color.GRAY);
58 | mChangeColor = ta.getColor(R.styleable.TabColorTextView_colortext_change_color,Color.WHITE);
59 | ta.recycle();
60 | /*Paint = new Paint();
61 | mPaint.setAntiAlias(true);
62 | mPaint.setDither(true);
63 | mPaint.setTextSize(getTextSize());*/
64 | mPaint = getPaint();
65 | // mPaint.setTypeface(Typeface.DEFAULT_BOLD);
66 | }
67 |
68 | @Override
69 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
70 | super.onSizeChanged(w, h, oldw, oldh);
71 | // mWidth = w;
72 | // mHeight = h;
73 |
74 | }
75 |
76 | @Override
77 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
78 | super.onLayout(changed, left, top, right, bottom);
79 | mWidth = getMeasuredWidth();
80 | mHeight = getMeasuredHeight();
81 | }
82 |
83 | /**
84 | * 公布出去,可以手动设置颜色和字体大小
85 | * @param defaultColor
86 | * @param changeColor
87 | */
88 | public void setCusTextColor(int defaultColor, int changeColor){
89 | mDefaultColor = defaultColor;
90 | mChangeColor = changeColor;
91 | isUseUserColor = false;
92 | invalidate();
93 | }
94 | private float mProgress = 0;
95 | public void setprogress(float progress,int decection) {
96 | isUseUserColor = false;
97 | mDecection = decection;
98 | mProgress = progress;
99 | invalidate();
100 | }
101 |
102 | @Override
103 | public void setTextColor(int color) {
104 | super.setTextColor(color);
105 | isUseUserColor = true;
106 | invalidate();
107 | }
108 |
109 | @Override
110 | protected void onDraw(Canvas canvas) {
111 | if (isUseUserColor){
112 | super.onDraw(canvas);
113 | }else {
114 | if (mDecection == DEC_RIGHT) {
115 | //绘制一遍黑色
116 | drawText(canvas, 0, mWidth, mDefaultColor);
117 | // 再绘制一遍其他颜色
118 | drawText(canvas, (int) ((1 - mProgress) * mWidth), mWidth, mChangeColor);
119 | } else {
120 | //绘制一遍黑色
121 | drawText(canvas, 0, mWidth, mDefaultColor);
122 | // 再绘制一遍其他颜色
123 | drawText(canvas, 0, (int) (mProgress * mWidth), mChangeColor);
124 | }
125 | }
126 | }
127 | private void drawText(Canvas canvas,int start,int end,int color){
128 | mPaint.setColor(color);
129 | canvas.save();
130 | canvas.clipRect(start,0,end,mHeight);
131 | String text = getText().toString();
132 |
133 | int t = getPaddingTop();
134 | int b = getPaddingBottom();
135 | float x;
136 | float ty;
137 | Paint.FontMetrics metrics = mPaint.getFontMetrics();
138 | float dy = (metrics.descent + metrics.ascent) / 2;
139 | float textWidth = mPaint.measureText(text);
140 | x = (mWidth - textWidth) / 2;
141 | //根据padding来
142 | if (getGravity() == Gravity.CENTER_VERTICAL || getGravity() == Gravity.CENTER){
143 | t = 0;
144 | b = 0;
145 | }
146 | ty = (mHeight+ t - b )*1.0f / 2 - dy;
147 |
148 |
149 |
150 | canvas.drawText(text,x,ty,mPaint);
151 | canvas.restore();
152 | }
153 |
154 | public int getChangeColor() {
155 | return mChangeColor;
156 | }
157 |
158 | public int getDefaultColor() {
159 | return mDefaultColor;
160 | }
161 |
162 | @NonNull
163 | @Override
164 | public Object clone() throws CloneNotSupportedException {
165 | return super.clone();
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/action/BViewPager.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.action;
2 |
3 | import androidx.viewpager.widget.ViewPager;
4 | import androidx.viewpager2.widget.ViewPager2;
5 |
6 | /**
7 | * @author by zhengshaorui 2020/9/13 10:26
8 | * describe:
9 | */
10 | public class BViewPager {
11 | private static final String TAG = "BViewPager";
12 | protected ViewPager2 mViewPager2;
13 | protected ViewPager mViewPager;
14 | private Pager2Listener mPager2Listener;
15 | protected boolean isChooseItemWhenPageSelected = false;
16 | public BViewPager setViewPager(ViewPager2 viewPager){
17 | if (viewPager != null) {
18 | mViewPager2 = viewPager;
19 | if (mPager2Listener != null) {
20 | mViewPager2.unregisterOnPageChangeCallback(mPager2Listener);
21 | }
22 | mViewPager2.registerOnPageChangeCallback(mPager2Listener = new Pager2Listener());
23 | }
24 |
25 | return this;
26 | }
27 |
28 | public BViewPager setViewPager(ViewPager viewPager){
29 | if (viewPager != null) {
30 | mViewPager = viewPager;
31 | mViewPager.addOnPageChangeListener(null);
32 | mViewPager.addOnPageChangeListener(new PagerListener());
33 | }
34 | return this;
35 | }
36 |
37 | public ViewPager getViewPager() {
38 | return mViewPager;
39 | }
40 |
41 | public ViewPager2 getViewPager2() {
42 | return mViewPager2;
43 | }
44 |
45 | public void chooseItemWhenPageSelected() {
46 | isChooseItemWhenPageSelected = true;
47 | }
48 |
49 |
50 |
51 | private class PagerListener implements ViewPager.OnPageChangeListener{
52 |
53 | @Override
54 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
55 | BViewPager.this.onPageScrolled(position,positionOffset,positionOffsetPixels);
56 | }
57 |
58 | @Override
59 | public void onPageSelected(int position) {
60 | BViewPager.this.onPageSelected(position);
61 | }
62 |
63 | @Override
64 | public void onPageScrollStateChanged(int state) {
65 | BViewPager.this.onPageScrollStateChanged(state);
66 | }
67 | }
68 |
69 | private class Pager2Listener extends ViewPager2.OnPageChangeCallback{
70 | @Override
71 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
72 | BViewPager.this.onPageScrolled(position,positionOffset,positionOffsetPixels);
73 | }
74 |
75 | @Override
76 | public void onPageSelected(int position) {
77 | BViewPager.this.onPageSelected(position);
78 | }
79 |
80 | @Override
81 | public void onPageScrollStateChanged(int state) {
82 | BViewPager.this.onPageScrollStateChanged(state);
83 | }
84 | }
85 |
86 |
87 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
88 |
89 | }
90 |
91 |
92 | public void onPageSelected(int position) {
93 |
94 | }
95 |
96 | public void onPageScrollStateChanged(int state) {
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/action/ColorAction.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.action;
2 |
3 | import android.graphics.Canvas;
4 |
5 | /**
6 | * @auther by zhengshaorui on 2020/1/9
7 | * describe:
8 | */
9 | public class ColorAction extends BaseVpAction {
10 | @Override
11 | public void draw(Canvas canvas) {
12 |
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/action/RectAction.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.action;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.view.View;
6 |
7 | import com.zhengsr.tablib.bean.TabValue;
8 | import com.zhengsr.tablib.view.flow.base.AbsFlowLayout;
9 |
10 | /**
11 | * @author by zhengshaorui on 2019/10/8
12 | * Describe: 绘制矩形
13 | */
14 | public class RectAction extends BaseVpAction {
15 | private static final String TAG = "RectAction";
16 |
17 | @Override
18 | public void config(AbsFlowLayout parentView) {
19 | super.config(parentView);
20 | mPaint.setStrokeCap(Paint.Cap.ROUND);
21 | View child = parentView.getChildAt(mCurrentIndex);
22 | if (child != null && mTabRect.isEmpty()) {
23 |
24 | float l =0;
25 | float t=0;
26 | float r=0;
27 | float b=0;
28 | if (isLeftAction()){
29 | l = child.getLeft() + mTabBean.tabMarginLeft;
30 | t = child.getTop() + mTabBean.tabMarginTop;
31 | r = l + mTabBean.tabWidth ;
32 | b = t + child.getBottom() - mTabBean.tabMarginBottom;
33 | if (mTabBean.tabHeight != -1){
34 | t += (child.getMeasuredHeight() - mTabBean.tabHeight)/2;
35 | b = t + mTabBean.tabHeight;
36 | }
37 | }else if (isRightAction()){
38 | l = child.getRight() - mTabBean.tabMarginRight;
39 | t = child.getTop() - mTabBean.tabMarginTop;
40 | r = l - mTabBean.tabWidth;
41 | b = t + mTabBean.tabHeight;
42 | if (mTabBean.tabHeight != -1){
43 | t += (child.getMeasuredHeight() - mTabBean.tabHeight)/2;
44 | b = t + mTabBean.tabHeight;
45 | }
46 | }else{
47 | l = mTabBean.tabMarginLeft + child.getLeft();
48 | t = mTabBean.tabMarginTop + child.getBottom() - mTabBean.tabHeight - mTabBean.tabMarginBottom;
49 | r = child.getRight() - mTabBean.tabMarginRight;
50 | b = t + mTabBean.tabHeight;
51 | if (mTabBean.tabWidth != -1) {
52 | l += (child.getMeasuredWidth() - mTabBean.tabWidth) / 2 ;
53 | r = mTabBean.tabWidth + l;
54 | }
55 | }
56 |
57 | mTabRect.set(l, t, r, b);
58 | }
59 | parentView.postInvalidate();
60 | }
61 |
62 | @Override
63 | protected void valueChange(TabValue value) {
64 | // super.valueChange(value);
65 | if (isVertical()){
66 | mTabRect.top = value.top ;
67 | mTabRect.bottom = value.bottom ;
68 | if (isLeftAction()) {
69 | mTabRect.left = value.left;
70 | mTabRect.right = mTabBean.tabWidth + mTabRect.left;
71 | }else{
72 | mTabRect.left = value.right;
73 | mTabRect.right = mTabRect.left - mTabBean.tabWidth;
74 | }
75 |
76 | }else{
77 | super.valueChange(value);
78 | }
79 | }
80 |
81 | @Override
82 | public void draw(Canvas canvas) {
83 | if (mTabBean.tabRoundSize != -1) {
84 | canvas.drawRoundRect(mTabRect, mTabBean.tabRoundSize, mTabBean.tabRoundSize, mPaint);
85 | } else {
86 | canvas.drawRect(mTabRect, mPaint);
87 | }
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/action/ResAction.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.action;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Canvas;
5 | import android.graphics.Rect;
6 | import android.graphics.drawable.Drawable;
7 | import android.view.View;
8 |
9 | import com.zhengsr.tablib.bean.TabBean;
10 | import com.zhengsr.tablib.bean.TabValue;
11 | import com.zhengsr.tablib.view.flow.base.AbsFlowLayout;
12 |
13 | /**
14 | * @author by zhengshaorui on 2019/10/8
15 | * Describe:
16 | */
17 | public class ResAction extends BaseVpAction {
18 | private static final String TAG = "ResAction";
19 | private Bitmap mBitmap;
20 | private Rect mSrcRect;
21 | private Drawable mDrawable;
22 | private int mRes = -1;
23 |
24 | @Override
25 | public void configAttrs(TabBean bean) {
26 | super.configAttrs(bean);
27 | mRes = bean.tabItemRes;
28 |
29 | }
30 |
31 |
32 |
33 | @Override
34 | public void config(AbsFlowLayout parentView) {
35 | super.config(parentView);
36 | if (mRes != -1) {
37 | mDrawable = mContext.getResources().getDrawable(mRes);
38 | }
39 | View child = parentView.getChildAt(0);
40 | if (child != null) {
41 | if (mDrawable != null) {
42 | int width = child.getMeasuredWidth();
43 | int height = child.getMeasuredHeight();
44 | mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
45 | Canvas canvas = new Canvas(mBitmap);
46 |
47 | float l = mTabBean.tabMarginLeft + child.getLeft();
48 | float t = mTabBean.tabMarginTop + child.getTop();
49 | float r = child.getRight() - mTabBean.tabMarginRight;
50 | float b = child.getBottom() - mTabBean.tabMarginBottom;
51 | mDrawable.setBounds(0, 0, width, height);
52 | mDrawable.draw(canvas);
53 | mTabRect.set(l, t, r, b);
54 | mSrcRect = new Rect(0, 0, width, height);
55 |
56 | }
57 |
58 | }
59 |
60 |
61 | }
62 |
63 | @Override
64 | protected void valueChange(TabValue value) {
65 | //super.valueChange(value);
66 | if (isVertical()){
67 | mTabRect.top = value.top ;
68 | mTabRect.bottom = value.bottom ;
69 | }
70 | mTabRect.left = value.left ;
71 | mTabRect.right = value.right ;
72 |
73 | }
74 |
75 | @Override
76 | public void draw(Canvas canvas) {
77 | if (mBitmap != null) {
78 | canvas.drawBitmap(mBitmap, mSrcRect, mTabRect, mPaint);
79 |
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/action/RoundAction.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.action;
2 |
3 | import android.graphics.Canvas;
4 | import android.view.View;
5 |
6 | import com.zhengsr.tablib.bean.TabBean;
7 | import com.zhengsr.tablib.bean.TabValue;
8 | import com.zhengsr.tablib.view.flow.base.AbsFlowLayout;
9 |
10 | /**
11 | * @author by zhengshaorui on 2019/10/8
12 | * Describe:
13 | */
14 | public class RoundAction extends BaseVpAction {
15 | private static final String TAG = "RoundAction";
16 | private float mRound;
17 |
18 |
19 | @Override
20 | public void configAttrs(TabBean bean) {
21 | super.configAttrs(bean);
22 | if (bean.tabRoundSize !=-1) {
23 | mRound = bean.tabRoundSize;
24 | }
25 | }
26 |
27 |
28 |
29 | @Override
30 | public void config(AbsFlowLayout parentView) {
31 | super.config(parentView);
32 | View child = parentView.getChildAt(0);
33 | if (child != null) {
34 | float l = mTabBean.tabMarginLeft + child.getLeft();
35 | float t = mTabBean.tabMarginTop + child.getTop();
36 | float r = child.getRight() - mTabBean.tabMarginRight;
37 | float b = child.getBottom() - mTabBean.tabMarginBottom;
38 | mTabRect.set(l, t, r, b);
39 | }
40 | parentView.postInvalidate();
41 | }
42 |
43 |
44 | @Override
45 | protected void valueChange(TabValue value) {
46 | //super.valueChange(value);
47 | if (isVertical()){
48 | mTabRect.top = value.top ;
49 | mTabRect.bottom = value.bottom ;
50 | }
51 | mTabRect.left = value.left ;
52 | mTabRect.right = value.right ;
53 |
54 | }
55 |
56 | @Override
57 | public void draw(Canvas canvas) {
58 | canvas.drawRoundRect(mTabRect, mRound, mRound, mPaint);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/action/TriAction.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.action;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Path;
5 | import android.util.Log;
6 | import android.view.View;
7 |
8 | import com.zhengsr.tablib.bean.TabValue;
9 | import com.zhengsr.tablib.view.flow.base.AbsFlowLayout;
10 |
11 | /**
12 | * @author by zhengshaorui on 2019/10/8
13 | * Describe:
14 | */
15 | public class TriAction extends BaseVpAction {
16 | private static final String TAG = "TriAction";
17 | private Path mPath;
18 |
19 | @Override
20 | public void config(AbsFlowLayout parentView) {
21 | super.config(parentView);
22 | mPath = new Path();
23 | View child = parentView.getChildAt(0);
24 | if (child != null) {
25 | float l ;
26 | float t;
27 | float r;
28 | float b;
29 | if (isLeftAction()){
30 | l = child.getLeft() + mTabBean.tabMarginLeft;
31 | t = child.getTop() + mTabBean.tabMarginTop;
32 | r = l + mTabBean.tabWidth ;
33 | b = t + child.getBottom() - mTabBean.tabMarginBottom;
34 | if (mTabBean.tabHeight != -1){
35 | t += (child.getMeasuredHeight() - mTabBean.tabHeight)/2;
36 | b = t + mTabBean.tabHeight;
37 | }
38 | }else if (isRightAction()){
39 | l = child.getRight() - mTabBean.tabMarginRight;
40 | t = child.getTop() - mTabBean.tabMarginTop;
41 | r = l - mTabBean.tabWidth;
42 | b = t + mTabBean.tabHeight;
43 | if (mTabBean.tabHeight != -1){
44 | t += (child.getMeasuredHeight() - mTabBean.tabHeight)/2;
45 | b = t + mTabBean.tabHeight;
46 | }
47 | }else{
48 | l = mTabBean.tabMarginLeft + child.getLeft();
49 | t = mTabBean.tabMarginTop + child.getBottom() - mTabBean.tabHeight - mTabBean.tabMarginBottom;
50 | r = child.getRight() - mTabBean.tabMarginRight;
51 | b = t + mTabBean.tabHeight;
52 |
53 | if (mTabBean.tabWidth != -1) {
54 | l += (child.getMeasuredWidth() - mTabBean.tabWidth) / 2;
55 | r = mTabBean.tabWidth + l;
56 | }
57 | }
58 |
59 |
60 | mTabRect.set(l, t, r, b);
61 |
62 | if (isVertical()){
63 | mPath.moveTo(r,t + mTabBean.tabHeight/2);
64 | mPath.lineTo(l,t);
65 | mPath.lineTo(l,b);
66 | }else{
67 |
68 | mPath.moveTo(l+mTabBean.tabWidth/ 2 , t);
69 | mPath.lineTo(l, b);
70 | mPath.lineTo(r, b);
71 | }
72 | }
73 | }
74 |
75 | @Override
76 | protected void valueChange(TabValue value) {
77 | super.valueChange(value);
78 | mPath.reset();
79 |
80 | if (isVertical()){
81 | mTabRect.set(value.valueToRect());
82 | float l = mTabRect.left;
83 | float t = mTabRect.top;
84 | float r = mTabRect.right;
85 | float b = mTabRect.bottom;
86 | if (isRightAction()){
87 | l = r;
88 | r = l - mTabBean.tabWidth;
89 | }
90 | mPath.moveTo(r,t + mTabBean.tabHeight/2);
91 | mPath.lineTo(l,t);
92 | mPath.lineTo(l,b);
93 | }else {
94 | mPath.moveTo(mTabRect.width() / 2 + mTabRect.left, mTabRect.top);
95 | mPath.lineTo(mTabRect.left, mTabRect.bottom);
96 | mPath.lineTo(mTabRect.right, mTabRect.bottom);
97 | }
98 | }
99 |
100 | @Override
101 | public void draw(Canvas canvas) {
102 | if (mPath != null) {
103 | canvas.drawPath(mPath, mPaint);
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/adapter/BaseFlowAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.adapter;
2 |
3 | import android.view.View;
4 | import android.widget.TextView;
5 |
6 | import com.zhengsr.tablib.callback.FlowListenerAdapter;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * @auther by zhengshaorui on 2020/1/8
12 | * describe:
13 | */
14 | public abstract class BaseFlowAdapter {
15 | private int mLayoutId;
16 | private List mDatas;
17 | public FlowListenerAdapter mListener;
18 |
19 | public BaseFlowAdapter(int layoutId, List data) {
20 | mLayoutId = layoutId;
21 | mDatas = data;
22 | }
23 |
24 | /**
25 | * 获取个数
26 | *
27 | * @return
28 | */
29 | public int getItemCount() {
30 | return mDatas == null ? 0 : mDatas.size();
31 | }
32 |
33 | /**
34 | * 获取id
35 | *
36 | * @return
37 | */
38 | public int getLayoutId() {
39 | return mLayoutId;
40 | }
41 |
42 |
43 | /**
44 | * 获取数据
45 | *
46 | * @return
47 | */
48 | public List getDatas() {
49 | return mDatas;
50 | }
51 |
52 | /**
53 | * 公布给外部的数据
54 | *
55 | * @param view
56 | * @param data
57 | * @param position
58 | */
59 | public void bindView(View view, T data, int position){
60 | //todo
61 | T t = mDatas.get(position);
62 | if (t instanceof String){
63 |
64 | }
65 | }
66 |
67 |
68 | /**
69 | * 单击
70 | *
71 | * @param view
72 | * @param position
73 | */
74 | public void onItemClick(View view, T data, int position) {
75 | }
76 |
77 |
78 | /**
79 | * 长按
80 | */
81 | public boolean onItemLongClick(View view,int position){
82 | return true;
83 | };
84 |
85 | /**
86 | * 子控件的点击事件
87 | * @param childView
88 | * @param position
89 | */
90 | public void onItemChildClick(View childView,int position){}
91 |
92 |
93 | public boolean onItemChildLongClick(View childView,int position){
94 | return true;
95 | }
96 |
97 | /**
98 | * 通知数据改变,全部刷新
99 | */
100 | public void notifyDataChanged() {
101 | if (mListener != null) {
102 | mListener.notifyDataChanged();
103 | }
104 | }
105 |
106 | /**
107 | * view 是否选中状态
108 | * @param view
109 | * @param isSelected
110 | */
111 | public void onItemSelectState(View view, boolean isSelected){}
112 |
113 | /**
114 | * 构建一个listener,用来改变数据
115 | */
116 | public void setListener(FlowListenerAdapter listener) {
117 | mListener = listener;
118 | }
119 |
120 |
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/adapter/LabelFlowAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.adapter;
2 |
3 | import android.view.View;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * @auther by zhengshaorui on 2020/1/8
9 | * describe:
10 | */
11 | public abstract class LabelFlowAdapter extends TemplateAdapter {
12 |
13 | public LabelFlowAdapter(int layoutId, List data) {
14 | super(layoutId, data);
15 | }
16 |
17 | /**
18 | * 达到最大值
19 | * @param ids
20 | * @param count
21 | */
22 | public void onReachMaxCount(List ids, int count){}
23 |
24 | /**
25 | * 上个焦点和当前焦点的焦点情况,方便自定义动画,或者其他属性
26 | * @param oldView
27 | * @param newView
28 | */
29 | public void onFocusChanged(View oldView, View newView){}
30 |
31 |
32 | /**
33 | * 显示更多
34 | * @param view
35 | */
36 | public void onShowMoreClick(View view){};
37 |
38 | /**
39 | * 收起
40 | * @param view
41 | */
42 | public void onHandUpClick(View view){};
43 |
44 |
45 | /**
46 | * 恢复所有状态
47 | */
48 | public void resetStatus(){
49 | if (mListener != null) {
50 | mListener.resetAllStatus();
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/adapter/TabFlowAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.adapter;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author by zhengshaorui on 2019/10/8
7 | * Describe: 数据构建基类
8 | */
9 | public class TabFlowAdapter extends TemplateAdapter {
10 |
11 |
12 | public TabFlowAdapter(int layoutId, List data) {
13 | super(layoutId, data);
14 | }
15 | public TabFlowAdapter(List data){
16 | super(-1,data);
17 | }
18 | /**
19 | * 恢复某个id的颜色
20 | */
21 | public void resetAllColor(int viewId, int color) {
22 | if (mListener != null) {
23 | mListener.resetAllTextColor(viewId, color);
24 | }
25 | }
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/adapter/TemplateAdapter.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.adapter;
2 |
3 | import android.graphics.Bitmap;
4 | import android.view.View;
5 | import android.widget.ImageView;
6 | import android.widget.TextView;
7 |
8 | import androidx.annotation.ColorInt;
9 | import androidx.annotation.ColorRes;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * @auther by zhengshaorui on 2020/1/8
15 | * describe: 模板类
16 | */
17 | public abstract class TemplateAdapter extends BaseFlowAdapter {
18 | public TemplateAdapter(int layoutId, List data) {
19 | super(layoutId, data);
20 | }
21 |
22 |
23 | /**
24 | * 如果布局里的子控件需要点击事件,需要现在这里注册
25 | * @param viewId
26 | * @return
27 | */
28 | public BaseFlowAdapter addChildrenClick(View view, int viewId, final int position){
29 | final View child = view.findViewById(viewId);
30 | if (child != null) {
31 | child.setOnClickListener(new View.OnClickListener() {
32 | @Override
33 | public void onClick(View view) {
34 | onItemChildClick(child,position);
35 | }
36 | });
37 | }
38 | return this;
39 | }
40 | /**
41 | * 如果布局里的子控件需要长按事件,需要现在这里注册
42 | * @param viewId
43 | * @return
44 | */
45 | public BaseFlowAdapter addChildrenLongClick(View view, int viewId, final int position){
46 | final View child = view.findViewById(viewId);
47 | if (child != null) {
48 | child.setOnLongClickListener(new View.OnLongClickListener() {
49 | @Override
50 | public boolean onLongClick(View v) {
51 | return onItemChildLongClick(child,position);
52 | }
53 | });
54 | }
55 | return this;
56 | }
57 |
58 |
59 | /**
60 | * 常用模板
61 | */
62 | public TemplateAdapter setText(View view, int viewId, int resId) {
63 | TextView textView = view.findViewById(viewId);
64 | if (textView != null) {
65 | textView.setText(resId);
66 | }
67 | return this;
68 | }
69 |
70 | public TemplateAdapter setText(View view, int viewId, String msg) {
71 | TextView textView = view.findViewById(viewId);
72 | if (textView != null) {
73 | textView.setText(msg);
74 | }
75 | return this;
76 | }
77 |
78 | /**
79 | * 常用模板
80 | */
81 | public TemplateAdapter setDefaultText(View view, int resId) {
82 | if (view instanceof TextView) {
83 | ((TextView) view).setText(resId);
84 | }
85 | return this;
86 | }
87 |
88 |
89 | public TemplateAdapter setDefaultText(View view, String msg) {
90 | if (view instanceof TextView) {
91 | ((TextView) view).setText(msg);
92 | }
93 | return this;
94 | }
95 |
96 | public TemplateAdapter setTextColor(View view, int viewId, int textColor) {
97 | TextView textView = view.findViewById(viewId);
98 | if (textView != null) {
99 | textView.setTextColor(textColor);
100 | }
101 | return this;
102 | }
103 |
104 | public TemplateAdapter setDefaultTextColor(View view,@ColorInt int textColor) {
105 | if (view instanceof TextView){
106 | ((TextView) view).setTextColor(textColor);
107 | }
108 | return this;
109 | }
110 |
111 |
112 | public TemplateAdapter setImageView(View view, int viewId, int res){
113 | ImageView imageView = view.findViewById(viewId);
114 | if (imageView != null) {
115 | imageView.setImageResource(res);
116 | }
117 | return this;
118 | }
119 |
120 | public TemplateAdapter setImageView(View view, int viewId, Bitmap bitmap){
121 | ImageView imageView = view.findViewById(viewId);
122 | if (imageView != null) {
123 | imageView.setImageBitmap(bitmap);
124 | }
125 | return this;
126 | }
127 |
128 |
129 | public TemplateAdapter setVisible(View view, int viewId, boolean isVisible) {
130 | View childView = view.findViewById(viewId);
131 | if (childView != null) {
132 | childView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
133 | }
134 | return this;
135 | }
136 | public TemplateAdapter setVisible(View view, int viewId, int visible) {
137 | View childView = view.findViewById(viewId);
138 | if (childView != null) {
139 | childView.setVisibility(visible);
140 | }
141 | return this;
142 | }
143 |
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/flow/TabFlowLayout.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.flow;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.os.Parcelable;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.View;
9 |
10 | import androidx.annotation.Nullable;
11 |
12 | import com.zhengsr.tablib.view.flow.base.AbsFlowLayout;
13 |
14 | /**
15 | * @author by zhengshaorui 2021/5/23 06:51
16 | * describe:不处理ViewPager的情况
17 | */
18 | public class TabFlowLayout extends AbsFlowLayout {
19 | private static final String TAG = TabFlowLayout.class.getSimpleName();
20 |
21 | public TabFlowLayout(Context context) {
22 | super(context);
23 | }
24 |
25 | public TabFlowLayout(Context context, @Nullable AttributeSet attrs) {
26 | super(context, attrs);
27 | }
28 |
29 | public TabFlowLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
30 | super(context, attrs, defStyleAttr);
31 | }
32 |
33 |
34 | @Override
35 | protected void onViewVisible() {
36 | /**
37 | * 当横竖屏,或者异常重启之后,需要重新对位置,选中 index 等恢复到原来的状态
38 | */
39 | mAction.chooseIndex(mLastIndex,mCurrentIndex);
40 | updateScroll(getChildAt(mCurrentIndex),false);
41 | }
42 |
43 |
44 |
45 | @Override
46 | public void computeScroll() {
47 | super.computeScroll();
48 |
49 | if (mScroller.computeScrollOffset()) {
50 | //有边界
51 | int offset;
52 | if (isVertical()) {
53 | offset = mScroller.getCurrY();
54 | if (offset >= mBottomRound - mHeight) {
55 | offset = mBottomRound - mHeight;
56 | }
57 | } else {
58 | offset = mScroller.getCurrX();
59 | if (offset >= mRightBound - mWidth) {
60 | offset = mRightBound - mWidth;
61 | }
62 | }
63 |
64 | if (offset <= 0) {
65 | offset = 0;
66 | }
67 | if (isVertical()) {
68 | scrollTo(0, offset);
69 | } else {
70 | scrollTo(offset, 0);
71 | }
72 | postInvalidate();
73 | }
74 | }
75 |
76 |
77 | @Override
78 | protected void onItemClick(View view, int position) {
79 | isItemClick = true;
80 | super.onItemClick(view, position);
81 | chooseItem(position, view);
82 | }
83 |
84 |
85 | @Override
86 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
87 | super.onLayout(changed, l, t, r, b);
88 | int childCount = getChildCount();
89 | //让tab标签回到最后一个
90 | if (childCount > 0 && (childCount - 1) < mCurrentIndex) {
91 | int temp = mCurrentIndex;
92 | mCurrentIndex = childCount - 1;
93 | mAction.chooseIndex(temp, mCurrentIndex);
94 | postInvalidate();
95 | }
96 | }
97 |
98 | /**
99 | * 由外部设置位置,为不是自身点击的
100 | * 这个常用于 recyclerview 的联动效果
101 | * @param position
102 | */
103 | private boolean isItemClick = false;
104 | public void setItemClickByOutside(int position) {
105 | isItemClick = false;
106 | if (position >= 0 && position < getChildCount()) {
107 | View view = getChildAt(position);
108 | chooseItem(position, view);
109 | }
110 |
111 | }
112 |
113 | public void setItemClick(boolean itemClick) {
114 | isItemClick = itemClick;
115 | }
116 |
117 | public boolean isItemClick() {
118 | return isItemClick;
119 | }
120 |
121 | /**
122 | * 选中某个tab
123 | *
124 | * @param position
125 | * @param view
126 | */
127 | private void chooseItem(int position, View view) {
128 | mLastIndex = mCurrentIndex;
129 | mCurrentIndex = position;
130 | if (mAction != null) {
131 | mAction.onItemClick(mLastIndex, position);
132 | }
133 | /**
134 | * 如果没有 viewpager,则需要使用 scroller 平滑过渡
135 | */
136 | updateScroll(view, true);
137 | postInvalidate();
138 |
139 | }
140 |
141 | @Override
142 | protected void onRestoreInstanceState(Parcelable state) {
143 | if (state instanceof Bundle) {
144 | Bundle bundle = (Bundle) state;
145 | state = bundle.getParcelable("instancestatus");
146 | mCurrentIndex = bundle.getInt("index");
147 | mLastIndex = bundle.getInt("lastindex");
148 | }
149 | super.onRestoreInstanceState(state);
150 | }
151 |
152 | @Nullable
153 | @Override
154 | protected Parcelable onSaveInstanceState() {
155 | Bundle bundle = new Bundle();
156 | bundle.putParcelable("instancestatus", super.onSaveInstanceState());
157 |
158 | if (mAction != null) {
159 | mLastIndex = mAction.getLastIndex();
160 | }
161 |
162 | bundle.putInt("index", mCurrentIndex);
163 | bundle.putInt("lastindex", mLastIndex);
164 | return bundle;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/tablibx/src/main/java/com/zhengsr/tablib/view/flow/TabVpFlowLayout.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib.view.flow;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.os.Parcelable;
6 | import android.util.AttributeSet;
7 | import android.view.View;
8 |
9 | import androidx.annotation.Nullable;
10 | import androidx.viewpager.widget.ViewPager;
11 | import androidx.viewpager2.widget.ViewPager2;
12 |
13 | import com.zhengsr.tablib.bean.TabBean;
14 | import com.zhengsr.tablib.bean.TabConfig;
15 | import com.zhengsr.tablib.view.action.BaseAction;
16 | import com.zhengsr.tablib.view.flow.base.AbsFlowLayout;
17 |
18 | /**
19 | * @author by zhengshaorui 2021/5/23 06:51
20 | * describe:不处理ViewPager的情况
21 | */
22 | public class TabVpFlowLayout extends AbsFlowLayout {
23 | private static final String TAG = TabVpFlowLayout.class.getSimpleName();
24 | private ViewPager mViewPager;
25 | private ViewPager2 mViewPager2;
26 |
27 | public TabVpFlowLayout(Context context) {
28 | super(context);
29 | }
30 |
31 | public TabVpFlowLayout(Context context, @Nullable AttributeSet attrs) {
32 | super(context, attrs);
33 | }
34 |
35 | public TabVpFlowLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
36 | super(context, attrs, defStyleAttr);
37 | }
38 |
39 | @Override
40 | protected void onViewVisible() {
41 | super.onViewVisible();
42 | mAction.chooseIndex(mLastIndex,mCurrentIndex);
43 | if (mViewPager != null) {
44 | mViewPager.setCurrentItem(mCurrentIndex,false);
45 | }
46 | if (mViewPager2 != null) {
47 | mViewPager2.setCurrentItem(mCurrentIndex,false);
48 | }
49 | View view = getChildAt(mCurrentIndex);
50 | if (view != null) {
51 | updateScroll(view,false);
52 | }
53 | }
54 |
55 | @Override
56 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
57 | super.onLayout(changed, l, t, r, b);
58 | int childCount = getChildCount();
59 | //让tab标签回到最后一个
60 | if (childCount > 0 && (childCount - 1) < mCurrentIndex) {
61 | int tem = mCurrentIndex;
62 | mCurrentIndex = childCount - 1;
63 | mAction.chooseIndex(tem, mCurrentIndex);
64 | postInvalidate();
65 | }
66 | }
67 |
68 | @Override
69 | public void setCusAction(BaseAction action) {
70 | super.setCusAction(action);
71 | if (mViewPager != null && mAction.getViewPager() == null) {
72 | mAction.setViewPager(mViewPager);
73 | }
74 | if (mViewPager2 != null && mAction.getViewPager2() == null) {
75 | mAction.setViewPager(mViewPager2);
76 | }
77 | }
78 |
79 | @Override
80 | public AbsFlowLayout setTabBean(TabBean bean) {
81 | if (mViewPager != null && mAction.getViewPager() == null) {
82 | mAction.setViewPager(mViewPager);
83 | }
84 | if (mViewPager2 != null && mAction.getViewPager2() == null) {
85 | mAction.setViewPager(mViewPager2);
86 | }
87 | return super.setTabBean(bean);
88 |
89 | }
90 |
91 | @Override
92 | protected void onTabConfig(TabConfig config) {
93 | super.onTabConfig(config);
94 | if (config == null) {
95 | return;
96 | }
97 | if (config.getViewPager2() != null) {
98 | mViewPager2 = config.getViewPager2();
99 | }
100 | if (config.getViewPager() != null) {
101 | mViewPager = config.getViewPager();
102 | }
103 | mCurrentIndex = config.getDefaultPos();
104 | }
105 |
106 |
107 | @Override
108 | protected void onItemClick(View view, int position) {
109 | super.onItemClick(view, position);
110 | mLastIndex = mCurrentIndex;
111 | mCurrentIndex = position;
112 | mAction.updatePos(mLastIndex,mCurrentIndex);
113 | if (mViewPager != null) {
114 | mViewPager.setCurrentItem(position,true);
115 | }
116 | if (mViewPager2 != null) {
117 | mViewPager2.setCurrentItem(position,true);
118 | }
119 |
120 | }
121 |
122 | /**
123 | * 设置viewpager,如果有多个配置,请使用{@link #setTabConfig(TabConfig)}
124 | */
125 | public TabVpFlowLayout setViewPager(ViewPager viewPager) {
126 | if (viewPager == null) {
127 | return this;
128 | }
129 | mViewPager = viewPager;
130 | if (mAction != null) {
131 | mAction.setViewPager(viewPager);
132 | }
133 | return this;
134 | }
135 |
136 | @Override
137 | protected void onRestoreInstanceState(Parcelable state) {
138 | if (state instanceof Bundle) {
139 | Bundle bundle = (Bundle) state;
140 | state = bundle.getParcelable("instancestatus");
141 | mCurrentIndex = bundle.getInt("index");
142 | mLastIndex = bundle.getInt("lastindex");
143 | }
144 | super.onRestoreInstanceState(state);
145 | }
146 |
147 | @Nullable
148 | @Override
149 | protected Parcelable onSaveInstanceState() {
150 | Bundle bundle = new Bundle();
151 | bundle.putParcelable("instancestatus", super.onSaveInstanceState());
152 | if (mViewPager != null) {
153 | mCurrentIndex = mViewPager.getCurrentItem();
154 | mLastIndex = 0;
155 | }else if (mViewPager2 != null) {
156 | mCurrentIndex = mViewPager2.getCurrentItem();
157 | mLastIndex = 0;
158 | } else {
159 | if (mAction != null) {
160 | mLastIndex = mAction.getLastIndex();
161 | }
162 | }
163 | bundle.putInt("index", mCurrentIndex);
164 | bundle.putInt("lastindex", mLastIndex);
165 | return bundle;
166 | }
167 |
168 |
169 | /**
170 | * 设置viewpager,如果有多个配置,请使用{@link #setTabConfig(TabConfig)}
171 | */
172 | public TabVpFlowLayout setViewPager(ViewPager2 viewpager2){
173 | mViewPager2 = viewpager2;
174 | if (mAction != null){
175 | mAction.setViewPager(viewpager2);
176 | }
177 | return this;
178 | }
179 | /**
180 | * 设置默认位置
181 | * 请使用{@link #setTabConfig(TabConfig)}
182 | */
183 | public AbsFlowLayout setDefaultPosition(int position) {
184 | mCurrentIndex = position;
185 | return this;
186 | }
187 |
188 | /**
189 | * 选择某个item,建议 viewpager setCurrentItem(position,false);
190 | * 此方法是为了优化当 viewpager 页面过多,从第一页选择到最后一页,此时
191 | * ViewPaper onPageScrolled 执行过多,导致滚动异常的问题。
192 | * @param position
193 | */
194 | public void chooseItem(int position){
195 | mLastIndex = mCurrentIndex;
196 | mCurrentIndex = position;
197 | mAction.chooseIndex(mLastIndex,position);
198 | mAction.chooseItemWhenPageSelected();
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/tablibx/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 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/tablibx/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | tablib
3 |
4 |
--------------------------------------------------------------------------------
/tablibx/src/test/java/com/zhengsr/tablib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zhengsr.tablib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------