├── settings.gradle.kts
├── pager-indicator
├── gradle.properties
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── res
│ │ └── values
│ │ │ └── attrs.xml
│ │ └── java
│ │ └── me
│ │ └── panpf
│ │ └── pagerid
│ │ └── PagerIndicator.java
├── .gitignore
├── proguard-rules.pro
└── build.gradle.kts
├── docs
├── logo.png
├── sample.gif
└── sample2.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── sample
├── src
│ └── main
│ │ ├── ic_launcher-web.png
│ │ ├── res
│ │ ├── values
│ │ │ ├── dimens.xml
│ │ │ ├── ids.xml
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── drawable-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── image_sliding_block.9.png
│ │ │ ├── pager_sliding_block.9.png
│ │ │ └── sliding_tab_strip_background.9.png
│ │ ├── drawable-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── layout
│ │ │ ├── tab.xml
│ │ │ ├── include_shadow_down.xml
│ │ │ ├── include_shadow_up.xml
│ │ │ └── activity_sliding_tab_strip.xml
│ │ ├── drawable
│ │ │ ├── shape_shadow_up.xml
│ │ │ ├── shape_shadow_down.xml
│ │ │ └── selector_slide_title.xml
│ │ └── color
│ │ │ └── selector_slide_title.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── me
│ │ └── panpf
│ │ └── pagerid
│ │ └── sample
│ │ ├── ViewPagerAdapter.java
│ │ ├── MainActivity.java
│ │ └── Colors.java
└── build.gradle.kts
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | include(":sample", ":pager-indicator")
--------------------------------------------------------------------------------
/pager-indicator/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=pagerindicator
--------------------------------------------------------------------------------
/docs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/docs/logo.png
--------------------------------------------------------------------------------
/docs/sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/docs/sample.gif
--------------------------------------------------------------------------------
/docs/sample2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/docs/sample2.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/pager-indicator/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/sample/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 2dp
3 |
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | PagerIndicator
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/image_sliding_block.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/res/drawable-hdpi/image_sliding_block.9.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/pager_sliding_block.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/res/drawable-hdpi/pager_sliding_block.9.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/sliding_tab_strip_background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/panpf/pager-indicator/HEAD/sample/src/main/res/drawable-hdpi/sliding_tab_strip_background.9.png
--------------------------------------------------------------------------------
/sample/src/main/res/layout/tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Oct 28 13:32:11 CST 2014
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.7.1-bin.zip
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/shape_shadow_up.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/shape_shadow_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/include_shadow_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #ff00bfff
8 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/selector_slide_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/include_shadow_up.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/color/selector_slide_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/pager-indicator/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | #*.apk
3 | *.ap_
4 | proguard_logs/
5 |
6 | # files for the dex VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Local configuration file (sdk path, etc)
13 | local.properties
14 |
15 | # Eclipse project files
16 | #.classpath
17 | #.project
18 | #.settings/
19 | bin/
20 | gen/
21 |
22 | # Idea files
23 | .idea/
24 | *.iml
25 |
26 | # Gradle files
27 | .gradle/
28 | build/
29 |
30 | # Mac files
31 | .DS_Store
32 |
33 | captures/
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | #*.apk
3 | *.ap_
4 | proguard_logs/
5 |
6 | # files for the dex VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Local configuration file (sdk path, etc)
13 | local.properties
14 |
15 | # Eclipse project files
16 | #.classpath
17 | #.project
18 | #.settings/
19 | bin/
20 | gen/
21 |
22 | # Idea files
23 | .idea/
24 | *.iml
25 |
26 | # Gradle files
27 | .gradle/
28 | build/
29 |
30 | # Mac files
31 | .DS_Store
32 |
33 | # Signature files
34 | *.jks
--------------------------------------------------------------------------------
/pager-indicator/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pager-indicator/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/sample/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | }
4 |
5 | android {
6 | compileSdkVersion(property("COMPILE_SDK_VERSION").toString().toInt())
7 |
8 | defaultConfig {
9 | applicationId = "me.panpf.pagerid.sample"
10 |
11 | minSdkVersion(property("MIN_SDK_VERSION").toString().toInt())
12 | targetSdkVersion(property("TARGET_SDK_VERSION").toString().toInt())
13 | versionCode = property("VERSION_CODE").toString().toInt()
14 | versionName = property("VERSION_NAME").toString()
15 | }
16 |
17 | buildTypes {
18 | getByName("release") {
19 | isMinifyEnabled = false
20 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation(project(":pager-indicator"))
27 | implementation("com.android.support:appcompat-v7:${property("ANDROID_SUPPORT_LIBRARY_VERSION")}")
28 | }
29 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
23 |
24 |
--------------------------------------------------------------------------------
/pager-indicator/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.library")
3 | }
4 |
5 | android {
6 | compileSdkVersion(property("COMPILE_SDK_VERSION").toString().toInt())
7 |
8 | defaultConfig {
9 | minSdkVersion(property("MIN_SDK_VERSION").toString().toInt())
10 | targetSdkVersion(property("TARGET_SDK_VERSION").toString().toInt())
11 | versionCode = property("VERSION_CODE").toString().toInt()
12 | versionName = property("VERSION_NAME").toString()
13 | }
14 |
15 | buildTypes {
16 | getByName("release") {
17 | isMinifyEnabled = false
18 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
19 | }
20 | }
21 | }
22 |
23 | dependencies {
24 | api("com.android.support:support-core-ui:${property("ANDROID_SUPPORT_LIBRARY_VERSION")}")
25 | }
26 |
27 | /**
28 | * publish config
29 | */
30 | if (hasProperty("signing.keyId") // configured in the ~/.gradle/gradle.properties file
31 | && hasProperty("signing.password") // configured in the ~/.gradle/gradle.properties file
32 | && hasProperty("signing.secretKeyRingFile") // configured in the ~/.gradle/gradle.properties file
33 | && hasProperty("mavenCentralUsername") // configured in the ~/.gradle/gradle.properties file
34 | && hasProperty("mavenCentralPassword") // configured in the ~/.gradle/gradle.properties file
35 | && hasProperty("GROUP") // configured in the rootProject/gradle.properties file
36 | && hasProperty("POM_ARTIFACT_ID") // configured in the project/gradle.properties file
37 | ) {
38 | apply { plugin("com.vanniktech.maven.publish") }
39 |
40 | configure {
41 | sonatypeHost = com.vanniktech.maven.publish.SonatypeHost.S01
42 | }
43 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | COMPILE_SDK_VERSION=25
21 |
22 | MIN_SDK_VERSION=9
23 | TARGET_SDK_VERSION=25
24 |
25 | VERSION_CODE=180
26 | VERSION_NAME=1.8.0
27 |
28 | ANDROID_SUPPORT_LIBRARY_VERSION=25.3.0
29 |
30 | #------------------------------------------ publish config ----------------------------------------#
31 | GROUP=io.github.panpf.pagerindicator
32 | #VERSION_NAME=1.0.0
33 |
34 | POM_NAME=PagerIndicator
35 | POM_DESCRIPTION=Android Pager Indicator
36 | POM_URL=https://github.com/panpf/pager-indicator
37 |
38 | POM_SCM_URL=https://github.com/panpf/pager-indicator
39 | POM_SCM_CONNECTION=https://github.com/panpf/pager-indicator.git
40 | POM_SCM_DEV_CONNECTION=https://github.com/panpf/pager-indicator.git
41 |
42 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
43 | POM_LICENCE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
44 | POM_LICENCE_DIST=repo
45 |
46 | POM_DEVELOPER_ID=panpf
47 | POM_DEVELOPER_NAME=panpf
48 | POM_DEVELOPER_URL=https://github.com/panpf/
--------------------------------------------------------------------------------
/sample/src/main/java/me/panpf/pagerid/sample/ViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Peng fei Pan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package me.panpf.pagerid.sample;
17 |
18 | import android.support.v4.view.PagerAdapter;
19 | import android.view.View;
20 | import android.view.ViewGroup;
21 |
22 | import java.util.List;
23 |
24 | /**
25 | * 滑动视图适配器
26 | */
27 | public class ViewPagerAdapter extends PagerAdapter {
28 | private List viewList;
29 |
30 | public ViewPagerAdapter(List viewList){
31 | setViewList(viewList);
32 | }
33 |
34 | @Override
35 | public void destroyItem(ViewGroup container, int position, Object object) {
36 | container.removeView(viewList.get(position));
37 | }
38 |
39 | @Override
40 | public Object instantiateItem(ViewGroup container, int position) {
41 | container.addView(viewList.get(position), 0);
42 | return viewList.get(position);
43 | }
44 |
45 | @Override
46 | public int getCount() {
47 | return viewList.size();
48 | }
49 |
50 | @Override
51 | public boolean isViewFromObject(View arg0, Object arg1) {
52 | return arg0 == arg1;
53 | }
54 |
55 | public List getViewList() {
56 | return viewList;
57 | }
58 |
59 | public void setViewList(List viewList) {
60 | this.viewList = viewList;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ![logo_image] PagerIndicator
2 |
3 | ![Platform][platform_image]
4 | [![API][min_api_image]][min_api_link]
5 | [![Android Arsenal][android_arsenal_image]][android_arsenal-link]
6 | [![Release Version][version_icon]][version_link]
7 |
8 | 这是 Android 上的一个 ViewPager 页面指示器组件,用于标识当前显示的页面
9 |
10 | ![sample_image]
11 |
12 | ## 特性
13 |
14 | * 当所有的 Tab 在横向上无法充满整个屏幕的时候,将会根据 allowWidthFull 参数决定是否调整所有的 Item 来充满。调整的规则是平均分配每个 Tab 的宽度,如果某个 Tab 的最小宽度大于平均宽度,那么其宽度保持不变
15 | * 当所有的 Tab 在横向上能够充满整个屏幕的时候,将会从左到右依次排列
16 | * 用法简单,支持在布局中直接包含 View 或者在代码中直接调用 PagerIndicator.addTab() 方法添加
17 | * Tab View 支持设置外边距
18 | * 支持通过 disableTensileSlidingBlock 属性设置是否拉伸滑块图片
19 |
20 | ## 开始使用
21 |
22 | ### 1. 从 mavenCentral 导入 PagerIndicator
23 |
24 | 在 app 的 build.gradle 文件的 dependencies 节点中加入依赖
25 |
26 | ```kotlin
27 | dependencies {
28 | implementation("io.github.panpf.pagerindicator:pagerindicator:${LAST_VERSION}")
29 | }
30 | ```
31 |
32 | `${LAST_VERSION}`: [![Download][version_icon]][version_link] (No include 'v')
33 |
34 | ### 2. 在布局中使用
35 |
36 | ```xml
37 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | ```
55 |
56 | 效果图如下:
57 |
58 | ![sample_image2]
59 |
60 | 你还可以在代码中通过 PagerIndicator.setTabViewFactory() 方法添加Tab
61 |
62 | 支持的布局属性:
63 |
64 | * ``pi_slidingBlock``:指定滑块图片,对应的方法是 PagerIndicator.setSlidingBlockDrawable(Drawable)
65 | * ``pi_allowWidthFull``:当所有 Tab 无法充满 PagerIndicator 时是否自动调整所有 Tab 的宽度来达到充满的目的,对应的方式是 PagerIndicator.setAllowWidthFull(boolean)
66 | * ``pi_disableViewPager``:禁用 ViewPager,禁用后不会有初始选中状态效果,也不会绘制滑块,你调用 setViewPager() 方法也不会起作用
67 | * ``pi_disableTensileSlidingBlock``:禁止拉伸滑块图片
68 |
69 | ### 3. 绑定 ViewPager
70 |
71 | ```java
72 | ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
73 | viewPager.setAdapter(...);
74 |
75 | PagerIndicator pagerIndicator = (PagerIndicator) findViewById(R.id.slidingTabStrip);
76 | pagerIndicator.setViewPager(viewPager);
77 | ```
78 |
79 | 注意:
80 |
81 | * 在调用 setViewPager(ViewPager) 方法之前要先设置 ViewPager 的 Adapter
82 |
83 | 你还可以直接调用 ViewPager.setCurrentItem(int) 方法来改变默认 Tab,无论是在调用 setViewPager(ViewPager) 方法之前还是之后都可以
84 |
85 | 更多内容请参见 sample 源码
86 |
87 | ## License
88 | Copyright (C) 2017 Peng fei Pan
89 |
90 | Licensed under the Apache License, Version 2.0 (the "License");
91 | you may not use this file except in compliance with the License.
92 | You may obtain a copy of the License at
93 |
94 | http://www.apache.org/licenses/LICENSE-2.0
95 |
96 | Unless required by applicable law or agreed to in writing, software
97 | distributed under the License is distributed on an "AS IS" BASIS,
98 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
99 | See the License for the specific language governing permissions and
100 | limitations under the License.
101 |
102 | [logo_image]: docs/logo.png
103 | [platform_image]: https://img.shields.io/badge/Platform-Android-brightgreen.svg
104 | [min_api_image]: https://img.shields.io/badge/API-9%2B-orange.svg
105 | [min_api_link]: https://android-arsenal.com/api?level=9
106 | [android_arsenal_image]: https://img.shields.io/badge/Android%20Arsenal-PagerIndicator-green.svg?style=true
107 | [android_arsenal-link]: https://android-arsenal.com/details/1/4176
108 | [version_icon]: https://img.shields.io/maven-central/v/io.github.panpf.pagerindicator/pagerindicator
109 | [version_link]: https://repo1.maven.org/maven2/io/github/panpf/pagerindicator/
110 | [sample_image]: docs/sample.gif
111 | [sample_image2]: docs/sample2.png
112 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/sample/src/main/java/me/panpf/pagerid/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package me.panpf.pagerid.sample;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.annotation.TargetApi;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.support.v4.view.ViewPager;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.view.LayoutInflater;
12 | import android.view.Menu;
13 | import android.view.MenuItem;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.Random;
22 |
23 | import me.panpf.pagerid.PagerIndicator;
24 |
25 | public class MainActivity extends AppCompatActivity {
26 | private static final int[] colors = new int[]{Colors.SKYBLUE, Colors.CHOCOLATE, Colors.CYAN, Colors.FUCHSIA, Colors.GOLD, Colors.BLUE, Colors.GREEN, Colors.RED, Colors.YELLOW, Colors.GRAY};
27 |
28 | @Override
29 | public void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_sliding_tab_strip);
32 |
33 | PagerIndicator pagerIndicator1 = (PagerIndicator) findViewById(R.id.slidingTabStrip_1);
34 | PagerIndicator pagerIndicator2 = (PagerIndicator) findViewById(R.id.slidingTabStrip_2);
35 | PagerIndicator pagerIndicator3 = (PagerIndicator) findViewById(R.id.slidingTabStrip_3);
36 | PagerIndicator pagerIndicator4 = (PagerIndicator) findViewById(R.id.slidingTabStrip_4);
37 | ViewPager viewPager1 = (ViewPager) findViewById(R.id.viewPager_1);
38 | ViewPager viewPager2 = (ViewPager) findViewById(R.id.viewPager_2);
39 | ViewPager viewPager3 = (ViewPager) findViewById(R.id.viewPager_3);
40 | ViewPager viewPager4 = (ViewPager) findViewById(R.id.viewPager_4);
41 |
42 | pagerIndicator3.setTabViewFactory(new PagerIndicator.TabViewFactory() {
43 | @Override
44 | public void addTabs(ViewGroup parent, int currentItemPosition) {
45 | parent.removeAllViews();
46 |
47 | TextView textView1 = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tab, parent, false);
48 | textView1.setText("详情");
49 | parent.addView(textView1);
50 |
51 | TextView textView2 = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tab, parent, false);
52 | textView2.setText("评论");
53 | parent.addView(textView2);
54 |
55 | TextView textView3 = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tab, parent, false);
56 | textView3.setText("攻略");
57 | parent.addView(textView3);
58 | }
59 | });
60 |
61 | pagerIndicator4.setTabViewFactory(new PagerIndicator.TabViewFactory() {
62 | @Override
63 | public void addTabs(ViewGroup parent, int currentItemPosition) {
64 | parent.removeAllViews();
65 |
66 | TextView textView1 = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tab, parent, false);
67 | textView1.setText("聊天");
68 | parent.addView(textView1);
69 |
70 | TextView textView2 = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tab, parent, false);
71 | textView2.setText("发现");
72 | parent.addView(textView2);
73 | }
74 | });
75 |
76 | init(0, pagerIndicator1, viewPager1);
77 | init(1, pagerIndicator2, viewPager2);
78 | init(2, pagerIndicator3, viewPager3);
79 | init(3, pagerIndicator4, viewPager4);
80 | }
81 |
82 | private void init(int index, PagerIndicator pagerIndicator, ViewPager viewPager) {
83 | int length = pagerIndicator.getTabCount();
84 | List views = new ArrayList(length);
85 | Random random = new Random();
86 | for (int w = 0; w < length; w++) {
87 | views.add(getContentView(colors[Math.abs(random.nextInt()) % colors.length]));
88 | }
89 | viewPager.setAdapter(new ViewPagerAdapter(views));
90 | viewPager.setCurrentItem(index < length ? index : length);
91 | pagerIndicator.setViewPager(viewPager);
92 |
93 | pagerIndicator.setOnClickTabListener(new PagerIndicator.OnClickTabListener() {
94 | @Override
95 | public void onClickTab(View tab, int index) {
96 | Toast.makeText(getBaseContext(), "点了第" + (index + 1) + "个TAB", Toast.LENGTH_SHORT).show();
97 | }
98 | });
99 |
100 | pagerIndicator.setOnDoubleClickTabListener(new PagerIndicator.OnDoubleClickTabListener() {
101 | @Override
102 | public void onDoubleClickTab(View view, int index) {
103 | Toast.makeText(getBaseContext(), "双击了第" + (index + 1) + "个TAB", Toast.LENGTH_SHORT).show();
104 | }
105 | });
106 | }
107 |
108 | private View getContentView(int color) {
109 | View view = new View(getBaseContext());
110 | view.setBackgroundColor(color);
111 | return view;
112 | }
113 |
114 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
115 | @SuppressLint({"NewApi", "AlwaysShowAction"})
116 | @Override
117 | public boolean onCreateOptionsMenu(Menu menu) {
118 | MenuItem menuItem = menu.add("GitHub");
119 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
120 | menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
121 | }
122 | return super.onCreateOptionsMenu(menu);
123 | }
124 |
125 | @Override
126 | public boolean onOptionsItemSelected(MenuItem item) {
127 | Intent intent = new Intent(Intent.ACTION_VIEW);
128 | intent.setData(Uri.parse("https://github.com/panpf/pager-indicator"));
129 | startActivity(intent);
130 | return super.onOptionsItemSelected(item);
131 | }
132 | }
--------------------------------------------------------------------------------
/sample/src/main/java/me/panpf/pagerid/sample/Colors.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Peng fei Pan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package me.panpf.pagerid.sample;
17 |
18 | /**
19 | * 提供一些常用的颜色
20 | */
21 | public class Colors {
22 | /** 白色 */
23 | public static final int WHITE = 0xffffffff;
24 |
25 | /** 白色 - 半透明 */
26 | public static final int WHITE_TRANSLUCENT = 0x80ffffff;
27 |
28 | /** 黑色 */
29 | public static final int BLACK = 0xff000000;
30 |
31 | /** 黑色 - 半透明 */
32 | public static final int BLACK_TRANSLUCENT = 0x80000000;
33 |
34 | /** 透明 */
35 | public static final int TRANSPARENT = 0x00000000;
36 |
37 | /** 红色 */
38 | public static final int RED = 0xffff0000;
39 |
40 | /** 红色 - 半透明 */
41 | public static final int RED_TRANSLUCENT = 0x80ff0000;
42 |
43 | /** 红色 - 深的 */
44 | public static final int RED_DARK = 0xff8b0000;
45 |
46 | /** 红色 - 深的 - 半透明 */
47 | public static final int RED_DARK_TRANSLUCENT = 0x808b0000;
48 |
49 | /** 绿色 */
50 | public static final int GREEN = 0xff00ff00;
51 |
52 | /** 绿色 - 半透明 */
53 | public static final int GREEN_TRANSLUCENT = 0x8000ff00;
54 |
55 | /** 绿色 - 深的 */
56 | public static final int GREEN_DARK = 0xff003300;
57 |
58 | /** 绿色 - 深的 - 半透明 */
59 | public static final int GREEN_DARK_TRANSLUCENT = 0x80003300;
60 |
61 | /** 绿色 - 浅的 */
62 | public static final int GREEN_LIGHT = 0xffccffcc;
63 |
64 | /** 绿色 - 浅的 - 半透明 */
65 | public static final int GREEN_LIGHT_TRANSLUCENT = 0x80ccffcc;
66 |
67 | /** 蓝色 */
68 | public static final int BLUE = 0xff0000ff;
69 |
70 | /** 蓝色 - 半透明 */
71 | public static final int BLUE_TRANSLUCENT = 0x800000ff;
72 |
73 | /** 蓝色 - 深的 */
74 | public static final int BLUE_DARK = 0xff00008b;
75 |
76 | /** 蓝色 - 深的 - 半透明 */
77 | public static final int BLUE_DARK_TRANSLUCENT = 0x8000008b;
78 |
79 | /** 蓝色 - 浅的 */
80 | public static final int BLUE_LIGHT = 0xff36a5E3;
81 |
82 | /** 蓝色 - 浅的 - 半透明 */
83 | public static final int BLUE_LIGHT_TRANSLUCENT = 0x8036a5E3;
84 |
85 | /** 天蓝 */
86 | public static final int SKYBLUE = 0xff87ceeb;
87 |
88 | /** 天蓝 - 半透明 */
89 | public static final int SKYBLUE_TRANSLUCENT = 0x8087ceeb;
90 |
91 | /** 天蓝 - 深的 */
92 | public static final int SKYBLUE_DARK = 0xff00bfff;
93 |
94 | /** 天蓝 - 深的 - 半透明 */
95 | public static final int SKYBLUE_DARK_TRANSLUCENT = 0x8000bfff;
96 |
97 | /** 天蓝 - 浅的 */
98 | public static final int SKYBLUE_LIGHT = 0xff87cefa;
99 |
100 | /** 天蓝 - 浅的 - 半透明 */
101 | public static final int SKYBLUE_LIGHT_TRANSLUCENT = 0x8087cefa;
102 |
103 | /** 灰色 */
104 | public static final int GRAY = 0xff969696;
105 |
106 | /** 灰色 - 半透明 */
107 | public static final int GRAY_TRANSLUCENT = 0x80969696;
108 |
109 | /** 灰色 - 深的 */
110 | public static final int GRAY_DARK = 0xffa9a9a9;
111 |
112 | /** 灰色 - 深的 - 半透明 */
113 | public static final int GRAY_DARK_TRANSLUCENT = 0x80a9a9a9;
114 |
115 | /** 灰色 - 暗的 */
116 | public static final int GRAY_DIM = 0xff696969;
117 |
118 | /** 灰色 - 暗的 - 半透明 */
119 | public static final int GRAY_DIM_TRANSLUCENT = 0x80696969;
120 |
121 | /** 灰色 - 浅的 */
122 | public static final int GRAY_LIGHT = 0xffd3d3d3;
123 |
124 | /** 灰色 - 浅的 - 半透明 */
125 | public static final int GRAY_LIGHT_TRANSLUCENT = 0x80d3d3d3;
126 |
127 | /** 橙色 */
128 | public static final int ORANGE = 0xffffa500;
129 |
130 | /** 橙色 - 半透明 */
131 | public static final int ORANGE_TRANSLUCENT = 0x80ffa500;
132 |
133 | /** 橙色 - 深的 */
134 | public static final int ORANGE_DARK = 0xffff8800;
135 |
136 | /** 橙色 - 深的 - 半透明 */
137 | public static final int ORANGE_DARK_TRANSLUCENT = 0x80ff8800;
138 |
139 | /** 橙色 - 浅的 */
140 | public static final int ORANGE_LIGHT = 0xffffbb33;
141 |
142 | /** 橙色 - 浅的 - 半透明 */
143 | public static final int ORANGE_LIGHT_TRANSLUCENT = 0x80ffbb33;
144 |
145 | /** 金色 */
146 | public static final int GOLD = 0xffffd700;
147 |
148 | /** 金色 - 半透明 */
149 | public static final int GOLD_TRANSLUCENT = 0x80ffd700;
150 |
151 | /** 粉色 */
152 | public static final int PINK = 0xffffc0cb;
153 |
154 | /** 粉色 - 半透明 */
155 | public static final int PINK_TRANSLUCENT = 0x80ffc0cb;
156 |
157 | /** 紫红色 */
158 | public static final int FUCHSIA = 0xffff00ff;
159 |
160 | /** 紫红色 - 半透明 */
161 | public static final int FUCHSIA_TRANSLUCENT = 0x80ff00ff;
162 |
163 | /** 灰白色 */
164 | public static final int GRAYWHITE = 0xfff2f2f2;
165 |
166 | /** 灰白色 - 半透明 */
167 | public static final int GRAYWHITE_TRANSLUCENT = 0x80f2f2f2;
168 |
169 | /** 紫色 */
170 | public static final int PURPLE = 0xff800080;
171 |
172 | /** 紫色 - 半透明 */
173 | public static final int PURPLE_TRANSLUCENT = 0x80800080;
174 |
175 | /** 青色 */
176 | public static final int CYAN = 0xff00ffff;
177 |
178 | /** 青色 - 半透明 */
179 | public static final int CYAN_TRANSLUCENT = 0x8000ffff;
180 |
181 | /** 青色 - 深的 */
182 | public static final int CYAN_DARK = 0xff008b8b;
183 |
184 | /** 青色 - 深的 - 半透明 */
185 | public static final int CYAN_DARK_TRANSLUCENT = 0x80008b8b;
186 |
187 | /** 黄色 */
188 | public static final int YELLOW = 0xffffff00;
189 |
190 | /** 黄色 - 半透明 */
191 | public static final int YELLOW_TRANSLUCENT = 0x80ffff00;
192 |
193 | /** 黄色 - 浅的 */
194 | public static final int YELLOW_LIGHT = 0xffffffe0;
195 |
196 | /** 黄色 - 浅的 - 半透明 */
197 | public static final int YELLOW_LIGHT_TRANSLUCENT = 0x80ffffe0;
198 |
199 | /** 巧克力色 */
200 | public static final int CHOCOLATE = 0xffd2691e;
201 |
202 | /** 巧克力色 - 半透明 */
203 | public static final int CHOCOLATE_TRANSLUCENT = 0x80d2691e;
204 |
205 | /** 番茄色 */
206 | public static final int TOMATO = 0xffff6347;
207 |
208 | /** 番茄色 - 半透明 */
209 | public static final int TOMATO_TRANSLUCENT = 0x80ff6347;
210 |
211 | /** 橙红色 */
212 | public static final int ORANGERED = 0xffff4500;
213 |
214 | /** 橙红色 - 半透明 */
215 | public static final int ORANGERED_TRANSLUCENT = 0x80ff4500;
216 |
217 | /** 银白色 */
218 | public static final int SILVER = 0xffc0c0c0;
219 |
220 | /** 银白色 - 半透明 */
221 | public static final int SILVER_TRANSLUCENT = 0x80c0c0c0;
222 |
223 | /** 高光 */
224 | public static final int HIGHLIGHT = 0x33ffffff;
225 |
226 | /** 低光 */
227 | public static final int LOWLIGHT = 0x33000000;
228 | }
229 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_sliding_tab_strip.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
20 |
21 |
24 |
25 |
28 |
29 |
32 |
33 |
36 |
37 |
40 |
41 |
44 |
45 |
48 |
49 |
52 |
53 |
56 |
57 |
60 |
61 |
64 |
65 |
68 |
69 |
72 |
73 |
76 |
77 |
80 |
81 |
84 |
85 |
86 |
87 |
91 |
92 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
108 |
109 |
116 |
117 |
120 |
121 |
124 |
125 |
128 |
129 |
132 |
133 |
136 |
137 |
138 |
139 |
143 |
144 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
160 |
161 |
166 |
167 |
171 |
172 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
188 |
189 |
195 |
196 |
200 |
201 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/pager-indicator/src/main/java/me/panpf/pagerid/PagerIndicator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Peng fei Pan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package me.panpf.pagerid;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.Canvas;
22 | import android.graphics.Paint;
23 | import android.graphics.drawable.Drawable;
24 | import android.os.Build;
25 | import android.support.v4.view.ViewPager;
26 | import android.support.v4.view.ViewPager.OnPageChangeListener;
27 | import android.util.AttributeSet;
28 | import android.view.GestureDetector;
29 | import android.view.Gravity;
30 | import android.view.MotionEvent;
31 | import android.view.View;
32 | import android.view.ViewGroup;
33 | import android.view.ViewTreeObserver;
34 | import android.widget.HorizontalScrollView;
35 | import android.widget.LinearLayout;
36 |
37 | import java.util.ArrayList;
38 | import java.util.Iterator;
39 | import java.util.List;
40 |
41 | /**
42 | * 专为 ViewPager 定制的页面指示器
43 | */
44 | public class PagerIndicator extends HorizontalScrollView {
45 | private int currentPosition; //当前位置
46 | private int lastOffset;
47 | private int lastScrollX = 0;
48 | private float currentPositionOffset; //当前位置偏移量
49 | private boolean start;
50 | private boolean allowWidthFull; // 内容宽度无法充满时,允许自动调整Item的宽度以充满
51 | private boolean disableViewPager; // 禁用ViewPager
52 | private Drawable slidingBlockDrawable; //滑块
53 | private ViewPager viewPager; //ViewPager
54 | private ViewGroup tabsLayout; //标题项布局
55 | private ViewPager.OnPageChangeListener onPageChangeListener; //页面改变监听器
56 | private OnClickTabListener onClickTabListener;
57 | private OnDoubleClickTabListener onDoubleClickTabListener;
58 | private List tabViews;
59 | private boolean disableTensileSlidingBlock; // 禁止拉伸滑块图片
60 | private TabViewFactory tabViewFactory;
61 | private Paint bottomLinePaint;
62 | private int bottomLineColor = -1;
63 | private int bottomLineHeight = -1;
64 | private final PageChangedListener pageChangedListener = new PageChangedListener();
65 | private final TabViewClickListener tabViewClickListener = new TabViewClickListener();
66 | private final SetSelectedTabListener setSelectedTabListener = new SetSelectedTabListener();
67 | private final DoubleClickGestureDetector tabViewDoubleClickGestureDetector;
68 |
69 | public PagerIndicator(Context context) {
70 | this(context, null);
71 | }
72 |
73 | public PagerIndicator(Context context, AttributeSet attrs) {
74 | super(context, attrs);
75 | setHorizontalScrollBarEnabled(false); //隐藏横向滑动提示条
76 | removeAllViews();
77 | if (attrs != null) {
78 | TypedArray attrsTypedArray = context.obtainStyledAttributes(attrs, R.styleable.PagerIndicator);
79 | if (attrsTypedArray != null) {
80 | allowWidthFull = attrsTypedArray.getBoolean(R.styleable.PagerIndicator_pi_allowWidthFull, false);
81 | slidingBlockDrawable = attrsTypedArray.getDrawable(R.styleable.PagerIndicator_pi_slidingBlock);
82 | disableViewPager = attrsTypedArray.getBoolean(R.styleable.PagerIndicator_pi_disableViewPager, false);
83 | disableTensileSlidingBlock = attrsTypedArray.getBoolean(R.styleable.PagerIndicator_pi_disableTensileSlidingBlock, false);
84 | bottomLineColor = attrsTypedArray.getColor(R.styleable.PagerIndicator_pi_bottomLineColor, -1);
85 | bottomLineHeight = (int) attrsTypedArray.getDimension(R.styleable.PagerIndicator_pi_bottomLineHeight, -1);
86 | attrsTypedArray.recycle();
87 | }
88 | }
89 | tabViewDoubleClickGestureDetector = new DoubleClickGestureDetector(context);
90 |
91 | getViewTreeObserver().addOnGlobalLayoutListener(setSelectedTabListener);
92 | }
93 |
94 | @Override
95 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
96 | if (allowWidthFull && tabsLayout != null) {
97 | View childView;
98 | for (int w = 0, size = tabsLayout.getChildCount(); w < size; w++) {
99 | childView = tabsLayout.getChildAt(w);
100 | ViewGroup.LayoutParams params = childView.getLayoutParams();
101 | params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
102 | childView.setLayoutParams(params);
103 | }
104 | }
105 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
106 |
107 | if (!allowWidthFull) {
108 | return;
109 | }
110 | ViewGroup tabsLayout = getTabsLayout();
111 | if (tabsLayout == null) {
112 | return;
113 | }
114 | if (tabsLayout.getChildCount() <= 0) {
115 | return;
116 | }
117 |
118 | if (tabViews == null) {
119 | tabViews = new ArrayList();
120 | } else {
121 | tabViews.clear();
122 | }
123 | for (int w = 0; w < tabsLayout.getChildCount(); w++) {
124 | tabViews.add(tabsLayout.getChildAt(w));
125 | }
126 |
127 | adjustChildWidthWithParent(tabViews, getMeasuredWidth() - tabsLayout.getPaddingLeft() - tabsLayout.getPaddingRight(), widthMeasureSpec, heightMeasureSpec);
128 |
129 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
130 | }
131 |
132 | /**
133 | * 调整views集合中的View,让所有View的宽度加起来正好等于parentViewWidth
134 | *
135 | * @param views 子View集合
136 | * @param parentViewWidth 父Vie的宽度
137 | * @param parentWidthMeasureSpec 父View的宽度规则
138 | * @param parentHeightMeasureSpec 父View的高度规则
139 | */
140 | private void adjustChildWidthWithParent(List views, int parentViewWidth, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
141 | // 先去掉所有子View的外边距
142 | for (View view : views) {
143 | if (view.getLayoutParams() instanceof MarginLayoutParams) {
144 | LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
145 | parentViewWidth -= lp.leftMargin + lp.rightMargin;
146 | }
147 | }
148 |
149 | // 去掉宽度大于平均宽度的View后再次计算平均宽度
150 | int averageWidth = parentViewWidth / views.size();
151 | int bigTabCount = views.size();
152 | while (true) {
153 | Iterator iterator = views.iterator();
154 | while (iterator.hasNext()) {
155 | View view = iterator.next();
156 | if (view.getMeasuredWidth() > averageWidth) {
157 | parentViewWidth -= view.getMeasuredWidth();
158 | bigTabCount--;
159 | iterator.remove();
160 | }
161 | }
162 | if (bigTabCount <= 0) {
163 | break;
164 | }
165 | averageWidth = parentViewWidth / bigTabCount;
166 | boolean end = true;
167 | for (View view : views) {
168 | if (view.getMeasuredWidth() > averageWidth) {
169 | end = false;
170 | }
171 | }
172 | if (end) {
173 | break;
174 | }
175 | }
176 |
177 | // 修改宽度小于新的平均宽度的View的宽度
178 | for (View view : views) {
179 | if (view.getMeasuredWidth() < averageWidth) {
180 | LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams();
181 | layoutParams.width = averageWidth;
182 | view.setLayoutParams(layoutParams);
183 | // 再次测量让新宽度生效
184 | if (layoutParams instanceof MarginLayoutParams) {
185 | measureChildWithMargins(view, parentWidthMeasureSpec, 0, parentHeightMeasureSpec, 0);
186 | } else {
187 | measureChild(view, parentWidthMeasureSpec, parentHeightMeasureSpec);
188 | }
189 | }
190 | }
191 | }
192 |
193 | @Override
194 | protected void onDraw(Canvas canvas) {
195 | super.onDraw(canvas);
196 | if (bottomLineColor != -1 && bottomLineHeight != -1) {
197 | if (bottomLinePaint == null) {
198 | bottomLinePaint = new Paint();
199 | bottomLinePaint.setColor(bottomLineColor);
200 | }
201 | canvas.drawRect(0, getBottom() - bottomLineHeight, getRight(), getBottom(), bottomLinePaint);
202 | }
203 |
204 | if (disableViewPager) return;
205 | /* 绘制滑块 */
206 | ViewGroup tabsLayout = getTabsLayout();
207 | if (tabsLayout != null && tabsLayout.getChildCount() > 0 && slidingBlockDrawable != null) {
208 | View currentTab = tabsLayout.getChildAt(currentPosition);
209 | if (currentTab != null) {
210 | float slidingBlockLeft = currentTab.getLeft();
211 | float slidingBlockRight = currentTab.getRight();
212 | if (currentPositionOffset > 0f && currentPosition < tabsLayout.getChildCount() - 1) {
213 | View nextTab = tabsLayout.getChildAt(currentPosition + 1);
214 | if (nextTab != null) {
215 | final float nextTabLeft = nextTab.getLeft();
216 | final float nextTabRight = nextTab.getRight();
217 | slidingBlockLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * slidingBlockLeft);
218 | slidingBlockRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * slidingBlockRight);
219 | }
220 | }
221 |
222 | // 不拉伸
223 | if (disableTensileSlidingBlock) {
224 | int center = (int) (slidingBlockLeft + (slidingBlockRight - slidingBlockLeft) / 2);
225 | slidingBlockLeft = center - slidingBlockDrawable.getIntrinsicWidth() / 2;
226 | slidingBlockRight = center + slidingBlockDrawable.getIntrinsicWidth() / 2;
227 | }
228 |
229 | slidingBlockDrawable.setBounds((int) slidingBlockLeft, getHeight() - slidingBlockDrawable.getIntrinsicHeight(), (int) slidingBlockRight, getHeight());
230 | slidingBlockDrawable.draw(canvas);
231 | }
232 | }
233 | }
234 |
235 | /**
236 | * 获取布局
237 | */
238 | private ViewGroup getTabsLayout() {
239 | if (tabsLayout == null) {
240 | if (getChildCount() > 0) {
241 | tabsLayout = (ViewGroup) getChildAt(0);
242 | } else {
243 | removeAllViews();
244 | LinearLayout tabsLayout = new LinearLayout(getContext());
245 | tabsLayout.setGravity(Gravity.CENTER_VERTICAL);
246 | this.tabsLayout = tabsLayout;
247 | addView(tabsLayout, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL));
248 | }
249 | }
250 | return tabsLayout;
251 | }
252 |
253 | /**
254 | * 重置,清除所有tab
255 | */
256 | public void reset() {
257 | if (tabViewFactory != null) {
258 | ViewGroup tabViewGroup = getTabsLayout();
259 | tabViewFactory.addTabs(tabViewGroup, viewPager != null ? viewPager.getCurrentItem() : 0);
260 | setTabClickEvent();
261 | }
262 | }
263 |
264 | private void setTabClickEvent(){
265 | ViewGroup tabViewGroup = getTabsLayout();
266 | if(tabViewGroup != null && tabViewGroup.getChildCount() > 0){
267 | //给每一个tab设置点击事件,当点击的时候切换Pager
268 | for (int w = 0; w < tabViewGroup.getChildCount(); w++) {
269 | View itemView = tabViewGroup.getChildAt(w);
270 | itemView.setTag(w);
271 | itemView.setOnClickListener(tabViewClickListener);
272 | itemView.setOnTouchListener(tabViewDoubleClickGestureDetector);
273 | }
274 | }
275 | }
276 |
277 | /**
278 | * 获取Tab
279 | *
280 | * @param position 位置
281 | * @return Tab的View
282 | */
283 | @SuppressWarnings("unused")
284 | public View getTab(int position) {
285 | if (tabsLayout != null && tabsLayout.getChildCount() > position) {
286 | return tabsLayout.getChildAt(position);
287 | } else {
288 | return null;
289 | }
290 | }
291 |
292 | /**
293 | * 滚动到指定的位置
294 | */
295 | private void scrollToChild(int position, int offset) {
296 | ViewGroup tabsLayout = getTabsLayout();
297 | if (tabsLayout != null && tabsLayout.getChildCount() > 0 && position < tabsLayout.getChildCount()) {
298 | View view = tabsLayout.getChildAt(position);
299 | if (view != null) {
300 | //计算新的X坐标
301 | int newScrollX = view.getLeft() + offset - getLeftMargin(view);
302 | if (position > 0 || offset > 0) {
303 | newScrollX -= getWidth() / 2 - getOffset(view.getWidth()) / 2;
304 | }
305 |
306 | //如果同上次X坐标不一样就执行滚动
307 | if (newScrollX != lastScrollX) {
308 | lastScrollX = newScrollX;
309 | scrollTo(newScrollX, 0);
310 | }
311 | }
312 | }
313 | }
314 |
315 | private int getLeftMargin(View view) {
316 | ViewGroup.LayoutParams params = view.getLayoutParams();
317 | if (params instanceof MarginLayoutParams) {
318 | MarginLayoutParams marginParams = (MarginLayoutParams) params;
319 | return marginParams.leftMargin;
320 | }
321 | return 0;
322 | }
323 |
324 | private int getRightMargin(View view) {
325 | ViewGroup.LayoutParams params = view.getLayoutParams();
326 | if (params instanceof MarginLayoutParams) {
327 | MarginLayoutParams marginParams = (MarginLayoutParams) params;
328 | return marginParams.rightMargin;
329 | }
330 | return 0;
331 | }
332 |
333 | /**
334 | * 获取偏移量
335 | */
336 | private int getOffset(int newOffset) {
337 | if (lastOffset < newOffset) {
338 | if (start) {
339 | lastOffset += 1;
340 | return lastOffset;
341 | } else {
342 | start = true;
343 | lastOffset += 1;
344 | return lastOffset;
345 | }
346 | }
347 | if (lastOffset > newOffset) {
348 | if (start) {
349 | lastOffset -= 1;
350 | return lastOffset;
351 | } else {
352 | start = true;
353 | lastOffset -= 1;
354 | return lastOffset;
355 | }
356 | } else {
357 | start = true;
358 | lastOffset = newOffset;
359 | return lastOffset;
360 | }
361 | }
362 |
363 | /**
364 | * 选中指定位置的TAB
365 | */
366 | private void selectedTab(int newSelectedTabPosition) {
367 | ViewGroup tabsLayout = getTabsLayout();
368 | if (newSelectedTabPosition > -1 && tabsLayout != null && newSelectedTabPosition < tabsLayout.getChildCount()) {
369 | for (int w = 0, size = tabsLayout.getChildCount(); w < size; w++) {
370 | View tabView = tabsLayout.getChildAt(w);
371 | tabView.setSelected(w == newSelectedTabPosition);
372 | }
373 | }
374 | }
375 |
376 | /**
377 | * 设置ViewPager
378 | *
379 | * @param viewPager ViewPager
380 | */
381 | public void setViewPager(ViewPager viewPager) {
382 | if (disableViewPager) return;
383 | this.viewPager = viewPager;
384 | this.viewPager.addOnPageChangeListener(pageChangedListener);
385 | setTabClickEvent();
386 | requestLayout();
387 | }
388 |
389 | /**
390 | * 设置Page切换监听器
391 | *
392 | * @param onPageChangeListener Page切换监听器
393 | */
394 | @SuppressWarnings("unused")
395 | public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
396 | this.onPageChangeListener = onPageChangeListener;
397 | }
398 |
399 | /**
400 | * 设置是否充满屏幕
401 | *
402 | * @param allowWidthFull true:当内容的宽度无法充满屏幕时,自动调整每一个Item的宽度以充满屏幕
403 | */
404 | public void setAllowWidthFull(boolean allowWidthFull) {
405 | this.allowWidthFull = allowWidthFull;
406 | requestLayout();
407 | }
408 |
409 | /**
410 | * 设置滑块图片
411 | */
412 | @SuppressWarnings("unused")
413 | public void setSlidingBlockDrawable(Drawable slidingBlockDrawable) {
414 | this.slidingBlockDrawable = slidingBlockDrawable;
415 | requestLayout();
416 | }
417 |
418 | /**
419 | * 获取滑块图片
420 | */
421 | @SuppressWarnings("unused")
422 | public Drawable getSlidingBlockDrawable() {
423 | return slidingBlockDrawable;
424 | }
425 |
426 | /**
427 | * 设置是否禁止拉伸滑块图片
428 | *
429 | * @param disableTensileSlidingBlock 是否禁止拉伸滑块图片
430 | */
431 | @SuppressWarnings("unused")
432 | public void setDisableTensileSlidingBlock(boolean disableTensileSlidingBlock) {
433 | this.disableTensileSlidingBlock = disableTensileSlidingBlock;
434 | invalidate();
435 | }
436 |
437 | /**
438 | * 获取Tab总数
439 | */
440 | public int getTabCount() {
441 | ViewGroup tabsLayout = getTabsLayout();
442 | return tabsLayout != null ? tabsLayout.getChildCount() : 0;
443 | }
444 |
445 | /**
446 | * 设置Tab点击监听器
447 | *
448 | * @param onClickTabListener Tab点击监听器
449 | */
450 | @SuppressWarnings("unused")
451 | public void setOnClickTabListener(OnClickTabListener onClickTabListener) {
452 | this.onClickTabListener = onClickTabListener;
453 | }
454 |
455 | /**
456 | * 设置TAB双击监听器
457 | *
458 | * @param onDoubleClickTabListener TAB双击监听器
459 | */
460 | public void setOnDoubleClickTabListener(OnDoubleClickTabListener onDoubleClickTabListener) {
461 | this.onDoubleClickTabListener = onDoubleClickTabListener;
462 | }
463 |
464 | /**
465 | * 设置不使用ViewPager
466 | *
467 | * @param disableViewPager 不使用ViewPager
468 | */
469 | @SuppressWarnings("unused")
470 | public void setDisableViewPager(boolean disableViewPager) {
471 | this.disableViewPager = disableViewPager;
472 | if (viewPager != null) {
473 | viewPager.removeOnPageChangeListener(onPageChangeListener);
474 | viewPager = null;
475 | }
476 | requestLayout();
477 | }
478 |
479 | /**
480 | * 设置TabView生成器
481 | *
482 | * @param tabViewFactory TabView生成器
483 | */
484 | @SuppressWarnings("unused")
485 | public void setTabViewFactory(TabViewFactory tabViewFactory) {
486 | this.tabViewFactory = tabViewFactory;
487 |
488 | reset();
489 |
490 | getViewTreeObserver().addOnGlobalLayoutListener(setSelectedTabListener);
491 | }
492 |
493 | /**
494 | * 设置底线的颜色
495 | *
496 | * @param bottomLineColor 底线的颜色
497 | */
498 | @SuppressWarnings("unused")
499 | public void setBottomLineColor(int bottomLineColor) {
500 | this.bottomLineColor = bottomLineColor;
501 | if (bottomLinePaint != null) {
502 | bottomLinePaint.setColor(bottomLineColor);
503 | }
504 | postInvalidate();
505 | }
506 |
507 | /**
508 | * 设置底线的高度
509 | *
510 | * @param bottomLineHeight 底线的高度
511 | */
512 | @SuppressWarnings("unused")
513 | public void setBottomLineHeight(int bottomLineHeight) {
514 | this.bottomLineHeight = bottomLineHeight;
515 | postInvalidate();
516 | }
517 |
518 | /**
519 | * Tab点击监听器
520 | */
521 | public interface OnClickTabListener {
522 | void onClickTab(View tab, int index);
523 | }
524 |
525 | /**
526 | * Tab双击监听器
527 | */
528 | public interface OnDoubleClickTabListener {
529 | void onDoubleClickTab(View view, int index);
530 | }
531 |
532 | /**
533 | * TabView生成器
534 | */
535 | public interface TabViewFactory {
536 | /**
537 | * 添加tab
538 | *
539 | * @param parent 父View
540 | * @param currentItemPosition 当前选中的位置
541 | */
542 | void addTabs(ViewGroup parent, int currentItemPosition);
543 | }
544 |
545 | private class PageChangedListener implements ViewPager.OnPageChangeListener {
546 | @Override
547 | public void onPageSelected(int position) {
548 | selectedTab(position);
549 | if (onPageChangeListener != null) {
550 | onPageChangeListener.onPageSelected(position);
551 | }
552 | }
553 |
554 | @Override
555 | public void onPageScrolled(int nextPagePosition, float positionOffset, int positionOffsetPixels) {
556 | ViewGroup tabsLayout = getTabsLayout();
557 | if (nextPagePosition < tabsLayout.getChildCount()) {
558 | View view = tabsLayout.getChildAt(nextPagePosition);
559 | if (view != null) {
560 | currentPosition = nextPagePosition;
561 | currentPositionOffset = positionOffset;
562 | scrollToChild(nextPagePosition, (int) (positionOffset * (view.getWidth() + getLeftMargin(view) + getRightMargin(view))));
563 | invalidate();
564 | }
565 | }
566 | if (onPageChangeListener != null) {
567 | onPageChangeListener.onPageScrolled(nextPagePosition, positionOffset, positionOffsetPixels);
568 | }
569 | }
570 |
571 | @Override
572 | public void onPageScrollStateChanged(int arg0) {
573 | if (onPageChangeListener != null) {
574 | onPageChangeListener.onPageScrollStateChanged(arg0);
575 | }
576 | }
577 | }
578 |
579 | private class TabViewClickListener implements OnClickListener {
580 | @Override
581 | public void onClick(View v) {
582 | int index = (Integer) v.getTag();
583 | if (onClickTabListener != null) {
584 | onClickTabListener.onClickTab(v, index);
585 | }
586 | if (viewPager != null) {
587 | viewPager.setCurrentItem(index, true);
588 | }
589 | }
590 | }
591 |
592 | private class SetSelectedTabListener implements ViewTreeObserver.OnGlobalLayoutListener {
593 | @Override
594 | public void onGlobalLayout() {
595 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
596 | getViewTreeObserver().removeGlobalOnLayoutListener(this);
597 | } else {
598 | getViewTreeObserver().removeOnGlobalLayoutListener(this);
599 | }
600 |
601 | ViewGroup tabViewGroup = getTabsLayout();
602 | if (tabViewGroup != null) {
603 | currentPosition = viewPager != null ? viewPager.getCurrentItem() : 0;
604 | if (!disableViewPager) {
605 | scrollToChild(currentPosition, 0);
606 | selectedTab(currentPosition);
607 | }
608 | }
609 | }
610 | }
611 |
612 | private class DoubleClickGestureDetector extends GestureDetector.SimpleOnGestureListener implements OnTouchListener {
613 | private GestureDetector gestureDetector;
614 | private View currentView;
615 |
616 | public DoubleClickGestureDetector(Context context) {
617 | gestureDetector = new GestureDetector(context, this);
618 | gestureDetector.setOnDoubleTapListener(this);
619 | }
620 |
621 | @Override
622 | public boolean onDoubleTap(MotionEvent e) {
623 | if (onDoubleClickTabListener != null) {
624 | onDoubleClickTabListener.onDoubleClickTab(currentView, (Integer) currentView.getTag());
625 | return true;
626 | } else {
627 | return false;
628 | }
629 | }
630 |
631 | @Override
632 | public boolean onTouch(View v, MotionEvent event) {
633 | currentView = v;
634 | return gestureDetector.onTouchEvent(event);
635 | }
636 | }
637 | }
--------------------------------------------------------------------------------