前言

第一次书写技术类的文章,希望能够将自己的所学和成长记录下来。

内容

由于公司的项目需要,需要制作一个指针滑动的seekbar,如图。

查阅了网上大量的相关实例和知识,在此进行一个总结,如有问题希望大家能够提出。

功能需求是这样的:需要一个带有标尺的滑动条,滑动部分为游标而不是常见的滑动背景的标尺,滑动游标的时候其他的如TextView的控件可以直接拿到当前游标所指的值。因此考虑首先需要一个标尺,本来考虑标尺的展示使用图片,但是后来考虑到适配的问题较为繁琐,因此采用自定义控件的时候画出来。而游标方面,也考虑样式固定化,也采用的是绘制的方式。

绘制部分代码如下:

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.save();//画最下面的线canvas.drawLine(PADDING_LEFT,getHeight(),widthOfProgress,getHeight(),mLinePaint);for (int i = minProgress; i <= maxProgress; i=i+oneItemValue) {if (i % oneGroupValue == 0 || i == minProgress) {//起点x坐标10像素,画厘米线canvas.drawLine(PADDING_LEFT, getHeight(), PADDING_LEFT, getHeight()/2+16*scaleX, mLinePaint);//计算刻度数String text = i + "";Rect rect = new Rect();//获取文本宽度float txtWidth = mTextPaint.measureText(text);mTextPaint.getTextBounds(text, 0, text.length(), rect);//画标尺的数字canvas.drawText(text, PADDING_LEFT - txtWidth / 2, getHeight()/2+16*scaleX-rect.height()  , mTextPaint);} else if (i % oneItemValue == 0) {//每隔小单位画间隔线,lineHeight越长,线越短double lineHeight = (getHeight()/2)*0.6;canvas.drawLine(PADDING_LEFT, getHeight(), PADDING_LEFT, getHeight()/2+(float)lineHeight, mLinePaint);}
//            else {
//                //画毫米线
//                double lineHeight = (getHeight()/2)*0.4;
//                canvas.drawLine(44, getHeight(), 44, getHeight()/2+(float)lineHeight, mLinePaint);
//            }//每隔一个单位像素移动一次达到划线效果canvas.translate(widthOfItem, 0);}canvas.restore();//画红线游标canvas.drawLine(xProgress, getHeight()/2, xProgress, getHeight(), mRulerPaint);Log.i("--++",cursorRadius+"");canvas.drawCircle(xProgress, getHeight()/2, cursorRadius, mRulerPaint);//测试用显示progress
//        BigDecimal bd = new BigDecimal((progrees - 18) / 180);
//        bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);
//        mTextPaint.setTextSize(36);
//        float cursorTextWidth = mTextPaint.measureText(bd.floatValue()+"");
//        canvas.drawText(progrees+"", getWidth()/2-cursorTextWidth/2, cursorTextWidth, mTextPaint);}
复制代码

attrs文件中的内容:

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="RangeSeekBar"><attr name="line_color" format="color"></attr><attr name="cursor_color" format="color"></attr><attr name="text_color" format="color"></attr><attr name="max_progress" format="integer"></attr><attr name="min_progress" format="integer"></attr><attr name="oneitem_value" format="integer"></attr><attr name="one_group_value" format="integer"></attr><attr name="current_progress" format="float"></attr><attr name="linewidth" format="float"></attr><attr name="scrollable" format="boolean"></attr></declare-styleable>
</resources>
复制代码

由于项目需要,该控件中的scrollable功能默认设置是true的,如果改为false,那么该控件就变成只能选择最大值和最小值。 该控件还做了滑动处理,当滑动到刻度中间时就自动滑动到附近最近的线上面。该部分的处理在该控件的事件处理当中,代码如下:

@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_POINTER_DOWN:if (event.getX() > PADDING_LEFT + widthOfProgress || event.getX() < PADDING_LEFT){isCanMove = false;}else{isCanMove = true;}break;case MotionEvent.ACTION_MOVE:if (!isCanMove) {return false;}float x = event.getX();if (x<PADDING_LEFT || x>widthOfProgress){return false;}if (scrollable){xProgress =  x;progrees = minProgress+Math.round((xProgress-PADDING_LEFT)/widthOfItem)*oneItemValue;if (onRangeRulerChangeListener != null){onRangeRulerChangeListener.onValueChanged((int)progrees);}invalidate();}else{if (x < widthOfProgress / 2){xProgress = PADDING_LEFT;}else{xProgress = widthOfProgress;}progrees = minProgress+Math.round((xProgress-PADDING_LEFT)/widthOfItem)*oneItemValue;if (onRangeRulerChangeListener != null){onRangeRulerChangeListener.onValueChanged((int)progrees);}invalidate();}break;case MotionEvent.ACTION_POINTER_UP:case MotionEvent.ACTION_UP:float x1 = event.getX();if (scrollable){int number = Math.round((x1 - PADDING_LEFT)/ widthOfItem);if (number < 0){number = 0;}else if (number >= numberOfItem){number = numberOfItem;}xProgress = PADDING_LEFT + number * widthOfItem;invalidate();}else{if (x1  >= widthOfProgress/2){xProgress = PADDING_LEFT + numberOfItem * widthOfItem;}else{xProgress = PADDING_LEFT;}invalidate();}progrees = minProgress+Math.round((xProgress-PADDING_LEFT)/widthOfItem)*oneItemValue;if (onRangeRulerChangeListener != null){onRangeRulerChangeListener.onValueChanged((int)progrees);}break;}return true;}
复制代码

最后放上Main的逻辑,可以用来设置该控件的默认值和一些属性: Main.java方面:

public class MainActivity extends AppCompatActivity {private RangeSeekBar rangeSeekBar;private TextView tv1;private RangeSeekBar dayView;private TextView tvDay;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);rangeSeekBar = (RangeSeekBar)findViewById(R.id.seekbar_money);tv1 = (TextView)findViewById(R.id.tv_money);dayView = (RangeSeekBar) findViewById(R.id.seekbar_day);tvDay = (TextView) findViewById(R.id.tv_day);rangeSeekBar.setOnRangeRulerChangeListener(new OnRangeRulerChangeListener() {@Overridepublic void onValueChanged(int value) {tv1.setText(value+"");}});//设置当前值一定要在设置了监听之后rangeSeekBar.setCurrentProgress(500);dayView.setOnRangeRulerChangeListener(new OnRangeRulerChangeListener() {@Overridepublic void onValueChanged(int value) {tvDay.setText(value+"");}});}}
复制代码

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"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#f0f0f0"><LinearLayoutandroid:gravity="center_horizontal"android:layout_width="match_parent"android:orientation="vertical"android:layout_height="0dp"android:layout_weight="4"><TextViewandroid:layout_centerHorizontal="true"android:layout_marginTop="10dp"android:id="@+id/tv_credirLine"android:gravity="center_vertical"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""android:textSize="17sp"/><RelativeLayoutandroid:layout_marginTop="15dp"android:id="@+id/rl_money"android:gravity="center_horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><ImageViewandroid:layout_centerVertical="true"android:id="@+id/iv_money"android:layout_width="20dp"android:layout_height="20dp"/><TextViewandroid:layout_marginLeft="15dp"android:layout_toRightOf="@+id/iv_money"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="借款金额"android:textSize="16sp"/></RelativeLayout><RelativeLayoutandroid:padding="15dp"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"><TextViewandroid:layout_centerHorizontal="true"android:id="@+id/tv_money"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="300"android:textSize="18sp"/><TextViewandroid:layout_marginLeft="15dp"android:layout_centerHorizontal="true"android:layout_toRightOf="@+id/tv_money"android:id="@+id/tv_1"android:layout_centerVertical="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#333333"android:text="元"android:textSize="15sp"/></RelativeLayout><RelativeLayoutandroid:layout_marginTop="15dp"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"><com.moyu.wh.testcustomseekbar.customview.RangeSeekBarandroid:id="@+id/seekbar_money"android:layout_width="match_parent"android:layout_height="match_parent"app:line_color="#dddddd"app:text_color="#dddddd"/><!--<ImageView--><!--android:layout_centerInParent="true"--><!--android:layout_width="15dp"--><!--android:layout_height="50dp"--><!--android:layout_alignParentBottom="true"--><!--android:src="@drawable/ic_scoll_line"--><!--/>--></RelativeLayout></LinearLayout><LinearLayoutandroid:layout_marginTop="50dp"android:gravity="center_horizontal"android:layout_width="match_parent"android:orientation="vertical"android:layout_height="0dp"android:layout_weight="3"><RelativeLayoutandroid:layout_marginTop="25dp"android:id="@+id/rl_day"android:gravity="center_horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><ImageViewandroid:layout_centerVertical="true"android:id="@+id/iv_day"android:layout_width="24dp"android:layout_height="24dp"/><TextViewandroid:layout_marginLeft="10dp"android:layout_toRightOf="@+id/iv_day"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="借款期数"android:textSize="16sp"/></RelativeLayout><RelativeLayoutandroid:padding="15dp"android:gravity="center_horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_centerHorizontal="true"android:id="@+id/tv_day"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="7"android:textSize="18sp"/><TextViewandroid:layout_centerVertical="true"android:layout_marginLeft="3dp"android:layout_toRightOf="@+id/tv_day"android:layout_centerHorizontal="true"android:id="@+id/tv_2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#333333"android:text="天"android:textSize="15sp"/></RelativeLayout><LinearLayoutandroid:id="@+id/ll_day"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:orientation="horizontal"><com.moyu.wh.testcustomseekbar.customview.RangeSeekBarandroid:id="@+id/seekbar_day"android:layout_width="match_parent"android:layout_height="match_parent"app:max_progress="14"app:min_progress="7"app:one_group_value="7"app:oneitem_value="1"app:scrollable="false"app:current_progress="7"app:line_color="#dddddd"app:text_color="#dddddd"/></LinearLayout></LinearLayout><LinearLayoutandroid:layout_marginTop="50dp"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="2"></LinearLayout></LinearLayout>
复制代码

谢谢阅读,如有问题可以前来询问,新人不才,代码如存在问题,敬请指点,互相学习成长进步。 Demo位置(CSDN)

自定义带标尺的seekbar相关推荐

  1. Android——自定义带刻度的SeekBar单向拖动条

    时间过得真快,才发现好久没来逛逛了.没写博客的这段时间一直在做项目,连续完成了两个大型app,这个过程很享受,这是独立开发的,所以中途有很多很多的问题需要自己一个一个的去解决,现在接近尾声了,发现自己 ...

  2. android 自定义带刻度的seekbar,[Android开发]仿天天P图带气泡显示百分比进度的自定义SeekBar...

    仿天天P图图像美化修改工具,素材来自于天天P图,效果图 效果就是点击之后会有气泡显示进度,优点是气泡不占用控件的高度 其他效果可参看https://github.com/AnderWeb/discre ...

  3. Android之自定义带圆角的水纹波效果

    1 需求 自定义带圆角的水温波效果 2 代码实现 bg_navigation_ripple.xml <?xml version="1.0" encoding="ut ...

  4. android 自定义进度条 水量,Android自定义带水滴的进度条样式(带渐变色效果)...

    一.直接看效果 二.直接上代码 1.自定义控件部分 package com.susan.project.myapplication; import android.app.Activity; impo ...

  5. android伸缩动画自定义,Android干货:自定义带动画的View

    对于一个自定义View来说,onMeasure只是用来计算View尺寸,onDraw()才是真正执行View的绘制,所以一般我们都需要重写onDraw()函数来绘制我们期望的UI界面,下面我以一个具体 ...

  6. 进度条上的小圆点怎么做_Android自定义带圆点的半圆形进度条

    本文实例为大家分享了Android自定义带圆点的半圆形进度条,供大家参考,具体内容如下 仅限用于半圆形,如须要带圆点的圆形进度条,圆点会出现错位现象,此代码仅供,带圆点的圆形进度条有空研究一下!图片效 ...

  7. android自定义带进度条的圆形图片

    前言:在项目听新闻的改版中需要实现环绕圆形新闻图片的进度条功能,作为技术预备工作我就去看了一些网上的相关的原理,做了一个自定义带进度条的圆形图片的demo,并将这个实现写成文章发布出来,谁需要了可以进 ...

  8. 自定义带取景框的camera

    前言:公司项目需求,在图像信息采集时只采集肩部以上部位的图片(和我们平时的一寸证件照很像),首先想到的是用第三方的图片选择器,他们都自带裁剪功能,不过每次拍完照后的手动裁剪,结果老大说简化业务人员的操 ...

  9. Qt之自定义带游标的QSlider

    最近翻看6年前写了一篇关于QSlider的博客:Qt自定义带游标的slider,在滑块正上方显示当前值 发现存在很多问题,比如游标的坐标不准确:如果游标宽度稍大,滑到Slider最左或最右的时候会显示 ...

最新文章

  1. (C++)判断一个序列是non-increasing/non-decreasing还是两者都不的两个方法
  2. FPGA和DSP间基于SRIO的高速通信系统设计
  3. 一看就懂的感知机算法PLA
  4. 安装 | MatlabR2019b: License Manager Error -8. License checkout failed.
  5. 合并两个有序链表—leetcode21
  6. 移位运算符<< >>
  7. linux查看内核分区,如何根据bootloader中MTD分区信息修改linux内核中的MTD分区
  8. 自学python能找到工作吗-学习Python真的能找到工作吗?
  9. 在ubuntu12.04下编译android4.1.2添加JNI层出现问题
  10. pku1833 排列(use next_permutation)
  11. Jupyter编程完成对手写体Mnist数据集中10个字符 (0-9)的分类识别
  12. js处理服务器传递的json文件,获取js 文件传递的参数并使用json2进行json数据转换...
  13. 数据库操作:更新数据update
  14. 野生二粒小麦基因组在science发布
  15. 用计算机写作文教学难点,《用计算机写作文》教学设计
  16. 几何分布期望与方差推导
  17. 用python和adb将一加便签内容迁移到小米或其他品牌便签软件
  18. Spring boot 获取本机的IP地址mac地址以及电脑名称!
  19. C select 函数
  20. 台式计算机win如何联网,Win10台式机怎么连接无线网(wifi)?

热门文章

  1. apache+mod_wsgi配置
  2. Symbian S60 签名工具
  3. 构建虚拟工控环境系列 - 罗克韦尔虚拟PLC
  4. 自制简单表单验证relative与absolute定位
  5. [C#参考]字符编码
  6. nagios监控linux主机及服务信息
  7. 浅析权限认证中的有状态和无状态
  8. HashMap中的hash算法的几个思考
  9. Cilium创建pod network源码解析
  10. Dubbo(一) 使用Java RMI 实现RPC(远程过程调用)