项目中用到自定义尺子的样式:
原代码在github上找的,地址:https://github.com/QQabby/HorizontalRuler
原效果为
因为跟自己要使用的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" ?> < item android:id = "@+id/shape_id" > <!--<!– 正三角 –>--> <!--<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://zxbcw.cn/post/183330/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)