代码地址如下:
http://www.demodashi.com/demo/13502.html

简介

主要提供一个漂亮而强大的自定义SeekBar,进度变化由提示牌 (sign)展示,具有强大的属性设置,支持设置section(节点)、mark(标记)、track(轨迹)、thumb(拖动块)、progress(进度)、sign(提示框)等功能

主要功能

  • 强大的track(轨迹)和second track (选中轨迹)的最小值、最大值、轨迹粗细,颜色等设置;
  • 灵活的数字显示,支持设置进度展示、节点文本展示采用整数还是浮点数;
  • 支持设置进度单位,例如 10s,15km/h、平方,对数等;
  • 支持手柄拖动块thumb半径、颜色、阴影、透明度等;
  • 支持节点个数、文字大小、颜色设置;
  • 支持指示牌宽高、颜色、圆角半径、三角arrow指示、border边框、跟随thumb移动等;
  • 支持设置拖动进度监听回掉;
  • 支持格式化进度数字,完全自定义进度样式
  • ......

演示

xml

  1. <com.zhouyou.view.seekbar.SignSeekBar
  2. android:id="@+id/seek_bar"
  3. android:layout_width="match_parent"
  4. android:layout_height="16dp"
  5. app:ssb_section_text_position="bottom_sides"
  6. app:ssb_show_progress_in_float="false"
  7. app:ssb_show_section_mark="false"
  8. app:ssb_show_section_text="true"
  9. app:ssb_show_sign="true"
  10. app:ssb_show_thumb_text="false"
  11. app:ssb_sign_arrow_height="5dp"
  12. app:ssb_sign_arrow_width="10dp"
  13. app:ssb_sign_border_color="@color/color_red"
  14. app:ssb_sign_border_size="1dp"
  15. app:ssb_sign_color="@color/color_gray"
  16. app:ssb_sign_show_border="true"/>

java

  1. signSeekBar.getConfigBuilder()
  2. .min(0)
  3. .max(4)
  4. .progress(2)
  5. .sectionCount(4)
  6. .trackColor(ContextCompat.getColor(getContext(), R.color.color_gray))
  7. .secondTrackColor(ContextCompat.getColor(getContext(), R.color.color_blue))
  8. .thumbColor(ContextCompat.getColor(getContext(), R.color.color_blue))
  9. .sectionTextColor(ContextCompat.getColor(getContext(), R.color.colorPrimary))
  10. .sectionTextSize(16)
  11. .thumbTextColor(ContextCompat.getColor(getContext(), R.color.color_red))
  12. .thumbTextSize(18)
  13. .signColor(ContextCompat.getColor(getContext(), R.color.color_green))
  14. .signTextSize(18)
  15. .autoAdjustSectionMark()
  16. .sectionTextPosition(SignSeekBar.TextPosition.BELOW_SECTION_MARK)
  17. .build();

回调

  1. signSeekBar.setOnProgressChangedListener(new SignSeekBar.OnProgressChangedListener() {
  2. @Override
  3. public void onProgressChanged(SignSeekBar signSeekBar, int progress, float progressFloat,boolean fromUser) {
  4. //fromUser 表示是否是用户触发 是否是用户touch事件产生
  5. String s = String.format(Locale.CHINA, "onChanged int:%d, float:%.1f", progress, progressFloat);
  6. progressText.setText(s);
  7. }
  8. @Override
  9. public void getProgressOnActionUp(SignSeekBar signSeekBar, int progress, float progressFloat) {
  10. String s = String.format(Locale.CHINA, "onActionUp int:%d, float:%.1f", progress, progressFloat);
  11. progressText.setText(s);
  12. }
  13. @Override
  14. public void getProgressOnFinally(SignSeekBar signSeekBar, int progress, float progressFloat,boolean fromUser) {
  15. String s = String.format(Locale.CHINA, "onFinally int:%d, float:%.1f", progress, progressFloat);
  16. progressText.setText(s + getContext().getResources().getStringArray(R.array.labels)[progress]);
  17. }
  18. });

Attributes

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="SignSeekBar">
  4. <attr name="ssb_min" format="float|reference"/> <!--min < max, default: 0.0f-->
  5. <attr name="ssb_max" format="float|reference"/> <!--min < max, default: 100.0f-->
  6. <attr name="ssb_progress" format="float|reference"/> <!--real time progress value, default: min-->
  7. <attr name="ssb_is_float_type" format="boolean"/> <!--support for float type-->
  8. <attr name="ssb_track_size" format="dimension|reference"/> <!--height of right-track(on the right of thumb), default: 2dp-->
  9. <!--height of left-track(on the left of thumb), default: 2dp higher than right-track's height-->
  10. <attr name="ssb_second_track_size" format="dimension|reference"/>
  11. <attr name="ssb_thumb_radius" format="dimension|reference"/> <!--radius of thumb, default: 2dp higher than left-track's height-->
  12. <!--radius of thumb when be dragging, default: 2 times of left-track's height-->
  13. <attr name="ssb_thumb_radius_on_dragging" format="dimension|reference"/>
  14. <attr name="ssb_track_color" format="color|reference"/> <!--color of right-track, default: R.color.colorPrimary-->
  15. <attr name="ssb_second_track_color" format="color|reference"/> <!--color of left-track, default: R.color.colorAccent-->
  16. <attr name="ssb_thumb_color" format="color|reference"/> <!--color of thumb, default: same as left-track's color-->
  17. <attr name="ssb_section_count" format="integer|reference"/> <!--shares of whole progress(max - min), default: 10-->
  18. <attr name="ssb_show_section_mark" format="boolean"/> <!--show demarcation points or not, default: false-->
  19. <attr name="ssb_auto_adjust_section_mark" format="boolean"/> <!--auto scroll to the nearest section_mark or not, default: false-->
  20. <attr name="ssb_show_section_text" format="boolean"/> <!--show section-text or not, default: false-->
  21. <attr name="ssb_section_text_size" format="dimension|reference"/> <!--text size of section-text, default: 14sp-->
  22. <attr name="ssb_section_text_color" format="color|reference"/> <!--text color of section-text, default: same as right-track's color-->
  23. <!--text position of section-text relative to track, sides, bottom_sides, below_section_mark, default: sides-->
  24. <attr name="ssb_section_text_position">
  25. <enum name="sides" value="0"/>
  26. <enum name="bottom_sides" value="1"/>
  27. <enum name="below_section_mark" value="2"/>
  28. </attr>
  29. <attr name="ssb_section_text_interval" format="integer"/> <!--the interval of two section-text, default: 1-->
  30. <attr name="ssb_show_thumb_text" format="boolean"/> <!--show real time progress-text under thumb or not, default: false-->
  31. <attr name="ssb_thumb_text_size" format="dimension|reference"/> <!--text size of progress-text, default: 14sp-->
  32. <attr name="ssb_thumb_text_color" format="color|reference"/> <!--text color of progress-text, default: same as left-track's color-->
  33. <attr name="ssb_show_progress_in_float" format="boolean"/> <!--show Sign-progress in float or not, default: false-->
  34. <attr name="ssb_touch_to_seek" format="boolean"/> <!--touch anywhere on track to quickly seek, default: false-->
  35. <attr name="ssb_seek_by_section" format="boolean"/> <!--seek by section, the progress may not be linear, default: false-->
  36. <attr name="ssb_sign_color" format="color|reference"/> <!--color of sign, default: same as left-track's color-->
  37. <attr name="ssb_sign_border_color" format="color|reference"/> <!--color of sign, border-->
  38. <attr name="ssb_sign_show_border" format="boolean"/> <!--color of sign, default: same as left-track's color-->
  39. <attr name="ssb_sign_text_size" format="dimension|reference"/> <!--text size of sign-progress, default: 14sp-->
  40. <attr name="ssb_sign_border_size" format="dimension|reference"/> <!--border size, default: 1dp-->
  41. <attr name="ssb_sign_text_color" format="color|reference"/> <!--text color of sign-progress, default: #ffffffff-->
  42. <attr name="ssb_anim_duration" format="integer"/> <!--duration of animation, default: 200ms-->
  43. <attr name="ssb_show_sign" format="boolean"/> <!--hide sign, default: false-->
  44. <attr name="ssb_text_space" format="dimension|reference"/><!--default:2dp-->
  45. <attr name="ssb_sides_labels" format="reference"/><!--default:null-->
  46. <attr name="ssb_thumb_bg_alpha" format="float|reference"/> <!--0.0f-1.0f, default: 0.2f-->
  47. <attr name="ssb_thumb_ratio" format="float|reference"/> <!--0.0f-1.0f, default: 0.7f-->
  48. <attr name="ssb_show_thumb_shadow" format="boolean"/> <!--0.0f-1.0f, default: false-->
  49. <attr name="ssb_sign_arrow_autofloat" format="boolean"/> <!--sign arrow auto float, default: true-->
  50. <attr name="ssb_sign_height" format="dimension|reference"/> <!--sign height,default:22dp-->
  51. <attr name="ssb_sign_width" format="dimension|reference"/> <!--sign_width ,default:72dp-->
  52. <attr name="ssb_sign_arrow_height" format="dimension|reference"/> <!--sign arrow height ,default:3dp-->
  53. <attr name="ssb_sign_arrow_width" format="dimension|reference"/> <!--sign arrow width, default:5dp-->
  54. <attr name="ssb_sign_round" format="dimension|reference"/> <!--sign round, default:3dp-->
  55. </declare-styleable>
  56. </resources>

主要实现思路介绍

概况

本库自定义控件主要是用了Canvas相关的drawXXX系列方法、一些简单的算法和动画来完成的。比如拖动轨迹、滑块thumb拖动、放大、自动滚动最近节点、指示牌、区段节点标记、进度单位显示等。接下来会讲解下主要的实现思路,对于自定义View的其它基本流程,属性获取和设置、onMeasure的重写等都不重点介绍,想了解完整流程请看源码

track(轨道)绘制

画轨道比较简单,主要实现方式就是画两条不同颜色的线条(其实画的是一条分为左右两部分,衔接的地方是有个thumb遮挡着),主要是要求出滑动thumb的中心点mThumbCenterX,mThumbCenterX的计算非常重要,本库的很多计算都是围绕mThumbCenterX,mThumbCenterX是通过onTouchEvent事件MotionEvent

根据down、move事件实时计算出中心点x坐标。

  1. // draw track
  2. mPaint.setColor(mSecondTrackColor);
  3. mPaint.setStrokeWidth(mSecondTrackSize);
  4. canvas.drawLine(xLeft, yTop, mThumbCenterX, yTop, mPaint);
  5. // draw second track
  6. mPaint.setColor(mTrackColor);
  7. mPaint.setStrokeWidth(mTrackSize);
  8. canvas.drawLine(mThumbCenterX, yTop, xRight, yTop, mPaint);

track(轨道)接触有效计算

MotionEvent的getX()和getY()获得的永远是相对view的触摸位置坐标,getRawX()和getRawY()获得的是相对屏幕的位置,轨道计算用的是getX,getY 相对于容器的位置坐标x,y,计算x,y坐标是否在轨道的矩形方框内,从而判断是否在轨道上。

  1. private boolean isTrackTouched(MotionEvent event) {
  2. return isEnabled() && event.getX() >= getPaddingLeft() && event.getX() <= getMeasuredWidth() - getPaddingRight()
  3. && event.getY() >= getPaddingTop() && event.getY() <= getMeasuredHeight() - getPaddingBottom();
  4. }

thumb(滑块)接触有效计算

thumb就是轨道上的圆形滑块,如何判断手指拖动的区域是否在滑块上呢,使用圆的标准方程(x-a)²+(y-b)²=r²来判断

  1. private boolean isThumbTouched(MotionEvent event) {
  2. if (!isEnabled())
  3. return false;
  4. float mCircleR = isThumbOnDragging ? mThumbRadiusOnDragging : mThumbRadius;
  5. float x = mTrackLength / mDelta * (mProgress - mMin) + mLeft;
  6. float y = getMeasuredHeight() / 2f;
  7. return (event.getX() - x) * (event.getX() - x) + (event.getY() - y) * (event.getY() - y)
  8. <= (mLeft + mCircleR) * (mLeft + mCircleR);
  9. }

thumb(滑块)透明度实现

滑块的透明度,是将滑块的颜色值进行计算加上alpha,求出一个新的颜色值,主要是使用Color这个工具类的方法,大家经常用到的是Color的parseColor(@Size(min=1) String colorString)方法,库中主要用的是Color的另一些方法alpha(int color)、red(int color)、green(int color)、blue(int color)方法分别求出argb值,求出的透明度经过计算修改后,再用 Color.argb(alpha, r, g, b)组合得出一个新的颜色值。

  1. /**
  2. * 计算新的透明度颜色
  3. *
  4. * @param color 旧颜色
  5. * @param ratio 透明度系数
  6. */
  7. public int getColorWithAlpha(int color, float ratio) {
  8. int newColor = 0;
  9. int alpha = Math.round(Color.alpha(color) * ratio);
  10. int r = Color.red(color);
  11. int g = Color.green(color);
  12. int b = Color.blue(color);
  13. newColor = Color.argb(alpha, r, g, b);
  14. return newColor;
  15. }

thumb(滑块) 最近节点位置计算方法

根据节点个数mSectionCount和两个节点之间的间隔mSectionOffset,与滑块当前位置mThumbCenterX的比较,求出最近一个节点的位置。

  1. //计算最近节点位置,mSectionCount:节点个数,mSectionOffset:两个节点间隔距离,mThumbCenterX:滑块中心点位置
  2. float x = 0;
  3. for (i = 0; i <= mSectionCount; i++) {
  4. x = i * mSectionOffset + mLeft;
  5. if (x <= mThumbCenterX && mThumbCenterX - x <= mSectionOffset) {
  6. break;
  7. }
  8. }

thumb(滑块) 滚动最近节点动画效果实现

滑块自动滚动到最近节点增加了动画移动效果,使用ValueAnimator实现动画,Property Animation提供了Animator.AnimatorListener和Animator.AnimatorUpdateListener两个监听器用于动画在播放过程中的重要动画事件。其中AnimatorUpdateListener监听中onAnimationUpdate() 方法,动画每播放一帧时调用,在动画过程中,可侦听此事件来获取并使用 ValueAnimator 计算出来的属性值。利用传入事件的 ValueAnimator 对象,调用其 getAnimatedValue() 方法即可获取当前的属性值,就是修改后滑块的位置mThumbCenterX。此动画还配合有Interpolator,动画播放采用LinearInterpolator线性插值的方式执行动画。插值器它定义了动画变化过程中的属性变化规则,它根据时间比例因子计算出一个插值因子,用于设定目标对象的动画执行是否为线性变化、非线性变化或先加速后减速等等。Android系统本身内置了一些通用的Interpolator(插值器),如下:

类或接口名 说明
AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置

完整源码:

  1. private void autoAdjustSection() {
  2. int i;
  3. //计算最近节点位置,mSectionCount:节点个数,mSectionOffset:两个节点间隔距离,mThumbCenterX:滑块中心点位置
  4. float x = 0;
  5. for (i = 0; i <= mSectionCount; i++) {
  6. x = i * mSectionOffset + mLeft;
  7. if (x <= mThumbCenterX && mThumbCenterX - x <= mSectionOffset) {
  8. break;
  9. }
  10. }
  11. BigDecimal bigDecimal = BigDecimal.valueOf(mThumbCenterX);
  12. //BigDecimal setScale保留1位小数,四舍五入,2.35变成2.4
  13. float x_ = bigDecimal.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
  14. boolean onSection = x_ == x; // 就在section处,不作valueAnim,优化性能
  15. AnimatorSet animatorSet = new AnimatorSet();
  16. ValueAnimator valueAnim = null;
  17. if (!onSection) {
  18. if (mThumbCenterX - x <= mSectionOffset / 2f) {
  19. valueAnim = ValueAnimator.ofFloat(mThumbCenterX, x);
  20. } else {
  21. valueAnim = ValueAnimator.ofFloat(mThumbCenterX, (i + 1) * mSectionOffset + mLeft);
  22. }
  23. valueAnim.setInterpolator(new LinearInterpolator());
  24. valueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  25. @Override
  26. public void onAnimationUpdate(ValueAnimator animation) {
  27. mThumbCenterX = (float) animation.getAnimatedValue();
  28. mProgress = (mThumbCenterX - mLeft) * mDelta / mTrackLength + mMin;
  29. invalidate();
  30. if (mProgressListener != null) {
  31. mProgressListener.onProgressChanged(SignSeekBar.this, getProgress(), getProgressFloat(),true);
  32. }
  33. }
  34. });
  35. }
  36. if (!onSection) {
  37. animatorSet.setDuration(mAnimDuration).playTogether(valueAnim);
  38. }
  39. animatorSet.addListener(new AnimatorListenerAdapter() {
  40. @Override
  41. public void onAnimationEnd(Animator animation) {
  42. mProgress = (mThumbCenterX - mLeft) * mDelta / mTrackLength + mMin;
  43. isThumbOnDragging = false;
  44. isTouchToSeekAnimEnd = true;
  45. invalidate();
  46. if (mProgressListener != null) {
  47. mProgressListener.getProgressOnFinally(SignSeekBar.this, getProgress(), getProgressFloat(),true);
  48. }
  49. }
  50. @Override
  51. public void onAnimationCancel(Animator animation) {
  52. mProgress = (mThumbCenterX - mLeft) * mDelta / mTrackLength + mMin;
  53. isThumbOnDragging = false;
  54. isTouchToSeekAnimEnd = true;
  55. invalidate();
  56. }
  57. });
  58. animatorSet.start();
  59. }

采用BigDecimal处理小数

代码中的小数采用BigDecimal来处理,只介绍setScale相关方法,其它更多方法可以自己去学习,这里只是抛砖引玉。

BigDecimal.setScale()方法用于格式化小数点

setScale(1)表示保留一位小数,默认用四舍五入方式

setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3

setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4

setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4

setScaler(1,BigDecimal.ROUND_HALF_DOWN)四舍五入,2.35变成2.3,如果是5则向下舍

Sign 提示框--三角形边框绘制

单纯的进度提示框实现比较简单,主要是由矩形框+三角形组成,但是加边框绘制的时候比较麻烦一点,需要留出矩形和三角形交接的地方不能画线,这里做了假象交接的地方其实额外绘制了三角形的底边,颜色采用的是矩形库填充的颜色。三角形边框绘制如下:

  1. private void drawTriangleBoder(Canvas canvas, Point point1, Point point2, Point point3, Paint paint) {
  2. triangleboderPath.reset();
  3. triangleboderPath.moveTo(point1.x, point1.y);
  4. triangleboderPath.lineTo(point2.x, point2.y);
  5. paint.setColor(signPaint.getColor());
  6. float value = mSignBorderSize / 6;
  7. paint.setStrokeWidth(mSignBorderSize + 1f);
  8. canvas.drawPath(triangleboderPath, paint);
  9. triangleboderPath.reset();
  10. paint.setStrokeWidth(mSignBorderSize);
  11. triangleboderPath.moveTo(point1.x - value, point1.y - value);
  12. triangleboderPath.lineTo(point3.x, point3.y);
  13. triangleboderPath.lineTo(point2.x + value, point2.y - value);
  14. paint.setColor(mSignBorderColor);
  15. canvas.drawPath(triangleboderPath, paint);
  16. }

Sign 提示框--进度单位unit实现方式

进度单位很多需求也是需要的,不是单纯的用canvas.drawText来绘制。这里采用的是StaticLayout。使用Canvas的drawText绘制文本是不会自动换行的,即使一个很长很长的字符串,drawText也只显示一行,超出部分被隐藏在屏幕之外。可以逐个计算每个字符的宽度,通过一定的算法将字符串分割成多个部分,然后分别调用drawText一部分一部分的显示, 但是这种显示效率会很低。StaticLayout是android中处理文字换行的一个工具类,StaticLayout已经实现了文本绘制换行处理,也支持标签属性<small>,m/s<sup>2</sup>,μmol/l,μ/l从而实现强大灵活的单位设置。

  1. private void createValueTextLayout() {
  2. String value = isShowProgressInFloat ? String.valueOf(getProgressFloat()) : String.valueOf(getProgress());
  3. if (value != null && unit != null && !unit.isEmpty())
  4. value += String.format(" <small>%s</small>", unit);
  5. Spanned spanned = Html.fromHtml(value);
  6. valueTextLayout = new StaticLayout(spanned, valueTextPaint, mSignWidth, Layout.Alignment.ALIGN_CENTER, 1, 0, false);
  7. }

圆圈中心绘制文本

圆圈中心绘制文字,高度是比较难控制的,特别是中文,不能简单的通过bounds.height()来获取高度的方式计算,需要先求出baseline这种方式来处理,求baseline的方式是固定的。下面提供一个通用的方法:

  1. /**
  2. * 精确画圆圈中心文字(通用方法),其中文字的高度是最难计算适配的,采用此方法,可以完美解决
  3. *
  4. * @param canvas 画板
  5. * @param paint 画笔panit
  6. * @param centerX 圆圈中心X坐标
  7. * @param centerY 圆圈中心Y坐标
  8. * @param radius 半径
  9. * @param text 显示的文本
  10. */
  11. private void drawCircleText(Canvas canvas, Paint paint, float centerX, float centerY, float radius, String text) {
  12. paint.setTextAlign(Paint.Align.LEFT);
  13. Rect bounds = new Rect();
  14. paint.getTextBounds(text, 0, text.length(), bounds);
  15. Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
  16. float baseline = centerY - radius + (2 * radius - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
  17. canvas.drawText(text, centerX - radius + radius - bounds.width() / 2, baseline, paint);
  18. }

项目结构目录截图

一个漂亮而强大的自定义view

代码地址如下:
http://www.demodashi.com/demo/13502.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

一个漂亮而强大的自定义view的更多相关文章

  1. 一个漂亮而强大的RecyclerView

    代码地址如下:http://www.demodashi.com/demo/13470.html 简介 主要提供了简单易用强大的RecyclerView库,包括自定义刷新加载效果.极简通用的万能适配器A ...

  2. Android自定义view(一):制作一个最最最简单的自定义view

    转载:https://blog.csdn.net/wsyizmao/article/details/78491422 浅谈安卓自定义view(一):制作一个最最最简单的自定义view 对于安卓程序员来 ...

  3. Android 自定义View合集

    自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...

  4. 创建自定义view(翻译 androidtraining)

    创建自定义view 一个设计良好的的自定义view应该是一个设计良好的class,它包含了很多实用的功能,让人们更加容易使用接口.它充分利用GPU与内存的性能等等. 另外作为一个设计良好的类,一个自定 ...

  5. Android中View的绘制过程 onMeasure方法简述 附有自定义View例子

    Android中View的绘制过程 onMeasure方法简述 附有自定义View例子 Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android fr ...

  6. Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明地址:http://blog.csdn.net/xiaanming/article/detail ...

  7. 【转】Android中View的绘制过程 onMeasure方法简述 附有自定义View例子

    Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android framework将会处理绘制过程,Activity只需提供它的布局的根节点. 绘制过程从布 ...

  8. Android 自定义View修炼-自定义View-带百分比进度的圆形进度条(采用自定义属性)

    很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己来自定义一个能满足我们需求的View,自定义View我们需要先继承View,添加类的构造方法,重写父类View的一些方法,例如o ...

  9. 推翻自己和过往,重学自定义View

    http://blog.csdn.net/lfdfhl/article/details/51671038 深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 A ...

随机推荐

  1. 【贪心】【后缀自动机】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem E. Enter the Word

    题意:给你一个串,让你从左到右构造这个串,一次操作可以直接在当前串后面添加一个任意字符,或者拷贝当前串的任意一个子串到当前串的后面.问你最少要多少次操作才能构造出这个串. 从前向后贪心,从当前已构造的 ...

  2. 【推导】计蒜客17119 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F. Trig Function

    题意:给你n,m,让你求cos(nx)的展开式的(cos(x))^m项的系数. 更一般的式子是这样的:. 队友的代码: #include<cstdio> #include<algor ...

  3. 【递推+高精度】POJ2506-Tiling

    思路别人那里讲的很清楚了,我就不阐述了.链接 #include<iostream> #include<cstdio> #include<cmath> #includ ...

  4. (小规模)b牌棋盘完美覆盖数

    (小规模)b牌棋盘完美覆盖数 考虑一个普通的国际象棋棋盘,它被分成8*8(8行8列)的64个正方形.设有形状一样的多米诺骨牌,每张牌恰好覆盖棋盘上相邻的两个方格(即1*2的骨牌).那么能否把32个这样 ...

  5. Codeforces Round #127 (Div. 1) B. Guess That Car! 扫描线

    B. Guess That Car! 题目连接: http://codeforces.com/contest/201/problem/B Description A widely known amon ...

  6. .Net 2014 Connect() 相关文章合集

    微软在11月中旬的Connect()研讨会中公布了一系列 2015年的发展规划,今天在MSDN Blog上看到了一篇比较全的相关文章合集,这里转录一下,感兴趣的朋友可以看看. Announcement ...

  7. Inno Setup入门(二十二)——Inno Setup类参考(8)

    http://379910987.blog.163.com/blog/static/33523797201121331832201/ 列表框 列表框(ListBox)是Windows应用程序中重要的输 ...

  8. 从connect到express01-connect

    介绍 Connect是一个node中间件框架.每个中间件在http处理过程中通过改写request, response的数据.状态,实现了特定的功能. 根据中间件在整个http处理流程的位置,将中间件 ...

  9. Android关于JSON数据解析

    一.什么是json json(Javascript Object Notation)是一种轻量级的数据交换格式,相比于xml这种数据交换格式来说,因为解析xml比较的复杂,而且需要编写大段的代码,所以 ...

  10. 【spring data jpa】根据一个时间字段 查询 时间段的处理方法

    处理方法  包含结束时间00.00.00 Date createDate = boxCodeLog.getCreateDate(); if (createDate != null){ LocalDat ...