添加命名空间
xmlns:qishui="http://schemas.android.com/apk/res-auto"
使用控件布局
android:id="@+id/id_indicator"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/colorPrimary"
android:orientation="horizontal"
qishui:item_count="5">
android:id="@+id/id_vp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
逻辑设置
final List mDatas = Arrays.asList(UiUtils.getStringArray(R.array.tab_names));
mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Fragment getItem(int position) {
return FragmentFactory.createFragment(position);
}
};
//设置Tab上的标题
mIndicator.setTabItemTitles(mDatas);
mViewPager.setAdapter(mAdapter);
//设置关联的ViewPager
mIndicator.setViewPager(mViewPager, 0);
其中mDatas获取到的是一串在Strings.xml字符集合
首页
活动
辅练
商城
我的
简单点可以直接定义出来,不必获取xml中的;其中FragmentFactory就是创建不同的fragment简单点new 一个定义好的即可。
此文只为记录,向hongyang大佬致敬
相关资料下载
圆形指示器
public class CircleIndicatorView extends View implements ViewPager.OnPageChangeListener{
private static final String LETTER[] = new String[]{"A","B","C","D","E","F","G","H","I","G","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
// private int mSelectColor = Color.parseColor("#E38A7C");
private int mSelectColor = Color.parseColor("#FFFFFF");
private Paint mCirclePaint;
private Paint mTextPaint;
private int mCount; // indicator 的数量
private int mRadius;//半径
private int mStrokeWidth;//border
private int mTextColor;// 小圆点中文字的颜色
private int mDotNormalColor;// 小圆点默认颜色
private int mSpace = 0;// 圆点之间的间距
private List mIndicators;
private int mSelectPosition = 0; // 选中的位置
private FillMode mFillMode = FillMode.NONE;// 默认只有小圆点
private ViewPager mViewPager;
private OnIndicatorClickListener mOnIndicatorClickListener;
/**
* 是否允许点击Indicator切换ViewPager
*/
private boolean mIsEnableClickSwitch = false;
public CircleIndicatorView(Context context) {
super(context);
init();
}
public CircleIndicatorView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
getAttr(context,attrs);
init();
}
public CircleIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
getAttr(context,attrs);
init();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CircleIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
getAttr(context,attrs);
init();
}
private void init(){
mCirclePaint = new Paint();
mCirclePaint.setDither(true);
mCirclePaint.setAntiAlias(true);
mCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTextPaint = new Paint();
mTextPaint.setDither(true);
mTextPaint.setAntiAlias(true);
// 默认值
mIndicators = new ArrayList<>();
initValue();
}
private void initValue(){
mCirclePaint.setColor(mDotNormalColor);
mCirclePaint.setStrokeWidth(mStrokeWidth);
mTextPaint.setColor(mTextColor);
mTextPaint.setTextSize(mRadius);
}
/**
* 获取自定义属性
* @param context
* @param attrs
*/
private void getAttr(Context context,AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicatorView);
mRadius = (int) typedArray.getDimensionPixelSize(R.styleable.CircleIndicatorView_indicatorRadius,dpToPx(6));
mStrokeWidth = (int) typedArray.getDimensionPixelSize(R.styleable.CircleIndicatorView_indicatorBorderWidth,dpToPx(2));
mSpace = typedArray.getDimensionPixelSize(R.styleable.CircleIndicatorView_indicatorSpace,dpToPx(5));
// color
mTextColor = typedArray.getColor(R.styleable.CircleIndicatorView_indicatorTextColor,Color.BLACK);
mSelectColor = typedArray.getColor(R.styleable.CircleIndicatorView_indicatorSelectColor,Color.WHITE);
mDotNormalColor = typedArray.getColor(R.styleable.CircleIndicatorView_indicatorColor,Color.GRAY);
mIsEnableClickSwitch = typedArray.getBoolean(R.styleable.CircleIndicatorView_enableIndicatorSwitch,false);
int fillMode = typedArray.getInt(R.styleable.CircleIndicatorView_fill_mode,2);
if(fillMode == 0){
mFillMode = FillMode.LETTER;
}else if(fillMode == 1){
mFillMode = FillMode.NUMBER;
}else{
mFillMode = FillMode.NONE;
}
typedArray.recycle();
}
/**
* 测量每个圆点的位置
*/
private void measureIndicator(){
mIndicators.clear();
float cx = 0;
for(int i=0;i
Indicator indicator = new Indicator();
if( i== 0){
cx = mRadius + mStrokeWidth;
}else{
cx += (mRadius + mStrokeWidth) * 2 +mSpace;
}
indicator.cx = cx;
indicator.cy = getMeasuredHeight() / 2;
mIndicators.add(indicator);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = (mRadius+mStrokeWidth)* 2 * mCount + mSpace *(mCount - 1);
int height = mRadius * 2 + mSpace * 2;
setMeasuredDimension(width,height);
measureIndicator();
}
@Override
protected void onDraw(Canvas canvas) {
for(int i=0;i
Indicator indicator = mIndicators.get(i);
float x = indicator.cx;
float y = indicator.cy;
if(mSelectPosition == i){
mCirclePaint.setStyle(Paint.Style.FILL);
mCirclePaint.setColor(mSelectColor);
}else{
mCirclePaint.setColor(mDotNormalColor);
if(mFillMode != FillMode.NONE){
mCirclePaint.setStyle(Paint.Style.STROKE);
}else{
mCirclePaint.setStyle(Paint.Style.FILL);
}
}
canvas.drawCircle(x,y, mRadius, mCirclePaint);
// 绘制小圆点中的内容
if(mFillMode != FillMode.NONE){
String text = "";
if(mFillMode == FillMode.LETTER){
if(i >= 0 && i
text = LETTER[i];
}
}else{
text = String.valueOf(i+1);
}
Rect bound = new Rect();
mTextPaint.getTextBounds(text,0,text.length(),bound);
int textWidth = bound.width();
int textHeight = bound.height();
float textStartX = x - textWidth / 2;
float textStartY = y + textHeight / 2;
canvas.drawText(text,textStartX,textStartY, mTextPaint);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float xPoint = 0;
float yPoint = 0;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
xPoint = event.getX();
yPoint = event.getY();
handleActionDown(xPoint,yPoint);
break;
}
return super.onTouchEvent(event);
}
private void handleActionDown(float xDis,float yDis){
for(int i=0;i
Indicator indicator = mIndicators.get(i);
if(xDis < (indicator.cx + mRadius+mStrokeWidth)
&& xDis >=(indicator.cx - (mRadius + mStrokeWidth))
&& yDis >= (yDis - (indicator.cy+mStrokeWidth))
&& yDis
// 找到了点击的Indicator
// 是否允许切换ViewPager
if(mIsEnableClickSwitch){
mViewPager.setCurrentItem(i,false);
}
// 回调
if(mOnIndicatorClickListener!=null){
mOnIndicatorClickListener.onSelected(i);
}
break;
}
}
}
public void setOnIndicatorClickListener(OnIndicatorClickListener onIndicatorClickListener) {
mOnIndicatorClickListener = onIndicatorClickListener;
}
private void setCount(int count) {
mCount = count;
invalidate();
}
/**
* 设置 border
* @param borderWidth
*/
public void setBorderWidth(int borderWidth){
mStrokeWidth = borderWidth;
initValue();
}
/**
* 设置文字的颜色
* @param textColor
*/
public void setTextColor(int textColor) {
mTextColor = textColor;
initValue();
}
/**
* 设置选中指示器的颜色
* @param selectColor
*/
public void setSelectColor(int selectColor) {
mSelectColor = selectColor;
}
/**
* 设置指示器默认颜色
* @param dotNormalColor
*/
public void setDotNormalColor(int dotNormalColor) {
mDotNormalColor = dotNormalColor;
initValue();
}
/**
* 设置选中的位置
* @param selectPosition
*/
public void setSelectPosition(int selectPosition) {
mSelectPosition = selectPosition;
}
/**
* 设置Indicator 模式
* @param fillMode
*/
public void setFillMode(FillMode fillMode) {
mFillMode = fillMode;
}
/**
* 设置Indicator 半径
* @param radius
*/
public void setRadius(int radius) {
mRadius = radius;
initValue();
}
public void setSpace(int space) {
mSpace = space;
}
public void setEnableClickSwitch(boolean enableClickSwitch){
mIsEnableClickSwitch = enableClickSwitch;
}
/**
* 与ViewPager 关联
* @param viewPager
*/
public void setUpWithViewPager(ViewPager viewPager){
releaseViewPager();
if(viewPager == null){
return;
}
mViewPager = viewPager;
mViewPager.addOnPageChangeListener(this);
int count = mViewPager.getAdapter().getCount();
setCount(count);
}
/**
* 重置ViewPager
*/
private void releaseViewPager(){
if(mViewPager!=null){
mViewPager.removeOnPageChangeListener(this);
mViewPager = null;
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
mSelectPosition = position;
invalidate();
}
@Override
public void onPageScrollStateChanged(int state) {
}
/**
* Indicator 点击回调
*/
public interface OnIndicatorClickListener{
public void onSelected(int position);
}
public static class Indicator{
public float cx; // 圆心x坐标
public float cy; // 圆心y 坐标
}
public enum FillMode{
LETTER,
NUMBER,
NONE
}
public int dpToPx(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
}
public int pxToDp(float px) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, Resources.getSystem().getDisplayMetrics());
}
}
自定义属性
xml设置
android:id="@+id/indicator_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="50dp"
android:layout_centerHorizontal="true"
app:indicatorSelectColor="#00A882"
app:fill_mode="letter"
app:indicatorBorderWidth="2dp"
app:indicatorRadius="8dp"
app:indicatorColor="@color/colorAccent"
app:indicatorTextColor="@android:color/white"
/>
.class设置
// 初始化ViewPager 相关
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mPagerAdapter = new ViewPagerAdapter();
mViewPager.setAdapter(mPagerAdapter);
mIndicatorView = (CircleIndicatorView) findViewById(R.id.indicator_view);
// 关联ViewPager
mIndicatorView.setUpWithViewPager(mViewPager);
相关设置可以不在xml中设置,在代码中同样可以设置
// 在代码中设置相关属性
CircleIndicatorView indicatorView = (CircleIndicatorView) findViewById(R.id.indicator_view3);
// 设置半径
indicatorView.setRadius(DisplayUtils.dpToPx(15));
// 设置Border
indicatorView.setBorderWidth(DisplayUtils.dpToPx(2));
// 设置文字颜色
indicatorView.setTextColor(Color.WHITE);
// 设置选中颜色
indicatorView.setSelectColor(Color.parseColor("#FEBB50"));
//
indicatorView.setDotNormalColor(Color.parseColor("#E38A7C"));
// 设置指示器间距
indicatorView.setSpace(DisplayUtils.dpToPx(10));
// 设置模式
indicatorView.setFillMode(CircleIndicatorView.FillMode.LETTER);
// 设置点击Indicator可以切换ViewPager
indicatorView.setEnableClickSwitch(true);
// 最重要的一步:关联ViewPager
indicatorView.setUpWithViewPager(mViewPager);
自定义属性
属性名
属性意义
取值
indicatorRadius
设置指示器圆点的半径
单位为 dp 的值
indicatorBorderWidth
设置指示器的border
单位为 dp 的值
indicatorSpace
设置指示器之间的距离
单位为 dp 的值
indicatorTextColor
设置指示器中间的文字颜色
颜色值,如:#FFFFFF
indicatorColor
设置指示器圆点的颜色
颜色值
indicatorSelectColor
设置指示器选中的颜色
颜色值
fill_mode
设置指示器的模式
枚举值:有三种,分别是letter,number和none
enableIndicatorSwitch
设置是否点击Indicator切换ViewPager,默认为false
布尔值
源代码参见