網上想找個類似的控件,好像不是那麼好找。找到一個是繼承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