自定义圆点刻度可滑动的SeekBar,也可设置刻度

 

自定义SeekBar,源码如下

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 androidx.appcompat.widget.AppCompatSeekBar;
import android.util.AttributeSet;

/**
 * @author:ligc
 * @time 2022/12/06
 * <p>
 * 类描述:自定义SeekBar
 */
public class CircleSeekBar extends AppCompatSeekBar {

    /**
     * 绘制的类型 0为圆点,1为刻度
     */
    private int drawStyle = 1;

    /**
     * 是否绘制文字
     */
    private boolean drawText = false;

    /**
     * 刻度线画笔
     */
    private Paint mRulerPaint;
    /**
     * 圆点画笔
     */
    private Paint mCirclePaint;
    /**
     * 字体画笔
     */
    private Paint mTestPaint;

    /**
     * 绘制的个数,等分数等于刻度线的个数加1
     */
    private int mCount = 10;

    /**
     * 每条刻度线的宽度
     */
    private int mRulerWidth = 2;

    /**
     * 刻度线的颜色
     */
    private int mRulerColor = Color.WHITE;

    /**
     * 圆点的颜色
     */
    private int mCircleColor = Color.WHITE;

    /**
     * 字体的颜色
     */
    private int mTextColor = Color.WHITE;

    /**
     * 滑块上面是否要显示
     */
    private boolean isShowTopOfThumb = false;

    public CircleSeekBar(Context context) {
        super(context);
        init();
    }

    public CircleSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CircleSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        //创建绘制刻度线的画笔
        mRulerPaint = new Paint();
        mRulerPaint.setColor(mRulerColor);
        mRulerPaint.setAntiAlias(true);

        //创建绘制圆点的画笔
        mCirclePaint = new Paint();
        mCirclePaint.setColor(mCircleColor);
        mCirclePaint.setAntiAlias(true);

        //创建绘制文字的画笔
        mTestPaint = new Paint();
        mTestPaint.setTextSize(35F);
        mTestPaint.setColor(mTextColor);
        mTestPaint.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 || mCount <= 0) {
            return;
        }
        //获取每一份的长度
        int length = 0;
        if (drawStyle==0){
            length = (getWidth()) / (mCount + 1);
        }else if (drawStyle==1){
            length = (getWidth() - getPaddingLeft() - getPaddingRight() - mCount * mRulerWidth) / (mCount + 1);
        }

        //计算刻度线的顶部坐标和底部坐标 注意绘制刻度的时候要设置minHeight
        int rulerTop = getHeight() / 2 - getMinimumHeight() / 2;
        int rulerBottom = rulerTop + getMinimumHeight();

        float drawY = (float) ((rulerTop+rulerBottom) / 2);
        float drawTestY = (float) ((rulerTop+rulerBottom) / 2) -50;
        //获取滑块的位置信息
        Rect thumbRect = null;
        if (getThumb() != null) {
            thumbRect = getThumb().getBounds();
        }

        int rulerLeft = 0 , rulerRight = 0;
        float drawX = 0 ;

        //绘制刻度线
        for (int i = 1; i <= mCount; i++) {
            //计算刻度线的左边坐标和右边坐标
            if (drawStyle==0){
                 rulerLeft = i * length;
                 rulerRight = rulerLeft ;
                 drawX = (float) rulerLeft;
            }else if (drawStyle==1){
                 rulerLeft = i * length + getPaddingLeft();
                 rulerRight = rulerLeft + mRulerWidth;
                 drawX = (float) ((rulerLeft+rulerRight)/2);
            }
            float drawTestX = (float) ((rulerLeft)-10);
            //判断是否需要绘制刻度线
            if (!isShowTopOfThumb && thumbRect != null && rulerLeft - getPaddingLeft() > thumbRect.left && rulerRight - getPaddingLeft() < thumbRect.right) {
                continue;
            }
            //进行绘制
            if (drawStyle==0){
                canvas.drawCircle(drawX, drawY, 8.0F, mCirclePaint);
            }else if (drawStyle==1){
                canvas.drawRect(rulerLeft, rulerTop, rulerRight, rulerBottom, mRulerPaint);
            }
            //是否绘制文字
            if (drawText){
                canvas.drawText(String.valueOf(i-1), drawTestX, drawTestY, mTestPaint);
            }
        }
    }

    /**
     * 设置绘制的个数
     *
     * @param mCount
     */
    public void setCount(int mCount) {
        this.mCount = mCount;
        requestLayout();
    }

    /**
     * 设置绘制类型
     *
     * @param mStyle
     */
    public void setDrawStyle (int mStyle) {
        this.drawStyle = mStyle;
        requestLayout();
    }

    /**
     * 设置是否绘制文字
     *
     * @param drawText
     */
    public void setDrawText (boolean drawText) {
        this.drawText = drawText;
        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 mCircleColor
     */
    public void setCircleColor(int mCircleColor) {
        this.mCircleColor = mCircleColor;
        if (mCirclePaint != null) {
            mCirclePaint.setColor(mCircleColor);
            requestLayout();
        }
    }

    /**
     * 设置字体的颜色
     *
     * @param TextColor
     */
    public void setTextColor(int TextColor) {
        this.mTextColor = TextColor;
        if (mTestPaint != null) {
            mTestPaint.setColor(mTextColor);
            requestLayout();
        }
    }

    /**
     * 设置整体颜色
     *
     * @param mCircleColor,mTextColor
     */
    public void setAllColor(int mCircleColor,int mTextColor) {
        //圆的颜色
        this.mCircleColor = mCircleColor;
        //字体的颜色
        this.mTextColor = mTextColor;
        if (mCirclePaint != null && mTestPaint != null) {
            mCirclePaint.setColor(mCircleColor);
            mTestPaint.setColor(mTextColor);
            requestLayout();
        }
    }

    /**
     * 滑块上面是否需要显示刻度线
     *
     * @param isShowTopOfThumb
     */
    public void setShowTopOfThumb(boolean isShowTopOfThumb) {
        this.isShowTopOfThumb = isShowTopOfThumb;
        requestLayout();
    }
}

 在Main中调用


import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements CircleSeekBar.OnSeekBarChangeListener{


    private  CircleSeekBar mSeekBar;
    private  TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSeekBar = (CircleSeekBar)findViewById(R.id.seek_bar);
        textView = (TextView)findViewById(R.id.tv_show);
        //设置相关属性值
        mSeekBar.setDrawStyle(0);
        mSeekBar.setCount(11);
        mSeekBar.setDrawText(true);
        mSeekBar.setAllColor(Color.WHITE,R.color.gray79);
        mSeekBar.setShowTopOfThumb(true);

        mSeekBar.setOnSeekBarChangeListener(this);
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        if (seekBar.getProgress()<100){
            seekBar.setProgress(Math.round(seekBar.getProgress()/10)*10+5);
        }else {
            seekBar.setProgress(105);
        }


        textView.setText((seekBar.getProgress()-5)/10+"");

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
}

相关xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.ligc.demo.CircleSeekBar
        android:layout_gravity="center"
        android:id="@+id/seek_bar"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:minHeight="16dp"
        android:splitTrack="false"
        android:max="110"
        android:progress="5"
        android:thumb="@drawable/shape_seekbar_circle"
        android:progressDrawable="@drawable/seekbar_bg"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        tools:ignore="MissingConstraints" />

    <TextView
        android:id="@+id/tv_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

shape_seekbar_circle.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 边 -->
    <item>
        <shape android:shape="oval">
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />
            <solid android:color="#50CCCCCC" />
            <corners android:radius="8dp" />
            <size
                android:width="30dp"
                android:height="30dp" />
        </shape>
    </item>

    <!-- 中心背景 -->
    <item>
        <shape
            android:shape="oval"
            android:useLevel="false">
            <!-- 实心 -->
            <solid android:color="#ffffff" />
            <corners android:radius="10dp" />
            <padding
                android:bottom="10dp"
                android:left="10dp"
                android:right="10dp"
                android:top="10dp" />
            <size
                android:width="30dp"
                android:height="30dp" />
        </shape>
    </item>
</layer-list>

seekbar_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="10dp"/>
            <solid android:color="#DBEDF4"/>
        </shape>
        <!--    背景颜色-->
        <color android:color="#CCCCCC"/>
    </item>

    <item android:id="@android:id/progress">
        <clip
            android:clipOrientation="horizontal"
            android:gravity="left">
            <shape>
                <corners android:radius="10dp"/>
                <!--  开始颜色,中途颜色,最后颜色-->
                <gradient
                    android:startColor="#FF0000"
                    android:centerColor="#FFFF00"
                    android:endColor="#00FF00"/>
            </shape>
        </clip>
    </item>
</layer-list>

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十一多一点。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值