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

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

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外,上下各需要显示的备选项数目

*/

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;

// 画背景图中单独的画笔

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的正负号,以实现上滚或下滚

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的计算才能达到居中,y值是text中心坐标

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的位置由当前位置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文件中设置mWheelView.setWheelStyle(WheelStyle.STYLE_YEAR);就可以显示WheelStyle类中设置的类型了。这个类中的样式种类读者可以根据自己的需要自行添加。

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

以上是 iOS自定义时间滚动选择控件 的全部内容, 来源链接: utcz.com/z/332751.html

回到顶部