网上想找个类似的控件,好像不是那么好找。找到一个是继承view实现的,看的眼花缭乱,然后自己就继承listview实现一下。
一共实现了DatePicker, TimePicker, DateTimePcker三个控件,其实就是组装了一下。
先上效果图
先说下思路:
1.先画出可以上下滑动并可以自动归位的滑动条目WheelView,上图就是由五个这样的条目组成。
2.组装视图, 利用RelativieLayout定位,把放置上下两个线条级年月日等文字。
3. 实现自定义组合控件的DateTimePikder。
遇到的问题
1. listview的颜色控制
2. listview平滑,smoothScrollBy post到主线程后才会生效。
3. 连接滑动线程阻塞
4. datePicker日的变换比较麻烦
WheelView主要分三部分
1. onMeasure中设置高度为5个item的高度
2. 设置onScrollChangeListener控件滑动
3. onScroll方法中控制item的颜色变化
4. onScrollStateChanged方法中实现滑动松开后的平滑归位
下面是WheelView的主要代码,后边会给 同完整代码
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() > 0) { //设置listview高度为五个item
itemHeight = getChildAt(0).getMeasuredHeight();
setMeasuredDimension(widthMeasureSpec, (itemHeight + getDividerHeight()) * MAX_ITEM_COUNT);
setDividerHeight(0);
if (isFirst) { //只在第一次设值
currentValue = Integer.parseInt(((TextView) getChildAt(2)).getText().toString());
isFirst = false;
}
}
}
/**
* 自动滑动到顶部位置
*/
public void doScroll() {
final int offsetY = getChildAt(0).getBottom();
final int distance;
if (offsetY < itemHeight / 2) { //向上
distance = offsetY;
currentValue = Integer.parseInt(((TextView) getChildAt(3)).getText().toString()); //上滑时取下边一个
} else {
distance = offsetY - itemHeight;
currentValue = Integer.parseInt(((TextView) getChildAt(2)).getText().toString());
}
postDelayed(new Runnable() { //这里要post到主线程度才会有平滑的效果, delay 100ms解决连续滚动时的阻塞
@Override
public void run() {
if (isIdle && distance != 0) {
smoothScrollBy(distance, 400 * Math.abs(distance) / itemHeight); //下滑时取下边一个,可能是滑动方法是异步的
}
}
}, 100);
if (onItemChangedListener != null) {
onItemChangedListener.onItemSelected(currentValue);
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
isIdle = true;
doScroll();
} else {
isIdle = false;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (visibleItemCount > 0) {
int offsetY = getChildAt(0).getBottom() + getDividerHeight();
if (offsetY > itemHeight / 2) {// 控制滑过一半改变颜色
((TextView) getChildAt(2)).setTextColor(0xffE75A3E);
((TextView) getChildAt(1)).setTextColor(0xff989898);
((TextView) getChildAt(3)).setTextColor(0xff989898);
((TextView) getChildAt(0)).setTextColor(0xffCBCBCB);
((TextView) getChildAt(4)).setTextColor(0xffCBCBCB);
if (getChildCount() > 5)
((TextView) getChildAt(5)).setTextColor(0xffCBCBCB);
} else {
((TextView) getChildAt(3)).setTextColor(0xffE75A3E);
((TextView) getChildAt(2)).setTextColor(0xff989898);
((TextView) getChildAt(4)).setTextColor(0xff989898);
((TextView) getChildAt(1)).setTextColor(0xffCBCBCB);
((TextView) getChildAt(0)).setTextColor(0xffCBCBCB);
if (getChildCount() > 5)
((TextView) getChildAt(5)).setTextColor(0xffCBCBCB);
}
}
}
这里只说下TimePicker,这个组装起来最简单,其它的读者自己看代码。
主要就是在构造方法中初始个控件布局和并监听条目的变化
private void initView(final Context context) {
LayoutInflater.from(context).inflate(R.layout.my_timepicker_layout, this,
true);
mCalendar = Calendar.getInstance();
int hour = mCalendar.get(Calendar.HOUR_OF_DAY);
int minute = mCalendar.get(Calendar.MINUTE);
txtTime = (TextView) findViewById(R.id.txtTime);
txtTime.setText(formatDate(hour, minute));
wvHour = (WheelView) findViewById(R.id.wvHour);
WheelViewAdapter adapterHour = new WheelViewAdapter(0, 23, context);
wvHour.setAdapter(adapterHour);
Log.d("dd", ""+ hour);
wvHour.setCurrentItem(hour + 24 * 5); //设置到中间位置实现循环滑动
wvMinute = (WheelView) findViewById(R.id.wvMinute);
WheelViewAdapter adapterMinute = new WheelViewAdapter(0, 60, context);
wvMinute.setAdapter(adapterMinute);
wvMinute.setCurrentItem(minute + 12 * 5); //设置到中间位置实现循环滑动
wvHour.setOnItemChangedListener(new WheelView.OnItemChangedListener() {
@Override
public void onItemSelected(int value) {
//月份是从0开始, 格式化时要减一
txtTime.setText(formatDate(value, wvMinute.getCurrentValue()));
if (onTimeSetListener != null) {
onTimeSetListener.onTimeSet(value, wvMinute.getCurrentValue());
}
}
});
wvMinute.setOnItemChangedListener(new WheelView.OnItemChangedListener() {
@Override
public void onItemSelected(int value) {
txtTime.setText(formatDate(wvHour.getCurrentValue(), value));
if (onTimeSetListener != null) {
onTimeSetListener.onTimeSet(wvHour.getCurrentValue(), value);
}
}
});
}
看看布局文件, 用RelativieLayout便于固定文字和线条,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:gravity="center"
android:padding="10dp"
android:text="10:30"
android:textColor="#626262"
android:textSize="18dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/txtTime"
android:orientation="horizontal">
<wei.jiang.datepicker.view.WheelView
android:id="@+id/wvHour"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1">
</wei.jiang.datepicker.view.WheelView>
<wei.jiang.datepicker.view.WheelView
android:id="@+id/wvMinute"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1">
</wei.jiang.datepicker.view.WheelView>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_below="@+id/txtTime"
android:layout_marginTop="70dp"
android:background="#E1E1E1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/txtTime"
android:layout_marginTop="76dp"
android:orientation="horizontal">
<TextView
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:paddingLeft="42dp"
android:text="时"
android:textColor="#E75A3E"
android:textSize="16dp" />
<TextView
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:paddingLeft="40dp"
android:text="分"
android:textColor="#E75A3E"
android:textSize="16dp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_below="@+id/txtTime"
android:layout_marginTop="105dp"
android:background="#E1E1E1" />
</RelativeLayout>
之前有不少bug,github更新了下,csdn传资源系统抽风。
github地址 https://github.com/jw1352/myDatetimePicker/
csdn下载地址:http://download.csdn.net/detail/u012325403/9381756