源码整理

This commit is contained in:
2025-12-17 14:14:07 +08:00
parent 740ab932a4
commit dbcb5259d9

View File

@@ -6,91 +6,142 @@ import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.widget.SeekBar; import android.widget.SeekBar;
public class VerticalSeekBar extends SeekBar { import cc.winboll.studio.libappbase.LogUtils;
public static final String TAG = VerticalSeekBar.class.getSimpleName();
public volatile int _mnProgress = -1; /**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/17 14:11
* @Describe 垂直进度条控件,适配 API30支持逆时针旋转0在下100在上修复滑块同步bug
*/
public class VerticalSeekBar extends SeekBar {
// ======================== 静态常量(置顶,唯一标识)========================
private static final String TAG = VerticalSeekBar.class.getSimpleName();
// ======================== 成员变量(私有优先, volatile 关键字保留,确保线程可见性)========================
private volatile int mProgress = -1; // 当前进度缓存,修复滑块同步问题
// ======================== 构造方法(按参数个数升序排列,适配 Java7 语法)========================
public VerticalSeekBar(Context context) { public VerticalSeekBar(Context context) {
super(context); super(context);
} initView();
LogUtils.d(TAG, "VerticalSeekBar: 单参数构造方法初始化完成");
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} }
public VerticalSeekBar(Context context, AttributeSet attrs) { public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
// 去除冗余的水平阴影 initView();
LogUtils.d(TAG, "VerticalSeekBar: 双参数构造方法初始化完成");
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
LogUtils.d(TAG, "VerticalSeekBar: 三参数构造方法初始化完成");
}
// ======================== 初始化方法(封装通用逻辑,避免构造方法冗余)========================
/**
* 初始化视图配置,适配 API30 资源管控
*/
private void initView() {
// 移除水平默认阴影,优化垂直显示效果,减少 API30 不必要的绘制开销
setBackgroundDrawable(null); setBackgroundDrawable(null);
LogUtils.d(TAG, "initView: 视图初始化完成,移除默认背景阴影");
} }
protected void onSizeChanged(int w, int h, int oldw, int oldh) { // ======================== 重写测量/布局方法(按执行顺序排列:测量→尺寸变化→绘制)========================
super.onSizeChanged(h, w, oldh, oldw); /**
} * 重写测量方法,交换宽高适配垂直显示,兼容 API30 测量机制
*/
@Override @Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec); super.onMeasure(heightMeasureSpec, widthMeasureSpec);
// 交换测量结果,将原高度作为宽度、原宽度作为高度,实现垂直布局
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
LogUtils.v(TAG, "onMeasure: 垂直测量完成,宽=" + getMeasuredHeight() + ", 高=" + getMeasuredWidth());
} }
protected void onDraw(Canvas c) { /**
// 0--------100,顺时针旋转,小在上 * 重写尺寸变化方法,确保进度变化时视图同步刷新,适配 API30 布局刷新机制
// c.rotate(+90); */
// c.translate(0, -getWidth()); @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// 0--------100,逆时针旋转,小在下 super.onSizeChanged(h, w, oldh, oldw);
c.rotate(-90); LogUtils.v(TAG, "onSizeChanged: 尺寸变化,新宽=" + h + ", 新高=" + w + ", 旧宽=" + oldh + ", 旧高=" + oldw);
c.translate(-getHeight(), 0);
super.onDraw(c);
} }
/**
* 重写绘制方法逆时针旋转90度实现垂直显示0在下100在上适配 API30 画布渲染
*/
@Override
protected void onDraw(Canvas canvas) {
// 逆时针旋转90度平移画布避免绘制偏移核心垂直显示逻辑
canvas.rotate(-90);
canvas.translate(-getHeight(), 0);
super.onDraw(canvas);
LogUtils.v(TAG, "onDraw: 垂直绘制完成,旋转角度=-90°");
}
// ======================== 重写触摸事件方法(核心交互逻辑,适配 API30 事件分发)========================
/**
* 重写触摸事件,转换坐标计算垂直进度,确保 OnSeekBarChangeListener 正常回调
*/
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
// 调用基类的处理函数 // 调用父类方法,保证 OnSeekBarChangeListener 的 onStart/onStopTrackingTouch 正常触发(关键!)
// 该方法可以使得
// SeekBar.OnSeekBarChangeListener
// 的 onStopTrackingTouch 和 onStartTrackingTouch 等函数有效。
boolean handled = super.onTouchEvent(event); boolean handled = super.onTouchEvent(event);
LogUtils.d(TAG, "onTouchEvent: 触摸事件触发action=" + event.getAction() + ", 父类处理结果=" + handled);
if (handled) { if (handled) {
int action = event.getAction(); switch (event.getAction()) {
switch (action) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
LogUtils.d(TAG, "onTouchEvent: 触摸按下坐标Y=" + event.getY());
break;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
// 0--------100,顺时针旋转,小在上 // 计算垂直进度逆时针旋转Y越小进度越大0在下100在上
//_mnProgress = (int)(getMax() * event.getY() / getHeight()); calculateProgress(event.getY());
// // 0--------100,逆时针旋转,小在下 setProgress(mProgress);
_mnProgress = getMax() - (int) (getMax() * event.getY() / getHeight()); LogUtils.v(TAG, "onTouchEvent: 触摸滑动,进度更新为=" + mProgress);
_mnProgress = _mnProgress > 100 ? 100 : _mnProgress ; break;
//LogUtils.d(TAG, "_mnProgress is " + Integer.toString(_mnProgress)); case MotionEvent.ACTION_UP:
setProgress(_mnProgress); // 滑动结束,最终更新进度
//onSizeChanged(getWidth(), getHeight(), 0, 0); calculateProgress(event.getY());
setProgress(mProgress);
LogUtils.d(TAG, "onTouchEvent: 触摸抬起,最终进度=" + mProgress);
break; break;
case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_CANCEL:
break; LogUtils.d(TAG, "onTouchEvent: 触摸取消,进度保持=" + getProgress());
default :
//LogUtils.d(TAG, "event.getAction() is " + event.getAction());
break; break;
} }
} }
// 返回父类处理结果,确保事件分发完整,适配 API30 事件机制
return handled; return handled;
} }
// 解决调用setProgress方法时滑块不跟随的bug // ======================== 重写进度设置方法修复滑块同步bug适配 API30 进度更新)========================
/**
* 重写进度设置,调用尺寸变化方法强制刷新,解决 setProgress 滑块不跟随问题
*/
@Override @Override
public synchronized void setProgress(int progress) { public synchronized void setProgress(int progress) {
super.setProgress(progress); super.setProgress(progress);
// 强制触发尺寸变化同步刷新滑块位置核心bug修复逻辑
onSizeChanged(getWidth(), getHeight(), 0, 0); onSizeChanged(getWidth(), getHeight(), 0, 0);
mProgress = progress;
LogUtils.d(TAG, "setProgress: 进度设置完成,进度=" + progress + ", 滑块同步刷新");
}
// ======================== 内部工具方法(封装重复逻辑,提升复用性)========================
/**
* 计算垂直进度,校准范围 0~100避免异常值
* @param touchY 触摸点Y坐标
*/
private void calculateProgress(float touchY) {
// 核心进度计算公式(逆时针旋转适配)
mProgress = getMax() - (int) (getMax() * touchY / getHeight());
// 校准进度范围,防止超出 0~100兼容 API30 进度边界校验)
mProgress = Math.max(0, Math.min(mProgress, getMax()));
LogUtils.v(TAG, "calculateProgress: 进度计算完成触摸Y=" + touchY + ", 计算进度=" + mProgress);
} }
} }