iOS自定義時間滾動選擇控件
本文實(shí)例為大家分享了iOS自定義時間滾動選擇控件的具體代碼,供大家參考,具體內(nèi)容如下
1.先上自定義的控件:
/**
* 滾輪選擇器
* author LH
* data 2016/8/20 17:26
*/
public class WheelView extends View {
public static final String TAG = "WheelView";
/**
* 自動回滾到中間的速度
*/
public static final float SPEED = 2;
/**
* 除選中item外,上下各需要顯示的備選項數(shù)目
*/
public static final int SHOW_SIZE = 1;
private Context context;
private List<String> itemList;
private int itemCount;
/**
* item高度
*/
private int itemHeight = 50;
/**
* 選中的位置,這個位置是mDataList的中心位置,一直不變
*/
private int currentItem;
private Paint selectPaint;
private Paint mPaint;
// 畫背景圖中單獨(dú)的畫筆
private Paint centerLinePaint;
private float centerY;
private float centerX;
private float mLastDownY;
/**
* 滑動的距離
*/
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ù)號,以實(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的計算才能達(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 畫布
* @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) {
// 往下滑超過離開距離
mMoveLen = mMoveLen - itemHeight;
currentItem--;
if (currentItem < 0) {
currentItem = itemCount - 1;
}
} else if (mMoveLen < -itemHeight / 2) {
// 往上滑超過離開距離
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.然后是時間選擇控件的樣式工具類
/**
* 時間選擇樣式
* 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" + "時", 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;
}
/**
* 計算閏月
*
* @param month
* @return
*/
private static boolean isLeapMonth(int month) {
return month == 1 || month == 3 || month == 5 || month == 7
|| month == 8 || month == 10 || month == 12;
}
/**
* 計算閏年
*
* @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類中設(shè)置的類型了。這個類中的樣式種類讀者可以根據(jù)自己的需要自行添加。
5.獲取當(dāng)前選擇的項也很簡單mWheelView.getCurrentItem();就能獲取到控件的當(dāng)前選擇的項。獲取到所在的項以后剩下的就是邏輯操作了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS整個APP實(shí)現(xiàn)灰色主題的示例代碼
這篇文章主要介紹了iOS整個APP實(shí)現(xiàn)灰色主題的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
IOS開發(fā)UIPasteboard類的粘貼板全面詳解
這篇文章主要為大家介紹了IOS開發(fā)UIPasteboard類的粘貼板全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
iOS使用自帶的UIViewController實(shí)現(xiàn)qq加號下拉菜單的功能(實(shí)例代碼)
這篇文章主要介紹了iOS使用自帶的UIViewController實(shí)現(xiàn)qq加號下拉菜單的功能(實(shí)例代碼),需要的朋友可以參考下2017-05-05
IOS中UITextView或UITextField字?jǐn)?shù)限制的實(shí)現(xiàn)
這篇文章主要介紹了IOS中UITextView或UITextField字?jǐn)?shù)限制的實(shí)現(xiàn)的相關(guān)資料,希望通過本文能幫助到大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10
iOS開發(fā)中常見的項目文件與MVC結(jié)構(gòu)優(yōu)化思路解析
這篇文章主要介紹了iOS開發(fā)中常見的項目文件與MVC結(jié)構(gòu)優(yōu)化思路解析,示例代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-12-12
iOS實(shí)現(xiàn)動態(tài)元素的引導(dǎo)圖效果
這篇文章給大家介紹了iOS實(shí)現(xiàn)動態(tài)元素的引導(dǎo)圖效果的步驟,文章給出了示例代碼介紹的很詳細(xì),有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-09-09

