自定义标尺控件
程序员文章站
2022-06-07 15:33:51
...
原文地址:https://blog.csdn.net/qq_31433525/article/details/79107871
示例
功能描述
通过输入的list节点表示标尺刻度,不规定每一个相同,当长度相同,取得的值只能是节点上的值,没有中间值。支持左滑右滑,滑动有动画,并且划过一般自动滑到节点,未满一半返回原节点。
代码
public class RulerView extends View {
/**屏幕宽度*/
private int screenWidth;
/**控件高度*/
private int viewHeight;
/**view宽度*/
private int viewWidth;
/**m每一小格的长度*/
private int oneItemValue;
/**端点节点*/
private List<String> list =new ArrayList<>();
/**滑动监听器*/
private OnRulerChangeListener rulerListener;
/**滚动计算类*/
private Scroller scroller;
/**手势监听*/
private GestureDetector gestureDetector;
/**偏移量*/
private int offset;
/**绘制的开始位置*/
private int location;
/**显示哪个list值*/
private int distanceInteger;
/**游标颜色*/
private int cursorColor;
/**刻度颜色*/
private int scaleColor;
/**刻度字体颜色*/
private int scaleTextColor;
/**刻度字体大小*/
private int scaleTextSize;
/**手指抬起时的偏移量*/
private int upOffset;
/**是否标尺往回走*/
private boolean isBack;
/**字体所处高度比例*/
private float scaleTextHeight;
/**游标长度比例*/
private float cursorHeight;
public void setList(List<String> list) {
this.list = list;
invalidate();
}
public void setRulerListener(OnRulerChangeListener rulerListener) {
this.rulerListener = rulerListener;
}
public RulerView(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(dm);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RulerView);
cursorColor = typedArray.getColor(R.styleable.RulerView_cursor_color, Color.rgb(255,0,0));
scaleColor = typedArray.getColor(R.styleable.RulerView_scale_color,Color.argb(255,102,102,102));
scaleTextColor = typedArray.getColor(R.styleable.RulerView_scale_text_color,Color.argb(255,102,102,102));
scaleTextSize = typedArray.getDimensionPixelOffset(R.styleable.RulerView_scale_text_size,36);
scaleTextHeight = typedArray.getFloat(R.styleable.RulerView_scale_text_height,(float)0.25);
cursorHeight = typedArray.getFloat(R.styleable.RulerView_cursor_height,(float) 0);
screenWidth = dm.widthPixels;
oneItemValue = screenWidth/20;
//滚动计算器
scroller = new Scroller(context);
//一定要加,不然只会收到onDown,onShowPress,onLongPress3个事件
setClickable(true);
//手势解析
gestureDetector = new GestureDetector(context, gestureListener);
//是否允许长点击
gestureDetector.setIsLongpressEnabled(false);
location=screenWidth/2;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
if(list.size() == 0){
list.add("0");
}
viewWidth=oneItemValue*(list.size()-1)*5;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
viewWidth=oneItemValue*(list.size()-1)*5;
drawBottomLine(canvas);
drawScale(canvas);
drawCursor(canvas);
}
/**绘制刻度*/
private void drawScale(Canvas canvas) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(3);
paint.setColor(scaleColor);
Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
paintText.setTextSize(scaleTextSize);
paintText.setColor(scaleTextColor);
for(int i=0;i <= (list.size()-1)*5;i++){
int currentLocation=location+i*oneItemValue;
if(i % 5 == 0){
String drawStr;
drawStr = list.get(i/5);
Rect bounds = new Rect();
paintText.getTextBounds(drawStr, 0, drawStr.length(), bounds);
canvas.drawText(drawStr, currentLocation - bounds.width() / 2, viewHeight-viewHeight*scaleTextHeight, paintText);
canvas.drawLine(currentLocation, viewHeight-viewHeight/5, currentLocation, viewHeight, paint);
}else{
canvas.drawLine(currentLocation, viewHeight-viewHeight/8, currentLocation, viewHeight, paint);
}
}
}
/**绘制游标*/
private void drawCursor(Canvas canvas) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(3);
paint.setColor(cursorColor);
if(scroller.computeScrollOffset()){
canvas.drawLine(screenWidth/2+scroller.getCurrX(), viewHeight*cursorHeight, screenWidth/2+scroller.getCurrX(), viewHeight, paint);
}else{
canvas.drawLine(screenWidth/2+offset, viewHeight*cursorHeight, screenWidth/2+offset, viewHeight, paint);
}
}
/**绘制底部横线*/
private void drawBottomLine(Canvas canvas) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(3);
paint.setColor(Color.rgb(102,102,102));
if(scroller.computeScrollOffset()){
canvas.drawLine(scroller.getCurrX(),viewHeight,screenWidth+scroller.getCurrX(), viewHeight, paint);
}else{
canvas.drawLine(offset, viewHeight, screenWidth+offset, viewHeight, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
if(event.getAction() == MotionEvent.ACTION_UP){
changeValue();
upOffset = offset;
offset = distanceInteger *5*oneItemValue;
if(isBack){
scroller.startScroll(upOffset,0,-(upOffset-offset),0,1000);
}else{
scroller.startScroll(upOffset,0,(offset-upOffset),0,1000);
}
invalidate();
}
return super.onTouchEvent(event);
}
/**改变textView*/
private void changeValue(){
distanceInteger= offset/(oneItemValue*5);
int distanceRemainder = offset % (oneItemValue*5);
if(distanceRemainder >=oneItemValue*5/2){
distanceInteger=distanceInteger+1;
isBack=false;
}else{
isBack=true;
}
if(rulerListener != null){
if(distanceInteger >= list.size()){
distanceInteger = list.size() -1;
}
rulerListener.setValue(Integer.valueOf(list.get(distanceInteger)));
}
}
private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener(){
/**
* @param e1 滑动事件的起点(也就是说onDown()的时候)
* @param e2 当前滑动位置点(手指的位置)
* @param distanceX 上次滑动(调用onScroll)到这次滑动的X轴的距离px
* @param distanceY 上次滑动(调用onScroll)到这次滑动的Y轴的距离px
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if(offset >= viewWidth && distanceX >= 0){
distanceX =0;
offset=viewWidth;
}else if(offset <= 0 && distanceX <= 0){
distanceX = 0;
offset =0;
}
scroller.forceFinished(true);
offset=offset+(int)distanceX;
scrollTo(offset,0);
return super.onScroll(e1, e2, distanceX, distanceY);
}
/***
* @param e1 拖动动事件的起点(也就是说onDown()的时候)
* @param e2 onFling()调用时,手指的位置
* @param velocityX X轴上每秒滑动像素值
* @param velocityY Y轴上每秒滑动像素值
* 当拖动速率velocityX或velocityY超过ViewConfiguration.getMinimumFlingVelocity()最小拖动速率时,才会调用onFling(),
* 也就是如果只拖动一点,或是慢慢的拖动,是不会触发该方法
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
scroller.fling(offset, 0, (int) (-velocityX / 1.5), 0, 0, viewWidth, 0, 0);
return super.onFling(e1, e2, velocityX, velocityY);
}
};
@Override
public void computeScroll() {
super.computeScroll();
if(scroller.computeScrollOffset()){
scrollTo(scroller.getCurrX(),0);
invalidate();
}else{
scrollTo(offset,0);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
public interface OnRulerChangeListener {
/**设置值*/
void setValue(int value);
}
- 1
- 2
- 3
- 4
- 5
<resources>
<declare-styleable name="RulerView">
<!--游标的颜色-->
<attr name="cursor_color" format="color"></attr>
<!--刻度颜色-->
<attr name="scale_color" format="color"></attr>
<!--刻度字体颜色-->
<attr name="scale_text_color" format="color"></attr>
<!--刻度字体大小-->
<attr name="scale_text_size" format="dimension"></attr>
<!--字体所处高度-->
<attr name="scale_text_height" format="float"></attr>
<!--游标长度比例-->
<attr name="cursor_height" format="float"></attr>
</declare-styleable>
</resources>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
使用
<com.example.RulerView
android:id="@+id/rulerview"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginTop="10dp"
app:cursor_color="#ff0000"
app:scale_color="#333333"
app:scale_text_color="#333333"
app:scale_text_size="20sp" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
public class MainActivity extends AppCompatActivity implements OnRulerChangeListener {
TextView textView;
RulerView rulerView;
int num;
private int currLocation = 500;
private List<String> list=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list.add(0,"500");
list.add(1,"1000");
list.add(2,"1400");
rulerView = (RulerView) findViewById(R.id.rulerview);
rulerView.setRulerListener(this);
rulerView.setList(list);
textView = (TextView) findViewById(R.id.tvValue);
textView.setText(currLocation + "");
}
@Override
public void setValue(int value) {
textView.setText(value+"");
}
}
下一篇: Mysql通过存储过程分割字符串为数组