iOS自定义时间滚动选择控件

前端之家收集整理的这篇文章主要介绍了iOS自定义时间滚动选择控件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

本文实例为大家分享了iOS自定义时间滚动选择控件的具体代码,供大家参考,具体内容如下

1.先上自定义的控件:

  1. /**
  2. * 滚轮选择器
  3. * author LH
  4. * data 2016/8/20 17:26
  5. */
  6. public class WheelView extends View {
  7.  
  8. public static final String TAG = "WheelView";
  9.  
  10. /**
  11. * 自动回滚到中间的速度
  12. */
  13. public static final float SPEED = 2;
  14.  
  15. /**
  16. * 除选中item外,上下各需要显示的备选项数目
  17. */
  18. public static final int SHOW_SIZE = 1;
  19.  
  20. private Context context;
  21.  
  22. private List<String> itemList;
  23. private int itemCount;
  24.  
  25. /**
  26. * item高度
  27. */
  28. private int itemHeight = 50;
  29.  
  30. /**
  31. * 选中的位置,这个位置是mDataList的中心位置,一直不变
  32. */
  33. private int currentItem;
  34.  
  35. private Paint selectPaint;
  36. private Paint mPaint;
  37. // 画背景图中单独的画笔
  38. private Paint centerLinePaint;
  39.  
  40. private float centerY;
  41. private float centerX;
  42.  
  43. private float mLastDownY;
  44. /**
  45. * 滑动的距离
  46. */
  47. private float mMoveLen = 0;
  48. private boolean isInit = false;
  49. private SelectListener mSelectListener;
  50. private Timer timer;
  51. private MyTimerTask mTask;
  52.  
  53. Handler updateHandler = new Handler() {
  54.  
  55. @Override
  56. public void handleMessage(Message msg) {
  57. if (Math.abs(mMoveLen) < SPEED) {
  58. // 如果偏移量少于最少偏移量
  59. mMoveLen = 0;
  60. if (null != timer) {
  61. timer.cancel();
  62. timer.purge();
  63. timer = null;
  64. }
  65. if (mTask != null) {
  66. mTask.cancel();
  67. mTask = null;
  68. performSelect();
  69. }
  70. } else {
  71. // 这里mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚
  72. mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED;
  73. }
  74. invalidate();
  75. }
  76.  
  77. };
  78.  
  79. public WheelView(Context context) {
  80. super(context);
  81. init(context);
  82. }
  83.  
  84. public WheelView(Context context,AttributeSet attrs) {
  85. super(context,attrs);
  86. init(context);
  87. }
  88.  
  89. public void setOnSelectListener(SelectListener listener) {
  90. mSelectListener = listener;
  91. }
  92.  
  93. public void setWheelStyle(int style) {
  94. itemList = WheelStyle.getItemList(context,style);
  95. if (itemList != null) {
  96. itemCount = itemList.size();
  97. resetCurrentSelect();
  98. invalidate();
  99. } else {
  100. Log.i(TAG,"item is null");
  101. }
  102. }
  103.  
  104. public void setWheelItemList(List<String> itemList) {
  105. this.itemList = itemList;
  106. if (itemList != null) {
  107. itemCount = itemList.size();
  108. resetCurrentSelect();
  109. } else {
  110. Log.i(TAG,"item is null");
  111. }
  112. }
  113.  
  114. private void resetCurrentSelect() {
  115. if (currentItem < 0) {
  116. currentItem = 0;
  117. }
  118. while (currentItem >= itemCount) {
  119. currentItem--;
  120. }
  121. if (currentItem >= 0 && currentItem < itemCount) {
  122. invalidate();
  123. } else {
  124. Log.i(TAG,"current item is invalid");
  125. }
  126. }
  127.  
  128. public int getItemCount() {
  129. return itemCount;
  130. }
  131. /**
  132. * 选择选中的item的index
  133. * author LH
  134. * data 2016/9/4 11:09
  135. */
  136. public void setCurrentItem(int selected) {
  137. currentItem = selected;
  138. resetCurrentSelect();
  139. }
  140.  
  141. public int getCurrentItem() {
  142. return currentItem;
  143. }
  144.  
  145. @Override
  146. protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) {
  147. super.onMeasure(widthMeasureSpec,heightMeasureSpec);
  148. int mViewHeight = getMeasuredHeight();
  149. int mViewWidth = getMeasuredWidth();
  150. centerX = (float) (mViewWidth / 2.0);
  151. centerY = (float) (mViewHeight / 2.0);
  152.  
  153. isInit = true;
  154. invalidate();
  155. }
  156.  
  157. private void init(Context context) {
  158. this.context = context;
  159.  
  160. timer = new Timer();
  161. itemList = new ArrayList<>();
  162.  
  163. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  164. mPaint.setStyle(Style.FILL);
  165. mPaint.setTextAlign(Align.CENTER);
  166. mPaint.setColor(getResources().getColor(R.color.wheel_unselect_text));
  167. int size1 = (int) (SupportDisplay.getLayoutScale()*22+0.5);
  168. mPaint.setTextSize(size1);
  169.  
  170. selectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  171. selectPaint.setStyle(Style.FILL);
  172. selectPaint.setTextAlign(Align.CENTER);
  173. selectPaint.setColor(getResources().getColor(R.color.color_1a1a1a));
  174. int size2 = (int) (SupportDisplay.getLayoutScale()*24+0.5);
  175. selectPaint.setTextSize(size2);
  176.  
  177. centerLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  178. centerLinePaint.setStyle(Style.FILL);
  179. centerLinePaint.setTextAlign(Align.CENTER);
  180. centerLinePaint.setColor(getResources().getColor(R.color.wheel_unselect_text));
  181.  
  182. // 绘制背景
  183. setBackground(null);
  184. }
  185.  
  186. @Override
  187. protected void onDraw(Canvas canvas) {
  188. super.onDraw(canvas);
  189. if (isInit) {
  190. drawData(canvas);
  191. }
  192. }
  193.  
  194. private void drawData(Canvas canvas) {
  195. // 先绘制选中的text再往上往下绘制其余的text
  196. if (!itemList.isEmpty()) {
  197. // 绘制中间data
  198. drawCenterText(canvas);
  199. // 绘制上方data
  200. for (int i = 1; i < SHOW_SIZE + 1; i++) {
  201. drawOtherText(canvas,i,-1);
  202. }
  203. // 绘制下方data
  204. for (int i = 1; i < SHOW_SIZE + 1; i++) {
  205. drawOtherText(canvas,1);
  206. }
  207. }
  208. }
  209.  
  210. private void drawCenterText(Canvas canvas) {
  211. // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标
  212. float y = centerY + mMoveLen;
  213. FontMetricsInt fmi = selectPaint.getFontMetricsInt();
  214. float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
  215. canvas.drawText(itemList.get(currentItem),centerX,baseline,selectPaint);
  216. }
  217.  
  218. /**
  219. * 绘制文本
  220. * author LH
  221. * data 2016/9/4 11:10
  222. * @param canvas 画布
  223. * @param position 距离mCurrentSelected的差值
  224. * @param type 1表示向下绘制,-1表示向上绘制
  225. */
  226. private void drawOtherText(Canvas canvas,int position,int type) {
  227. int index = currentItem + type * position;
  228. if (index >= itemCount) {
  229. index = index - itemCount;
  230. }
  231. if (index < 0) {
  232. index = index + itemCount;
  233. }
  234. String text = itemList.get(index);
  235.  
  236. int itemHeight = getHeight() / (SHOW_SIZE * 2 + 1);
  237. float d = itemHeight * position + type * mMoveLen;
  238. float y = centerY + type * d;
  239.  
  240. FontMetricsInt fmi = mPaint.getFontMetricsInt();
  241. float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
  242. canvas.drawText(text,mPaint);
  243. }
  244.  
  245. @Override
  246. public void setBackground(Drawable background) {
  247. background = new Drawable() {
  248. @Override
  249. public void draw(Canvas canvas) {
  250. itemHeight = getHeight() / (SHOW_SIZE * 2 + 1);
  251. int width = getWidth();
  252.  
  253. canvas.drawLine(0,itemHeight,width,centerLinePaint);
  254. canvas.drawLine(0,itemHeight * 2,centerLinePaint);
  255.  
  256. centerLinePaint.setColor(getResources().getColor(R.color.wheel_bg));
  257. Rect topRect = new Rect(0,itemHeight);
  258. canvas.drawRect(topRect,centerLinePaint);
  259. Rect bottomRect = new Rect(0,itemHeight * 3);
  260. canvas.drawRect(bottomRect,centerLinePaint);
  261. }
  262.  
  263. @Override
  264. public void setAlpha(int alpha) {
  265.  
  266. }
  267.  
  268. @Override
  269. public void setColorFilter(ColorFilter cf) {
  270.  
  271. }
  272.  
  273. @Override
  274. public int getOpacity() {
  275. return 0;
  276. }
  277. };
  278. super.setBackground(background);
  279. }
  280.  
  281. @Override
  282. public boolean onTouchEvent(MotionEvent event) {
  283. switch (event.getActionMasked()) {
  284. case MotionEvent.ACTION_DOWN:
  285. doDown(event);
  286. break;
  287. case MotionEvent.ACTION_MOVE:
  288. doMove(event);
  289. break;
  290. case MotionEvent.ACTION_UP:
  291. doUp();
  292. break;
  293. default:
  294. break;
  295. }
  296. return true;
  297. }
  298.  
  299. private void doDown(MotionEvent event) {
  300. if (mTask != null) {
  301. mTask.cancel();
  302. mTask = null;
  303. }
  304. mLastDownY = event.getY();
  305. }
  306.  
  307. private void doMove(MotionEvent event) {
  308.  
  309. mMoveLen += (event.getY() - mLastDownY);
  310. if (mMoveLen > itemHeight / 2) {
  311. // 往下滑超过离开距离
  312. mMoveLen = mMoveLen - itemHeight;
  313. currentItem--;
  314. if (currentItem < 0) {
  315. currentItem = itemCount - 1;
  316. }
  317. } else if (mMoveLen < -itemHeight / 2) {
  318. // 往上滑超过离开距离
  319. mMoveLen = mMoveLen + itemHeight;
  320. currentItem++;
  321. if (currentItem >= itemCount) {
  322. currentItem = 0;
  323. }
  324. }
  325.  
  326. mLastDownY = event.getY();
  327. invalidate();
  328. }
  329.  
  330. private void doUp() {
  331. // 抬起手后mCurrentSelected的位置由当前位置move到中间选中位置
  332. if (Math.abs(mMoveLen) < 0.0001) {
  333. mMoveLen = 0;
  334. return;
  335. }
  336. if (mTask != null) {
  337. mTask.cancel();
  338. mTask = null;
  339. }
  340. if (null == timer) {
  341. timer = new Timer();
  342. }
  343. mTask = new MyTimerTask(updateHandler);
  344. timer.schedule(mTask,10);
  345. }
  346.  
  347. class MyTimerTask extends TimerTask {
  348. Handler handler;
  349.  
  350. public MyTimerTask(Handler handler) {
  351. this.handler = handler;
  352. }
  353.  
  354. @Override
  355. public void run() {
  356. handler.sendMessage(handler.obtainMessage());
  357. }
  358.  
  359. }
  360.  
  361. private void performSelect() {
  362. if (mSelectListener != null) {
  363. mSelectListener.onSelect(currentItem,itemList.get(currentItem));
  364. } else {
  365. Log.i(TAG,"null listener");
  366. }
  367. }
  368.  
  369. public interface SelectListener {
  370. void onSelect(int index,String text);
  371. }
  372.  
  373. }

2.然后是时间选择控件的样式工具类

  1. /**
  2. * 时间选择样式
  3. * author LH
  4. * data 2016/9/4 11:05
  5. */
  6. public class WheelStyle {
  7.  
  8. public static final int minYear = 1980;
  9. public static final int maxYear = 2020;
  10.  
  11. /**
  12. * Wheel Style Hour
  13. */
  14. public static final int STYLE_HOUR = 1;
  15. /**
  16. * Wheel Style Minute
  17. */
  18. public static final int STYLE_MINUTE = 2;
  19. /**
  20. * Wheel Style Year
  21. */
  22. public static final int STYLE_YEAR = 3;
  23. /**
  24. * Wheel Style Month
  25. */
  26. public static final int STYLE_MONTH = 4;
  27. /**
  28. * Wheel Style Day
  29. */
  30. public static final int STYLE_DAY = 5;
  31. /**
  32. * Wheel Style Simple Day
  33. */
  34. public static final int STYLE_SIMPLE_DAY = 6;
  35. /**
  36. * Wheel Style Set Warn
  37. */
  38. public static final int STYLE_SET_WARN = 7;
  39. /**
  40. * Wheel Style Work Answer
  41. */
  42. public static final int STYLE_WORK_ANSWER = 8;
  43.  
  44. private WheelStyle() {
  45. }
  46.  
  47. public static List<String> getItemList(Context context,int Style) {
  48. if (Style == STYLE_HOUR) {
  49. return createHourString();
  50. } else if (Style == STYLE_MINUTE) {
  51. return createMinuteString();
  52. } else if (Style == STYLE_YEAR) {
  53. return createYearString();
  54. } else if (Style == STYLE_MONTH) {
  55. return createMonthString();
  56. } else if (Style == STYLE_DAY) {
  57. return createDayString();
  58. } else if (Style == STYLE_SIMPLE_DAY) {
  59. return createSimpleDayString();
  60. } else if (Style == STYLE_SET_WARN) {
  61. return createSetWarnTimeString();
  62. } else {
  63. throw new IllegalArgumentException("style is illegal");
  64. }
  65. }
  66.  
  67. private static List<String> createHourString() {
  68. List<String> wheelString = new ArrayList<>();
  69. for (int i = 0; i < 24; i++) {
  70. wheelString.add(String.format("%02d" + "时",i));
  71. }
  72. return wheelString;
  73. }
  74.  
  75. private static List<String> createMinuteString() {
  76. List<String> wheelString = new ArrayList<>();
  77. for (int i = 0; i < 60; i++) {
  78. wheelString.add(String.format("%02d" + "分",i));
  79. }
  80. return wheelString;
  81. }
  82.  
  83. private static List<String> createYearString() {
  84. List<String> wheelString = new ArrayList<>();
  85. for (int i = minYear; i <= maxYear; i++) {
  86. wheelString.add(Integer.toString(i));
  87. }
  88. return wheelString;
  89. }
  90.  
  91. private static List<String> createMonthString() {
  92. List<String> wheelString = new ArrayList<>();
  93. for (int i = 1; i <= 12; i++) {
  94. wheelString.add(String.format("%02d" + "月",i));
  95. }
  96. return wheelString;
  97. }
  98.  
  99. private static List<String> createDayString() {
  100. List<String> wheelString = new ArrayList<>();
  101. for (int i = 1; i <= 31; i++) {
  102. wheelString.add(String.format("%02d" + "日",i));
  103. }
  104. return wheelString;
  105. }
  106.  
  107. private static List<String> createSimpleDayString() {
  108. List<String> wheelString = new ArrayList<>();
  109. wheelString.add("一天后");
  110. wheelString.add("两天后");
  111. wheelString.add("三天后");
  112. return wheelString;
  113. }
  114.  
  115. private static List<String> createSetWarnTimeString() {
  116. List<String> wheelString = new ArrayList<>();
  117. wheelString.add("30分钟");
  118. wheelString.add("60分钟");
  119. wheelString.add("90分钟");
  120. wheelString.add("120分钟");
  121. return wheelString;
  122. }
  123. /**
  124. * 计算闰月
  125. *
  126. * @param month
  127. * @return
  128. */
  129. private static boolean isLeapMonth(int month) {
  130. return month == 1 || month == 3 || month == 5 || month == 7
  131. || month == 8 || month == 10 || month == 12;
  132. }
  133.  
  134. /**
  135. * 计算闰年
  136. *
  137. * @param year
  138. * @return
  139. */
  140. private static boolean isLeapYear(int year) {
  141. return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
  142. }
  143. }

3.使用的xml

  1. <com.example.view.timeview.WheelView
  2. android:id="@+id/select_time_simple_wheel"
  3. android:layout_width="match_parent"
  4. android:layout_height="150dp"
  5. android:layout_marginLeft="20dp"
  6. android:layout_marginRight="20dp"
  7. android:layout_weight="1" />

4.在Java文件中设置mWheelView.setWheelStyle(WheelStyle.STYLE_YEAR);就可以显示WheelStyle类中设置的类型了。这个类中的样式种类读者可以根据自己的需要自行添加

5.获取当前选择的项也很简单mWheelView.getCurrentItem();就能获取到控件的当前选择的项。获取到所在的项以后剩下的就是逻辑操作了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

猜你在找的iOS相关文章