溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

iOS中怎么自定義一個(gè)時(shí)間滾動(dòng)選擇控件

發(fā)布時(shí)間:2021-06-11 17:03:51 來(lái)源:億速云 閱讀:278 作者:Leah 欄目:移動(dòng)開(kāi)發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)iOS中怎么自定義一個(gè)時(shí)間滾動(dòng)選擇控件,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

1.先上自定義的控件:

public class WheelView extends View {
 
 public static final String TAG = "WheelView";
 
 /**
 * 自動(dòng)回滾到中間的速度
 */
 public static final float SPEED = 2;
 
 /**
 * 除選中item外,上下各需要顯示的備選項(xiàng)數(shù)目
 */
 public static final int SHOW_SIZE = 1;
 
 private Context context;
 
 private List<String> itemList;
 private int itemCount;
 
 /**
 * item高度
 */
 private int itemHeight = 50;
 
 /**
 * 選中的位置,這個(gè)位置是mDataList的中心位置,一直不變
 */
 private int currentItem;
 
 private Paint selectPaint;
 private Paint mPaint;
 // 畫(huà)背景圖中單獨(dú)的畫(huà)筆
 private Paint centerLinePaint;
 
 private float centerY;
 private float centerX;
 
 private float mLastDownY;
 /**
 * 滑動(dòng)的距離
 */
 private float mMoveLen = 0;
 private boolean isInit = false;
 private SelectListener mSelectListener;
 private Timer timer;
 private MyTimerTask mTask;
 
 Handler updateHandler = new Handler() {
 
 @Override
 public void handleMessage(Message msg) {
  if (Math.abs(mMoveLen) < SPEED) {
  // 如果偏移量少于最少偏移量
  mMoveLen = 0;
  if (null != timer) {
   timer.cancel();
   timer.purge();
   timer = null;
  }
  if (mTask != null) {
   mTask.cancel();
   mTask = null;
   performSelect();
  }
  } else {
  // 這里mMoveLen / Math.abs(mMoveLen)是為了保有mMoveLen的正負(fù)號(hào),以實(shí)現(xiàn)上滾或下滾
  mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED;
  }
  invalidate();
 }
 
 };
 
 public WheelView(Context context) {
 super(context);
 init(context);
 }
 
 public WheelView(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(context);
 }
 
 public void setOnSelectListener(SelectListener listener) {
 mSelectListener = listener;
 }
 
 public void setWheelStyle(int style) {
 itemList = WheelStyle.getItemList(context, style);
 if (itemList != null) {
  itemCount = itemList.size();
  resetCurrentSelect();
  invalidate();
 } else {
  Log.i(TAG, "item is null");
 }
 }
 
 public void setWheelItemList(List<String> itemList) {
 this.itemList = itemList;
 if (itemList != null) {
  itemCount = itemList.size();
  resetCurrentSelect();
 } else {
  Log.i(TAG, "item is null");
 }
 }
 
 private void resetCurrentSelect() {
 if (currentItem < 0) {
  currentItem = 0;
 }
 while (currentItem >= itemCount) {
  currentItem--;
 }
 if (currentItem >= 0 && currentItem < itemCount) {
  invalidate();
 } else {
  Log.i(TAG, "current item is invalid");
 }
 }
 
 public int getItemCount() {
 return itemCount;
 }
 /**
 * 選擇選中的item的index
 * author LH
 * data 2016/9/4 11:09
 */
 public void setCurrentItem(int selected) {
 currentItem = selected;
 resetCurrentSelect();
 }
 
 public int getCurrentItem() {
 return currentItem;
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 int mViewHeight = getMeasuredHeight();
 int mViewWidth = getMeasuredWidth();
 centerX = (float) (mViewWidth / 2.0);
 centerY = (float) (mViewHeight / 2.0);
 
 isInit = true;
 invalidate();
 }
 
 
 private void init(Context context) {
 this.context = context;
 
 timer = new Timer();
 itemList = new ArrayList<>();
 
 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 mPaint.setStyle(Style.FILL);
 mPaint.setTextAlign(Align.CENTER);
 mPaint.setColor(getResources().getColor(R.color.wheel_unselect_text));
 int size1 = (int) (SupportDisplay.getLayoutScale()*22+0.5);
 mPaint.setTextSize(size1);
 
 selectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 selectPaint.setStyle(Style.FILL);
 selectPaint.setTextAlign(Align.CENTER);
 selectPaint.setColor(getResources().getColor(R.color.color_1a1a1a));
 int size2 = (int) (SupportDisplay.getLayoutScale()*24+0.5);
 selectPaint.setTextSize(size2);
 
 centerLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 centerLinePaint.setStyle(Style.FILL);
 centerLinePaint.setTextAlign(Align.CENTER);
 centerLinePaint.setColor(getResources().getColor(R.color.wheel_unselect_text));
 
 // 繪制背景
 setBackground(null);
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 if (isInit) {
  drawData(canvas);
 }
 }
 
 private void drawData(Canvas canvas) {
 // 先繪制選中的text再往上往下繪制其余的text
 if (!itemList.isEmpty()) {
  // 繪制中間data
  drawCenterText(canvas);
  // 繪制上方data
  for (int i = 1; i < SHOW_SIZE + 1; i++) {
  drawOtherText(canvas, i, -1);
  }
  // 繪制下方data
  for (int i = 1; i < SHOW_SIZE + 1; i++) {
  drawOtherText(canvas, i, 1);
  }
 }
 }
 
 private void drawCenterText(Canvas canvas) {
 // text居中繪制,注意baseline的計(jì)算才能達(dá)到居中,y值是text中心坐標(biāo)
 float y = centerY + mMoveLen;
 FontMetricsInt fmi = selectPaint.getFontMetricsInt();
 float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
 canvas.drawText(itemList.get(currentItem), centerX, baseline, selectPaint);
 }
 
 /**
 * 繪制文本
 * author LH
 * data 2016/9/4 11:10
 * @param canvas 畫(huà)布
 * @param position 距離mCurrentSelected的差值
 * @param type 1表示向下繪制,-1表示向上繪制
 */
 private void drawOtherText(Canvas canvas, int position, int type) {
 int index = currentItem + type * position;
 if (index >= itemCount) {
  index = index - itemCount;
 }
 if (index < 0) {
  index = index + itemCount;
 }
 String text = itemList.get(index);
 
 int itemHeight = getHeight() / (SHOW_SIZE * 2 + 1);
 float d = itemHeight * position + type * mMoveLen;
 float y = centerY + type * d;
 
 FontMetricsInt fmi = mPaint.getFontMetricsInt();
 float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
 canvas.drawText(text, centerX, baseline, mPaint);
 }
 
 @Override
 public void setBackground(Drawable background) {
 background = new Drawable() {
  @Override
  public void draw(Canvas canvas) {
  itemHeight = getHeight() / (SHOW_SIZE * 2 + 1);
  int width = getWidth();
 
  canvas.drawLine(0, itemHeight, width, itemHeight, centerLinePaint);
  canvas.drawLine(0, itemHeight * 2, width, itemHeight * 2, centerLinePaint);
 
  centerLinePaint.setColor(getResources().getColor(R.color.wheel_bg));
  Rect topRect = new Rect(0, 0, width, itemHeight);
  canvas.drawRect(topRect, centerLinePaint);
  Rect bottomRect = new Rect(0, itemHeight * 2, width, itemHeight * 3);
  canvas.drawRect(bottomRect, centerLinePaint);
  }
 
  @Override
  public void setAlpha(int alpha) {
 
  }
 
  @Override
  public void setColorFilter(ColorFilter cf) {
 
  }
 
  @Override
  public int getOpacity() {
  return 0;
  }
 };
 super.setBackground(background);
 }
 
 @Override
 public boolean onTouchEvent(MotionEvent event) {
 switch (event.getActionMasked()) {
  case MotionEvent.ACTION_DOWN:
  doDown(event);
  break;
  case MotionEvent.ACTION_MOVE:
  doMove(event);
  break;
  case MotionEvent.ACTION_UP:
  doUp();
  break;
  default:
  break;
 }
 return true;
 }
 
 private void doDown(MotionEvent event) {
 if (mTask != null) {
  mTask.cancel();
  mTask = null;
 }
 mLastDownY = event.getY();
 }
 
 private void doMove(MotionEvent event) {
 
 mMoveLen += (event.getY() - mLastDownY);
 if (mMoveLen > itemHeight / 2) {
  // 往下滑超過(guò)離開(kāi)距離
  mMoveLen = mMoveLen - itemHeight;
  currentItem--;
  if (currentItem < 0) {
  currentItem = itemCount - 1;
  }
 } else if (mMoveLen < -itemHeight / 2) {
  // 往上滑超過(guò)離開(kāi)距離
  mMoveLen = mMoveLen + itemHeight;
  currentItem++;
  if (currentItem >= itemCount) {
  currentItem = 0;
  }
 }
 
 mLastDownY = event.getY();
 invalidate();
 }
 
 private void doUp() {
 // 抬起手后mCurrentSelected的位置由當(dāng)前位置move到中間選中位置
 if (Math.abs(mMoveLen) < 0.0001) {
  mMoveLen = 0;
  return;
 }
 if (mTask != null) {
  mTask.cancel();
  mTask = null;
 }
 if (null == timer) {
  timer = new Timer();
 }
 mTask = new MyTimerTask(updateHandler);
 timer.schedule(mTask, 0, 10);
 }
 
 class MyTimerTask extends TimerTask {
 Handler handler;
 
 public MyTimerTask(Handler handler) {
  this.handler = handler;
 }
 
 @Override
 public void run() {
  handler.sendMessage(handler.obtainMessage());
 }
 
 }
 
 private void performSelect() {
 if (mSelectListener != null) {
  mSelectListener.onSelect(currentItem, itemList.get(currentItem));
 } else {
  Log.i(TAG, "null listener");
 }
 }
 
 public interface SelectListener {
 void onSelect(int index, String text);
 }
 
}

2.然后是時(shí)間選擇控件的樣式工具類(lèi)

/**
 * 時(shí)間選擇樣式
 * author LH
 * data 2016/9/4 11:05
 */
public class WheelStyle {
 
 public static final int minYear = 1980;
 public static final int maxYear = 2020;
 
 /**
 * Wheel Style Hour
 */
 public static final int STYLE_HOUR = 1;
 /**
 * Wheel Style Minute
 */
 public static final int STYLE_MINUTE = 2;
 /**
 * Wheel Style Year
 */
 public static final int STYLE_YEAR = 3;
 /**
 * Wheel Style Month
 */
 public static final int STYLE_MONTH = 4;
 /**
 * Wheel Style Day
 */
 public static final int STYLE_DAY = 5;
 /**
 * Wheel Style Simple Day
 */
 public static final int STYLE_SIMPLE_DAY = 6;
 /**
 * Wheel Style Set Warn
 */
 public static final int STYLE_SET_WARN = 7;
 /**
 * Wheel Style Work Answer
 */
 public static final int STYLE_WORK_ANSWER = 8;
 
 private WheelStyle() {
 }
 
 public static List<String> getItemList(Context context, int Style) {
 if (Style == STYLE_HOUR) {
  return createHourString();
 } else if (Style == STYLE_MINUTE) {
  return createMinuteString();
 } else if (Style == STYLE_YEAR) {
  return createYearString();
 } else if (Style == STYLE_MONTH) {
  return createMonthString();
 } else if (Style == STYLE_DAY) {
  return createDayString();
 } else if (Style == STYLE_SIMPLE_DAY) {
  return createSimpleDayString();
 } else if (Style == STYLE_SET_WARN) {
  return createSetWarnTimeString();
 } else {
  throw new IllegalArgumentException("style is illegal");
 }
 }
 
 private static List<String> createHourString() {
 List<String> wheelString = new ArrayList<>();
 for (int i = 0; i < 24; i++) {
  wheelString.add(String.format("%02d" + "時(shí)", i));
 }
 return wheelString;
 }
 
 private static List<String> createMinuteString() {
 List<String> wheelString = new ArrayList<>();
 for (int i = 0; i < 60; i++) {
  wheelString.add(String.format("%02d" + "分", i));
 }
 return wheelString;
 }
 
 private static List<String> createYearString() {
 List<String> wheelString = new ArrayList<>();
 for (int i = minYear; i <= maxYear; i++) {
  wheelString.add(Integer.toString(i));
 }
 return wheelString;
 }
 
 private static List<String> createMonthString() {
 List<String> wheelString = new ArrayList<>();
 for (int i = 1; i <= 12; i++) {
  wheelString.add(String.format("%02d" + "月", i));
 }
 return wheelString;
 }
 
 private static List<String> createDayString() {
 List<String> wheelString = new ArrayList<>();
 for (int i = 1; i <= 31; i++) {
  wheelString.add(String.format("%02d" + "日", i));
 }
 return wheelString;
 }
 
 private static List<String> createSimpleDayString() {
 List<String> wheelString = new ArrayList<>();
 wheelString.add("一天后");
 wheelString.add("兩天后");
 wheelString.add("三天后");
 return wheelString;
 }
 
 private static List<String> createSetWarnTimeString() {
 List<String> wheelString = new ArrayList<>();
 wheelString.add("30分鐘");
 wheelString.add("60分鐘");
 wheelString.add("90分鐘");
 wheelString.add("120分鐘");
 return wheelString;
 }
 /**
 * 計(jì)算閏月
 *
 * @param month
 * @return
 */
 private static boolean isLeapMonth(int month) {
 return month == 1 || month == 3 || month == 5 || month == 7
  || month == 8 || month == 10 || month == 12;
 }
 
 /**
 * 計(jì)算閏年
 *
 * @param year
 * @return
 */
 private static boolean isLeapYear(int year) {
 return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
 }
}

3.使用的xml

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

4.在Java文件中設(shè)置mWheelView.setWheelStyle(WheelStyle.STYLE_YEAR);就可以顯示W(wǎng)heelStyle類(lèi)中設(shè)置的類(lèi)型了。這個(gè)類(lèi)中的樣式種類(lèi)讀者可以根據(jù)自己的需要自行添加。

5.獲取當(dāng)前選擇的項(xiàng)也很簡(jiǎn)單mWheelView.getCurrentItem();就能獲取到控件的當(dāng)前選擇的項(xiàng)。獲取到所在的項(xiàng)以后剩下的就是邏輯操作了。

關(guān)于iOS中怎么自定義一個(gè)時(shí)間滾動(dòng)選擇控件就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

ios
AI