当前位置:   article > 正文

android 时间滚动控件 底部弹出_android timepickerdialog底部弹出

android timepickerdialog底部弹出

下载地址:http://download.csdn.net/detail/ldd119/7440895 转载请说明出处

先上个效果图


第一步:先自定义一个View

  1. package com.wheel.widget;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import java.util.logging.Level;
  5. import java.util.logging.Logger;
  6. import com.example.mywheel.R;
  7. import android.content.Context;
  8. import android.graphics.Canvas;
  9. import android.graphics.Paint;
  10. import android.graphics.Rect;
  11. import android.graphics.drawable.Drawable;
  12. import android.graphics.drawable.GradientDrawable;
  13. import android.graphics.drawable.GradientDrawable.Orientation;
  14. import android.os.Handler;
  15. import android.os.Message;
  16. import android.text.Layout;
  17. import android.text.StaticLayout;
  18. import android.text.TextPaint;
  19. import android.util.AttributeSet;
  20. import android.util.DisplayMetrics;
  21. import android.util.FloatMath;
  22. import android.view.GestureDetector;
  23. import android.view.GestureDetector.SimpleOnGestureListener;
  24. import android.view.MotionEvent;
  25. import android.view.View;
  26. import android.view.animation.Interpolator;
  27. import android.widget.Scroller;
  28. public class WheelView extends View {
  29. /** Scrolling duration */
  30. private static final int SCROLLING_DURATION = 400;
  31. /** Minimum delta for scrolling */
  32. private static final int MIN_DELTA_FOR_SCROLLING = 1;
  33. /** Current value & label text color */
  34. public static int VALUE_TEXT_COLOR = 0xe0000000;
  35. /** Items text color */
  36. private static final int ITEMS_TEXT_COLOR = 0xe0000000;
  37. /** Top and bottom shadows colors */
  38. private static final int[] SHADOWS_COLORS = new int[] { 0x00000000,
  39. 0x00000000, 0x00000000 };
  40. /** Additional items height (is added to standard text item height) */
  41. private static final int ADDITIONAL_ITEM_HEIGHT = 15;
  42. /** Text size */
  43. private static final int TEXT_SIZE = 15;
  44. /** Top and bottom items offset (to hide that) */
  45. private static final int ITEM_OFFSET = TEXT_SIZE / 5;
  46. /** Additional width for items layout */
  47. private static final int ADDITIONAL_ITEMS_SPACE = 10;
  48. /** Label offset */
  49. private static final int LABEL_OFFSET = 8;
  50. /** Left and right padding value */
  51. private static final int PADDING = 5;
  52. /** Default count of visible items */
  53. private static final int DEF_VISIBLE_ITEMS = 5;
  54. // Wheel Values
  55. private WheelAdapter adapter = null;
  56. private int currentItem = 0;
  57. // Widths
  58. private int itemsWidth = 0;
  59. private int labelWidth = 0;
  60. // Count of visible items
  61. private int visibleItems = DEF_VISIBLE_ITEMS;
  62. // Item height
  63. private int itemHeight = 0;
  64. // Text paints
  65. private TextPaint itemsPaint;
  66. private TextPaint valuePaint;
  67. // Layouts
  68. private StaticLayout itemsLayout;
  69. private StaticLayout labelLayout;
  70. private StaticLayout valueLayout;
  71. // Label & background
  72. private String label;
  73. private Drawable centerDrawable;
  74. // Shadows drawables
  75. private GradientDrawable topShadow;
  76. private GradientDrawable bottomShadow;
  77. // Scrolling
  78. private boolean isScrollingPerformed;
  79. private int scrollingOffset;
  80. // Scrolling animation
  81. private GestureDetector gestureDetector;
  82. private Scroller scroller;
  83. private int lastScrollY;
  84. // Cyclic
  85. boolean isCyclic = true;
  86. // Listeners
  87. private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();
  88. private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();
  89. /**
  90. * Constructor
  91. */
  92. public WheelView(Context context, AttributeSet attrs, int defStyle) {
  93. super(context, attrs, defStyle);
  94. initData(context);
  95. }
  96. /**
  97. * Constructor
  98. */
  99. public WheelView(Context context, AttributeSet attrs) {
  100. super(context, attrs);
  101. initData(context);
  102. }
  103. /**
  104. * Constructor
  105. */
  106. public WheelView(Context context) {
  107. super(context);
  108. initData(context);
  109. }
  110. /**
  111. * Initializes class data
  112. * @param context the context
  113. */
  114. private void initData(Context context) {
  115. gestureDetector = new GestureDetector(context, gestureListener);
  116. gestureDetector.setIsLongpressEnabled(false);
  117. scroller = new Scroller(context);
  118. }
  119. /**
  120. * Gets wheel adapter
  121. * @return the adapter
  122. */
  123. public WheelAdapter getAdapter() {
  124. return adapter;
  125. }
  126. /**
  127. * Sets wheel adapter
  128. * @param adapter the new wheel adapter
  129. */
  130. public void setAdapter(WheelAdapter adapter) {
  131. this.adapter = adapter;
  132. invalidateLayouts();
  133. invalidate();
  134. }
  135. /**
  136. * Set the the specified scrolling interpolator
  137. * @param interpolator the interpolator
  138. */
  139. public void setInterpolator(Interpolator interpolator) {
  140. scroller.forceFinished(true);
  141. scroller = new Scroller(getContext(), interpolator);
  142. }
  143. /**
  144. * Gets count of visible items
  145. *
  146. * @return the count of visible items
  147. */
  148. public int getVisibleItems() {
  149. return visibleItems;
  150. }
  151. /**
  152. * Sets count of visible items
  153. *
  154. * @param count
  155. * the new count
  156. */
  157. public void setVisibleItems(int count) {
  158. visibleItems = count;
  159. invalidate();
  160. }
  161. /**
  162. * Gets label
  163. *
  164. * @return the label
  165. */
  166. public String getLabel() {
  167. return label;
  168. }
  169. /**
  170. * Sets label
  171. *
  172. * @param newLabel
  173. * the label to set
  174. */
  175. public void setLabel(String newLabel) {
  176. if (label == null || !label.equals(newLabel)) {
  177. label = newLabel;
  178. labelLayout = null;
  179. invalidate();
  180. }
  181. }
  182. /**
  183. * Adds wheel changing listener
  184. * @param listener the listener
  185. */
  186. public void addChangingListener(OnWheelChangedListener listener) {
  187. changingListeners.add(listener);
  188. }
  189. /**
  190. * Removes wheel changing listener
  191. * @param listener the listener
  192. */
  193. public void removeChangingListener(OnWheelChangedListener listener) {
  194. changingListeners.remove(listener);
  195. }
  196. /**
  197. * Notifies changing listeners
  198. * @param oldValue the old wheel value
  199. * @param newValue the new wheel value
  200. */
  201. protected void notifyChangingListeners(int oldValue, int newValue) {
  202. for (OnWheelChangedListener listener : changingListeners) {
  203. listener.onChanged(this, oldValue, newValue);
  204. }
  205. }
  206. /**
  207. * Adds wheel scrolling listener
  208. * @param listener the listener
  209. */
  210. public void addScrollingListener(OnWheelScrollListener listener) {
  211. scrollingListeners.add(listener);
  212. }
  213. /**
  214. * Removes wheel scrolling listener
  215. * @param listener the listener
  216. */
  217. public void removeScrollingListener(OnWheelScrollListener listener) {
  218. scrollingListeners.remove(listener);
  219. }
  220. /**
  221. * Notifies listeners about starting scrolling
  222. */
  223. protected void notifyScrollingListenersAboutStart() {
  224. for (OnWheelScrollListener listener : scrollingListeners) {
  225. listener.onScrollingStarted(this);
  226. }
  227. }
  228. /**
  229. * Notifies listeners about ending scrolling
  230. */
  231. protected void notifyScrollingListenersAboutEnd() {
  232. for (OnWheelScrollListener listener : scrollingListeners) {
  233. listener.onScrollingFinished(this);
  234. }
  235. }
  236. /**
  237. * Gets current value
  238. *
  239. * @return the current value
  240. */
  241. public int getCurrentItem() {
  242. return currentItem;
  243. }
  244. /**
  245. * Sets the current item. Does nothing when index is wrong.
  246. *
  247. * @param index the item index
  248. * @param animated the animation flag
  249. */
  250. public void setCurrentItem(int index, boolean animated) {
  251. if (adapter == null || adapter.getItemsCount() == 0) {
  252. return; // throw?
  253. }
  254. if (index < 0 || index >= adapter.getItemsCount()) {
  255. if (isCyclic) {
  256. while (index < 0) {
  257. index += adapter.getItemsCount();
  258. }
  259. index %= adapter.getItemsCount();
  260. } else{
  261. return; // throw?
  262. }
  263. }
  264. if (index != currentItem) {
  265. if (animated) {
  266. scroll(index - currentItem, SCROLLING_DURATION);
  267. } else {
  268. invalidateLayouts();
  269. int old = currentItem;
  270. currentItem = index;
  271. notifyChangingListeners(old, currentItem);
  272. invalidate();
  273. }
  274. }
  275. }
  276. /**
  277. * Sets the current item w/o animation. Does nothing when index is wrong.
  278. *
  279. * @param index the item index
  280. */
  281. public void setCurrentItem(int index) {
  282. setCurrentItem(index, false);
  283. }
  284. /**
  285. * Tests if wheel is cyclic. That means before the 1st item there is shown the last one
  286. * @return true if wheel is cyclic
  287. */
  288. public boolean isCyclic() {
  289. return isCyclic;
  290. }
  291. /**
  292. * Set wheel cyclic flag
  293. * @param isCyclic the flag to set
  294. */
  295. public void setCyclic(boolean isCyclic) {
  296. this.isCyclic = isCyclic;
  297. invalidate();
  298. invalidateLayouts();
  299. }
  300. /**
  301. * Invalidates layouts
  302. */
  303. private void invalidateLayouts() {
  304. itemsLayout = null;
  305. valueLayout = null;
  306. scrollingOffset = 0;
  307. }
  308. /**
  309. * Initializes resources
  310. */
  311. private void initResourcesIfNecessary() {
  312. DisplayMetrics dm = this.getResources().getDisplayMetrics();
  313. int textsize = (int) (TEXT_SIZE* dm.density);
  314. if (itemsPaint == null) {
  315. itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG
  316. | Paint.FAKE_BOLD_TEXT_FLAG);
  317. itemsPaint.density = getResources().getDisplayMetrics().density;
  318. itemsPaint.setTextSize(textsize);
  319. }
  320. if (valuePaint == null) {
  321. valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG
  322. | Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG);
  323. //valuePaint.density = getResources().getDisplayMetrics().density;
  324. valuePaint.setTextSize(textsize);
  325. valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0);
  326. }
  327. if (centerDrawable == null) {
  328. centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val);
  329. }
  330. if (topShadow == null) {
  331. topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
  332. }
  333. if (bottomShadow == null) {
  334. bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
  335. }
  336. setBackgroundResource(R.drawable.wheel_bg);
  337. }
  338. /**
  339. * Calculates desired height for layout
  340. *
  341. * @param layout
  342. * the source layout
  343. * @return the desired layout height
  344. */
  345. private int getDesiredHeight(Layout layout) {
  346. if (layout == null) {
  347. return 0;
  348. }
  349. DisplayMetrics dm = this.getResources().getDisplayMetrics();
  350. int height = (int) (ADDITIONAL_ITEM_HEIGHT* dm.density);
  351. int desired = getItemHeight() * visibleItems - ITEM_OFFSET * 2
  352. - height;
  353. // Check against our minimum height
  354. desired = Math.max(desired, getSuggestedMinimumHeight());
  355. return desired;
  356. }
  357. /**
  358. * Returns text item by index
  359. * @param index the item index
  360. * @return the item or null
  361. */
  362. private String getTextItem(int index) {
  363. if (adapter == null || adapter.getItemsCount() == 0) {
  364. return null;
  365. }
  366. int count = adapter.getItemsCount();
  367. if ((index < 0 || index >= count) && !isCyclic) {
  368. return null;
  369. } else {
  370. while (index < 0) {
  371. index = count + index;
  372. }
  373. }
  374. index %= count;
  375. return adapter.getItem(index);
  376. }
  377. /**
  378. * Builds text depending on current value
  379. *
  380. * @param useCurrentValue
  381. * @return the text
  382. */
  383. private String buildText(boolean useCurrentValue) {
  384. StringBuilder itemsText = new StringBuilder();
  385. int addItems = visibleItems / 2 + 1;
  386. for (int i = currentItem - addItems; i <= currentItem + addItems; i++) {
  387. if (useCurrentValue || i != currentItem) {
  388. String text = getTextItem(i);
  389. if (text != null) {
  390. itemsText.append(text);
  391. }
  392. }
  393. if (i < currentItem + addItems) {
  394. itemsText.append("\n");
  395. }
  396. }
  397. return itemsText.toString();
  398. }
  399. /**
  400. * Returns the max item length that can be present
  401. * @return the max length
  402. */
  403. private int getMaxTextLength() {
  404. WheelAdapter adapter = getAdapter();
  405. if (adapter == null) {
  406. return 0;
  407. }
  408. int adapterLength = adapter.getMaximumLength();
  409. if (adapterLength > 0) {
  410. return adapterLength;
  411. }
  412. String maxText = null;
  413. int addItems = visibleItems / 2;
  414. for (int i = Math.max(currentItem - addItems, 0);
  415. i < Math.min(currentItem + visibleItems, adapter.getItemsCount()); i++) {
  416. String text = adapter.getItem(i);
  417. if (text != null && (maxText == null || maxText.length() < text.length())) {
  418. maxText = text;
  419. }
  420. }
  421. return maxText != null ? maxText.length() : 0;
  422. }
  423. /**
  424. * Returns height of wheel item
  425. * @return the item height
  426. */
  427. private int getItemHeight() {
  428. if (itemHeight != 0) {
  429. return itemHeight;
  430. } else if (itemsLayout != null && itemsLayout.getLineCount() > 2) {
  431. itemHeight = itemsLayout.getLineTop(2) - itemsLayout.getLineTop(1);
  432. return itemHeight;
  433. }
  434. return getHeight() / visibleItems;
  435. }
  436. /**
  437. * Calculates control width and creates text layouts
  438. * @param widthSize the input layout width
  439. * @param mode the layout mode
  440. * @return the calculated control width
  441. */
  442. private int calculateLayoutWidth(int widthSize, int mode) {
  443. initResourcesIfNecessary();
  444. int width = widthSize;
  445. int maxLength = getMaxTextLength();
  446. if (maxLength > 0) {
  447. float textWidth = FloatMath.ceil(Layout.getDesiredWidth("0", itemsPaint));
  448. itemsWidth = (int) (maxLength * textWidth);
  449. } else {
  450. itemsWidth = 0;
  451. }
  452. itemsWidth += ADDITIONAL_ITEMS_SPACE; // make it some more
  453. labelWidth = 0;
  454. if (label != null && label.length() > 0) {
  455. labelWidth = (int) FloatMath.ceil(Layout.getDesiredWidth(label, valuePaint));
  456. }
  457. boolean recalculate = false;
  458. if (mode == MeasureSpec.EXACTLY) {
  459. width = widthSize;
  460. recalculate = true;
  461. } else {
  462. width = itemsWidth + labelWidth + 2 * PADDING;
  463. if (labelWidth > 0) {
  464. width += LABEL_OFFSET;
  465. }
  466. // Check against our minimum width
  467. width = Math.max(width, getSuggestedMinimumWidth());
  468. if (mode == MeasureSpec.AT_MOST && widthSize < width) {
  469. width = widthSize;
  470. recalculate = true;
  471. }
  472. }
  473. if (recalculate) {
  474. // recalculate width
  475. int pureWidth = width - LABEL_OFFSET - 2 * PADDING;
  476. if (pureWidth <= 0) {
  477. itemsWidth = labelWidth = 0;
  478. }
  479. if (labelWidth > 0) {
  480. double newWidthItems = (double) itemsWidth * pureWidth
  481. / (itemsWidth + labelWidth);
  482. itemsWidth = (int) newWidthItems;
  483. labelWidth = pureWidth - itemsWidth;
  484. } else {
  485. itemsWidth = pureWidth + LABEL_OFFSET; // no label
  486. }
  487. }
  488. if (itemsWidth > 0) {
  489. createLayouts(itemsWidth, labelWidth);
  490. }
  491. return width;
  492. }
  493. /**
  494. * Creates layouts
  495. * @param widthItems width of items layout
  496. * @param widthLabel width of label layout
  497. */
  498. private void createLayouts(int widthItems, int widthLabel) {
  499. DisplayMetrics dm = this.getResources().getDisplayMetrics();
  500. int height = (int) (ADDITIONAL_ITEM_HEIGHT* dm.density);
  501. if (itemsLayout == null || itemsLayout.getWidth() > widthItems) {
  502. itemsLayout = new StaticLayout(buildText(isScrollingPerformed), itemsPaint, widthItems,
  503. widthLabel > 0 ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_CENTER,
  504. 1, height, false);
  505. } else {
  506. itemsLayout.increaseWidthTo(widthItems);
  507. }
  508. if (!isScrollingPerformed && (valueLayout == null || valueLayout.getWidth() > widthItems)) {
  509. String text = getAdapter() != null ? getAdapter().getItem(currentItem) : null;
  510. valueLayout = new StaticLayout(text != null ? text : "",
  511. valuePaint, widthItems, widthLabel > 0 ?
  512. Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_CENTER,
  513. 1, height, false);
  514. } else if (isScrollingPerformed) {
  515. valueLayout = null;
  516. } else {
  517. valueLayout.increaseWidthTo(widthItems);
  518. }
  519. if (widthLabel > 0) {
  520. if (labelLayout == null || labelLayout.getWidth() > widthLabel) {
  521. labelLayout = new StaticLayout(label, valuePaint,
  522. widthLabel, Layout.Alignment.ALIGN_NORMAL, 1,
  523. height, false);
  524. } else {
  525. labelLayout.increaseWidthTo(widthLabel);
  526. }
  527. }
  528. }
  529. @Override
  530. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  531. int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  532. int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  533. int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  534. int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  535. int width = calculateLayoutWidth(widthSize, widthMode);
  536. int height;
  537. if (heightMode == MeasureSpec.EXACTLY) {
  538. height = heightSize;
  539. } else {
  540. height = getDesiredHeight(itemsLayout);
  541. if (heightMode == MeasureSpec.AT_MOST) {
  542. height = Math.min(height, heightSize);
  543. }
  544. }
  545. setMeasuredDimension(width, height);
  546. }
  547. @Override
  548. protected void onDraw(Canvas canvas) {
  549. super.onDraw(canvas);
  550. if (itemsLayout == null) {
  551. if (itemsWidth == 0) {
  552. calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);
  553. } else {
  554. createLayouts(itemsWidth, labelWidth);
  555. }
  556. }
  557. if (itemsWidth > 0) {
  558. canvas.save();
  559. // Skip padding space and hide a part of top and bottom items
  560. canvas.translate(PADDING, -ITEM_OFFSET);
  561. drawItems(canvas);
  562. drawValue(canvas);
  563. canvas.restore();
  564. }
  565. drawCenterRect(canvas);
  566. drawShadows(canvas);
  567. }
  568. /**
  569. * Draws shadows on top and bottom of control
  570. * @param canvas the canvas for drawing
  571. */
  572. private void drawShadows(Canvas canvas) {
  573. topShadow.setBounds(0, 0, getWidth(), getHeight() / visibleItems);
  574. topShadow.draw(canvas);
  575. bottomShadow.setBounds(0, getHeight() - getHeight() / visibleItems,
  576. getWidth(), getHeight());
  577. bottomShadow.draw(canvas);
  578. }
  579. /**
  580. * Draws value and label layout
  581. * @param canvas the canvas for drawing
  582. */
  583. private void drawValue(Canvas canvas) {
  584. valuePaint.setColor(VALUE_TEXT_COLOR);
  585. valuePaint.drawableState = getDrawableState();
  586. Rect bounds = new Rect();
  587. itemsLayout.getLineBounds(visibleItems / 2, bounds);
  588. // draw label
  589. if (labelLayout != null) {
  590. canvas.save();
  591. canvas.translate(itemsLayout.getWidth() + LABEL_OFFSET, bounds.top);
  592. labelLayout.draw(canvas);
  593. canvas.restore();
  594. }
  595. // draw current value
  596. if (valueLayout != null) {
  597. canvas.save();
  598. canvas.translate(0, bounds.top + scrollingOffset);
  599. valueLayout.draw(canvas);
  600. canvas.restore();
  601. }
  602. }
  603. /**
  604. * Draws items
  605. * @param canvas the canvas for drawing
  606. */
  607. private void drawItems(Canvas canvas) {
  608. canvas.save();
  609. int top = itemsLayout.getLineTop(1);
  610. canvas.translate(0, - top + scrollingOffset);
  611. Logger.getLogger(WheelView.class.getName()).log(Level.WARNING, ".....top....>>"+top);
  612. Logger.getLogger(WheelView.class.getName()).log(Level.WARNING, "....scrollingOffset...>>"+scrollingOffset);
  613. itemsPaint.setColor(ITEMS_TEXT_COLOR);
  614. itemsPaint.drawableState = getDrawableState();
  615. itemsLayout.draw(canvas);
  616. canvas.restore();
  617. }
  618. /**
  619. * Draws rect for current value
  620. * @param canvas the canvas for drawing
  621. */
  622. private void drawCenterRect(Canvas canvas) {
  623. int center = getHeight() / 2;
  624. int offset = getItemHeight() / 2;
  625. centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);
  626. centerDrawable.draw(canvas);
  627. }
  628. @Override
  629. public boolean onTouchEvent(MotionEvent event) {
  630. WheelAdapter adapter = getAdapter();
  631. if (adapter == null) {
  632. return true;
  633. }
  634. if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {
  635. justify();
  636. }
  637. return true;
  638. }
  639. /**
  640. * Scrolls the wheel
  641. * @param delta the scrolling value
  642. */
  643. private void doScroll(int delta) {
  644. scrollingOffset += delta;
  645. int count = scrollingOffset / getItemHeight();
  646. int pos = currentItem - count;
  647. if (isCyclic && adapter.getItemsCount() > 0) {
  648. // fix position by rotating
  649. while (pos < 0) {
  650. pos += adapter.getItemsCount();
  651. }
  652. pos %= adapter.getItemsCount();
  653. } else if (isScrollingPerformed) {
  654. //
  655. if (pos < 0) {
  656. count = currentItem;
  657. pos = 0;
  658. } else if (pos >= adapter.getItemsCount()) {
  659. count = currentItem - adapter.getItemsCount() + 1;
  660. pos = adapter.getItemsCount() - 1;
  661. }
  662. } else {
  663. // fix position
  664. pos = Math.max(pos, 0);
  665. pos = Math.min(pos, adapter.getItemsCount() - 1);
  666. }
  667. int offset = scrollingOffset;
  668. if (pos != currentItem) {
  669. setCurrentItem(pos, false);
  670. } else {
  671. invalidate();
  672. }
  673. // update offset
  674. scrollingOffset = offset - count * getItemHeight();
  675. if (scrollingOffset > getHeight()) {
  676. scrollingOffset = scrollingOffset % getHeight() + getHeight();
  677. }
  678. }
  679. // gesture listener
  680. private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
  681. public boolean onDown(MotionEvent e) {
  682. if (isScrollingPerformed) {
  683. scroller.forceFinished(true);
  684. clearMessages();
  685. return true;
  686. }
  687. return false;
  688. }
  689. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
  690. startScrolling();
  691. doScroll((int)-distanceY);
  692. return true;
  693. }
  694. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  695. lastScrollY = currentItem * getItemHeight() + scrollingOffset;
  696. int maxY = isCyclic ? 0x7FFFFFFF : adapter.getItemsCount() * getItemHeight();
  697. int minY = isCyclic ? -maxY : 0;
  698. scroller.fling(0, lastScrollY, 0, (int) -velocityY / 2, 0, 0, minY, maxY);
  699. setNextMessage(MESSAGE_SCROLL);
  700. return true;
  701. }
  702. };
  703. // Messages
  704. private final int MESSAGE_SCROLL = 0;
  705. private final int MESSAGE_JUSTIFY = 1;
  706. /**
  707. * Set next message to queue. Clears queue before.
  708. *
  709. * @param message the message to set
  710. */
  711. private void setNextMessage(int message) {
  712. clearMessages();
  713. animationHandler.sendEmptyMessage(message);
  714. }
  715. /**
  716. * Clears messages from queue
  717. */
  718. private void clearMessages() {
  719. animationHandler.removeMessages(MESSAGE_SCROLL);
  720. animationHandler.removeMessages(MESSAGE_JUSTIFY);
  721. }
  722. // animation handler
  723. private Handler animationHandler = new Handler() {
  724. public void handleMessage(Message msg) {
  725. scroller.computeScrollOffset();
  726. int currY = scroller.getCurrY();
  727. int delta = lastScrollY - currY;
  728. lastScrollY = currY;
  729. if (delta != 0) {
  730. doScroll(delta);
  731. }
  732. // scrolling is not finished when it comes to final Y
  733. // so, finish it manually
  734. if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
  735. currY = scroller.getFinalY();
  736. scroller.forceFinished(true);
  737. }
  738. if (!scroller.isFinished()) {
  739. animationHandler.sendEmptyMessage(msg.what);
  740. } else if (msg.what == MESSAGE_SCROLL) {
  741. justify();
  742. } else {
  743. finishScrolling();
  744. }
  745. }
  746. };
  747. /**
  748. * Justifies wheel
  749. */
  750. private void justify() {
  751. if (adapter == null) {
  752. return;
  753. }
  754. lastScrollY = 0;
  755. int offset = scrollingOffset;
  756. int itemHeight = getItemHeight();
  757. boolean needToIncrease = offset > 0 ? currentItem < adapter.getItemsCount() : currentItem > 0;
  758. if ((isCyclic || needToIncrease) && Math.abs((float) offset) > (float) itemHeight / 2) {
  759. if (offset < 0)
  760. offset += itemHeight + MIN_DELTA_FOR_SCROLLING;
  761. else
  762. offset -= itemHeight + MIN_DELTA_FOR_SCROLLING;
  763. }
  764. if (Math.abs(offset) > MIN_DELTA_FOR_SCROLLING) {
  765. scroller.startScroll(0, 0, 0, offset, SCROLLING_DURATION);
  766. setNextMessage(MESSAGE_JUSTIFY);
  767. } else {
  768. finishScrolling();
  769. }
  770. }
  771. /**
  772. * Starts scrolling
  773. */
  774. private void startScrolling() {
  775. if (!isScrollingPerformed) {
  776. isScrollingPerformed = true;
  777. notifyScrollingListenersAboutStart();
  778. }
  779. }
  780. /**
  781. * Finishes scrolling
  782. */
  783. void finishScrolling() {
  784. if (isScrollingPerformed) {
  785. notifyScrollingListenersAboutEnd();
  786. isScrollingPerformed = false;
  787. }
  788. invalidateLayouts();
  789. invalidate();
  790. }
  791. /**
  792. * Scroll the wheel
  793. * @param itemsToSkip items to scroll
  794. * @param time scrolling duration
  795. */
  796. public void scroll(int itemsToScroll, int time) {
  797. scroller.forceFinished(true);
  798. lastScrollY = scrollingOffset;
  799. int offset = itemsToScroll * getItemHeight();
  800. scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time);
  801. setNextMessage(MESSAGE_SCROLL);
  802. startScrolling();
  803. }
  804. public int getScroolingOffset(){
  805. return scrollingOffset;
  806. }
  807. }
里面可以修改字体大小颜色 间距等等

第二步,创建一个适配器

  1. package com.wheel.widget;
  2. /**
  3. * Numeric Wheel adapter.
  4. */
  5. public class NumericWheelAdapter implements WheelAdapter {
  6. /** The default min value */
  7. public static final int DEFAULT_MAX_VALUE = 9;
  8. /** The default max value */
  9. private static final int DEFAULT_MIN_VALUE = 0;
  10. // Values
  11. private int minValue;
  12. private int maxValue;
  13. // Values
  14. private double minValue1;
  15. private double maxValue1;
  16. // format
  17. private String format;
  18. private String values = null;
  19. private String data[] = new String[215];
  20. /**
  21. * Constructor
  22. *
  23. * @param minValue
  24. * the wheel min value
  25. * @param maxValue
  26. * the wheel max value
  27. */
  28. public NumericWheelAdapter(int minValue, int maxValue) {
  29. this.minValue = minValue;
  30. this.maxValue = maxValue;
  31. }
  32. /**
  33. * Constructor
  34. *
  35. * @param minValue
  36. * the wheel min value
  37. * @param maxValue
  38. * the wheel max value
  39. * @param format
  40. * the format string
  41. */
  42. public NumericWheelAdapter(int minValue, int maxValue, String format) {
  43. this.minValue = minValue;
  44. this.maxValue = maxValue;
  45. this.format = format;
  46. }
  47. public String getItem(int index) {
  48. if (index >= 0 && index < getItemsCount()) {
  49. int value = minValue + index;
  50. values = (format != null ? String.format(format, value) : Integer
  51. .toString(value));
  52. setValue(values);
  53. return values;
  54. }
  55. return null;
  56. }
  57. // 杩斿洖褰撳墠閫変腑鐨勫?
  58. public String getValues() {
  59. return values;
  60. }
  61. public void setValue(String value) {
  62. this.values = value;
  63. }
  64. public int getItemsCount() {
  65. return maxValue - minValue + 1;
  66. }
  67. // 得到最大项目长度。它是用来确定轮宽度。
  68. // 如果返回1,将使用默认轮宽度
  69. public int getMaximumLength() {
  70. int max = Math.max(Math.abs(maxValue), Math.abs(minValue));
  71. int maxLen = Integer.toString(max).length();
  72. if (minValue < 0) {
  73. maxLen++;
  74. }
  75. return maxValue - minValue + 1;
  76. }
  77. }

第三步:布局文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="wrap_content"
  5. android:orientation="vertical" >
  6. <LinearLayout
  7. android:id="@+id/top_layout"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:background="@color/green"
  11. android:gravity="center"
  12. android:orientation="horizontal" >
  13. <Button
  14. android:id="@+id/confirm_btn"
  15. android:layout_width="wrap_content"
  16. android:layout_height="45dp"
  17. android:layout_weight="0.3"
  18. android:background="@null"
  19. android:text="@string/confirm"
  20. android:textColor="@color/white"
  21. android:textSize="16sp" />
  22. <TextView
  23. android:id="@+id/diaolog_title_tv"
  24. android:layout_width="wrap_content"
  25. android:layout_height="45dp"
  26. android:layout_weight="1.5"
  27. android:gravity="center"
  28. android:padding="10dp"
  29. android:text="生日"
  30. android:textColor="@color/white"
  31. android:textSize="16sp" />
  32. <Button
  33. android:id="@+id/cancel_btn"
  34. android:layout_width="wrap_content"
  35. android:layout_height="45dp"
  36. android:layout_weight="0.3"
  37. android:background="@null"
  38. android:text="@string/cancel"
  39. android:textColor="@color/white"
  40. android:textSize="16sp" />
  41. </LinearLayout>
  42. <ImageView
  43. android:layout_width="fill_parent"
  44. android:layout_height="1px"
  45. android:background="@color/black"
  46. android:padding="1dp" />
  47. <LinearLayout
  48. android:id="@+id/date_selelct_layout"
  49. android:layout_width="fill_parent"
  50. android:layout_height="fill_parent"
  51. android:background="@color/white"
  52. android:orientation="horizontal" >
  53. <com.wheel.widget.WheelView
  54. android:id="@+id/year"
  55. android:layout_width="fill_parent"
  56. android:layout_height="wrap_content"
  57. android:layout_gravity="center_vertical"
  58. android:layout_margin="5dp"
  59. android:layout_weight="1"
  60. android:padding="5dp" />
  61. <com.wheel.widget.WheelView
  62. android:id="@+id/month"
  63. android:layout_width="fill_parent"
  64. android:layout_height="wrap_content"
  65. android:layout_gravity="center_vertical"
  66. android:layout_marginTop="5dp"
  67. android:layout_marginBottom="5dp"
  68. android:layout_weight="1"
  69. android:padding="5dp" />
  70. <com.wheel.widget.WheelView
  71. android:id="@+id/day"
  72. android:layout_width="fill_parent"
  73. android:layout_height="wrap_content"
  74. android:layout_gravity="center_vertical"
  75. android:layout_margin="5dp"
  76. android:layout_weight="1"
  77. android:padding="5dp" />
  78. <com.wheel.widget.WheelView
  79. android:id="@+id/hours"
  80. android:layout_width="fill_parent"
  81. android:layout_height="wrap_content"
  82. android:layout_gravity="center_vertical"
  83. android:layout_marginTop="5dp"
  84. android:layout_marginBottom="5dp"
  85. android:layout_weight="1"
  86. android:padding="5dp" />
  87. <com.wheel.widget.WheelView
  88. android:id="@+id/mins"
  89. android:layout_width="fill_parent"
  90. android:layout_height="wrap_content"
  91. android:layout_gravity="center_vertical"
  92. android:layout_margin="5dp"
  93. android:layout_weight="1"
  94. android:padding="5dp" />
  95. <com.wheel.widget.WheelView
  96. android:id="@+id/seconds"
  97. android:layout_width="fill_parent"
  98. android:layout_height="wrap_content"
  99. android:layout_gravity="center_vertical"
  100. android:layout_marginTop="5dp"
  101. android:layout_marginBottom="5dp"
  102. android:layout_marginRight="5dp"
  103. android:layout_weight="1"
  104. android:padding="5dp" />
  105. </LinearLayout>
  106. </LinearLayout>
第四步 : 自定义一个dialog

  1. package com.wheel.view;
  2. import java.util.Arrays;
  3. import java.util.Calendar;
  4. import java.util.List;
  5. import android.app.Dialog;
  6. import android.content.Context;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.View;
  10. import android.view.Window;
  11. import android.widget.Button;
  12. import android.widget.LinearLayout;
  13. import android.widget.LinearLayout.LayoutParams;
  14. import android.widget.TextView;
  15. import com.example.mywheel.R;
  16. import com.wheel.widget.NumericWheelAdapter;
  17. import com.wheel.widget.OnWheelChangedListener;
  18. import com.wheel.widget.WheelView;
  19. /**
  20. * 日期选择�?
  21. *
  22. * @author Administrator
  23. *
  24. */
  25. public class BirthDateDialog extends Dialog implements
  26. android.view.View.OnClickListener {
  27. /**
  28. * 自定义Dialog监听�?
  29. */
  30. public interface PriorityListener {
  31. /**
  32. * 回调函数,用于在Dialog的监听事件触发后刷新Activity的UI显示
  33. */
  34. public void refreshPriorityUI(String year, String month, String day,
  35. String hours, String mins);
  36. }
  37. private PriorityListener lis;
  38. private boolean scrolling = false;
  39. private Context context = null;
  40. public Button softInfo = null;
  41. public Button softInfoButton = null;
  42. private NumericWheelAdapter year_adapter = null;
  43. private NumericWheelAdapter month_adapter = null;
  44. private NumericWheelAdapter day_adapter = null;
  45. private NumericWheelAdapter hours_adapter = null;
  46. private NumericWheelAdapter mins_adapter = null;
  47. private NumericWheelAdapter seconds_adapter = null;
  48. private Button btn_sure = null;
  49. private Button btn_cancel = null;
  50. private int curYear = 0;
  51. private int curMonth = 0;
  52. private int curDay = 0;
  53. private int hours = 0;
  54. private int mins = 0;
  55. private int seconds = 0;
  56. private WheelView monthview = null;
  57. private WheelView yearview = null;
  58. private WheelView dayview = null;
  59. private WheelView hoursview = null;
  60. private WheelView minsview = null;
  61. private WheelView secondsview = null;
  62. private static int theme = R.style.myDialog;// 主题
  63. private LinearLayout date_layout;
  64. private int width, height;// 对话框宽高
  65. private TextView title_tv;
  66. private String title;
  67. public BirthDateDialog(final Context context,
  68. final PriorityListener listener, int currentyear, int currentmonth,
  69. int currentday, int hours, int mins, int seconds, int width,
  70. int height, String title) {
  71. super(context, theme);
  72. this.context = context;
  73. lis = listener;
  74. this.curYear = currentyear;
  75. this.curMonth = currentmonth;
  76. this.curDay = currentday;
  77. this.width = width;
  78. this.title = title;
  79. this.hours = hours;
  80. this.mins = mins;
  81. this.height = height;
  82. this.seconds = seconds;
  83. }
  84. @Override
  85. protected void onCreate(Bundle savedInstanceState) {
  86. // TODO Auto-generated method stub
  87. super.onCreate(savedInstanceState);
  88. setContentView(R.layout.date_select_wheel);
  89. btn_sure = (Button) findViewById(R.id.confirm_btn);
  90. btn_sure.setOnClickListener(this);
  91. btn_cancel = (Button) findViewById(R.id.cancel_btn);
  92. btn_cancel.setOnClickListener(this);
  93. date_layout = (LinearLayout) findViewById(R.id.date_selelct_layout);
  94. LayoutParams lparams_hours = new LayoutParams(width, height / 3 + 10);
  95. date_layout.setLayoutParams(lparams_hours);
  96. title_tv = (TextView) findViewById(R.id.diaolog_title_tv);
  97. title_tv.setText(title);
  98. yearview = (WheelView) findViewById(R.id.year);
  99. monthview = (WheelView) findViewById(R.id.month);
  100. dayview = (WheelView) findViewById(R.id.day);
  101. hoursview = (WheelView) findViewById(R.id.hours);
  102. minsview = (WheelView) findViewById(R.id.mins);
  103. secondsview = (WheelView) findViewById(R.id.seconds);
  104. OnWheelChangedListener listener = new OnWheelChangedListener() {
  105. public void onChanged(WheelView wheel, int oldValue, int newValue) {
  106. if (!scrolling) {
  107. updateDays(yearview, monthview, dayview);
  108. }
  109. }
  110. };
  111. monthview.addChangingListener(listener);
  112. yearview.addChangingListener(listener);
  113. Calendar calendar = Calendar.getInstance();
  114. if (this.curYear == 0 || this.curMonth == 0) {
  115. curYear = calendar.get(Calendar.YEAR);
  116. curMonth = calendar.get(Calendar.MONTH) + 1;
  117. curDay = calendar.get(Calendar.DAY_OF_MONTH);
  118. }
  119. // 初始化数�?�?
  120. year_adapter = new NumericWheelAdapter(1900, 2100);
  121. yearview.setAdapter(year_adapter);
  122. int cc = curYear - 1900;// 按下标来�?
  123. yearview.setCurrentItem(cc);// 传�?过去的是下标
  124. yearview.setVisibleItems(5);
  125. month_adapter = new NumericWheelAdapter(1, 12, "%02d");
  126. monthview.setAdapter(month_adapter);
  127. monthview.setCurrentItem(curMonth - 1);
  128. monthview.setCyclic(false);
  129. monthview.setVisibleItems(5);
  130. updateDays(yearview, monthview, dayview);
  131. dayview.setCyclic(false);
  132. dayview.setVisibleItems(5);
  133. hours_adapter = new NumericWheelAdapter(0, 23, "%02d");
  134. hoursview.setAdapter(hours_adapter);
  135. hoursview.setCurrentItem(hours);
  136. hoursview.setCyclic(false);
  137. hoursview.setVisibleItems(5);
  138. mins_adapter = new NumericWheelAdapter(0, 59, "%02d");
  139. minsview.setAdapter(mins_adapter);
  140. minsview.setCurrentItem(mins);
  141. minsview.setCyclic(false);
  142. minsview.setVisibleItems(5);
  143. seconds_adapter = new NumericWheelAdapter(0, 59, "%02d");
  144. secondsview.setAdapter(seconds_adapter);
  145. secondsview.setCurrentItem(seconds);
  146. secondsview.setCyclic(false);
  147. secondsview.setVisibleItems(5);
  148. }
  149. /**
  150. * 根据年份和月份来更新日期
  151. */
  152. private void updateDays(WheelView year, WheelView month, WheelView day) {
  153. // 添加大小月月份并将其转换为list,方便之后的判�?
  154. String[] months_big = { "1", "3", "5", "7", "8", "10", "12" };
  155. String[] months_little = { "4", "6", "9", "11" };
  156. final List<String> list_big = Arrays.asList(months_big);
  157. final List<String> list_little = Arrays.asList(months_little);
  158. int year_num = year.getCurrentItem() + 1900;
  159. // 判断大小月及是否闰年,用来确定"�?的数�?
  160. if (list_big.contains(String.valueOf(month.getCurrentItem() + 1))) {
  161. day_adapter = new NumericWheelAdapter(1, 31, "%02d");
  162. } else if (list_little
  163. .contains(String.valueOf(month.getCurrentItem() + 1))) {
  164. day_adapter = new NumericWheelAdapter(1, 30, "%02d");
  165. } else {
  166. if ((year_num % 4 == 0 && year_num % 100 != 0)
  167. || year_num % 400 == 0)
  168. day_adapter = new NumericWheelAdapter(1, 29, "%02d");
  169. else
  170. day_adapter = new NumericWheelAdapter(1, 28, "%02d");
  171. }
  172. dayview.setAdapter(day_adapter);
  173. dayview.setCurrentItem(curDay - 1);
  174. }
  175. public BirthDateDialog(Context context, PriorityListener listener) {
  176. super(context, theme);
  177. this.context = context;
  178. }
  179. public BirthDateDialog(Context context, String birthDate) {
  180. super(context, theme);
  181. this.context = context;
  182. }
  183. @Override
  184. public void onClick(View v) {
  185. switch (v.getId()) {
  186. case R.id.confirm_btn:
  187. lis.refreshPriorityUI(year_adapter.getValues(),
  188. month_adapter.getValues(), day_adapter.getValues(),
  189. hours_adapter.getValues(), mins_adapter.getValues());
  190. this.dismiss();
  191. break;
  192. case R.id.cancel_btn:
  193. this.dismiss();
  194. break;
  195. default:
  196. break;
  197. }
  198. }
  199. @Override
  200. public void dismiss() {
  201. super.dismiss();
  202. }
  203. @Override
  204. protected void onStop() {
  205. super.onStop();
  206. }
  207. }

第五步:dialog样式 在底部

  1. // 时间
  2. public void getDate() {
  3. DisplayMetrics dm = new DisplayMetrics();
  4. this.getWindowManager().getDefaultDisplay().getMetrics(dm);
  5. int width = dm.widthPixels;
  6. int height = dm.heightPixels;
  7. String curDate = date_tv.getText().toString();
  8. int[] date = getYMDArray(curDate, "-");
  9. int[] time = getYMDArray(time_tv.getText().toString(), ":");
  10. BirthDateDialog birthDiolog = new BirthDateDialog(this,
  11. new PriorityListener() {
  12. @Override
  13. public void refreshPriorityUI(String year, String month,
  14. String day, String hours, String mins) {
  15. date_tv.setText(year + "-" + month + "-" + day);
  16. time_tv.setText(hours + ":" + mins);
  17. }
  18. }, date[0], date[1], date[2], time[0], time[1], time[2], width,
  19. height, "测量时间");
  20. Window window = birthDiolog.getWindow();
  21. window.setGravity(Gravity.BOTTOM); // 此处可以设置dialog显示的位置
  22. window.setWindowAnimations(R.style.dialogstyle); // 添加动画
  23. birthDiolog.setCancelable(true);
  24. birthDiolog.show();
  25. }


以上就是关键代码,待会会把整个项目贴上来  有不足之处 请多多谅解



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/278828?site
推荐阅读
相关标签
  

闽ICP备14008679号