public class WheelView extendsScrollView {public static final String TAG = WheelView.class.getSimpleName();public static classOnWheelViewListener {public void onSelected(intselectedIndex, String item) {
}
}privateContext context;privateLinearLayout views;publicWheelView(Context context) {super(context);
init(context);
}publicWheelView(Context context, AttributeSet attrs) {super(context, attrs);
init(context);
}public WheelView(Context context, AttributeSet attrs, intdefStyle) {super(context, attrs, defStyle);
init(context);
}//String[] items;
Listitems;private ListgetItems() {returnitems;
}public void setItems(Listlist) {if (null ==items) {
items= new ArrayList();
}
items.clear();
items.addAll(list);//前面和後面補全
for (int i = 0; i < offset; i++) {
items.add(0, "");
items.add("");
}
initData();
}public static final int OFF_SET_DEFAULT = 1;int offset = OFF_SET_DEFAULT; //偏移量(需要在最前面和最後面補全)
public intgetOffset() {returnoffset;
}public void setOffset(intoffset) {this.offset =offset;
}int displayItemCount; //每頁顯示的數量
int selectedIndex = 1;private voidinit(Context context) {this.context =context;
Log.d(TAG,"parent: " + this.getParent());this.setVerticalScrollBarEnabled(false);
views= newLinearLayout(context);
views.setOrientation(LinearLayout.VERTICAL);this.addView(views);
scrollerTask= newRunnable() {public voidrun() {int newY =getScrollY();if (initialY - newY == 0) { //stopped
final int remainder = initialY %itemHeight;final int divided = initialY /itemHeight;if (remainder == 0) {
selectedIndex= divided +offset;
onSeletedCallBack();
}else{if (remainder > itemHeight / 2) {
WheelView.this.post(newRunnable() {
@Overridepublic voidrun() {
WheelView.this.smoothScrollTo(0, initialY - remainder +itemHeight);
selectedIndex= divided + offset + 1;
onSeletedCallBack();
}
});
}else{
WheelView.this.post(newRunnable() {
@Overridepublic voidrun() {
WheelView.this.smoothScrollTo(0, initialY -remainder);
selectedIndex= divided +offset;
onSeletedCallBack();
}
});
}
}
}else{
initialY=getScrollY();
WheelView.this.postDelayed(scrollerTask, newCheck);
}
}
};
}intinitialY;
Runnable scrollerTask;int newCheck = 50;public voidstartScrollerTask() {
initialY=getScrollY();this.postDelayed(scrollerTask, newCheck);
}private voidinitData() {
displayItemCount= offset * 2 + 1;for(String item : items) {
views.addView(createView(item));
}
refreshItemView(0);
}int itemHeight = 0;
privateTextView createView(String item) {
TextView tv= newTextView(context);
tv.setLayoutParams(newLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv.setSingleLine(true);//設定字型大小為20sp
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);//設定文字内容
tv.setText(item);//設定文字居中
tv.setGravity(Gravity.CENTER);//設定内邊距
int padding = dip2px(15);
tv.setPadding(padding, padding, padding, padding);if (0 ==itemHeight) {
itemHeight=getViewMeasuredHeight(tv);
Log.d(TAG,"itemHeight: " +itemHeight);
views.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight *displayItemCount));
LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams) this.getLayoutParams();this.setLayoutParams(new LinearLayout.LayoutParams(lp.width, itemHeight *displayItemCount));
}returntv;
}
@Overrideprotected void onScrollChanged(int l, int t, int oldl, intoldt) {super.onScrollChanged(l, t, oldl, oldt);
refreshItemView(t);if (t >oldt) {
Log.d(TAG,"向下滾動");
scrollDirection=SCROLL_DIRECTION_DOWN;
}else{
Log.d(TAG,"向上滾動");
scrollDirection=SCROLL_DIRECTION_UP;
}
}private void refreshItemView(inty) {int position = y / itemHeight +offset;int remainder = y %itemHeight;int divided = y /itemHeight;if (remainder == 0) {
position= divided +offset;
}else{if (remainder > itemHeight / 2) {
position= divided + offset + 1;
}
}int childSize =views.getChildCount();for (int i = 0; i < childSize; i++) {
TextView itemView=(TextView) views.getChildAt(i);if (null ==itemView) {return;
}if (position ==i) {
itemView.setTextColor(Color.parseColor("#0288ce"));
}else{
itemView.setTextColor(Color.parseColor("#bbbbbb"));
}
}
}
int[] selectedAreaBorder;private int[] obtainSelectedAreaBorder() {if (null ==selectedAreaBorder) {
selectedAreaBorder= new int[2];
selectedAreaBorder[0] = itemHeight *offset;
selectedAreaBorder[1] = itemHeight * (offset + 1);
}returnselectedAreaBorder;
}private int scrollDirection = -1;private static final int SCROLL_DIRECTION_UP = 0;private static final int SCROLL_DIRECTION_DOWN = 1;
Paint paint;intviewWidth;
@Overridepublic voidsetBackgroundDrawable(Drawable background) {if (viewWidth == 0) {
viewWidth=((Activity) context).getWindowManager().getDefaultDisplay().getWidth();
Log.d(TAG,"viewWidth: " +viewWidth);
}if (null ==paint) {
paint= newPaint();
paint.setColor(Color.parseColor("#83cde6"));
paint.setStrokeWidth(dip2px(1f));
}
background= newDrawable() {
@Overridepublic voiddraw(Canvas canvas) {
canvas.drawLine(viewWidth* 1 / 6, obtainSelectedAreaBorder()[0], viewWidth * 5 / 6, obtainSelectedAreaBorder()[0], paint);
canvas.drawLine(viewWidth* 1 / 6, obtainSelectedAreaBorder()[1], viewWidth * 5 / 6, obtainSelectedAreaBorder()[1], paint);
}
@Overridepublic void setAlpha(intalpha) {
}
@Overridepublic voidsetColorFilter(ColorFilter cf) {
}
@Overridepublic intgetOpacity() {return 0;
}
};super.setBackgroundDrawable(background);
}
@Overrideprotected void onSizeChanged(int w, int h, int oldw, intoldh) {super.onSizeChanged(w, h, oldw, oldh);
Log.d(TAG,"w: " + w + ", h: " + h + ", oldw: " + oldw + ", oldh: " +oldh);
viewWidth=w;
setBackgroundDrawable(null);
}
private voidonSeletedCallBack() {if (null !=onWheelViewListener) {
onWheelViewListener.onSelected(selectedIndex, items.get(selectedIndex));
}
}public void setSeletion(intposition) {final int p =position;
selectedIndex= p +offset;this.post(newRunnable() {
@Overridepublic voidrun() {
WheelView.this.smoothScrollTo(0, p *itemHeight);
}
});
}publicString getSeletedItem() {returnitems.get(selectedIndex);
}public intgetSeletedIndex() {return selectedIndex -offset;
}
@Overridepublic void fling(intvelocityY) {super.fling(velocityY / 3);
}
@Overridepublic booleanonTouchEvent(MotionEvent ev) {if (ev.getAction() ==MotionEvent.ACTION_UP) {
startScrollerTask();
}return super.onTouchEvent(ev);
}privateOnWheelViewListener onWheelViewListener;publicOnWheelViewListener getOnWheelViewListener() {returnonWheelViewListener;
}public voidsetOnWheelViewListener(OnWheelViewListener onWheelViewListener) {this.onWheelViewListener =onWheelViewListener;
}private int dip2px(floatdpValue) {final float scale =context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);
}private intgetViewMeasuredHeight(View view) {int width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
view.measure(width, expandSpec);returnview.getMeasuredHeight();
}
}