android 时间选择器

最近项目里要做个时间选择器,网上看了很多demo,自定义view学习很久了,自己打算做一个。.废话不多说,先了解下大概思路吧。首先要知道界面可滑动(这不废话吗),滑动到最大距离和最小距离自动弹回,滑动的总距离对item取余得到距离如果大于二分之一item则继续滑动剩余的长度,否则回弹到原来的位置;主要就是利用 Scroller和scrollby来是界面滑动,剩下就是一些距离计算和逻辑处理,看代码吧;有问题邮件给我965949332@qq.com
package com.calazova.club.guangzhu.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Scroller;

import com.calazova.club.guangzhu.R;

import java.util.ArrayList;
import java.util.List;

@SuppressLint("DrawAllocation")
public class WheelView extends View {

   private Scroller scroller;
  
   private List<String> dataListItems = new ArrayList<String>();
   private GestureDetector gestureDetector;
   private TypedArray obtainStyle;
   private float textsizeFefValue = 30;
   private float spacingmult = 15.0f;//调整这个大小可调整界面的高度
   private float spacingadd = 2.0f;
   private int visibleItemNumber = 3;// 显示的个数从而决定view的高度
   private int viewWidth = 0;// view宽度
   private int touchSlop;
   private int flingVelocity;
   private float pulloff = 1.3f;// 阻尼系数
   private int fontHeight;// 字体高度
   private Paint textPaintItems;
   private Paint textPaintValues;
   private int currtPos;// 当前的item位置
   private StringBuffer sb;
   private Context mContext;
   private Rect rect;

   public WheelView(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
      init(context, attrs);
   }

   public WheelView(Context context, AttributeSet attrs) {
      super(context, attrs);
      init(context, attrs);
   }

   public WheelView(Context context) {
      super(context);
   }

   public void init(Context context, AttributeSet attrs) {
      mContext = context;
      scroller = new Scroller(context);
      gestureDetector = new GestureDetector(context, gestureListener);
      gestureDetector.setIsLongpressEnabled(false);
      obtainStyle = context.obtainStyledAttributes(attrs,
            R.styleable.wheelview);
      textsizeFefValue = obtainStyle.getDimension(
            R.styleable.wheelview_textsize, textsizeFefValue);
      obtainStyle.recycle();
      getViewTreeObserver().addOnGlobalLayoutListener(
            new OnGlobalLayoutListener() {
               @Override
               public void onGlobalLayout() {
                  viewWidth = getWidth();
                  getViewTreeObserver()
                        .removeGlobalOnLayoutListener(this);
               }
            });
      ViewConfiguration config = ViewConfiguration.get(context);
      touchSlop = config.getScaledTouchSlop();
      flingVelocity = config.getScaledMinimumFlingVelocity();

      textPaintItems = new Paint();
      textPaintItems.setColor(Color.parseColor("#ffffff"));
      textPaintItems.setStyle(Style.FILL);
      textPaintItems.setTextSize(textsizeFefValue);

      textPaintValues = new TextPaint();
      textPaintValues.setColor(Color.parseColor("#76b347"));
      textPaintValues.setStyle(Style.FILL);
      textPaintValues.setTextSize(textsizeFefValue*1.3f);
      fontHeight = getFontHeight(textsizeFefValue, textPaintItems);
      sb = new StringBuffer();
      rect = new Rect();
   }

   @Override
   protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      //drawCenterRect(canvas);
      if(dataListItems.size()>0){
//       String message = sb.toString();
//       staticLayoutValue = new StaticLayout(message, textPaint, canvas.getWidth(),
//             Alignment.ALIGN_CENTER, spacingmult, spacingadd, false);
//       staticLayoutValue.draw(canvas);
//       canvas.restore();
         for (int i = 0; i < dataListItems.size(); i++) {
            FontMetrics fontMetrics = textPaintItems.getFontMetrics();
            float fontTotalHeight = fontMetrics.bottom - fontMetrics.top;
            float offY = fontTotalHeight / 2 - fontMetrics.bottom;
            //float newY = baseY + offY;
            int scrollDistance = (int) ((i+1) *(spacingmult) + fontHeight*(2*i+1)/2+offY);
            if(i == currtPos){
               textPaintValues.getTextBounds(dataListItems.get(currtPos), 0, 2, rect);
               int fontWidht = rect.width();
               canvas.drawText(dataListItems.get(currtPos), getMeasuredWidth()/2-fontWidht/2, scrollDistance, textPaintValues);
            }else{
               textPaintItems.getTextBounds(dataListItems.get(i), 0, 2, rect);
               int fontWidht = rect.width();
               canvas.drawText(dataListItems.get(i), getMeasuredWidth()/2-fontWidht/2, scrollDistance, textPaintItems);
            }
         }
      }


   }
   private String slideTag = "";
   private boolean isTouchFlag = false;
   private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
      public boolean onDown(MotionEvent e) {
         // isStopScroll = true;
         return true;
      };

      public boolean onScroll(MotionEvent e1, MotionEvent e2,
                        float distanceX, float distanceY) {
         float y = e2.getY() - e1.getY();
         isStopScroll=true;
         if (y > 0) {
            slideTag = "down";
            scroll(distanceY);
         } else if (y < 0) {
            slideTag = "up";
            scroll(distanceY);
         }
         return true;
      };

      public boolean onFling(MotionEvent e1,
                        MotionEvent e2, float velocityX, float velocityY) {
         return false;
      };
   };
   private float totalDistance;// 可滑动的距离
   private int scrollingOffset = 0;
   private int areaDetal;// 每次滑动的差值
   private boolean flag =false;

   public void scroll(float scrollDistance) {
      scrollingOffset = (int) (scrollDistance / pulloff);
      scroller.startScroll(0, lastScrollY, 0, scrollingOffset - lastScrollY);
      invalidate();
   }

   private int lastScrollY = 0;
   private int myLastScrollY = 0;

   @Override
   public void computeScroll() {
      super.computeScroll();
      if (scroller.computeScrollOffset()) {
         if(isStopScroll){
            isStopScroll=false;
            myLastScrollY = scroller.getFinalY();
            scrollBy(0, scroller.getFinalY());
            lastScrollY = getScrollY();
            System.out.println("lastScrollY:"+lastScrollY);
            currtPos = (int)(lastScrollY/(fontHeight+spacingmult)+1);
            System.out.println("currtPos:"+currtPos);
            finishScroll(selectFlag);
            postInvalidate();
         }
      }
   }
   private float startY = 0;
   @Override
   public boolean onTouchEvent(MotionEvent event) {
      if (event.getAction() == MotionEvent.ACTION_UP) {
         isStopScroll = true;
         jScroll();
         //this.getParent().requestDisallowInterceptTouchEvent(false);
         return false;
      }else {
         this.getParent().requestDisallowInterceptTouchEvent(true);
         gestureDetector.onTouchEvent(event);
      }
      return true;
   };

   private boolean isStopScroll = false;
   private int itemsHeight;
   //这个方法是最主要的
   public void jScroll() {
      int myHeight = (int)(fontHeight+spacingmult);
      int halfItemsHeight = myHeight/2;
      int areaHeight = lastScrollY%myHeight;// 没有超过一个身位的高度
      int scrollHeight=0;// 需要滚动的高度
      int offet = 0;//
      if (Math.abs(areaHeight) >= halfItemsHeight) {// 多移动scrollHeight高度
         scrollHeight = myHeight - Math.abs(areaHeight);
      } else {
         scrollHeight = Math.abs(areaHeight);
      }
      if(Math.abs(areaHeight) >= halfItemsHeight){
         offet =scrollHeight;
      }else{
         offet = -scrollHeight;
      }
      if(lastScrollY<=-myHeight){
         currtPos = 0;
         scroller.startScroll(0, 0, 0, -lastScrollY-myHeight);
      }else if (lastScrollY>=totalDistance){
         currtPos = dataListItems.size();
         scroller.startScroll(0, 0, 0, (int)(-lastScrollY+totalDistance));
      }else if(lastScrollY<=0&&lastScrollY>=-myHeight){
         if(lastScrollY >= -halfItemsHeight){//一半的高度
            scroller.startScroll(0, 0, 0, -lastScrollY);
         }else{
            scroller.startScroll(0, 0, 0, -lastScrollY-myHeight);
         }
      }else{
         scroller.startScroll(0, 0, 0, offet);
      }
      invalidate();
   }

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      int modeW = MeasureSpec.getMode(widthMeasureSpec);
      int sizeW = MeasureSpec.getSize(widthMeasureSpec);
      if (modeW == MeasureSpec.EXACTLY) {
         viewWidth = sizeW;
      } else {
         int myWidh = getPaddingLeft() + getPaddingRight() + viewWidth;
         if (modeW == MeasureSpec.AT_MOST) {
            viewWidth = Math.min(myWidh, modeW);
         } else {
            viewWidth = myWidh;
         }
      }
      float measuredHeight = (visibleItemNumber) * fontHeight
            + (visibleItemNumber+1) * spacingmult;
      itemsHeight = (int) (measuredHeight/3);
      setMeasuredDimension(viewWidth, (int) measuredHeight);
   }


   // 获取字体高度
   public int getFontHeight(float fontSize, Paint paint) {
      paint.setTextSize(fontSize);
      FontMetrics fm = paint.getFontMetrics();
      return (int) Math.ceil(fm.descent - fm.ascent);
   }

   /**
    * 设置item的显示的位置
    *
    * @param listItems
    *            时间集合
    * @param items
    *            显示的时间从几点开始
    */
   private int scrollTotalDistance = 0;
   private int getDefautY = 0;
   private int bytesize=0;
   public void setItem(List<String> listItems,
                  String items) {
      dataListItems.addAll(listItems);
      for (int i = 0; i < dataListItems.size(); i++) {
         sb.append(dataListItems.get(i) + "\n");
      }
      isStopScroll = true;
      currtPos = listItems.indexOf(items);
      // 默认中间显示的是第二个位置
      int detalPos = currtPos-1;
      int scrollDistance = (int) (detalPos*(spacingmult+fontHeight));
      int mysize = listItems.size()-2;
      totalDistance = (int) (mysize*(spacingmult+fontHeight));
      scroller.startScroll(0, lastScrollY, 0, scrollDistance-lastScrollY);
      invalidate();
   }
   public int getCurrtPos(){
      return currtPos;
   }

   /**
    *
    */
   public void limitArea(String mydata ){
      int limitPos = dataListItems.indexOf(mydata);
      if(limitPos>=currtPos){
         setAreaItem(mydata);
      }

   }
   LimitAreaListener limitAreaListener;
   public interface LimitAreaListener{
      public void limitArea();
   }
   public void addLimitAreaListener(LimitAreaListener limitAreaListener){
      this.limitAreaListener = limitAreaListener;
   }
   public void finishScroll(boolean flag){
      if(!flag){
         try {
            if(limitAreaListener!=null){
               limitAreaListener.limitArea();
            }
         }catch (Exception e){
            e.printStackTrace();
         }
      }
      try {
         if(limitNoonistener!=null){
            limitNoonistener.limitNoon();
         }
      }catch (Exception e){
         e.printStackTrace();
      }
   }

   public void setAreaItem(String items){
      isStopScroll = true;
      int limitPos = dataListItems.indexOf(items);
      int detalPos = limitPos-currtPos;
      int scrollDistance = (int)((detalPos)*(spacingmult+fontHeight));
      if(scrollDistance == 0){
         isStopScroll = false;
      }
      scroller.startScroll(0, 0, 0, scrollDistance);
      invalidate();
   }
   boolean selectFlag = false;
   public void setSelectFlag(boolean selectFlag){
      this.selectFlag = selectFlag;
   }

   LimitNoonistener limitNoonistener;
   public interface LimitNoonistener{
      public void limitNoon();
   }
   public void addLimitNoonistener(LimitNoonistener limitNoonistener){
      this.limitNoonistener = limitNoonistener;
   }
}
 
在activit里边初始化
public void initWheelView(){
 wheelview = (WheelView)findViewById(R.id.wheelview);
 for (int i=8;i<= 22;i++){
    if(i<10){
        listItemsTwo.add("0"+i);
    }else{
        listItemsTwo.add(i+"");
    }
 }
 wheelview.setItem(listItemsTwo, "08");
 
}
通过wheelview.getCurrtPos()得到滑动的位置来取值;
主要的在jScroll()这个方法里;
效果图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值