ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android 之 indicatorView的实现分析

2019-06-01 13:54:05  阅读:328  来源: 互联网

标签:分析 indicator 圆点 float Paint 圆心 indicatorView android 我们


android 之indicatorView的实现分析

使用一个软件常注意到刚使用软件时会有一个导览页,通过滑动页面来显示不同的图,底部有用于指示在哪一页的圆点,这就是我们将要实现的indicator(指示器),接来我们介绍在android 中如何实现?

indicator的实现

首先,我们需要了解indicator的组成,一般来说,它是由几个圆点组成,翻到对应页时,圆点颜色改变,有些indicator圆点还有字母或者数字,如图:

在这里插入图片描述
在这里插入图片描述

接下来,我们需要知道如何绘出这些圆和圆内的数字。要确定一个圆,需要知道圆的半径和圆心位置x,y,半径是由我们自行配置的,所以我们需要确定每个圆圆心的位置,而y是固定的,所以我们需要知道每个圆x的值,如图,我们可以观察到它的规律如下:第一个圆的x 就等于圆的半径,从第二个圆开始,当前圆的圆心x 坐标为 上一个圆的x 坐标 + (radius * 2 + mSpace)。 其中mSpace 是圆之间的间距。
图源网络
(图源网络)

那么,接下来我们绘制这些圆,生成一个继承View的CircleIndicatorView,在这个View中定义相关的属性,如半径,圆点颜色等,我们需要定义一个indicator类,用来存放圆点数据:

public static class Indicator{
    public float cx; // 圆心x坐标
    public float cy; // 圆心y 坐标
}

接下来,计算每个圆的圆点圆心的位置,第一个圆心的x坐标为半径加上边界值,y的值取View的高度除二,取中间位置,上面已经介绍了它的计算规律,我们只需按规律算出相应的值保存在mIndicators(存放圆心的一个List)中:

private void measureIndicator(){
    mIndicators.clear();//mIndicators为存放每个点的圆心的List
    float cx = 0;
    for(int i=0;i<mCount;i++){
        Indicator indicator = new Indicator();
        if( i== 0){
            cx = mRadius + mStrokeWidth;//第一个点,mStrokeWidth为边界值
        }else{
            cx += (mRadius + mStrokeWidth) * 2 +mSpace;//第二、三......个
        }

        indicator.cx = cx;
        indicator.cy = getMeasuredHeight() / 2;//getMeasuredHeight() 获取View的实际大小

        mIndicators.add(indicator);
    }
}

有了圆心的数据,我们就可以绘制圆了,我们需要定义画圆心和字符的Paint类(mCirclePaint、mTextPaint),Paint可以用于画几何图形,文本和bitmap,setStyle用于设置样式,样式有三种:
Paint.Style.FILL:填充内部
Paint.Style.FILL_AND_STROKE :填充内部和描边
Paint.Style.STROKE :描边
Paint还有其他属性:
setAntiAlias(boolean a) //设置抗锯齿,如果不设置,加载位图的时候可能会出现锯齿状的边界,如果设置,边界就会变的稍微有点模糊,锯齿就看不到了。
setDither(boolean dither) //设置是否抖动,如果不设置感觉就会有一些僵硬的线条,如果设置图像就会看的更柔和一些

protected void onDraw(Canvas canvas) {

    for(int i=0;i<mIndicators.size();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);                 
}

如果圆内有字母数字我们还需要再进行绘制,首先需要判断FillMode的值是什么,若为字母或数字则可进一步绘制,用Canvas来绘制文本需要给文本定位,我们借助Rect来获得文本的宽、高,Paint.getTextBounds用于获取文本的宽高,然后我们计算文本的开始位置,使文本居中:

// 绘制小圆点中的内容
    if(mFillMode != FillMode.NONE){
        String text = "";
        if(mFillMode == FillMode.LETTER){//圆内为字母
            if(i >= 0 && i<LETTER.length){
                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<mIndicators.size();i++){
        Indicator indicator = mIndicators.get(i);
        if(xDis < (indicator.cx + mRadius+mStrokeWidth)
                && xDis >=(indicator.cx - (mRadius + mStrokeWidth))
                && yDis >= (yDis - (indicator.cy+mStrokeWidth))
                && yDis <(indicator.cy+mRadius+mStrokeWidth)){
             // 找到了点击的Indicator
             // 是否允许切换ViewPager
             if(mIsEnableClickSwitch){
                 mViewPager.setCurrentItem(i,false);
             }

             // 回调
            if(mOnIndicatorClickListener!=null){
                mOnIndicatorClickListener.onSelected(i);
            }
            break;
        }
    }
}

我们需要与ViewPaper配合使用,所有还需要一个与ViewPaper关联的方法,并在其中设置ViewPaper监听该View:

public void setUpWithViewPager(ViewPager viewPager){
    releaseViewPager();
    if(viewPager == null){
        return;
    }
    mViewPager = viewPager;
    mViewPager.addOnPageChangeListener(this);
    int count = mViewPager.getAdapter().getCount();
    setCount(count);
}

基本的已实现,那么我们来应用它,在xml文件中,我们可以在这里设置很多属性,这些属性对应着attr.xml中的内容:

<resources>
    <declare-styleable name="CircleIndicatorView">
        <attr name="indicatorRadius" format="dimension"/>
        <attr name="indicatorBorderWidth" format="dimension"/>
        <attr name="indicatorSpace" format="dimension"/>
        <attr name="indicatorTextColor" format="color"/>
        <attr name="indicatorColor" format="color"/>
        <attr name="indicatorSelectColor" format="color"/>
        <attr name="enableIndicatorSwitch" format="boolean"/>
        <attr name="fill_mode">
            <enum name="letter" value="0"/>
            <enum name="number" value="1"/>
            <enum name="none" value="2"/>
        </attr>
    </declare-styleable>
</resources>
<com.zhouwei.indicatorview.CircleIndicatorView
    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"
    /> 

在activity中与ViewPaper关联:

mIndicatorView = (CircleIndicatorView) findViewById(R.id.indicator_view);
// 关联ViewPager
mIndicatorView.setUpWithViewPager(mViewPager);

实验效果:
在这里插入图片描述
到这里已经介绍完了,该控件已经有开源代码了,地址为:源码
我们可以在配置文件中设置即可直接使用:
在build.gradle(project)中添加:

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

在build.gradle(app)中dependencies添加:

implementation 'com.github.pinguo-zhouwei:CircleIndicatorView:v1.0.0'

sync一下即可直接使用

参考文章:
indicator的实现
一起看画布Android Canvas
Android文本测量

作者:贺苏娜
原文链接

标签:分析,indicator,圆点,float,Paint,圆心,indicatorView,android,我们
来源: https://blog.csdn.net/fjnu_se/article/details/90728067

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有