# GodIndicator
**Repository Path**: coder_lzx/GodIndicator
## Basic Information
- **Project Name**: GodIndicator
- **Description**: 一款自由度、扩展度更高的ViewPager、ViewPager2指示器库。
- **Primary Language**: Android
- **License**: BSD-3-Clause
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2020-01-17
- **Last Updated**: 2021-08-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# GodIndicator
#### 介绍
一款自由度、扩展度更高的ViewPager、ViewPager2指示器库。内置标题布局样式有标准文本、角标,最大程度的支持细节上的配置,如大小、颜色、间距、角标任意方向及偏移量等配置,还支持自定义布局。指示器内置样式支持支线、带箭头全屏直线、包裹状、点状,亦最大程度上的支持细节上的配置,如显示位置、大小、颜色、渐变效果、包裹边框大小颜色等配置。本库参考了大神@hackware1993的Magicindicator库的部分想法和算法,感谢!
#### 效果
什么都不说了,直观感受效果!
#### 使用说明
##### 第一步、XML添加控件
```xml
```
> 需要指定GodIndicator的高度!
##### 第二步、绑定配置Adapter
```java
GodIndicator godIndicator = findViewById(R.id.indicator);
godIndicator.setAdapter(new GodIndicatorAdapter(viewPager) {
@Override
protected TextTitleConfig bindTitleConfig() {
return TextTitleConfig.factory();
}
@Override
protected LineIndicatorConfig bindIndicatorConfig() {
return LineIndicatorConfig.factory();
}
});
```
##### 第三步、绑定ViewPager或ViewPager2
如adapter初始化时已传入viewpager,则可以忽略此步骤
```java
godIndicator.bindViewPager(mViewPager);
```
只需三步即可实现ViewPager指示器的展示。其中setAdapter支持三种Adapter类型,后面会重点介绍。
#### 概念



为防止概念混淆,我先标注说明两部分:指示器和标题布局。
#### Adapter
内置内容适配器有三种,分别是:`GodIndicatorAdapter`、`PointIndicatorAdapter`、`LayoutIndicatorAdapter`。其中分别代表的效果是:
`GodIndicatorAdapter`:纯文字标题、支持数字角标
`PointIndicatorAdapter`:点状效果
`LayoutIndicatorAdapter`:自定义布局标题
Adapter通用外部调用方法有:
+ `getCount()`:返回数量
+ `notifyDataSetChanged()`:更新数据视图
+ `setOnScrollResultListener(OnScrollResultListener listener)`:监听滑动事件,实现接口`OnScrollResultListener `
```java
public interface OnScrollResultListener {
/**
* 正在进入某个位置
*
* @param index 正在进入哪个位置
* @param totalCount 总数
* @param enterPercent 滑动百分比,完全进入后为1
* @param leftToRight 是否左到右
*/
void onEntering(BaseIndicatorAdapter adapter, int index, int totalCount, float enterPercent, boolean leftToRight);
/**
* 正在离开某个位置
*
* @param index 正在离开哪个位置
* @param totalCount 总数
* @param leavePercent 滑动百分比,完全离开后为1
* @param leftToRight 是否左到右
*/
void onLeaving(BaseIndicatorAdapter adapter, int index, int totalCount, float leavePercent, boolean leftToRight);
/**
* 已选中
*
* @param index 选中的位置
* @param totalCount 总数
*/
void onSelected(BaseIndicatorAdapter adapter, int index, int totalCount);
/**
* 已被移除选中
*
* @param index 离开的位置
* @param totalCount 总数
*/
void onCancelSelected(BaseIndicatorAdapter adapter, int index, int totalCount);
}
```
也可以实现`OnSimpleScrollResultListener`,继承自`OnScrollResultListener`,区别在于原来的四个方法不是必须实现,新增`onTitleClick`方法用于回调用户点击了标题的事件。
```java
/**
* 点击标题事件
*
* @param position
*/
public void onTitleClick(int position) {
}
```
##### GodIndicatorAdapter
纯文字标题、支持数字角标。
```java
godIndicator.setAdapter(new GodIndicatorAdapter(viewPager) {
@Override
protected void bindGlobalConfig(GlobalConfig config) {
//全局性配置,该方法选择实现,后面会详细介绍
}
@Override
protected TextTitleConfig bindTitleConfig() {
//返回文字标题的配置,该方法必须实现,后面会详细介绍
}
@Override
public String getTitleName(int position) {
//返回对应位置的标题名称,该方法选择实现
//默认使用adapter实例化时传入的数据
//其次再使用ViewPager的adapter上的数据
//如使用ViewPager2,没有传入数据时,则需要实现此方法
}
@Override
public int getCount() {
//返回数量,该方法选择实现
//默认使用adapter实例化时传入的数据
//其次再使用ViewPager的adapter上的数据
//如使用ViewPager2,没有传入数据时,则需要实现此方法
}
@Override
protected LineIndicatorConfig bindIndicatorConfig() {
//返回指示器配置,该方法必须实现,后面会详细介绍
}
@Override
public BadgeConfig bindBadgeConfig(int position) {
BadgeConfig config = BadgeConfig.factory();
//返回角标配置,该方法按需实现,后面会详细介绍
return config;
}
@Override
public int getBadgeNumber(int position) {
//返回角标数字,用于角标数字展示
}
});
```
特有开放外部调用方法有:
`notifyBadgeDataSetChanged()`:通知更新所有角标,更新的数字依赖于方法`getBadgeNumber`的返回值
`notifyBadgeDataSetChanged(int position, int badgeNumber)`:通知某个角标更新指定数字
实现该Adapter时需要指定泛型,即指示器配置类,目前只有两种:`LineIndicatorConfig`、`WrapIndicatorConfig`分别代表指示器的线性效果配置和包裹效果配置。传入不同类型,会产生对应不同的效果。
##### PointIndicatorAdapter
点状指示器无标题效果。
```java
godIndicator.setAdapter(new PointIndicatorAdapter(viewPager) {
@Override
protected void bindGlobalConfig(GlobalConfig config) {
//全局性配置,该方法选择实现,后面会详细介绍
}
@Override
public int getCount() {
//返回数量,该方法选择实现
//默认使用ViewPager或ViewPager2的adapter中的getCount或getItemCount方法返回的数据
}
@Override
protected PointIndicatorConfig bindIndicatorConfig() {
//返回点状指示器配置,该方法必须实现,后面会详细介绍
}
});
```
##### LayoutIndicatorAdapter
自定义布局。
```java
godIndicator.setAdapter(new LayoutIndicatorAdapter(
R.layout.custom_layout_item_one,
Arrays.asList(DATAS)) {
@Override
protected void bindGlobalConfig(GlobalConfig config) {
//全局性配置,该方法选择实现,后面会详细介绍
}
@Override
protected LayoutConfig bindTitleConfig() {
//自定义布局的相关配置,后面会详细介绍
}
@Override
protected View bindItemTitleView(View view, int position, String data) {
//此处用于实例化自定义布局里的控件,使用数据进行填充控件,最后返回给库由库进行装载显示
return view;
}
@Override
protected LineIndicatorConfig bindIndicatorConfig() {
//返回指示器配置,该方法必须实现,后面会详细介绍
}
});
```
实现该Adapter时需要指定两个泛型类型。第一个与GodIndicatorAdapter一致,第二个则表示传入的数据类型。
特有开放外部调用方法有:
`getItem(int position)`:获取对应位置数据
`getItemLayoutId()`:返回布局资源id
`updateDatas(List datas)`:更新数据
`setOnItemClickListener(OnItemClickListener listener)`:设置子控件点击事件监听,实现接口`OnItemClickListener`
```java
public interface OnItemClickListener {
/**
* 点击事件回调
*
* @param adapter 适配器
* @param parentView 父控件
* @param view 触发的控件,当没有绑定子控件时则为父控件(即ITEM布局的根布局)
* @param position ITEM所在的位置
*/
void onItemClick(LayoutIndicatorAdapter adapter, View parentView, View view, int position);
}
```
#### 配置
创建配置方式统一使用工厂方法`factory`创建实例。
##### 全局配置(GlobalConfig)
默认配置为:支持超出屏幕、切换后标题Item停留位置相对可滑动距离的百分比、随手指滑动、跨页时有掠过效果。
+ `setCanOffScreen(boolean isCanOffScreen)`:是否可以超出屏幕
+ `setPercentAfterScroll(float percentAfterScroll)`:点击切换后,item位置到左边距离与整个可滑动区域的百分比(小数)
+ `setFollowFinger(boolean followFinger)`:是否跟随手指滚动
+ `setFlit(boolean flit)`:跨页时是否显示掠过
+ `setPendingLeft(int pendingLeft)`:整体控件的左间距
+ `setPendingRight(int pendingRight)`:整体控件的右间距
+ `setNormalBold(boolean isNormalBold)`:设置未选中字体是否加粗
+ `setSelectedBold(boolean isNormalBold)`:设置选中字体是否加粗
+ `setMidDividerConfig(MidDividerConfig midDividerConfig)`:设置中间分隔线的配置
##### 标题配置
+ 纯文字标题:TextTitleConfig
+ `setNormalSize(int normalSize)`:未选中的字体大小
+ `setSelectedSize(int selectedSize)`:选中的字体大小
+ `setNormalColor(int normalColor)`:未选中的字体颜色
+ `setSelectedColor(int selectedColor)`:选中的字体颜色
+ `setNormalColors(List normalColors)`:未选中的字体颜色列表
+ `setNormalColors(Integer... normalColors)`:未选中的字体颜色列表
+ `addNormalColors(int normalColor)`:添加未选中颜色到列表,支持多次添加
+ `setSelectedColors(List selectedColors)`:选中的字体颜色列表
+ `setSelectedColors(Integer... selectedColors)`:选中的字体颜色列表
+ `addSelectedColor(int selectedColor)`:添加选中颜色到列表,支持多次添加
+ `setColorGradientFollowSlide(boolean isColorGradientFollowSlide)`:颜色是否随滑动渐变
+ `setSizeFollowSlideChange(boolean sizeFollowSlideChange)`:大小是否随滑动逐渐变化
+ `setPendingLeft(int pendingLeft)`:文字左间距
+ `setPendingRight(int pendingRight)`:文字右间距
+ 自定义布局:LayoutConfig
+ 包含TextTilteConfig全部属性配置,新增以下配置:
+ `setNeedAutoChangeTxtIds(@IdRes List needAutoChangeTxtIds)`:设置需要自动切换状态的文本控件资源id列表,比如切换选中的字体颜色或大小
+ `setNeedAutoChangeTxtIds(@IdRes Integer... needAutoChangeTxtIds)`:同上
+ `setNormalTxtSizes(List normalTxtSizes)`:设置未选中时文本控件字体的大小列表,对应needAutoChangeTxtIds的id列表
+ `setNormalTxtSizes(Integer... normalTxtSizes)`:同上
+ `setSelectedTxtSizes(List selectedTxtSizes)`:设置选中时文本控件字体的大小列表,对应needAutoChangeTxtIds的id列表
+ `setSelectedTxtSizes(Integer... selectedTxtSizes)`:同上
+ `setPendingTop(int pendingTop)`:设置上间距
+ `setPendingBottom(int pendingBottom)`:设置下间距
+ `bindClickIds(@IdRes Integer... clickIds)`:绑定点击事件,绑定后,点击id对应的控件后会回调事件`OnItemClickListener`,传入该View。如果没有调用该方法绑定id,则会返回父布局的View。
##### 角标配置(BadgeConfig)
默认配置为:处于文本右上角、颜色为红色、字体白色、文字左右间距为3px、显示数字、宽度不够时自动拉伸、圆角半径为10px、字体大小为10,半径为10。
用户可自定义样式,如纯圆点、带白色边框、数字太长自动拉伸为椭圆形。直接看效果:




+ `setAnchor(int anchor)`:设置锚点方向,使用BadgeConfig.BadgeAnchor进行配置,支持或运算,如:BadgeAnchor.CONTENT_TOP | BadgeAnchor.CONTENT_RIGHT
+ `setOffsetX(float offsetX)`:设置横向偏移量
+ `setOffsetY(float offsetY)`:设置竖向偏移量
+ `setBadgeColor(int badgeColor)`:设置角标颜色
+ `setTxtColor(int txtColor)`:设置文本字体颜色
+ `setTxtSize(float txtSize)`:设置文本字体大小
+ `setTxtPendingLR(int txtPendingLR)`:设置文字左右间距
+ `setRadius(float radius)`:设置半径
+ `setShowNumber(boolean showNumber)`:设置是否显示数字
+ `setCornerRadius(float cornerRadius)`:设置圆角半径
+ `setAutoStretch(boolean autoStretch)`:设置宽度不够时是否自动拉伸
+ `setStroke(float strokeWidth, int strokeColor)`:设置增加边框,strokeWidth:边框宽度、strokeColor:边框颜色
其中`BadgeAnchor`包含以下值,可以自由搭配:
```java
/**
* 整个区域左边
*/
LEFT
/**
* 整个区域上边
*/
TOP
/**
* 整个区域右边
*/
RIGHT
/**
* 整个区域下边
*/
BOTTOM
/**
* 具体内容区域左边
*/
CONTENT_LEFT
/**
* 具体内容区域上边
*/
CONTENT_TOP
/**
* 具体内容区域右边
*/
CONTENT_RIGHT
/**
* 具体内容区域下边
*/
CONTENT_BOTTOM
/**
* 整个区域横向中间
*/
CENTER_X
/**
* 整个区域竖向中间
*/
CENTER_Y
/**
* 左边空隙横向中间
*/
LEFT_EDGE_CENTER_X
/**
* 上边空隙竖向中间
*/
TOP_EDGE_CENTER_Y
/**
* 右边空隙横向中间
*/
RIGHT_EDGE_CENTER_X
/**
* 下边空隙竖向中间
*/
BOTTOM_EDGE_CENTER_Y
```
##### 指示器配置
+ 线性效果配置:LineIndicatorConfi
默认配置为:矩形、宽度全占、颜色随滑动逐渐变化、高度10px、白色。
+ `setShapeType(@IndicatorShapeType int shapeType)`:设置指示器形状,支持矩形、圆形、圆角矩形
+ `setColors(ArrayList colors)`:支持设置多个颜色,优先取用颜色列表
+ `addColor(int color)`:添加颜色到列表,支持多次添加
+ `setColor(int color)`:设置颜色,优先取用颜色列表
+ `setStartInterpolator(Interpolator interpolator)`:起点动画的插值器
+ `setEndInterpolator(Interpolator interpolator)`:终点动画的插值器
+ `setColorFollowSlideChange(boolean colorFollowSlideChange)`:颜色是否随滑动逐渐变化
+ `setHeight(int height)`:设置高度,当为圆形时,宽度与高度取最大值作为直径长度
+ `setWidth(int width)`:设置宽度,当为圆形时,宽度与高度取最大值作为直径长度。仅模式为自定义宽度有效。
+ `setWidthModel(@IndicatorWidthModel int widthModel)`:宽度模式,支持整个ITEM的宽度、内容宽度、自定义宽度。
+ `setSize(@IndicatorWidthModel int widthModel, int width, int height)`:集合上面高宽度与模式的配置
+ `setRadius(int radius)`:设置圆半径,且设置为圆形
+ `setRoundRadius(int roundRadius)`:圆角矩形圆角大小
+ `setPanding(int panding)`:四周间距,左右间距对自定义长度无效
+ `setPendingLeft(int pendingLeft)`:左间距,对自定义长度无效
+ `setPendingRight(int pendingRight)`:右间距,对自定义长度无效
+ `setPendingTop(int pendingTop)`:上间距
+ `setPendingBottom(int pendingBottom)`:下间距
+ `setUseBezierEffect(boolean useBezierEffect)`:是否使用贝塞尔曲线效果,不支持尖角形状、不支持非圆形
+ `setTop()`:设置显示在顶部
+ `setShowSharpCorner(boolean showSharpCorner)`:是否需要尖角,设置为true后,线宽度模式、线宽度、贝塞尔曲线效果皆无效,线长度将为整个可显示范围。
+ `setSharpCornerHeight(int sharpCornerHeight)`:设置尖角高度
+ `setSharpCornerWidth(int sharpCornerWidth)`:设置尖角宽度
> 不支持非圆形下使用贝塞尔曲线效果
+ 点状效果配置:PointIndicatorConfig
+ `setRectType(int normalWidth, int normalHeight, int selectedWidth, int selectedHeight)`:设置形状为矩形及两种状态的高宽度
+ `setRectType(int normalWH, int selectedWH)`:设置形状为矩形及两种状态的高宽度,高宽度相同
+ `setRoundRectType(int normalWidth, int normalHeight, int selectedWidth, int selectedHeight)`:设置形状为圆角矩形及两种状态的高宽度
+ `setRoundRectType(int normalWH, int selectedWH)`:设置形状为圆角矩形及两种状态的高宽度,高宽度相同
+ `setCircleType(int normalRadius, int selectedRadius)`:设置形状为圆形及两种状态的半径
+ `setCircleType(int radius)`:设置形状为圆形及半径
+ `setRoundRadius(int roundRadius)`:圆角矩形圆角大小
+ `setStroke(@StrokeType int strokeStyle, float strokeWidth)`:设置边框类型及边框宽度,类型可查看`StrokeType `类,分别为:全部状态都实心、只有未选中时才空心、只有选中时才空心、全部状态都空心
+ `setPanding(int panding)`:设置左右间距
+ `setPendingLeft(int pendingLeft)`:左间距
+ `setPendingRight(int pendingRight)`:右间距
+ `setNormalColor(int normalColor)`:未选中颜色
+ `setSelectedColor(int selectedColor)`:选中颜色
+ `setStartInterpolator(Interpolator interpolator)`:起点动画的插值器
+ 包裹状效果配置:WrapIndicatorConfig
默认配置为:圆角矩形、颜色随滑动逐渐变化、左面和下面间距为5px、圆角为10px、颜色为白色。
+ `setShapeType(@IndicatorShapeType int shapeType)`:设置指示器形状,支持矩形、圆角矩形
+ `setColor(int color)`:设置颜色
+ `setColors(ArrayList colors)`:设置多个颜色
+ `setColorFollowSlideChange(boolean colorFollowSlideChange)`:颜色是否随滑动逐渐变化
+ `setRoundRadius(int roundRadius)`:圆角矩形圆角大小
+ `setPanding(int panding)`:四周间距
+ `setPendingLeft(int pendingLeft)`:左间距
+ `setPendingRight(int pendingRight)`:右间距
+ `setPendingTop(int pendingTop)`:上间距
+ `setPendingBottom(int pendingBottom)`:下间距
+ `setStroke(boolean stroke, int strokeWidth)`:设置是否空心,默认填充。以及设置空心描边宽度。
+ `setStartInterpolator(Interpolator interpolator)`:起点动画的插值器
+ `setEndInterpolator(Interpolator interpolator)`:终点动画的插值器
##### Tab之间的分隔线配置

支持在TextTitleConfig、LayoutConfig中配置,方法为:`setMidDividerConfig(MidDividerConfig midDividerConfig)`。支持以下属性配置:
- `setWidth(int width)`:设置分隔线宽度
- `setHeight(int height)`:设置分隔线高度
- `setColor(int color)`:设置颜色
- `setRoundRadius(int roundRadius)`:设置圆角角度
- `setDrawable(Drawable drawable)`:设置Drawable,会覆盖color、roundRadius配置,建议使用xml生成Drawable,实现方便、直观
- `setMarginLeft(int marginLeft)`:设置左间距
- `setMarginRight(int marginRight)`:设置右间距
- `setMarginTop(int marginTop)`:设置顶部间距
- `setMarginBottom(int marginBottom)`:设置底部间距