服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - android尺子的自定义view——RulerView详解

android尺子的自定义view——RulerView详解

2022-12-01 14:40Sharley Android

这篇文章主要介绍了android尺子的自定义view——RulerView详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

项目中用到自定义尺子的样式:

android尺子的自定义view——RulerView详解

原代码在github上找的,地址:https://github.com/QQabby/HorizontalRuler

原效果为

android尺子的自定义view——RulerView详解

因为跟自己要使用的view稍有不同 所以做了一些修改,修改的注释都放在代码中了,特此记录一下。

首先是一个自定义View:

?
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
public class RuleView extends View {
 
  private Paint paint;
 
  private Context context;
 
  private int maxValue = 500;
  /**
   * 起点x的坐标
   */
  private float startX ;
 
  private float startY ;
  /**
   * 刻度线的长度
   */
  private float yLenght ;
  /**
   * 刻度的间隙
   */
//  private float gap = 8f;
  private float gap = 10;
  /**
   * 文本的间隙
   */
  private float textGap = 10f;
  /**
   * 短竖线的高度
   */
  private float smallHeight = 10f;
  /**
   * 长竖线的高度
   */
  private float largeHeight = 22f;
  
  /**
   * 文本显示格式化
   */
  private DecimalFormat format;
 
  private DisplayMetrics metrics = null;
  /**
   * 文本的字体大小
   */
  private float mFontSize;
 
  private Handler mScrollHandler = null;
 
  private MyHorizontalScrollView horizontalScrollView;
 
  private int mCurrentX = -999999999;
  /**
   * 刻度进制
   */
//  private float unit = 10f;
  private int unit = 10;//隔unit个刻度写一个数字
  //每个大刻度代表值iValue
  private int iValue = 10;
 
  boolean isDraw = true;
 
  public RuleView(Context context) {
    super(context);
    this.context = context;
    init();
  }
 
  public void setHorizontalScrollView(
      MyHorizontalScrollView horizontalScrollView) {
    this.horizontalScrollView = horizontalScrollView;
 
    this.horizontalScrollView.setOnTouchListener(new OnTouchListener() {
 
      @Override
      public boolean onTouch(View v, MotionEvent event) {
 
        final int action = event.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
 
          break;
        case MotionEvent.ACTION_MOVE:
 
          mScrollHandler.removeCallbacks(mScrollRunnable);
          break;
        case MotionEvent.ACTION_UP:
 
          mScrollHandler.post(mScrollRunnable);
          break;
        }
        return false;
      }
    });
  }
 
  public RuleView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
 
    init();
  }
 
  public void init() {
 
//    format = new DecimalFormat("0.0");
    format = new DecimalFormat("0");//不使用浮点数格式
 
    metrics = new DisplayMetrics();
    WindowManager wmg = (WindowManager) context
        .getSystemService(Context.WINDOW_SERVICE);
    wmg.getDefaultDisplay().getMetrics(metrics);
 
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setStyle(Paint.Style.FILL);
    paint.setStrokeWidth(getResources().getDimension(R.dimen.ui_1_dip));
//    paint.setStrokeWidth(2);
    paint.setColor(Color.parseColor("#999999"));
 
    mFontSize = ScreenUtil.dip2px(context, 16);
//    startY = ScreenUtil.dip2px(context, 20f);
    startY = ScreenUtil.dip2px(context, 0);//Y轴由0开始,即最顶端,不用设置适配布局文件RuleView的android:layout_marginTop="-20dp"
    yLenght = ScreenUtil.dip2px(context, 10);
//    gap = ScreenUtil.dip2px(context, 8f);
    gap = ScreenUtil.dip2px(context, 10);
//    startX = ScreenUtil.getScreenWidth(context)/ 2.0f- getResources().getDimension(R.dimen.ui_10_dip) ;
    startX = ScreenUtil.getScreenWidth(context)/ 2.0f;//X轴不减去10dp,则三角形顶点可以刚好最准0位置
 
    // + getResources().getDimension(R.dimen.text_h2)/2.0f
    // Util.dip2px(context, 13f) +
 
    mScrollHandler = new Handler(context.getMainLooper());
 
  }
 
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 
    float width = maxValue * gap + ScreenUtil.getScreenWidth(context) - getResources().getDimension(R.dimen.ui_10_dip)*2.0f ;
 
    // int widthMode = MeasureSpec.getMode(heightMeasureSpec);
    // if(widthMode == MeasureSpec.AT_MOST){
    // Log.d("TAG", "mode::AT_MOST");
    // }else if(widthMode == MeasureSpec.EXACTLY){
    // Log.d("TAG", "mode::EXACTLY");
    // }else if(widthMode == MeasureSpec.UNSPECIFIED){
    // Log.d("TAG", "mode::UNSPECIFIED");
    // }
 
    setMeasuredDimension((int) width, heightMeasureSpec);
  }
 
  @Override
  protected void onDraw(final Canvas canvas) {
    super.onDraw(canvas);
 
    // 画刻度线
    paint.setColor(getResources().getColor(R.color.gray_bg_high));// 刻度颜色
    for (int i = 0; i <= maxValue; i++) {
 
      if (i % 5 == 0) {
        yLenght = ScreenUtil.dip2px(context, largeHeight);
      } else {
        yLenght = ScreenUtil.dip2px(context, smallHeight);
      }
      canvas.drawLine(i * gap + startX, startY, i * gap + startX, yLenght
          + startY, paint);
    }
 
    paint.setTextSize(mFontSize);
 
    // 每10个刻度写一个数字
    textGap = gap * unit;
 
    // 画刻度文字30
    paint.setColor(getResources().getColor(R.color.textGray));// 文字颜色
    for (int i = 0; i <= maxValue / unit; i++) {
 
//      String text = format.format(i + 1) + "";//从0开始计数时不用加1
      String text = format.format(i * iValue) + "";//乘以每刻度的值iValue
      // 获取文本的宽度
      float width = ScreenUtil.px2dip(context, calculateTextWidth(text)) / 2f;
 
      canvas.drawText(
          text,
          startX - width + i * textGap,
          (startY + ScreenUtil.dip2px(context, largeHeight))
              + ScreenUtil.dip2px(context, 24), paint);//字体大小
    }
  }
 
  /**
   * 获取TextView中文本的宽度
   */
  private float calculateTextWidth(String text) {
    if (TextUtils.isEmpty(text)) {
      return 0;
    }
    TextPaint textPaint = new TextPaint();
    textPaint.setTextSize(mFontSize * metrics.scaledDensity);
    final float textWidth = textPaint.measureText(text);
 
    return textWidth;
  }
 
  DecimalFormat df = new DecimalFormat("0.0");
 
  /**
   * 当滑动尺子的时候
   */
  int scrollWidth = 0;
 
  public void setScrollerChanaged(int l, int t, int oldl, int oldt) {
    // 滑动的距离
    scrollWidth = l;
 
    float number = scrollWidth / gap;
    float result = number / unit;
 
    listener.onSlide(result);
  }
 
  public onChangedListener listener;
 
  public interface onChangedListener {
 
    void onSlide(float number);
  }
 
  public void onChangedListener(onChangedListener listener) {
    this.listener = listener;
  }
 
  /**
   * 滚动监听线程
   */
  private Runnable mScrollRunnable = new Runnable() {
 
    @Override
    public void run() {
      if (mCurrentX == horizontalScrollView.getScrollX()) {// 滚动停止了
 
        try {
 
          float x = horizontalScrollView.getScrollX();
          float value = (x / (gap * unit));// 当前的值
          String s = df.format(value);
 
          // 滑动到11.0 ok
          int scrollX = (int) (Double.parseDouble(s) * gap * unit);
 
          horizontalScrollView.smoothScrollTo(scrollX, 0);
 
        } catch (NumberFormatException numExp) {
          numExp.printStackTrace();
        }
        mScrollHandler.removeCallbacks(this);
      } else {
        mCurrentX = horizontalScrollView.getScrollX();
        mScrollHandler.postDelayed(this, 50);
      }
    }
  };
 
  /**
   * 设置默认刻度尺的刻度值,不会滚动到相应的位置
   *
   * @param scaleValue
   */
  public void setDefaultScaleValue(float scaleValue) {
 
//    final int scrollX = (int) ((scaleValue - 1.0f) * gap * unit);//从0开始计数时不用减去1
    final int scrollX = (int) (scaleValue * gap * unit / 10);//每个值在设置刻度时会乘以10,所以除去
 
    new Handler().postDelayed(new Runnable() {
 
      @Override
      public void run() {
 
        horizontalScrollView.smoothScrollTo(scrollX, 0);
      }
    }, 100);
  }
 
  /**
   * 设置刻度值
   */
  public void setScaleValue(int iValue) {
    this.iValue = iValue;
  }
 
  /**
   * 设置刻度最小值
   */
  public void setMinScaleValue(Float minScaleValue) {
    // this.minScaleValue = minScaleValue;
  }
 
  /**
   * 获取刻度最大值
   */
  public Float getMaxScaleValue() {
    // return maxScaleValue;
    return 33.0f;
  }
 
  /**
   * 设置刻度最大值
   */
  public void setMaxScaleValue(Float maxScaleValue) {
    // this.maxScaleValue = maxScaleValue;
  }
 
  /**
   * 设置当前刻度尺的刻度值,并滚动到相应的位置
   *
   * @param scaleValue
   */
  public void setScaleScroll(float scaleValue) {
 
    int scrollX = (int) ((scaleValue - 1.0f) * gap * unit);
 
    horizontalScrollView.smoothScrollTo(scrollX, 0);
  }
}

另外用到一个自定义的scrollView:

?
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
public class MyHorizontalScrollView extends HorizontalScrollView {
 
  private OnScrollListener onScrollListener = null;
 
  public MyHorizontalScrollView(Context context) {
    this(context, null);
  }
  public MyHorizontalScrollView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }
  public MyHorizontalScrollView(Context context, AttributeSet attrs,
      int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
 
  @Override
  protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
    if(onScrollListener != null){
      onScrollListener.onScrollChanged(l, t, oldl, oldt);
    }
  }
 
  public interface OnScrollListener {
    public void onScrollChanged(int l, int t, int oldl, int oldt);
  }
 
  public void setOnScrollListener(OnScrollListener onScrollListener) {
    this.onScrollListener = onScrollListener;
  }
}

直尺上的黄色三角标其实是嵌在布局上的,在drawble文件中实现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 
  <item android:id="@+id/shape_id">
    <!--&lt;!&ndash; 正三角 &ndash;&gt;-->
    <!--<rotate-->
    <!--android:fromDegrees="45"-->
    <!--android:toDegrees="45"-->
    <!--android:pivotX="-40%"-->
    <!--android:pivotY="80%">-->
    <!-- 倒三角 -->
    <rotate
      android:fromDegrees="45"
      android:toDegrees="45"
      android:pivotX="135%"
      android:pivotY="15%"
      >
      <shape android:shape="rectangle">
        <solid android:color="@color/main_yellow"/>
      </shape>
    </rotate>
  </item>
 
</layer-list>

下面是布局文件,注意RuleView是嵌在ScrollView中的:

?
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
<RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="300px"
      android:layout_marginTop="30px"
      android:background="#fff">
    <MyHorizontalScrollView
      android:id="@+id/hor_scrollview"
      android:layout_width="match_parent"
      android:layout_height="300px"
      android:scrollbars="none" >
 
 
      <RuleView
        android:id="@+id/rule_view"
        android:background="@color/main_white"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="top"/>
    </MyHorizontalScrollView>
      <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/gray_bg"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true" />
      <View
        android:layout_width="30px"
        android:layout_height="30px"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        android:background="@drawable/shape_triangle" />
    </RelativeLayout>

最后在界面中的使用:

?
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
ruleView = (RuleView) findViewById(R.id.rule_view);
 
    horizontalScrollView = (MyHorizontalScrollView) findViewById(R.id.hor_scrollview);
    horizontalScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);// 去掉超出滑动后出现的阴影效果
 
    // 设置水平滑动
    ruleView.setHorizontalScrollView(horizontalScrollView);
    ruleView.setDefaultScaleValue(num);
 
    // 当滑动尺子的时候
    horizontalScrollView.setOnScrollListener(new MyHorizontalScrollView.OnScrollListener() {
 
      @Override
      public void onScrollChanged(int l, int t, int oldl, int oldt) {
 
        ruleView.setScrollerChanaged(l, t, oldl, oldt);
      }
    });
 
 
    ruleView.onChangedListener(new RuleView.onChangedListener() {
      @Override
      public void onSlide(float number) {
 
        int num = (int) (number * 10);
        tvNum.setText(num+"");
      }
    });

以上这篇android尺子的自定义view——RulerView详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/Sharley/p/9229907.html

延伸 · 阅读

精彩推荐