Android 自定义SeekBar (一)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Android 自定义SeekBar (一),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含10979字,纯文字阅读大概需要16分钟。
内容图文
![Android 自定义SeekBar (一)](/upload/InfoBanner/zyjiaocheng/1325/8de7ee240ee741728e59015fc95bdc73.jpg)
一、前言
巩固自定义view基础用,本次尝试构建一个拖动条组件。代码参考于 https://github.com/woxingxiao/BubbleSeekBar ,精简其中高度可重用的部分,仅保留基本的拖拽功能,由于代码很巧妙,以后可以再深入探究学习。
本文在前面自定义view的基础上,增加了测量(onMeasure) 以及 触碰屏幕事件(onTouchEvent)。相信可以一步步踏实巩固,学会自定义view的知识。由于本拖动条仍是一个view,不需要涉及到布局(onLayout) 。以后学习自定义viewGroup时再另行探究。老规矩第一章先放效果图和全部代码。
二、效果图
三、代码
values/attr.xml
<? xml version="1.0" encoding="utf-8" ?> < resources > < declare-styleable name ="MySeekBar" > < attr name ="progress_max" format ="float|reference" /> <!-- 进度条最大值 --> < attr name ="progress_min" format ="float|reference" /> <!-- 进度条最小值 --> < attr name ="progress_default" format ="float|reference" /> <!-- 进度条默认值 --> < attr name ="track_left_height" format ="dimension|reference" /> <!-- 进度条左边高度 --> < attr name ="track_right_height" format ="dimension|reference" /> <!-- 进度条右边高度 --> < attr name ="track_left_color" format ="color|reference" /> <!-- 进度条左边颜色 --> < attr name ="track_right_color" format ="color|reference" /> <!-- 进度条右边颜色 --> < attr name ="thumb_color_default" format ="color|reference" /> <!-- 拖动滑块默认颜色 --> < attr name ="thumb_radius_default" format ="dimension|reference" /> <!-- 拖动滑块半径 --> < attr name ="thumb_color_on_dragging" format ="color|reference" /> <!-- 拖动滑块拖动中颜色 --> < attr name ="thumb_radius_on_dragging" format ="dimension|reference" /> <!-- 拖动滑块拖动中半径 --> </ declare-styleable > </ resources >
MySeekBar.java
package com.kms.myseekbar; /* * Created by kwy on 2020/5/22 */ import android.animation.ValueAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.LinearInterpolator; import com.kms.myseekbar.util.DimensionUtil; import androidx.annotation.Nullable; public class MySeekBar extends View { /********************** 参数 **********************/privatefloat progress_max; // 进度条最大值privatefloat progress_min; // 进度条最小值privatefloat progress_default; // 进度条默认值privateint track_left_height; // 进度条左边高度privateint track_right_height; // 进度条右边高度privateint track_left_color; // 进度条左边颜色privateint track_right_color; // 进度条右边颜色privateint thumb_color_default; // 拖动滑块默认颜色privateint thumb_radius_default; // 拖动滑块半径privateint thumb_color_on_dragging; // 拖动滑块拖动中颜色privateint thumb_radius_on_dragging; // 拖动滑块拖动中半径/********************** 绘制相关 **********************/private Paint paint; // 画笔privateint xLeft; // 实际的绘图区域按距离父布局左边 padding 算起privateint xRight; // 到距离父布局右边的的 padding 结束privateint yCenter; // 确定绘制进度条Y轴意义上的中点privateint thumb_radius; // 滑动滑块半径/********************** 构造函数 **********************/public MySeekBar(Context context) { this(context, null); } public MySeekBar(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public MySeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MySeekBar, defStyleAttr, 0); this.progress_max = typedArray.getFloat(R.styleable.MySeekBar_progress_max, 100); this.progress_min = typedArray.getFloat(R.styleable.MySeekBar_progress_min, 0); this.progress_default = typedArray.getFloat(R.styleable.MySeekBar_progress_default, progress_min); this.track_left_height = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_track_left_height, DimensionUtil.dp2px(8)); this.track_right_height = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_track_right_height, track_left_height - DimensionUtil.dp2px(2)); this.track_left_color = typedArray.getColor(R.styleable.MySeekBar_track_left_color, Color.BLUE); this.track_right_color = typedArray.getColor(R.styleable.MySeekBar_track_right_color, Color.LTGRAY); this.thumb_color_default = typedArray.getColor(R.styleable.MySeekBar_thumb_color_default, track_left_color); this.thumb_radius_default = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_thumb_radius_default, track_left_height + DimensionUtil.dp2px(2)); this.thumb_color_on_dragging = typedArray.getColor(R.styleable.MySeekBar_thumb_color_on_dragging, thumb_color_default); this.thumb_radius_on_dragging = typedArray.getDimensionPixelSize(R.styleable.MySeekBar_thumb_radius_on_dragging, thumb_radius_default + DimensionUtil.dp2px(2)); typedArray.recycle(); thumb_radius = thumb_radius_default; initPaint(); // 初始化画笔 } /********************** Getter and Setter **********************/publicfloat getProgressMax() { return progress_max; } public MySeekBar setProgressMax(float progressMax) { this.progress_max = progressMax; returnthis; } publicfloat getProgressMin() { return progress_min; } public MySeekBar setProgressMin(float progressMin) { this.progress_min = progressMin; returnthis; } publicfloat getProgressDefault() { return progress_default; } public MySeekBar setProgressDefault(float progressDefault) { this.progress_default = progressDefault; returnthis; } publicint getTrackLeftHeight() { return track_left_height; } public MySeekBar setTrackLeftHeight(int trackLeftHeight) { this.track_left_height = trackLeftHeight; returnthis; } publicint getTrackRightHeight() { return track_right_height; } public MySeekBar setTrackRightHeight(int trackRightHeight) { this.track_right_height = trackRightHeight; returnthis; } publicint getTrackLeftColor() { return track_left_color; } public MySeekBar setTrackLeftColor(int trackLeftColor) { this.track_left_color = trackLeftColor; returnthis; } publicint getTrackRightColor() { return track_right_color; } public MySeekBar setTrackRightColor(int trackRightColor) { this.track_right_color = trackRightColor; returnthis; } publicint getThumbColorDefault() { return thumb_color_default; } public MySeekBar setThumbColorDefault(int thumbColorDefault) { this.thumb_color_default = thumbColorDefault; returnthis; } publicint getThumbRadiusDefault() { return thumb_radius_default; } public MySeekBar setThumbRadiusDefault(int thumbRadiusDefault) { this.thumb_radius_default = thumbRadiusDefault; returnthis; } publicint getThumbColorOnDragging() { return thumb_color_on_dragging; } public MySeekBar setThumbColorOnDragging(int thumbColorOnDragging) { this.thumb_color_on_dragging = thumbColorOnDragging; returnthis; } publicint getThumbRadiusOnDragging() { return thumb_radius_on_dragging; } public MySeekBar setThumbRadiusOnDragging(int thumbRadiusOnDragging) { this.thumb_radius_on_dragging = thumbRadiusOnDragging; returnthis; } /********************** 绘制相关 **********************/privatevoid initPaint(){ paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeCap(Paint.Cap.ROUND); } @Override protectedvoid onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 仅当 android_layout_width = wrap_content 或未指定时生效,若测出来的size大于你所指定的size (譬如这里是180dp),则使用所指定的sizeint width = resolveSize(DimensionUtil.dp2px(180), widthMeasureSpec); int height = thumb_radius_on_dragging * 2; // 控件高度按拖动时的滑块直径 setMeasuredDimension(width, height); // 强制指定控件大小 xLeft = getPaddingLeft() + thumb_radius_on_dragging; // 实际的绘图区域按距离父布局左边 padding 算起 xRight = getMeasuredWidth() - getPaddingRight() - thumb_radius_on_dragging; // 到距离父布局右边的的 padding 结束 yCenter = getPaddingTop() + thumb_radius_on_dragging; // 确定绘制进度条Y轴意义上的中点 } @Override protectedvoid onDraw(Canvas canvas) { super.onDraw(canvas); int currentProgress = (int) (progress_default / progress_max * (xRight-xLeft)); drawRightTrack(canvas, currentProgress); drawLeftTrack(canvas, currentProgress); drawThumb(canvas, currentProgress); } /** * 绘制进度条左边 */privatevoid drawLeftTrack(Canvas canvas, int currentProgress){ paint.setColor(track_left_color); paint.setStrokeWidth(track_left_height); canvas.drawLine(xLeft, yCenter, xLeft + currentProgress, yCenter, paint); } /** * 绘制拖动滑块 */privatevoid drawThumb(Canvas canvas, int currentProgress){ paint.setColor(thumb_color_default); canvas.drawCircle(xLeft + currentProgress, yCenter, thumb_radius, paint); } /** * 绘制进度条右边 */privatevoid drawRightTrack(Canvas canvas, int currentProgress){ paint.setColor(track_right_color); paint.setStrokeWidth(track_right_height); canvas.drawLine(xLeft + currentProgress, yCenter, xRight, yCenter, paint); } publicvoid startAnim(){ final ValueAnimator animator = ValueAnimator.ofInt(0,100); animator.setDuration(100*500); animator.setRepeatCount(ValueAnimator.INFINITE); animator.setRepeatMode(ValueAnimator.RESTART); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override publicvoid onAnimationUpdate(ValueAnimator animation) { progress_default = (int) animation.getAnimatedValue(); invalidate(); } }); animator.start(); } @Override publicboolean onTouchEvent(MotionEvent event) { switch (event.getActionMasked()){ case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: performClick(); // 若 SeekBar设置了 OnClickListener,可以在此处唤醒监听器 getParent().requestDisallowInterceptTouchEvent(true); // 不允许父组件拦截触摸事件 thumb_radius = thumb_radius_on_dragging; progress_default = calculateDraggingX(event.getX()); break; default: thumb_radius = thumb_radius_default; } invalidate(); returntrue; } /** * 计算拖动值 * * @param x 屏幕上的event.getX() * @return 经转换后对应拖动条的进度值 */privatefloat calculateDraggingX(float x){ if(x < xLeft){ return progress_min; } if(x > xRight){ return progress_max; } return x / getMeasuredWidth() * progress_max; } }
layout/activity_main.xml
<? xml version="1.0" encoding="utf-8" ?> < androidx.constraintlayout.widget.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" android:padding ="10dp" > < com.kms.myseekbar.MySeekBar android:id ="@+id/my_seek_bar" android:layout_width ="match_parent" android:layout_height ="20dp" app:layout_constraintBottom_toBottomOf ="parent" app:layout_constraintLeft_toLeftOf ="parent" app:layout_constraintRight_toRightOf ="parent" app:layout_constraintTop_toTopOf ="parent" /> </ androidx.constraintlayout.widget.ConstraintLayout >
MainActivity.java
package com.kms.myseekbar; import android.graphics.Color; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { MySeekBar mySeekBar; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mySeekBar = findViewById(R.id.my_seek_bar); mySeekBar.setThumbColorDefault(Color.BLUE).setProgressDefault(50); // mySeekBar.startAnim(); } }
完!下一节将讲解下基本思路
原文:https://www.cnblogs.com/qq1094417747/p/12938516.html
内容总结
以上是互联网集市为您收集整理的Android 自定义SeekBar (一)全部内容,希望文章能够帮你解决Android 自定义SeekBar (一)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。