当前位置:   article > 正文

Android 类似Ios的时间滚轮控件_安卓实现定时滚轮控件

安卓实现定时滚轮控件

之前项目使用的,参考了别人的一个demo,但是原文链接找不到了。。。。

先说如何使用:

//参数1:上下文
//参数2:选中是的ResultHandler回调
//参数3:选择器最早时间
//参数4:选择器的最晚时间(本文用的当前时间)
//参数5:选择器的默认展示时间
val currentCalender = Calendar.getInstance()
val currentDate = DateUtil.format(currentCalender.getTime(), "yyyy/MM/dd")
val timeSelector2 = TimeSelector(this,object :TimeSelector.ResultHandler{
    override fun handle(time: String?) {
        birthday_tv.setText(time)
    }
},"1971/01/01", currentDate, "2001/01/01")

//需要显示可选择的小时数与分钟数时,在后面增加对应的两个参数。这时选择器的小时与分钟也会自动显示
val timeSelector2 = TimeSelector(this,object :TimeSelector.ResultHandler{
    override fun handle(time: String?) {
        birthday_tv.setText(time)
    }
},"1971/01/01", currentDate, "2001/01/01","08:30","20:30")
timeSelector.setMode(TimeSelector.MODE.YMD)
timeSelector.show()

滚动控件是自定义的view,PickerView:

R.styleable.PickerView
  1. public class PickerView extends View {
  2. /**
  3. * 新增字段 控制是否首尾相接循环显示 默认为循环显示
  4. */
  5. private boolean loop = true;
  6. /**
  7. * text之间间距和minTextSize之比
  8. */
  9. public static final float MARGIN_ALPHA = 2.8f;
  10. /**
  11. * 自动回滚到中间的速度
  12. */
  13. public static final float SPEED = 10;
  14. private List<String> mDataList;
  15. /**
  16. * 选中的位置,这个位置是mDataList的中心位置,一直不变
  17. */
  18. private int mCurrentSelected;
  19. private Paint mPaint, nPaint;
  20. private float mMaxTextSize = 80;
  21. private float mMinTextSize = 40;
  22. private float mMaxTextAlpha = 255;
  23. private float mMinTextAlpha = 120;
  24. private int mColorText = 0x333333;
  25. private int nColorText = 0x666666;
  26. private int mViewHeight;
  27. private int mViewWidth;
  28. private float mLastDownY;
  29. /**
  30. * 滑动的距离
  31. */
  32. private float mMoveLen = 0;
  33. private boolean isInit = false;
  34. private onSelectListener mSelectListener;
  35. private Timer timer;
  36. private MyTimerTask mTask;
  37. Handler updateHandler = new Handler() {
  38. @Override
  39. public void handleMessage(Message msg) {
  40. if (Math.abs(mMoveLen) < SPEED) {
  41. mMoveLen = 0;
  42. if (mTask != null) {
  43. mTask.cancel();
  44. mTask = null;
  45. performSelect();
  46. }
  47. } else
  48. // 这里mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚
  49. mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED;
  50. invalidate();
  51. }
  52. };
  53. private boolean canScroll = true;
  54. public PickerView(Context context) {
  55. super(context);
  56. init();
  57. }
  58. public PickerView(Context context, AttributeSet attrs) {
  59. super(context, attrs);
  60. TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.PickerView);
  61. loop = typedArray.getBoolean(R.styleable.PickerView_isLoop, loop);
  62. init();
  63. }
  64. public void setOnSelectListener(onSelectListener listener) {
  65. mSelectListener = listener;
  66. }
  67. private void performSelect() {
  68. if (mSelectListener != null)
  69. mSelectListener.onSelect(mDataList.get(mCurrentSelected));
  70. }
  71. public void setData(List<String> datas) {
  72. mDataList = datas;
  73. mCurrentSelected = datas.size() / 4;
  74. invalidate();
  75. }
  76. /**
  77. * 选择选中的item的index
  78. *
  79. * @param selected
  80. */
  81. public void setSelected(int selected) {
  82. mCurrentSelected = selected;
  83. if (loop) {
  84. int distance = mDataList.size() / 2 - mCurrentSelected;
  85. if (distance < 0)
  86. for (int i = 0; i < -distance; i++) {
  87. moveHeadToTail();
  88. mCurrentSelected--;
  89. }
  90. else if (distance > 0)
  91. for (int i = 0; i < distance; i++) {
  92. moveTailToHead();
  93. mCurrentSelected++;
  94. }
  95. }
  96. invalidate();
  97. }
  98. /**
  99. * 选择选中的内容
  100. *
  101. * @param mSelectItem
  102. */
  103. public void setSelected(String mSelectItem) {
  104. for (int i = 0; i < mDataList.size(); i++)
  105. if (mDataList.get(i).equals(mSelectItem)) {
  106. setSelected(i);
  107. break;
  108. }
  109. }
  110. private void moveHeadToTail() {
  111. if (loop) {
  112. String head = mDataList.get(0);
  113. mDataList.remove(0);
  114. mDataList.add(head);
  115. }
  116. }
  117. private void moveTailToHead() {
  118. if (loop) {
  119. String tail = mDataList.get(mDataList.size() - 1);
  120. mDataList.remove(mDataList.size() - 1);
  121. mDataList.add(0, tail);
  122. }
  123. }
  124. @Override
  125. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  126. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  127. mViewHeight = getMeasuredHeight();
  128. mViewWidth = getMeasuredWidth();
  129. // 按照View的高度计算字体大小
  130. mMaxTextSize = mViewHeight / 7f;
  131. mMinTextSize = mMaxTextSize / 2.2f;
  132. isInit = true;
  133. invalidate();
  134. }
  135. private void init() {
  136. timer = new Timer();
  137. mDataList = new ArrayList<String>();
  138. //第一个paint
  139. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  140. mPaint.setStyle(Style.FILL);
  141. mPaint.setTextAlign(Align.CENTER);
  142. mPaint.setColor(getResources().getColor(R.color.main_color));
  143. //第二个paint
  144. nPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  145. nPaint.setStyle(Style.FILL);
  146. nPaint.setTextAlign(Align.CENTER);
  147. nPaint.setColor(mColorText);
  148. }
  149. @Override
  150. protected void onDraw(Canvas canvas) {
  151. super.onDraw(canvas);
  152. // 根据index绘制view
  153. if (isInit)
  154. drawData(canvas);
  155. }
  156. private void drawData(Canvas canvas) {
  157. // 先绘制选中的text再往上往下绘制其余的text
  158. float scale = parabola(mViewHeight / 4.0f, mMoveLen);
  159. float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
  160. mPaint.setTextSize(size);
  161. mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));
  162. // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标
  163. float x = (float) (mViewWidth / 2.0);
  164. float y = (float) (mViewHeight / 2.0 + mMoveLen);
  165. FontMetricsInt fmi = mPaint.getFontMetricsInt();
  166. float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
  167. canvas.drawText(mDataList.get(mCurrentSelected), x, baseline, mPaint);
  168. // 绘制上方data
  169. for (int i = 1; (mCurrentSelected - i) >= 0; i++) {
  170. drawOtherText(canvas, i, -1);
  171. }
  172. // 绘制下方data
  173. for (int i = 1; (mCurrentSelected + i) < mDataList.size(); i++) {
  174. drawOtherText(canvas, i, 1);
  175. }
  176. }
  177. /**
  178. * @param canvas
  179. * @param position 距离mCurrentSelected的差值
  180. * @param type 1表示向下绘制,-1表示向上绘制
  181. */
  182. private void drawOtherText(Canvas canvas, int position, int type) {
  183. float d = (float) (MARGIN_ALPHA * mMinTextSize * position + type
  184. * mMoveLen);
  185. float scale = parabola(mViewHeight / 4.0f, d);
  186. float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
  187. nPaint.setTextSize(size);
  188. nPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));
  189. float y = (float) (mViewHeight / 2.0 + type * d);
  190. FontMetricsInt fmi = nPaint.getFontMetricsInt();
  191. float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
  192. canvas.drawText(mDataList.get(mCurrentSelected + type * position),
  193. (float) (mViewWidth / 2.0), baseline, nPaint);
  194. }
  195. /**
  196. * 抛物线
  197. *
  198. * @param zero 零点坐标
  199. * @param x 偏移量
  200. * @return scale
  201. */
  202. private float parabola(float zero, float x) {
  203. float f = (float) (1 - Math.pow(x / zero, 2));
  204. return f < 0 ? 0 : f;
  205. }
  206. @Override
  207. public boolean onTouchEvent(MotionEvent event) {
  208. switch (event.getActionMasked()) {
  209. case MotionEvent.ACTION_DOWN:
  210. doDown(event);
  211. break;
  212. case MotionEvent.ACTION_MOVE:
  213. mMoveLen += (event.getY() - mLastDownY);
  214. if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2) {
  215. if (!loop && mCurrentSelected == 0) {
  216. mLastDownY = event.getY();
  217. invalidate();
  218. return true;
  219. }
  220. if (!loop) mCurrentSelected--;
  221. // 往下滑超过离开距离
  222. moveTailToHead();
  223. mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;
  224. } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2) {
  225. if (mCurrentSelected == mDataList.size() - 1) {
  226. mLastDownY = event.getY();
  227. invalidate();
  228. return true;
  229. }
  230. if (!loop) mCurrentSelected++;
  231. // 往上滑超过离开距离
  232. moveHeadToTail();
  233. mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;
  234. }
  235. mLastDownY = event.getY();
  236. invalidate();
  237. break;
  238. case MotionEvent.ACTION_UP:
  239. doUp(event);
  240. break;
  241. }
  242. return true;
  243. }
  244. private void doDown(MotionEvent event) {
  245. if (mTask != null) {
  246. mTask.cancel();
  247. mTask = null;
  248. }
  249. mLastDownY = event.getY();
  250. }
  251. // private void doMove(MotionEvent event) {
  252. //
  253. // mMoveLen += (event.getY() - mLastDownY);
  254. //
  255. // if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2) {
  256. // // 往下滑超过离开距离
  257. // moveTailToHead();
  258. // mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;
  259. // } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2) {
  260. // // 往上滑超过离开距离
  261. // moveHeadToTail();
  262. // mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;
  263. // }
  264. //
  265. // mLastDownY = event.getY();
  266. // invalidate();
  267. // }
  268. private void doUp(MotionEvent event) {
  269. // 抬起手后mCurrentSelected的位置由当前位置move到中间选中位置
  270. if (Math.abs(mMoveLen) < 0.0001) {
  271. mMoveLen = 0;
  272. return;
  273. }
  274. if (mTask != null) {
  275. mTask.cancel();
  276. mTask = null;
  277. }
  278. mTask = new MyTimerTask(updateHandler);
  279. timer.schedule(mTask, 0, 10);
  280. }
  281. class MyTimerTask extends TimerTask {
  282. Handler handler;
  283. public MyTimerTask(Handler handler) {
  284. this.handler = handler;
  285. }
  286. @Override
  287. public void run() {
  288. handler.sendMessage(handler.obtainMessage());
  289. }
  290. }
  291. public interface onSelectListener {
  292. void onSelect(String text);
  293. }
  294. public void setCanScroll(boolean canScroll) {
  295. this.canScroll = canScroll;
  296. }
  297. @Override
  298. public boolean dispatchTouchEvent(MotionEvent event) {
  299. if (canScroll)
  300. return super.dispatchTouchEvent(event);
  301. else
  302. return false;
  303. }
  304. /**
  305. * 新增字段 控制内容是否首尾相连
  306. * by liuli
  307. *
  308. * @param isLoop
  309. */
  310. public void setIsLoop(boolean isLoop) {
  311. loop = isLoop;
  312. }
  313. }

R.styleable.PickerView:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="PickerView">
  4. <attr name="isLoop" format="boolean" />
  5. </declare-styleable>
  6. </resources>

 主要操作类是:TimeSelector:
 

  1. public class TimeSelector {
  2. public interface ResultHandler {
  3. void handle(String time);
  4. }
  5. public enum SCROLLTYPE {
  6. HOUR(1),
  7. MINUTE(2);
  8. private SCROLLTYPE(int value) {
  9. this.value = value;
  10. }
  11. public int value;
  12. }
  13. /**
  14. * 模式,一种只显示年月日,一种显示年月日时分
  15. */
  16. public enum MODE {
  17. YMD(1),
  18. YMDHM(2);
  19. private MODE(int value) {
  20. this.value = value;
  21. }
  22. public int value;
  23. }
  24. private int scrollUnits = SCROLLTYPE.HOUR.value + SCROLLTYPE.MINUTE.value;//3
  25. private ResultHandler handler;
  26. private Context context;
  27. // private final String FORMAT_STR = "yyyy-MM-dd HH:mm";
  28. private final String FORMAT_STR = "yyyy/MM/dd";
  29. private final String RESULT_FORMAT_STR = "dd/MM/yyyy";
  30. private final String YEAR_FORMAT_STR = "yyyy";
  31. private final String MONTH_FORMAT_STR = "MM";
  32. private final String DAY_FORMAT_STR = "DD";
  33. private Dialog seletorDialog;//选择日期与时间弹框
  34. private PickerView year_pv;//控件 年
  35. private PickerView month_pv;//控件 月
  36. private PickerView day_pv;//控件 天
  37. private PickerView hour_pv;//控件 时
  38. private PickerView minute_pv;//控件 分
  39. private final int MAXMINUTE = 59;//最大分钟数
  40. private int MAXHOUR = 23;//最大小时数(结束时间小时数)
  41. private final int MINMINUTE = 0;//最小分钟数
  42. private int MINHOUR = 0;//最小小时数(开始时间小时数)
  43. private final int MAXMONTH = 12;//最大月份数
  44. private ArrayList<String> year, month, day, hour, minute;//根据设定的开始日期时间、结束日期时间 存储年月日时分的ArrayList
  45. //开始年、月、时、分 结束年、月、时、分
  46. private int startYear, startMonth, startDay, startHour, startMininute,
  47. endYear, endMonth, endDay, endHour, endMininute,
  48. minute_workStart, minute_workEnd, hour_workStart, hour_workEnd;
  49. private boolean spanYear, spanMon, spanDay, spanHour, spanMin;//年月日时分是否是时间跨度
  50. private Calendar selectedCalender = Calendar.getInstance();//获取选中的时间日历
  51. private final long ANIMATORDELAY = 200L;//延时动画
  52. private final long CHANGEDELAY = 90L;//修改延时
  53. private String workStart_str;//开始时间
  54. private String workEnd_str;//结束时间
  55. private Calendar startCalendar;//开始日期日历
  56. private Calendar endCalendar;//结束日期日历
  57. private TextView tv_cancle;//取消按钮
  58. private TextView tv_select, tv_title;//选择按钮、弹框标题
  59. private TextView hour_text;//“时” 字样
  60. private TextView minute_text;//“分” 字样
  61. private Calendar defaultCalendar;//默认选择的日历
  62. public TimeSelector(Context context, ResultHandler resultHandler, String startDate, String endDate, String defaultDate) {
  63. this.context = context;
  64. this.handler = resultHandler;
  65. startCalendar = Calendar.getInstance();
  66. endCalendar = Calendar.getInstance();
  67. defaultCalendar = Calendar.getInstance();
  68. startCalendar.setTime(DateUtil.parse(startDate, FORMAT_STR));//开始日期
  69. endCalendar.setTime(DateUtil.parse(endDate, FORMAT_STR));//结束日期
  70. defaultCalendar.setTime(DateUtil.parse(defaultDate, FORMAT_STR));//默认选择日期
  71. initDialog();
  72. initView();
  73. }
  74. public TimeSelector(Context context, ResultHandler resultHandler, String startDate, String endDate, String defaultDate, String workStartTime, String workEndTime) {
  75. this(context, resultHandler, startDate, endDate,defaultDate);
  76. this.workStart_str = workStartTime;
  77. this.workEnd_str = workEndTime;
  78. }
  79. /**
  80. * 外部调用,弹出时间选择dialog
  81. */
  82. public void show() {
  83. if (startCalendar.getTime().getTime() >= endCalendar.getTime().getTime()) {
  84. Toast.makeText(context, "start>end", Toast.LENGTH_SHORT).show();
  85. return;
  86. }
  87. if (defaultCalendar.getTime().getTime() < startCalendar.getTime().getTime()) {
  88. Toast.makeText(context, "default<start", Toast.LENGTH_SHORT).show();
  89. return;
  90. }
  91. if (defaultCalendar.getTime().getTime() > endCalendar.getTime().getTime()) {
  92. Toast.makeText(context, "default>end", Toast.LENGTH_SHORT).show();
  93. return;
  94. }
  95. if (!excuteWorkTime()) return;
  96. initParameter();
  97. initTimer();
  98. addListener();
  99. seletorDialog.show();
  100. }
  101. /**
  102. * 初始化日期时间选择弹框
  103. */
  104. private void initDialog() {
  105. if (seletorDialog == null) {
  106. seletorDialog = new Dialog(context, R.style.time_dialog);
  107. seletorDialog.setCancelable(false);
  108. seletorDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
  109. seletorDialog.setContentView(R.layout.dlg_selector);
  110. Window window = seletorDialog.getWindow();
  111. window.setGravity(Gravity.BOTTOM);
  112. WindowManager.LayoutParams lp = window.getAttributes();
  113. //宽度为屏幕的宽
  114. int width = ScreenUtil.getInstance(context).getScreenWidth();
  115. lp.width = width;
  116. window.setAttributes(lp);
  117. }
  118. }
  119. /**
  120. * 初始化控件id,设置点击事件
  121. */
  122. private void initView() {
  123. year_pv = (PickerView) seletorDialog.findViewById(R.id.year_pv);
  124. month_pv = (PickerView) seletorDialog.findViewById(R.id.month_pv);
  125. day_pv = (PickerView) seletorDialog.findViewById(R.id.day_pv);
  126. hour_pv = (PickerView) seletorDialog.findViewById(R.id.hour_pv);
  127. minute_pv = (PickerView) seletorDialog.findViewById(R.id.minute_pv);
  128. tv_cancle = (TextView) seletorDialog.findViewById(R.id.tv_cancle);
  129. tv_select = (TextView) seletorDialog.findViewById(R.id.tv_select);
  130. tv_title = (TextView) seletorDialog.findViewById(R.id.tv_title);
  131. hour_text = (TextView) seletorDialog.findViewById(R.id.hour_text);
  132. minute_text = (TextView) seletorDialog.findViewById(R.id.minute_text);
  133. tv_cancle.setOnClickListener(new View.OnClickListener() {
  134. @Override
  135. public void onClick(View view) {
  136. seletorDialog.dismiss();
  137. }
  138. });
  139. tv_select.setOnClickListener(new View.OnClickListener() {
  140. @Override
  141. public void onClick(View view) {
  142. handler.handle(DateUtil.format(selectedCalender.getTime(), RESULT_FORMAT_STR));
  143. seletorDialog.dismiss();
  144. }
  145. });
  146. }
  147. /**
  148. * 此时的startCalendar、endCalendar都是经过检测是,正确时间,来分别获取年月日时分
  149. */
  150. private void initParameter() {
  151. startYear = startCalendar.get(Calendar.YEAR);
  152. startMonth = startCalendar.get(Calendar.MONTH) + 1;
  153. startDay = startCalendar.get(Calendar.DAY_OF_MONTH);
  154. startHour = startCalendar.get(Calendar.HOUR_OF_DAY);
  155. startMininute = startCalendar.get(Calendar.MINUTE);
  156. endYear = endCalendar.get(Calendar.YEAR);
  157. endMonth = endCalendar.get(Calendar.MONTH) + 1;
  158. endDay = endCalendar.get(Calendar.DAY_OF_MONTH);
  159. endHour = endCalendar.get(Calendar.HOUR_OF_DAY);
  160. endMininute = endCalendar.get(Calendar.MINUTE);
  161. spanYear = startYear != endYear;//
  162. spanMon = (!spanYear) && (startMonth != endMonth);//???年等 月不等
  163. spanDay = (!spanMon) && (startDay != endDay);//???月等 日不等
  164. spanHour = (!spanDay) && (startHour != endHour);
  165. spanMin = (!spanHour) && (startMininute != endMininute);
  166. // selectedCalender.setTime(startCalendar.getTime());
  167. //--------------------------------------
  168. // startYear = defaultCalendar.get(Calendar.YEAR);
  169. // startMonth = defaultCalendar.get(Calendar.MONTH) + 1;
  170. // startDay = defaultCalendar.get(Calendar.DAY_OF_MONTH);
  171. // startHour = defaultCalendar.get(Calendar.HOUR_OF_DAY);
  172. // startMininute = defaultCalendar.get(Calendar.MINUTE);
  173. //设置初始化时默认选择时间
  174. selectedCalender.setTime(defaultCalendar.getTime());
  175. }
  176. /**
  177. * ???
  178. * 根据年月日时分开始结束时间,造数据
  179. *
  180. */
  181. private void initTimer() {
  182. initArrayList();
  183. if (spanYear) {//分别向年月日时分list里添加数据
  184. for (int i = startYear; i <= endYear; i++) {
  185. year.add(String.valueOf(i));
  186. }
  187. for (int i = startMonth; i <= MAXMONTH; i++) {//<12
  188. month.add(fomatTimeUnit(i));
  189. }
  190. for (int i = startDay; i <= startCalendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {//startCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) startCalendar中月份的最大值
  191. day.add(fomatTimeUnit(i));
  192. }
  193. if ((scrollUnits & SCROLLTYPE.HOUR.value) != SCROLLTYPE.HOUR.value) {//(0 & 1) !=1
  194. hour.add(fomatTimeUnit(startHour));
  195. } else {
  196. for (int i = startHour; i <= MAXHOUR; i++) {//MAXHOUR 开始时间的小时数
  197. hour.add(fomatTimeUnit(i));
  198. }
  199. }
  200. if ((scrollUnits & SCROLLTYPE.MINUTE.value) != SCROLLTYPE.MINUTE.value) {//(0 & 2) !=1
  201. minute.add(fomatTimeUnit(startMininute));
  202. } else {
  203. for (int i = startMininute; i <= MAXMINUTE; i++) {
  204. minute.add(fomatTimeUnit(i));
  205. }
  206. }
  207. } else if (spanMon) {
  208. year.add(String.valueOf(startYear));
  209. for (int i = startMonth; i <= endMonth; i++) {
  210. month.add(fomatTimeUnit(i));
  211. }
  212. for (int i = startDay; i <= startCalendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
  213. day.add(fomatTimeUnit(i));
  214. }
  215. if ((scrollUnits & SCROLLTYPE.HOUR.value) != SCROLLTYPE.HOUR.value) {
  216. hour.add(fomatTimeUnit(startHour));
  217. } else {
  218. for (int i = startHour; i <= MAXHOUR; i++) {
  219. hour.add(fomatTimeUnit(i));
  220. }
  221. }
  222. if ((scrollUnits & SCROLLTYPE.MINUTE.value) != SCROLLTYPE.MINUTE.value) {
  223. minute.add(fomatTimeUnit(startMininute));
  224. } else {
  225. for (int i = startMininute; i <= MAXMINUTE; i++) {
  226. minute.add(fomatTimeUnit(i));
  227. }
  228. }
  229. } else if (spanDay) {
  230. year.add(String.valueOf(startYear));
  231. month.add(fomatTimeUnit(startMonth));
  232. for (int i = startDay; i <= endDay; i++) {
  233. day.add(fomatTimeUnit(i));
  234. }
  235. if ((scrollUnits & SCROLLTYPE.HOUR.value) != SCROLLTYPE.HOUR.value) {
  236. hour.add(fomatTimeUnit(startHour));
  237. } else {
  238. for (int i = startHour; i <= MAXHOUR; i++) {
  239. hour.add(fomatTimeUnit(i));
  240. }
  241. }
  242. if ((scrollUnits & SCROLLTYPE.MINUTE.value) != SCROLLTYPE.MINUTE.value) {
  243. minute.add(fomatTimeUnit(startMininute));
  244. } else {
  245. for (int i = startMininute; i <= MAXMINUTE; i++) {
  246. minute.add(fomatTimeUnit(i));
  247. }
  248. }
  249. } else if (spanHour) {
  250. year.add(String.valueOf(startYear));
  251. month.add(fomatTimeUnit(startMonth));
  252. day.add(fomatTimeUnit(startDay));
  253. if ((scrollUnits & SCROLLTYPE.HOUR.value) != SCROLLTYPE.HOUR.value) {
  254. hour.add(fomatTimeUnit(startHour));
  255. } else {
  256. for (int i = startHour; i <= endHour; i++) {
  257. hour.add(fomatTimeUnit(i));
  258. }
  259. }
  260. if ((scrollUnits & SCROLLTYPE.MINUTE.value) != SCROLLTYPE.MINUTE.value) {
  261. minute.add(fomatTimeUnit(startMininute));
  262. } else {
  263. for (int i = startMininute; i <= MAXMINUTE; i++) {
  264. minute.add(fomatTimeUnit(i));
  265. }
  266. }
  267. } else if (spanMin) {
  268. year.add(String.valueOf(startYear));
  269. month.add(fomatTimeUnit(startMonth));
  270. day.add(fomatTimeUnit(startDay));
  271. hour.add(fomatTimeUnit(startHour));
  272. if ((scrollUnits & SCROLLTYPE.MINUTE.value) != SCROLLTYPE.MINUTE.value) {
  273. minute.add(fomatTimeUnit(startMininute));
  274. } else {
  275. for (int i = startMininute; i <= endMininute; i++) {
  276. minute.add(fomatTimeUnit(i));
  277. }
  278. }
  279. }
  280. loadComponent();
  281. }
  282. /**
  283. * 主要为startCalendar、endCalendar设置正确与结束的日期、时间
  284. * 并根据startCalendar、endCalendar设置MINHOUR与MAXHOUR
  285. * @return
  286. */
  287. private boolean excuteWorkTime() {
  288. boolean res = true;
  289. //如果设置了开始时间与结束时间
  290. if (!TextUtil.isEmpty(workStart_str) && !TextUtil.isEmpty(workEnd_str)) {
  291. String[] start = workStart_str.split(":");//":"分割时间
  292. String[] end = workEnd_str.split(":");
  293. hour_workStart = Integer.parseInt(start[0]);//开始时间的小时
  294. minute_workStart = Integer.parseInt(start[1]);//开始时间的分钟
  295. hour_workEnd = Integer.parseInt(end[0]);//结束时间的小时
  296. minute_workEnd = Integer.parseInt(end[1]);//结束时间的分钟
  297. //1971-01-01T08:00:00.000+0800 此时的workStartCalendar是有小时和分钟的,但startCalendar不一定有,因为在只设置日期不设置时间时不会有小时和分钟
  298. Calendar workStartCalendar = Calendar.getInstance();
  299. workStartCalendar.setTime(startCalendar.getTime());//使用日历,获取初始化时设置开始的日期,再设置给workStartCalendar
  300. workStartCalendar.set(Calendar.HOUR_OF_DAY, hour_workStart);//根据获取的开始时间的小时数,设置小时
  301. workStartCalendar.set(Calendar.MINUTE, minute_workStart);//根据获取的开始时间的分钟数,设置分钟
  302. //2022-03-18T20:00:00.000+0800 此时的workEndCalendar是有小时和分钟的,但endCalendar不一定有,因为在只设置日期不设置时间时不会有小时和分钟
  303. Calendar workEndCalendar = Calendar.getInstance();
  304. workEndCalendar.setTime(endCalendar.getTime());//使用日历,获取初始化时设置结束的日期,再设置给workEndCalendar
  305. workEndCalendar.set(Calendar.HOUR_OF_DAY, hour_workEnd);//根据获取的结束时间的小时数,设置小时
  306. workEndCalendar.set(Calendar.MINUTE, minute_workEnd);//根据获取的结束时间的分钟数,设置分钟
  307. Calendar startTime = Calendar.getInstance();
  308. Calendar endTime = Calendar.getInstance();
  309. Calendar startWorkTime = Calendar.getInstance();
  310. Calendar endWorkTime = Calendar.getInstance();
  311. //这时的startCalendar、endCalendar 如果没有小时分钟的话,startTime、endTime的小时分钟也是0
  312. startTime.set(Calendar.HOUR_OF_DAY, startCalendar.get(Calendar.HOUR_OF_DAY));
  313. startTime.set(Calendar.MINUTE, startCalendar.get(Calendar.MINUTE));
  314. endTime.set(Calendar.HOUR_OF_DAY, endCalendar.get(Calendar.HOUR_OF_DAY));
  315. endTime.set(Calendar.MINUTE, endCalendar.get(Calendar.MINUTE));
  316. //走到这时,workStartCalendar、workEndCalendar一般都是有小时分钟的,赋值给startWorkTime
  317. startWorkTime.set(Calendar.HOUR_OF_DAY, workStartCalendar.get(Calendar.HOUR_OF_DAY));
  318. startWorkTime.set(Calendar.MINUTE, workStartCalendar.get(Calendar.MINUTE));
  319. endWorkTime.set(Calendar.HOUR_OF_DAY, workEndCalendar.get(Calendar.HOUR_OF_DAY));
  320. endWorkTime.set(Calendar.MINUTE, workEndCalendar.get(Calendar.MINUTE));
  321. //比较毫秒值~~不正常的情况 startTime与endTime是否相同 startWorkTime是否小于startTime endWorkTime是否小于startTime
  322. if (startTime.getTime().getTime() == endTime.getTime().getTime() || (startWorkTime.getTime().getTime() < startTime.getTime().getTime() && endWorkTime.getTime().getTime() < startTime.getTime().getTime())) {
  323. Toast.makeText(context, "Wrong parames!", Toast.LENGTH_LONG).show();
  324. return false;
  325. }
  326. //比较毫秒值~~正常的情况 startCalendar比workStartCalendar 毫秒值小 取大的?? 1971-01-01T00:00:00.000+0800 < 1971-01-01T08:00:00.000+0800
  327. startCalendar.setTime(startCalendar.getTime().getTime() < workStartCalendar.getTime().getTime() ? workStartCalendar.getTime() : startCalendar.getTime());
  328. //endCalendar比workEndCalendar 毫秒值小 取小的?? 2022-03-18T00:00:00.000+0800 >2022-03-18T20:00:00.000+0800
  329. endCalendar.setTime(endCalendar.getTime().getTime() > workEndCalendar.getTime().getTime() ? workEndCalendar.getTime() : endCalendar.getTime());
  330. MINHOUR = workStartCalendar.get(Calendar.HOUR_OF_DAY);
  331. MAXHOUR = workEndCalendar.get(Calendar.HOUR_OF_DAY);
  332. }
  333. return res;
  334. }
  335. /**
  336. * 格式月日,时分,单位补0
  337. * @param unit
  338. * @return
  339. */
  340. private String fomatTimeUnit(int unit) {
  341. return unit < 10 ? "0" + String.valueOf(unit) : String.valueOf(unit);
  342. }
  343. /**
  344. * 初始化年月日时分list
  345. */
  346. private void initArrayList() {
  347. if (year == null) year = new ArrayList<>();
  348. if (month == null) month = new ArrayList<>();
  349. if (day == null) day = new ArrayList<>();
  350. if (hour == null) hour = new ArrayList<>();
  351. if (minute == null) minute = new ArrayList<>();
  352. year.clear();
  353. month.clear();
  354. day.clear();
  355. hour.clear();
  356. minute.clear();
  357. }
  358. /**
  359. * 初始化各个PickerView监听
  360. */
  361. private void addListener() {
  362. year_pv.setOnSelectListener(new PickerView.onSelectListener() {
  363. @Override
  364. public void onSelect(String text) {
  365. selectedCalender.set(Calendar.YEAR, Integer.parseInt(text));//根据选择的年份设置selectedCalender
  366. monthChange();
  367. }
  368. });
  369. month_pv.setOnSelectListener(new PickerView.onSelectListener() {
  370. @Override
  371. public void onSelect(String text) {
  372. selectedCalender.set(Calendar.DAY_OF_MONTH, 1);
  373. selectedCalender.set(Calendar.MONTH, Integer.parseInt(text) - 1);//月份的特殊性要-1
  374. dayChange();
  375. }
  376. });
  377. day_pv.setOnSelectListener(new PickerView.onSelectListener() {
  378. @Override
  379. public void onSelect(String text) {
  380. selectedCalender.set(Calendar.DAY_OF_MONTH, Integer.parseInt(text));
  381. hourChange();
  382. }
  383. });
  384. hour_pv.setOnSelectListener(new PickerView.onSelectListener() {
  385. @Override
  386. public void onSelect(String text) {
  387. selectedCalender.set(Calendar.HOUR_OF_DAY, Integer.parseInt(text));
  388. minuteChange();
  389. }
  390. });
  391. minute_pv.setOnSelectListener(new PickerView.onSelectListener() {
  392. @Override
  393. public void onSelect(String text) {
  394. selectedCalender.set(Calendar.MINUTE, Integer.parseInt(text));
  395. }
  396. });
  397. }
  398. /**
  399. * 像年月日时分的PickerView 设置数据
  400. * 可以都设置为开始时间,
  401. * 但如果selectedCalender 不为空时,根据selectedCalender 的年月日 设置PickerView默认显示的年月日时分
  402. */
  403. private void loadComponent() {
  404. // year_pv.setSelected(0);
  405. // month_pv.setSelected(0);
  406. // day_pv.setSelected(0);
  407. // hour_pv.setSelected(0);
  408. // minute_pv.setSelected(0);
  409. year_pv.setData(year);
  410. month_pv.setData(month);
  411. day_pv.setData(day);
  412. hour_pv.setData(hour);
  413. minute_pv.setData(minute);
  414. String yearStr = DateUtil.format(selectedCalender.getTime(), YEAR_FORMAT_STR);
  415. String monthStr = DateUtil.format(selectedCalender.getTime(), MONTH_FORMAT_STR);
  416. String dayStr = DateUtil.format(selectedCalender.getTime(), DAY_FORMAT_STR);
  417. if(year.contains(yearStr)){
  418. int index = year.indexOf(yearStr);
  419. year_pv.setSelected(index);
  420. }else{
  421. year_pv.setSelected(0);
  422. }
  423. if(month.contains(monthStr)){
  424. int index = month.indexOf(monthStr);
  425. month_pv.setSelected(index);
  426. }else{
  427. month_pv.setSelected(0);
  428. }
  429. if(day.contains(dayStr)){
  430. int index = day.indexOf(dayStr);
  431. day_pv.setSelected(index);
  432. }else{
  433. day_pv.setSelected(0);
  434. }
  435. hour_pv.setSelected(0);
  436. minute_pv.setSelected(0);
  437. excuteScroll();
  438. }
  439. private void excuteScroll() {
  440. year_pv.setCanScroll(year.size() > 1);
  441. month_pv.setCanScroll(month.size() > 1);
  442. day_pv.setCanScroll(day.size() > 1);
  443. hour_pv.setCanScroll(hour.size() > 1 && (scrollUnits & SCROLLTYPE.HOUR.value) == SCROLLTYPE.HOUR.value);
  444. minute_pv.setCanScroll(minute.size() > 1 && (scrollUnits & SCROLLTYPE.MINUTE.value) == SCROLLTYPE.MINUTE.value);
  445. }
  446. /**
  447. * 处理月份变化的数据
  448. */
  449. private void monthChange() {
  450. month.clear();
  451. int selectedYear = selectedCalender.get(Calendar.YEAR);
  452. if (selectedYear == startYear) {//选择的年份是开始年份,则从开始月份重置monthList
  453. for (int i = startMonth; i <= MAXMONTH; i++) {
  454. month.add(fomatTimeUnit(i));
  455. }
  456. } else if (selectedYear == endYear) {//选择的年份是结束年份,则从开始月份重置monthList
  457. for (int i = 1; i <= endMonth; i++) {
  458. month.add(fomatTimeUnit(i));
  459. }
  460. } else {//既不是开始年也不是结束年,就按12个月处理
  461. for (int i = 1; i <= MAXMONTH; i++) {
  462. month.add(fomatTimeUnit(i));
  463. }
  464. }
  465. selectedCalender.set(Calendar.MONTH, Integer.parseInt(month.get(0)) - 1);//设置selectedCalender的月份,因为Calendar.MONTH的特殊之处,不能直接使用Integer.parseInt(month.get(0)),要-1
  466. month_pv.setData(month);
  467. month_pv.setSelected(0);
  468. excuteAnimator(ANIMATORDELAY, month_pv);
  469. month_pv.postDelayed(new Runnable() {
  470. @Override
  471. public void run() {
  472. dayChange();//月份变化后再处理日变化
  473. }
  474. }, CHANGEDELAY);
  475. }
  476. /**
  477. * 处理日变化的数据
  478. */
  479. private void dayChange() {
  480. day.clear();
  481. int selectedYear = selectedCalender.get(Calendar.YEAR);
  482. int selectedMonth = selectedCalender.get(Calendar.MONTH) + 1;
  483. if (selectedYear == startYear && selectedMonth == startMonth) {//选择的年份是年份\月份都是开始时间,则要从开始日期的天数重置dayList
  484. for (int i = startDay; i <= selectedCalender.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
  485. day.add(fomatTimeUnit(i));
  486. }
  487. } else if (selectedYear == endYear && selectedMonth == endMonth) {//选择的年份是年份\月份都是结束时间,则要从结束日期的天数重置dayList
  488. for (int i = 1; i <= endDay; i++) {
  489. day.add(fomatTimeUnit(i));
  490. }
  491. } else {//既不是开始日也不是结束日,就按正常天数处理
  492. for (int i = 1; i <= selectedCalender.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
  493. day.add(fomatTimeUnit(i));
  494. }
  495. }
  496. selectedCalender.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day.get(0)));
  497. day_pv.setData(day);
  498. day_pv.setSelected(0);
  499. excuteAnimator(ANIMATORDELAY, day_pv);
  500. day_pv.postDelayed(new Runnable() {
  501. @Override
  502. public void run() {
  503. hourChange();
  504. }
  505. }, CHANGEDELAY);
  506. }
  507. /**
  508. * 处理小时变化的数据
  509. */
  510. private void hourChange() {
  511. if ((scrollUnits & SCROLLTYPE.HOUR.value) == SCROLLTYPE.HOUR.value) {
  512. hour.clear();
  513. int selectedYear = selectedCalender.get(Calendar.YEAR);
  514. int selectedMonth = selectedCalender.get(Calendar.MONTH) + 1;
  515. int selectedDay = selectedCalender.get(Calendar.DAY_OF_MONTH);
  516. if (selectedYear == startYear && selectedMonth == startMonth && selectedDay == startDay) {//选择的年份是年份\月份\日都是开始时间,则要从开始日期小时数-最晚小时数重置hourList
  517. for (int i = startHour; i <= MAXHOUR; i++) {//结束时间小时数
  518. hour.add(fomatTimeUnit(i));
  519. }
  520. } else if (selectedYear == endYear && selectedMonth == endMonth && selectedDay == endDay) {//选择的年份是年份\月份\日都是结束时间,则要从最早小时数-结束日期小时数重置hourList
  521. for (int i = MINHOUR; i <= endHour; i++) {//开始时间小时数
  522. hour.add(fomatTimeUnit(i));
  523. }
  524. } else {
  525. for (int i = MINHOUR; i <= MAXHOUR; i++) {//既不是开始时也不是结束时,就按最小MINHOUR最大MAXHOUR
  526. hour.add(fomatTimeUnit(i));
  527. }
  528. }
  529. selectedCalender.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour.get(0)));
  530. hour_pv.setData(hour);
  531. hour_pv.setSelected(0);
  532. excuteAnimator(ANIMATORDELAY, hour_pv);
  533. }
  534. hour_pv.postDelayed(new Runnable() {
  535. @Override
  536. public void run() {
  537. minuteChange();
  538. }
  539. }, CHANGEDELAY);
  540. }
  541. /**
  542. * 处理分钟变化的数据
  543. */
  544. private void minuteChange() {
  545. if ((scrollUnits & SCROLLTYPE.MINUTE.value) == SCROLLTYPE.MINUTE.value) {
  546. minute.clear();
  547. int selectedYear = selectedCalender.get(Calendar.YEAR);
  548. int selectedMonth = selectedCalender.get(Calendar.MONTH) + 1;
  549. int selectedDay = selectedCalender.get(Calendar.DAY_OF_MONTH);
  550. int selectedHour = selectedCalender.get(Calendar.HOUR_OF_DAY);
  551. //选择的年份是年份\月份\日\时都是开始时间,则要从开始日期分钟数-最晚分钟数重置minuteList
  552. if (selectedYear == startYear && selectedMonth == startMonth && selectedDay == startDay && selectedHour == startHour) {
  553. for (int i = startMininute; i <= MAXMINUTE; i++) {
  554. minute.add(fomatTimeUnit(i));
  555. }
  556. //选择的年份是年份\月份\日\时都是结束时间,则要从最早分钟数-结束日期分钟数重置minuteList
  557. } else if (selectedYear == endYear && selectedMonth == endMonth && selectedDay == endDay && selectedHour == endHour) {
  558. for (int i = MINMINUTE; i <= endMininute; i++) {
  559. minute.add(fomatTimeUnit(i));
  560. }
  561. //选择的小时数等于开始时间的小时数,则要从开始分钟数-最晚分钟数重置minuteList
  562. } else if (selectedHour == hour_workStart) {
  563. for (int i = minute_workStart; i <= MAXMINUTE; i++) {
  564. minute.add(fomatTimeUnit(i));
  565. }
  566. //选择的小时数等于结束时间的小时数,则要从开始分钟数-最晚分钟数重置minuteList
  567. } else if (selectedHour == hour_workEnd) {
  568. for (int i = MINMINUTE; i <= minute_workEnd; i++) {
  569. minute.add(fomatTimeUnit(i));
  570. }
  571. } else {
  572. //没有限制,则要从最早分钟数-最晚分钟数重置minuteList
  573. for (int i = MINMINUTE; i <= MAXMINUTE; i++) {
  574. minute.add(fomatTimeUnit(i));
  575. }
  576. }
  577. selectedCalender.set(Calendar.MINUTE, Integer.parseInt(minute.get(0)));
  578. minute_pv.setData(minute);
  579. minute_pv.setSelected(0);
  580. excuteAnimator(ANIMATORDELAY, minute_pv);
  581. }
  582. excuteScroll();
  583. }
  584. /**
  585. * 给PickerView 设置渐变、缩放动画(非必要)
  586. * @param ANIMATORDELAY
  587. * @param view
  588. */
  589. private void excuteAnimator(long ANIMATORDELAY, View view) {
  590. PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
  591. 0f, 1f);
  592. PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
  593. 1.3f, 1f);
  594. PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
  595. 1.3f, 1f);
  596. ObjectAnimator.ofPropertyValuesHolder(view,pvhX, pvhY, pvhZ).setDuration(ANIMATORDELAY).start();
  597. }
  598. /**
  599. * 设置右上角文案
  600. * @param str
  601. */
  602. public void setNextBtTip(String str) {
  603. tv_select.setText(str);
  604. }
  605. /**
  606. *设置中间文案
  607. * @param str
  608. */
  609. public void setTitle(String str) {
  610. tv_title.setText(str);
  611. }
  612. /**
  613. * ?????
  614. * @param scrolltypes
  615. * @return
  616. */
  617. public int disScrollUnit(SCROLLTYPE... scrolltypes) {
  618. if (scrolltypes == null || scrolltypes.length == 0)
  619. scrollUnits = SCROLLTYPE.HOUR.value + SCROLLTYPE.MINUTE.value;//3
  620. for (SCROLLTYPE scrolltype : scrolltypes) {
  621. scrollUnits ^= scrolltype.value;//scrollUnits基础上-scrolltype.value
  622. }
  623. return scrollUnits;
  624. }
  625. public void setMode(MODE mode) {
  626. switch (mode.value) {
  627. case 1://只显示年月日的控件
  628. disScrollUnit(SCROLLTYPE.HOUR, SCROLLTYPE.MINUTE);
  629. hour_pv.setVisibility(View.GONE);
  630. minute_pv.setVisibility(View.GONE);
  631. hour_text.setVisibility(View.GONE);
  632. minute_text.setVisibility(View.GONE);
  633. break;
  634. case 2://显示年月日时分的控件
  635. disScrollUnit();
  636. hour_pv.setVisibility(View.VISIBLE);
  637. minute_pv.setVisibility(View.VISIBLE);
  638. hour_text.setVisibility(View.VISIBLE);
  639. minute_text.setVisibility(View.VISIBLE);
  640. break;
  641. }
  642. }
  643. public void setIsLoop(boolean isLoop) {
  644. this.year_pv.setIsLoop(isLoop);
  645. this.month_pv.setIsLoop(isLoop);
  646. this.day_pv.setIsLoop(isLoop);
  647. this.hour_pv.setIsLoop(isLoop);
  648. this.minute_pv.setIsLoop(isLoop);
  649. }
  650. }
R.style.time_dialog:
  1. <style name="time_dialog" parent="android:style/Theme.Dialog">
  2. <item name="android:windowFrame">@null</item>
  3. <item name="android:windowNoTitle">true</item>
  4. <item name="android:windowIsFloating">true</item>
  5. <item name="android:windowContentOverlay">@null</item>
  6. <item name="android:windowBackground">@color/white</item>
  7. </style>
R.layout.dlg_selector:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical">
  7. <LinearLayout
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:orientation="vertical">
  11. <RelativeLayout
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:background="#ffffff"
  15. android:padding="10dp">
  16. <TextView
  17. android:id="@+id/tv_cancle"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:layout_centerVertical="true"
  21. android:padding="10dp"
  22. android:text="@string/cancel"
  23. android:textColor="@color/main_color"
  24. android:textSize="16sp" />
  25. <TextView
  26. android:id="@+id/tv_title"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:layout_centerInParent="true"
  30. android:text="@string/chosetime"
  31. android:textColor="@color/main_color"
  32. android:textSize="20sp" />
  33. <TextView
  34. android:id="@+id/tv_select"
  35. android:layout_width="wrap_content"
  36. android:layout_height="wrap_content"
  37. android:layout_alignParentRight="true"
  38. android:layout_centerVertical="true"
  39. android:padding="10dp"
  40. android:text="@string/chose"
  41. android:textColor="@color/main_color"
  42. android:textSize="16sp" />
  43. </RelativeLayout>
  44. <View
  45. android:layout_width="fill_parent"
  46. android:layout_height="0.5dp"
  47. android:background="#11112233" />
  48. <RelativeLayout
  49. android:layout_width="fill_parent"
  50. android:layout_height="wrap_content">
  51. <LinearLayout
  52. android:layout_width="fill_parent"
  53. android:layout_height="wrap_content"
  54. android:layout_marginBottom="5dp"
  55. android:background="#ffffff"
  56. android:orientation="horizontal"
  57. android:paddingLeft="20dp"
  58. android:paddingTop="15dp"
  59. android:paddingRight="20dp"
  60. android:paddingBottom="15dp">
  61. <com.sange.cashfloater.cfwidget.timeselector.view.PickerView
  62. android:id="@+id/year_pv"
  63. android:layout_width="0dp"
  64. android:layout_height="160dp"
  65. android:layout_weight="3" />
  66. <TextView
  67. android:layout_width="0dp"
  68. android:layout_height="match_parent"
  69. android:layout_weight="1"
  70. android:gravity="center"
  71. android:text="年"
  72. android:textColor="#333333"
  73. android:textSize="18sp" />
  74. <com.sange.cashfloater.cfwidget.timeselector.view.PickerView
  75. android:id="@+id/month_pv"
  76. android:layout_width="0dp"
  77. android:layout_height="160dp"
  78. android:layout_weight="2"
  79. app:isLoop="false" />
  80. <TextView
  81. android:text="月"
  82. android:layout_width="0dp"
  83. android:layout_height="match_parent"
  84. android:layout_weight="1"
  85. android:gravity="center"
  86. android:textColor="#333333"
  87. android:textSize="18sp" />
  88. <com.sange.cashfloater.cfwidget.timeselector.view.PickerView
  89. android:id="@+id/day_pv"
  90. android:layout_width="0dp"
  91. android:layout_height="160dp"
  92. android:layout_weight="2" />
  93. <TextView
  94. android:text="日"
  95. android:layout_width="0dp"
  96. android:layout_height="match_parent"
  97. android:layout_weight="1"
  98. android:gravity="center"
  99. android:textColor="#333333"
  100. android:textSize="18sp" />
  101. <com.sange.cashfloater.cfwidget.timeselector.view.PickerView
  102. android:id="@+id/hour_pv"
  103. android:layout_width="0dp"
  104. android:layout_height="160dp"
  105. android:layout_weight="2" />
  106. <TextView
  107. android:id="@+id/hour_text"
  108. android:layout_width="0dp"
  109. android:layout_height="match_parent"
  110. android:layout_weight="1"
  111. android:gravity="center"
  112. android:text="时"
  113. android:textColor="#333333"
  114. android:textSize="18sp" />
  115. <com.sange.cashfloater.cfwidget.timeselector.view.PickerView
  116. android:id="@+id/minute_pv"
  117. android:layout_width="0dp"
  118. android:layout_height="160dp"
  119. android:layout_weight="2" />
  120. <TextView
  121. android:id="@+id/minute_text"
  122. android:layout_width="0dp"
  123. android:layout_height="match_parent"
  124. android:layout_weight="1"
  125. android:text="分"
  126. android:gravity="center"
  127. android:textColor="#333333"
  128. android:textSize="18sp" />
  129. </LinearLayout>
  130. </RelativeLayout>
  131. </LinearLayout>
  132. </LinearLayout>

相关工具类:
ScreenUtil:

  1. public class ScreenUtil {
  2. public static int height;
  3. public static int width;
  4. private Context context;
  5. private static ScreenUtil instance;
  6. public static ScreenUtil getInstance(Context context) {
  7. if (instance == null) {
  8. instance = new ScreenUtil(context);
  9. }
  10. return instance;
  11. }
  12. private ScreenUtil(Context context) {
  13. this.context = context;
  14. WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  15. DisplayMetrics dm = new DisplayMetrics();
  16. manager.getDefaultDisplay().getMetrics(dm);
  17. width = dm.widthPixels;
  18. height = dm.heightPixels;
  19. }
  20. public int getScreenWidth() {
  21. return width;
  22. }
  23. }
DateUtil:

  1. public class DateUtil {
  2. public static Date parse(String strDate, String pattern) {
  3. if (TextUtil.isEmpty(strDate)) {
  4. return null;
  5. }
  6. try {
  7. SimpleDateFormat df = new SimpleDateFormat(pattern);
  8. return df.parse(strDate);
  9. } catch (Exception e) {
  10. e.printStackTrace();
  11. return null;
  12. }
  13. }
  14. public static String format(Date date, String pattern) {
  15. String returnValue = "";
  16. if (date != null) {
  17. SimpleDateFormat df = new SimpleDateFormat(pattern);
  18. returnValue = df.format(date);
  19. }
  20. return (returnValue);
  21. }
  22. }
TextUtil:

  1. public class TextUtil {
  2. public static boolean isEmpty(String str) {
  3. if (str == null || "".equals(str) || "null".equalsIgnoreCase(str)) {
  4. return true;
  5. }
  6. for (int i = 0; i < str.length(); i++) {
  7. char c = str.charAt(i);
  8. if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
  9. return false;
  10. }
  11. }
  12. return true;
  13. }
  14. }

over~

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

闽ICP备14008679号