自定义带刻度线的SeekBar

在开发中遇到了一个需求就是实现带有刻度线的SeekBar,本文就简单记录一下自定义SeekBar的过程。下面是最终的两张效果图,一张是滑块上显示刻度线,一张是滑块上不显示刻度线:
自定义带刻度线的SeekBar_第1张图片
自定义带刻度线的SeekBar_第2张图片

思路就是继承系统的SeekBar,重写onDraw方法绘制刻度线。代码如下:

package cn.znh.customview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.support.v7.widget.AppCompatSeekBar;
import android.util.AttributeSet;

/**
 * @author:zhaonh
 * @time 2018/8/25 18:32
 * 

* 类描述:自定义带刻度线的SeekBar */ public class RulerSeekBar extends AppCompatSeekBar { /** * 刻度线画笔 */ private Paint mRulerPaint; /** * 刻度线的个数,等分数等于刻度线的个数加1 */ private int mRulerCount = 4; /** * 每条刻度线的宽度 */ private int mRulerWidth = 2; /** * 刻度线的颜色 */ private int mRulerColor = Color.WHITE; /** * 滑块上面是否要显示刻度线 */ private boolean isShowTopOfThumb = false; public RulerSeekBar(Context context) { super(context); init(); } public RulerSeekBar(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RulerSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } /** * 初始化 */ private void init() { //创建绘制刻度线的画笔 mRulerPaint = new Paint(); mRulerPaint.setColor(mRulerColor); mRulerPaint.setAntiAlias(true); //Api21及以上调用,去掉滑块后面的背景 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setSplitTrack(false); } } /** * 重写onDraw方法绘制刻度线 * * @param canvas */ @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); //极限条件校验 if (getWidth() <= 0 || mRulerCount <= 0) { return; } //获取每一份的长度 int length = (getWidth() - getPaddingLeft() - getPaddingRight() - mRulerCount * mRulerWidth) / (mRulerCount + 1); //计算刻度线的顶部坐标和底部坐标 int rulerTop = getHeight() / 2 - getMinimumHeight() / 2; int rulerBottom = rulerTop + getMinimumHeight(); //获取滑块的位置信息 Rect thumbRect = null; if (getThumb() != null) { thumbRect = getThumb().getBounds(); } //绘制刻度线 for (int i = 1; i <= mRulerCount; i++) { //计算刻度线的左边坐标和右边坐标 int rulerLeft = i * length + getPaddingLeft(); int rulerRight = rulerLeft + mRulerWidth; //判断是否需要绘制刻度线 if (!isShowTopOfThumb && thumbRect != null && rulerLeft - getPaddingLeft() > thumbRect.left && rulerRight - getPaddingLeft() < thumbRect.right) { continue; } //进行绘制 canvas.drawRect(rulerLeft, rulerTop, rulerRight, rulerBottom, mRulerPaint); } } /** * 设置刻度线的个数 * * @param mRulerCount */ public void setRulerCount(int mRulerCount) { this.mRulerCount = mRulerCount; requestLayout(); } /** * 设置刻度线的宽度,单位(px) * * @param mRulerWidth */ public void setRulerWidth(int mRulerWidth) { this.mRulerWidth = mRulerWidth; requestLayout(); } /** * 设置刻度线的颜色 * * @param mRulerColor */ public void setRulerColor(int mRulerColor) { this.mRulerColor = mRulerColor; if (mRulerPaint != null) { mRulerPaint.setColor(mRulerColor); requestLayout(); } } /** * 滑块上面是否需要显示刻度线 * * @param isShowTopOfThumb */ public void setShowTopOfThumb(boolean isShowTopOfThumb) { this.isShowTopOfThumb = isShowTopOfThumb; requestLayout(); } }

注意:

  • 代码中的getHeight()是整个SeekBar的高度值,getMinimumHeight()是进度条的高度值
  • thumbRect里的滑块坐标信息都是去除padding后的

简单定义了几个属性:

  • mRulerCount:刻度线的个数,等分数等于刻度线的个数加1
  • mRulerWidth:每条刻度线的宽度
  • mRulerColor:刻度线的颜色
  • isShowTopOfThumb:滑块上面是否要显示刻度线

使用就跟系统的SeekBar一样使用就行:


<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <cn.znh.rulerseebar.RulerSeekBar
        android:id="@+id/seek_bar"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:maxHeight="16dp"
        android:minHeight="16dp"
        android:progress="50"
        android:progressDrawable="@drawable/shape_progress_drawable"
        android:thumb="@drawable/shape_thumb_icon"
        android:thumbOffset="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

android.support.constraint.ConstraintLayout>

Demo地址:https://github.com/huihuigithub/RulerSeekBar.git

你可能感兴趣的:(Android)