自定义Dialog实现日期选择器

自定义Dialog实现日期选择器

1.用WheelView实现

老规矩,先看看实现的效果:



1. 先自定义View写一个WheelView:

package com.example.administrator.myapplication;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

/**
 * ClassName:WheelView
 * Author:JiangPing
 * Fuction:WheelView滚轮
 * CreateDate:
 * UpdateAuthor:
 * UpdateDate:
 */
public class WheelView extends View {

    /**
     *

     Attributes
     attr 属性	description 描述
     lineColor	divider line color 分割线颜色
     lineHeight	divider line height 分割线高度
     itemNumber	wheelview show item count 此wheelView显示item的个数
     maskHight	mask height 蒙版高度(normalText的位置)
     noEmpty	if set true select area can't be null(empty),or could be empty 设置true则选中不能为空,否则可以是空
     normalTextColor	unSelected Text color 未选中文本颜色
     normalTextSize	unSelected Text size 未选中文本字体大小
     selectedTextColor	selected Text color 选中文本颜色
     selectedTextSize	selected Text size 选中文本字体大小
     unitHight	item unit height 每个item单元的高度

     Method
     1. setData(ArrayList data)

     set WheelView data
     设置WheelView的数据

     2. resetData(ArrayList data)

     reset WheelView data ,if you has setData
     重置 WheelView的数据,如果已经设置过的话

     3. int getSelected()

     get selected item index
     获取选中项的index

     4. String getSelectedText()

     get selected item text
     获取选中项的文本信息

     5. boolean isScrolling

     is WheelView is scrolling
     获取WheelView是否在滚动中

     6. boolean isEnable()

     is WheelView is enable
     获取wheelView是否可用

     7. void setEnable(boolean isEnable)

     set WheelView enable
     设置WheelView是否可用

     8. void setDefault(int index)

     set default selected index
     设置默认选中项的index

     9. int getListSize()

     get WheelView item count
     获取WheelView的item项个数

     10. String getItemText(int index)

     get the text by index
     获取index位置上的文本数据

     11. void setOnSelectListener(OnSelectListener onSelectListener)

     set listener on WheelView that can get info when WheelView is scrolling or stop scroll.
     对WheelView设置监听,在 滑动过程 或者 滑动停止 返回数据信息。
     */

    /**
     * 控件宽度
     */
    private float controlWidth;
    /**
     * 控件高度
     */
    private float controlHeight;
    /**
     * 是否滑动中
     */
    private boolean isScrolling = false;
    /**
     * 选择的内容
     */
    private ArrayList
   
   
    
     itemList = new ArrayList<>();
    /**
     * 设置数据
     */
    private ArrayList
    
    
     
      dataList = new ArrayList<>();
    /**
     * 按下的坐标
     */
    private int downY;
    /**
     * 按下的时间
     */
    private long downTime = 0;
    /**
     * 短促移动
     */
    private long goonTime = 200;
    /**
     * 短促移动距离
     */
    private int goonDistence = 100;
    /**
     * 画线画笔
     */
    private Paint linePaint;
    /**
     * 线的默认颜色
     */
    private int lineColor = 0xff000000;
    /**
     * 线的默认宽度
     */
    private float lineWidth = 2f;
    /**
     * 默认字体
     */
    private float normalFont = 14.0f;
    /**
     * 选中的时候字体
     */
    private float selectedFont = 22.0f;
    /**
     * 单元格高度
     */
    private int unitHeight = 50;
    /**
     * 显示多少个内容
     */
    private int itemNumber = 7;
    /**
     * 默认字体颜色
     */
    private int normalColor = 0xff000000;
    /**
     * 选中时候的字体颜色
     */
    private int selectedColor = 0xffff0000;
    /**
     * 蒙板高度
     */
    private float maskHight = 48.0f;
    /**
     * 选择监听
     */
    private OnSelectListener onSelectListener;
    /**
     * 是否可用
     */
    private boolean isEnable = true;
    /**
     * 刷新界面
     */
    private static final int REFRESH_VIEW = 0x001;
    /**
     * 移动距离
     */
    private static final int MOVE_NUMBER = 5;
    /**
     * 是否允许选空
     */
    private boolean noEmpty = true;

    /**
     * 正在修改数据,避免ConcurrentModificationException异常
     */
    private boolean isClearing = false;

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

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

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (!isEnable)
            return true;
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isScrolling = true;
                downY = (int) event.getY();
                downTime = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                actionMove(y - downY);
                onSelectListener();
                break;
            case MotionEvent.ACTION_UP:
                int move = Math.abs(y - downY);
                // 判断段时间移动的距离
                if (System.currentTimeMillis() - downTime < goonTime
                        && move > goonDistence) {
                    goonMove(y - downY);
                } else {
                    actionUp(y - downY);
                }
                noEmpty();
                isScrolling = false;
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawLine(canvas);
        drawList(canvas);
        drawMask(canvas);
    }

    private synchronized void drawList(Canvas canvas) {
        if (isClearing)
            return;
        try {
            for (ItemObject itemObject : itemList) {
                itemObject.drawSelf(canvas);
            }
        } catch (Exception e) {
        }

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
                            int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        controlWidth = getWidth();
        if (controlWidth != 0) {
            setMeasuredDimension(getWidth(), itemNumber * unitHeight);
            controlWidth = getWidth();
        }

    }

    /**
     * 继续移动一定距离
     */
    private synchronized void goonMove(final int move) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                int distence = 0;
                while (distence < unitHeight * MOVE_NUMBER) {
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    actionThreadMove(move > 0 ? distence : distence * (-1));
                    distence += 10;

                }
                actionUp(move > 0 ? distence - 10 : distence * (-1) + 10);
                noEmpty();
            }
        }).start();
    }

    /**
     * 不能为空,必须有选项
     */
    private void noEmpty() {
        if (!noEmpty)
            return;
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return;
        }
        int move = (int) itemList.get(0).moveToSelected();
        if (move < 0) {
            defaultMove(move);
        } else {
            defaultMove((int) itemList.get(itemList.size() - 1)
                    .moveToSelected());
        }
        for (ItemObject item : itemList) {
            if (item.isSelected()) {
                if (onSelectListener != null)
                    onSelectListener.endSelect(this, item.id, item.itemText);
                break;
            }
        }
    }

    /**
     * 初始化数据
     */
    private void initData() {
        isClearing = true;
        itemList.clear();
        for (int i = 0; i < dataList.size(); i++) {
            ItemObject itmItemObject = new ItemObject();
            itmItemObject.id = i;
            itmItemObject.itemText = dataList.get(i);
            itmItemObject.x = 0;
            itmItemObject.y = i * unitHeight;
            itemList.add(itmItemObject);
        }
        isClearing = false;
    }

    /**
     * 移动的时候
     *
     * @param move
     */
    private void actionMove(int move) {
        for (ItemObject item : itemList) {
            item.move(move);
        }
        invalidate();
    }

    /**
     * 移动,线程中调用
     *
     * @param move
     */
    private void actionThreadMove(int move) {
        for (ItemObject item : itemList) {
            item.move(move);
        }
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);
    }

    /**
     * 松开的时候
     *
     * @param move
     */
    private void actionUp(int move) {
        int newMove = 0;
        if (move > 0) {
            for (int i = 0; i < itemList.size(); i++) {
                if (itemList.get(i).isSelected()) {
                    newMove = (int) itemList.get(i).moveToSelected();
                    if (onSelectListener != null)
                        onSelectListener.endSelect(this, itemList.get(i).id,
                                itemList.get(i).itemText);
                    break;
                }
            }
        } else {
            for (int i = itemList.size() - 1; i >= 0; i--) {
                if (itemList.get(i).isSelected()) {
                    newMove = (int) itemList.get(i).moveToSelected();
                    if (onSelectListener != null)
                        onSelectListener.endSelect(WheelView.this, itemList.get(i).id,
                                itemList.get(i).itemText);
                    break;
                }
            }
        }
        for (ItemObject item : itemList) {
            item.newY(move + 0);
        }
        slowMove(newMove);
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);

    }

    /**
     * 缓慢移动
     *
     * @param move
     */
    private synchronized void slowMove(final int move) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                // 判断政府
                int m = move > 0 ? move : move * (-1);
                int i = move > 0 ? 1 : (-1);
                // 移动速度
                int speed = 1;
                while (true) {
                    m = m - speed;
                    if (m <= 0) {
                        for (ItemObject item : itemList) {
                            item.newY(m * i);
                        }
                        Message rMessage = new Message();
                        rMessage.what = REFRESH_VIEW;
                        handler.sendMessage(rMessage);
                        try {
                            Thread.sleep(2);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                    for (ItemObject item : itemList) {
                        item.newY(speed * i);
                    }
                    Message rMessage = new Message();
                    rMessage.what = REFRESH_VIEW;
                    handler.sendMessage(rMessage);
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (ItemObject item : itemList) {
                    if (item.isSelected()) {
                        if (onSelectListener != null)
                            onSelectListener.endSelect(WheelView.this, item.id, item.itemText);
                        break;
                    }
                }

            }
        }).start();
    }

    /**
     * 移动到默认位置
     *
     * @param move
     */
    private void defaultMove(int move) {
        for (ItemObject item : itemList) {
            item.newY(move);
        }
        Message rMessage = new Message();
        rMessage.what = REFRESH_VIEW;
        handler.sendMessage(rMessage);
    }

    /**
     * 滑动监听
     */
    private void onSelectListener() {
        if (onSelectListener == null)
            return;
        for (ItemObject item : itemList) {
            if (item.isSelected()) {
                onSelectListener.selecting(WheelView.this, item.id, item.itemText);
            }
        }
    }

    /**
     * 绘制线条
     *
     * @param canvas
     */
    private void drawLine(Canvas canvas) {

        if (linePaint == null) {
            linePaint = new Paint();
            linePaint.setColor(lineColor);
            linePaint.setAntiAlias(true);
            linePaint.setStrokeWidth(lineWidth);
        }

        canvas.drawLine(0, controlHeight / 2 - unitHeight / 2 + 2,
                controlWidth, controlHeight / 2 - unitHeight / 2 + 2, linePaint);
        canvas.drawLine(0, controlHeight / 2 + unitHeight / 2 - 2,
                controlWidth, controlHeight / 2 + unitHeight / 2 - 2, linePaint);
    }

    /**
     * 绘制遮盖板
     *
     * @param canvas
     */
    private void drawMask(Canvas canvas) {
        LinearGradient lg = new LinearGradient(0, 0, 0, maskHight, 0x00f2f2f2,
                0x00f2f2f2, TileMode.MIRROR);
        Paint paint = new Paint();
        paint.setShader(lg);
        canvas.drawRect(0, 0, controlWidth, maskHight, paint);

        LinearGradient lg2 = new LinearGradient(0, controlHeight - maskHight,
                0, controlHeight, 0x00f2f2f2, 0x00f2f2f2, TileMode.MIRROR);
        Paint paint2 = new Paint();
        paint2.setShader(lg2);
        canvas.drawRect(0, controlHeight - maskHight, controlWidth,
                controlHeight, paint2);
    }

    /**
     * 初始化,获取设置的属性
     *
     * @param context
     * @param attrs
     */
    private void init(Context context, AttributeSet attrs) {

        TypedArray attribute = context.obtainStyledAttributes(attrs,
                R.styleable.WheelView);
        unitHeight = (int) attribute.getDimension(
                R.styleable.WheelView_unitHight, 32);
        normalFont = attribute.getDimension(
                R.styleable.WheelView_normalTextSize, 14.0f);
        selectedFont = attribute.getDimension(
                R.styleable.WheelView_selectedTextSize, 22.0f);
        itemNumber = attribute.getInt(R.styleable.WheelView_itemNumber, 7);
        normalColor = attribute.getColor(
                R.styleable.WheelView_normalTextColor, 0xff000000);
        selectedColor = attribute.getColor(
                R.styleable.WheelView_selectedTextColor, 0xffff0000);
        lineColor = attribute.getColor(R.styleable.WheelView_lineColor,
                0xff000000);
        lineWidth = attribute.getDimension(R.styleable.WheelView_lineHeight, 2f);
        maskHight = attribute.getDimension(R.styleable.WheelView_maskHight,
                48.0f);
        noEmpty = attribute.getBoolean(R.styleable.WheelView_noEmpty, true);
        isEnable = attribute
                .getBoolean(R.styleable.WheelView_isEnable, true);
        attribute.recycle();

        controlHeight = itemNumber * unitHeight;

    }

    /**
     * 设置数据 (第一次)
     *
     * @param data
     */
    public void setData(ArrayList
     
     
      
       data) {
        this.dataList = data;
        initData();
    }

    /**
     * 重置数据
     *
     * @param data
     */
    public void resetData(ArrayList
      
      
       
        data) {
        setData(data);
        invalidate();
    }

    /**
     * 获取返回项 id
     *
     * @return
     */
    public int getSelected() {
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return item.id;
        }
        return -1;
    }

    /**
     * 获取返回的内容
     *
     * @return
     */
    public String getSelectedText() {
        for (ItemObject item : itemList) {
            if (item.isSelected())
                return item.itemText;
        }
        return "";
    }

    /**
     * 是否正在滑动
     *
     * @return
     */
    public boolean isScrolling() {
        return isScrolling;
    }

    /**
     * 是否可用
     *
     * @return
     */
    public boolean isEnable() {
        return isEnable;
    }

    /**
     * 设置是否可用
     *
     * @param isEnable
     */
    public void setEnable(boolean isEnable) {
        this.isEnable = isEnable;
    }

    /**
     * 设置默认选项
     *
     * @param index
     */
    public void setDefault(int index) {
        if (index > itemList.size() - 1)
            return;
        float move = itemList.get(index).moveToSelected();
        defaultMove((int) move);
    }

    /**
     * 获取列表大小
     *
     * @return
     */
    public int getListSize() {
        if (itemList == null)
            return 0;
        return itemList.size();
    }

    /**
     * 获取某项的内容
     *
     * @param index
     * @return
     */
    public String getItemText(int index) {
        if (itemList == null)
            return "";
        return itemList.get(index).itemText;
    }

    /**
     * 监听
     *
     * @param onSelectListener
     */
    public void setOnSelectListener(OnSelectListener onSelectListener) {
        this.onSelectListener = onSelectListener;
    }

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case REFRESH_VIEW:
                    invalidate();
                    break;
                default:
                    break;
            }
        }

    };

    /**
     * 单条内容
     *
     * @author JiangPing
     */
    private class ItemObject {
        /**
         * id
         */
        public int id = 0;
        /**
         * 内容
         */
        public String itemText = "";
        /**
         * x坐标
         */
        public int x = 0;
        /**
         * y坐标
         */
        public int y = 0;
        /**
         * 移动距离
         */
        public int move = 0;
        /**
         * 字体画笔
         */
        private Paint textPaint;
        /**
         * 字体范围矩形
         */
        private Rect textRect;

        public ItemObject() {
            super();
        }

        /**
         * 绘制自身
         *
         * @param canvas
         */
        public void drawSelf(Canvas canvas) {

            if (textPaint == null) {
                textPaint = new Paint();
                textPaint.setAntiAlias(true);
            }

            if (textRect == null)
                textRect = new Rect();

            // 判断是否被选择
            if (isSelected()) {
                textPaint.setColor(selectedColor);
                // 获取距离标准位置的距离
                float moveToSelect = moveToSelected();
                moveToSelect = moveToSelect > 0 ? moveToSelect : moveToSelect
                        * (-1);
                // 计算当前字体大小
                float textSize = (float) normalFont
                        + ((float) (selectedFont - normalFont) * (1.0f - (float) moveToSelect
                        / (float) unitHeight));
                textPaint.setTextSize(textSize);
            } else {
                textPaint.setColor(normalColor);
                textPaint.setTextSize(normalFont);
            }

            // 返回包围整个字符串的最小的一个Rect区域
            textPaint.getTextBounds(itemText, 0, itemText.length(), textRect);
            // 判断是否可视
            if (!isInView())
                return;

            // 绘制内容
            canvas.drawText(itemText, x + controlWidth / 2 - textRect.width()
                            / 2, y + move + unitHeight / 2 + textRect.height() / 2,
                    textPaint);

        }

        /**
         * 是否在可视界面内
         *
         * @return
         */
        public boolean isInView() {
            if (y + move > controlHeight
                    || (y + move + unitHeight / 2 + textRect.height() / 2) < 0)
                return false;
            return true;
        }

        /**
         * 移动距离
         *
         * @param _move
         */
        public void move(int _move) {
            this.move = _move;
        }

        /**
         * 设置新的坐标
         *
         * @param _move
         */
        public void newY(int _move) {
            this.move = 0;
            this.y = y + _move;
        }

        /**
         * 判断是否在选择区域内
         *
         * @return
         */
        public boolean isSelected() {
            if ((y + move) >= controlHeight / 2 - unitHeight / 2 + 2
                    && (y + move) <= controlHeight / 2 + unitHeight / 2 - 2)
                return true;
            if ((y + move + unitHeight) >= controlHeight / 2 - unitHeight / 2
                    + 2
                    && (y + move + unitHeight) <= controlHeight / 2
                    + unitHeight / 2 - 2)
                return true;
            if ((y + move) <= controlHeight / 2 - unitHeight / 2 + 2
                    && (y + move + unitHeight) >= controlHeight / 2
                    + unitHeight / 2 - 2)
                return true;
            return false;
        }

        /**
         * 获取移动到标准位置需要的距离
         */
        public float moveToSelected() {
            return (controlHeight / 2 - unitHeight / 2) - (y + move);
        }
    }

    /**
     * 选择监听
     *
     * @author JiangPing
     */
    public interface OnSelectListener {
        /**
         * 结束选择
         *
         * @param id
         * @param text
         */
        public void endSelect(View view, int id, String text);

        /**
         * 选中的内容
         *
         * @param id
         * @param text
         */
        public void selecting(View view, int id, String text);

    }
}

      
      
     
     
    
    
   
   

2. 自定义一个Dialog,嵌套三个WheelView来实现年月日的选择。Dialog刚打开时显示的是当前日期:

package com.example.administrator.myapplication;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

/**
 * Created by Administrator on 2017/3/8.
 */
public class DateDialog extends Dialog implements WheelView.OnSelectListener{

    private TextView tv_date_cancel, tv_date_sure;
    private onNoOnclickListener noOnclickListener;//取消按钮被点击了的监听器
    private onYesOnclickListener yesOnclickListener;//确定按钮被点击了的监听器
    Context mContext;
    TextView tv_title;
    String title,date;
    CallBackListener mCallBackListener;

    /**
     * 获取选择的年
     *
     * @return
     */
    public String getYear() {
        Log.d("TAG", mWheelYear.getSelectedText());
        return mWheelYear.getSelectedText();
    }

    /**
     * 获取选择的月
     *
     * @return
     */
    public String getMonth() {
        Log.d("TAG", mWheelMonth.getSelectedText());
        return mWheelMonth.getSelectedText();
    }

    /**
     * 获取选择的日
     *
     * @return
     */
    public String getDay() {
        Log.d("TAG", mWheelDay.getSelectedText());
        return mWheelDay.getSelectedText();
    }

    public String getDate() {
        Log.d("TAG", mWheelYear.getSelectedText() + "-" + mWheelMonth.getSelectedText() + "-" + mWheelDay.getSelectedText());
        date = mWheelYear.getSelectedText() + "-" + mWheelMonth.getSelectedText() + "-" + mWheelDay.getSelectedText();
        return date;
    }

    private WheelView mWheelYear;
    private WheelView mWheelMonth;
    private WheelView mWheelDay;



    public DateDialog(Context context, String str) {
        super(context);
        mContext = context;
        title = str;
    }


    public DateDialog(Context context, int themeResId) {
        super(context, R.style.MyDialog);
    }


    /**
     * 设置取消按钮的显示内容和监听
     *
     * @param onNoOnclickListener
     */
    public void setNoOnclickListener(onNoOnclickListener onNoOnclickListener) {

        this.noOnclickListener = onNoOnclickListener;
    }


    /**
     * 设置确定按钮的显示内容和监听
     *
     * @param onYesOnclickListener
     */
    public void setYesOnclickListener(onYesOnclickListener onYesOnclickListener) {
        this.yesOnclickListener = onYesOnclickListener;
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.datepicker_layout);
        //按空白处不能取消动画
        setCanceledOnTouchOutside(false);
        //初始化界面控件
        setupViews();
        //操作事件
        initEvent();
    }

    private void initEvent() {
        tv_date_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (noOnclickListener != null) {
                    noOnclickListener.onNoClick();
                }
            }
        });
        tv_date_sure.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (yesOnclickListener != null) {
                    yesOnclickListener.onYesClick();
                    mCallBackListener.getDate(date);
                }
            }
        });
    }

    private void setupViews() {
        tv_date_cancel = (TextView) findViewById(R.id.tv_date_cancel);
        tv_date_sure = (TextView) findViewById(R.id.tv_date_sure);
        tv_title = (TextView) findViewById(R.id.tv_title);
        tv_title.setText(title);

        mWheelYear = (WheelView) findViewById(R.id.wv_year);
        mWheelMonth = (WheelView) findViewById(R.id.wv_month);
        mWheelDay = (WheelView) findViewById(R.id.wv_day);

        // 格式化当前时间,并转换为年月日整型数据
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
        String[] split = sdf.format(new Date()).split("-");
        int currentYear = Integer.parseInt(split[0]);
        int currentMonth = Integer.parseInt(split[1]);
        int currentDay = Integer.parseInt(split[2]);

        // 设置默认年月日为当前日期
        mWheelYear.setData(getYearData(currentYear));
        mWheelYear.setDefault(0);
        mWheelMonth.setData(getMonthData());
        mWheelMonth.setDefault(currentMonth - 1);
        mWheelDay.setData(getDayData(getLastDay(currentYear, currentMonth)));
        mWheelDay.setDefault(currentDay - 1);

        mWheelYear.setOnSelectListener(this);
        mWheelMonth.setOnSelectListener(this);
        mWheelDay.setOnSelectListener(this);
    }

    /**
     * 年范围在:1900~今年
     *
     * @param currentYear
     * @return
     */
    private ArrayList
    
    
     
      getYearData(int currentYear) {
        ArrayList
     
     
      
       list = new ArrayList<>();
        for (int i = currentYear; i >= 1900; i--) {
            list.add(String.valueOf(i));
        }
        return list;
    }

    private ArrayList
      
      
       
        getMonthData() {
        ArrayList
       
       
        
         list = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            list.add(String.valueOf(i));
        }
        return list;
    }

    /**
     * 日范围在1~lastDay
     *
     * @param lastDay
     * @return
     */
    private ArrayList
        
        
          getDayData(int lastDay) { //ignore condition ArrayList 
         
           list = new ArrayList<>(); for (int i = 1; i <= lastDay; i++) { list.add(String.valueOf(i)); } return list; } /** * 判断是否闰年 * * @param year * @return */ private boolean isLeapYear(int year) { return (year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0); } /** * 获取特定年月对应的天数 * * @param year * @param month * @return */ private int getLastDay(int year, int month) { if (month == 2) { // 2月闰年的话返回29,防止28 return isLeapYear(year) ? 29 : 28; } // 一三五七八十腊,三十一天永不差 return month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ? 31 : 30; } @Override public void endSelect(View view, int id, String text) { // 滚轮滑动停止后调用 switch (view.getId()) { case R.id.wv_year:{ getYear(); } case R.id.wv_month: { getMonth(); // 记录当前选择的天数 int selectDay = Integer.parseInt(getDay()); // 根据当前选择的年月获取对应的天数 int lastDay = getLastDay(Integer.parseInt(getYear()), Integer.parseInt(getMonth())); // 设置天数 mWheelDay.setData(getDayData(lastDay)); // 如果选中的天数大于实际天数,那么将默认天数设为实际天数;否则还是设置默认天数为选中的天数 if (selectDay > lastDay) { mWheelDay.setDefault(lastDay - 1); } else { mWheelDay.setDefault(selectDay - 1); } } case R.id.wv_day: { getDay(); } getDate(); } } @Override public void selecting(View view, int id, String text) { } /** * 设置确定按钮和取消被点击的接口 */ public interface onYesOnclickListener { public void onYesClick(); } public interface onNoOnclickListener { public void onNoClick(); } //接口回调,返回日期数据 public interface CallBackListener { public void getDate(String date); } public void setCallBackListener(CallBackListener mCallBackListener){ this.mCallBackListener = mCallBackListener; } } 
          
        
       
       
      
      
     
     
    
    

3. MainActivity的代码实现:

package com.example.administrator.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    TextView tv_start_date, tv_end_date;
    DateDialog dateDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化控件
        setupViews();
        //设置监听事件
        initEvent();
    }

    private void initEvent() {
        final String[] title = {"选择初始时间", "选择结束时间"};
        tv_start_date.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dateDialog = new DateDialog(MainActivity.this, title[0]);
                dateDialog.show();
                dateDialog.setYesOnclickListener(new DateDialog.onYesOnclickListener() {
                    @Override
                    public void onYesClick() {
                        dateDialog.setCallBackListener(new DateDialog.CallBackListener() {
                            @Override
                            public void getDate(String date) {
                                if (date == null) {
                                    tv_start_date.setText(getDefautDate());
                                } else {
                                    tv_start_date.setText(date);
                                }
                            }
                        });
                        dateDialog.dismiss();
                    }
                });
                dateDialog.setNoOnclickListener(new DateDialog.onNoOnclickListener() {
                    @Override
                    public void onNoClick() {
                        dateDialog.dismiss();
                    }
                });
            }
        });

        tv_end_date.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dateDialog = new DateDialog(MainActivity.this, title[1]);
                dateDialog.show();
                dateDialog.setYesOnclickListener(new DateDialog.onYesOnclickListener() {
                    @Override
                    public void onYesClick() {
                        dateDialog.setCallBackListener(new DateDialog.CallBackListener() {
                            @Override
                            public void getDate(String date) {
                                if (date == null) {
                                    tv_end_date.setText(getDefautDate());
                                } else {
                                    tv_end_date.setText(date);
                                }
                            }
                        });
                        dateDialog.dismiss();
                    }
                });
                dateDialog.setNoOnclickListener(new DateDialog.onNoOnclickListener() {
                    @Override
                    public void onNoClick() {
                        dateDialog.dismiss();
                    }
                });
            }
        });
    }

    private void setupViews() {
        tv_start_date = (TextView) findViewById(R.id.tv_start_date);
        tv_end_date = (TextView) findViewById(R.id.tv_end_date);
        tv_start_date.setText(getDefautDate());
        tv_end_date.setText(getDefautDate());
    }

    public String getDefautDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }
}


源码:https://github.com/shaoyu00/MyApplication


2.用LoopView来实现

效果图如下:

部分关键代码:

Dialog布局主要由三个LoopView和两个按钮组成,三个LoopView分别加载年月日

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/picker_rel"
        android:focusableInTouchMode="true"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#FFFFFF">
            <TextView
                android:id="@+id/tv_cancle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="取消"
                android:gravity="center|left"
                android:textColor="#606060"
                android:textSize="14sp"
                android:paddingLeft="12dp"
                android:paddingRight="12dp"
                android:background="@drawable/selectableitem_background_borderless"/>
            <TextView
                android:id="@+id/tv_true"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="确定"
                android:gravity="center|right"
                android:textColor="#266497"
                android:textSize="14sp"
                android:paddingLeft="12sp"
                android:paddingRight="12sp"
                android:background="@drawable/selectableitem_background_borderless"
                android:layout_alignParentRight="true"/>
        </RelativeLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="216dp"
            android:background="@mipmap/picker_background"
            android:padding="10dp">
            <View
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"/>
            <com.weigan.loopview.LoopView
                android:id="@+id/loopView_year"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1.3" />
            <com.weigan.loopview.LoopView
                android:id="@+id/loopView_month"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1" />
            <com.weigan.loopview.LoopView
                android:id="@+id/loopView_day"
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"/>
            <View
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"/>
        </LinearLayout>

    </LinearLayout>
</RelativeLayout>

自定义的日期Dialog:加载年月日数据以及关联三个LoopView

public class DateDialog extends Dialog {

    private Context context;
    private ClickListenerInterface clickListenerInterface;
    //private ItemSelectedListenerInterface itemSelectedListenerInterface;

    LoopView loopView_year;
    LoopView loopView_month;
    LoopView loopView_day;
    //年月日选择器打开是显示的索引位置
    int yearIndex = 0;
    int monthIndex=0;
    int dayIndex=0;
    //----------初始化日期显示值 --当天年月日
    int currentYear;
    int currentMonth;
    int currentDay;
    List<String> list_year;
    List<String> list_month;
    List<String> list_day;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
    }
    @Override
    public void show() {
        super.show();
        // 设置dialog显示动画
        getWindow().setWindowAnimations(R.style.PopupAnimation);
        // 设置显示位置为底部
        getWindow().setGravity(Gravity.BOTTOM);
    }

    public DateDialog(Context context) {
        super(context, R.style.MyDialog);
        this.context = context;
    }

    public void init() {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.picker_date_lay, null);
        setContentView(view);
        setCanceledOnTouchOutside(true);

        Window dialogWindow = getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        dialogWindow.setAttributes(lp);

        loopView_year = (LoopView) view.findViewById(R.id.loopView_year);
        loopView_month = (LoopView) view.findViewById(R.id.loopView_month);
        loopView_day = (LoopView) view.findViewById(R.id.loopView_day);
        TextView tvConfirm = (TextView) view.findViewById(R.id.tv_true);
        TextView tvCancel = (TextView) view.findViewById(R.id.tv_cancle);
        tvConfirm.setOnClickListener(new clickListener());
        tvCancel.setOnClickListener(new clickListener());

        //----------初始化日期显示值 --当天年月日
        Calendar calendar = Calendar.getInstance();
        currentYear=calendar.get(Calendar.YEAR);
        currentMonth=calendar.get(Calendar.MONTH)+1;
        currentDay=calendar.get(Calendar.DAY_OF_MONTH);

        //-----------年 月  日  数据
        list_year=new ArrayList<>();
        for (int i = 1900; i <= currentYear; i++) {
            list_year.add(i+"");
        }
         list_month=new ArrayList<>();
        for (int i = 1; i <=12; i++) {
            list_month.add(i+"");
        }
        list_day=new ArrayList<>();
        for (int i = 1; i <= getLastDay(currentYear,currentMonth); i++) {
            list_day.add(i+"");
        }
        for (int i=0;i<list_year.size();i++){
            String year=list_year.get(i);
            if ((currentYear+"").equals(year.substring(0,year.indexOf("")))){
                yearIndex=i;
            }
        }
        for (int i=0;i<list_month.size();i++){
            String month=list_month.get(i);
            if ((currentMonth+"").equals(month.substring(0,month.indexOf("")))){
                monthIndex=i;
            }
        }
        for (int i=0;i<list_day.size();i++){
            String day=list_day.get(i);
            if ((currentDay+"").equals(day.substring(0,day.indexOf("")))){
                dayIndex=i;
            }
        }
        //设置是否循环播放
        //loopView_year.setNotLoop();
        //loopView_month.setNotLoop();
        //loopView_day.setNotLoop();
        //设置原始数据
        loopView_year.setItems(list_year);
        loopView_month.setItems(list_month);
        loopView_day.setItems(list_day);
        //设置初始位置
        loopView_year.setInitPosition(yearIndex);
        loopView_month.setInitPosition(monthIndex);
        loopView_day.setInitPosition(dayIndex);
        //----------------初始化 当前年 月 日位置索引
        loopView_year.setCurrentIndex(yearIndex);
        loopView_month.setCurrentIndex(monthIndex);
        loopView_day.setCurrentIndex(dayIndex);
        //设置字体大小
        loopView_year.setTextSize(18);
        loopView_month.setTextSize(18);
        loopView_day.setTextSize(18);

        loopView_year.setListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(int index) {
                // 记录当前选择的年
                loopView_year.setCurrentIndex(index);
                int selectedYear=loopView_year.getCurrentIndex()+1900;
                int selectedMonth=loopView_month.getCurrentIndex()+1;
                if (selectedMonth==2){ //----------当滚动时间时  当选中的月份为2月  需要重新计算天数
                    List<String> newlist_day=new ArrayList<>();
                    for (int i = 1; i <= getLastDay(selectedYear,selectedMonth); i++) {
                        newlist_day.add(i+"");
                    }
                    loopView_day.setItems(newlist_day);
                }
            }
        });
        loopView_month.setListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(int index) {
                loopView_month.setCurrentIndex(index);
                int selectedYear=loopView_year.getCurrentIndex()+1900;
                int selectedMonth=loopView_month.getCurrentIndex()+1;
                List<String> newlist_day=new ArrayList<>();
                for (int i = 1; i <= getLastDay(selectedYear,selectedMonth); i++) {
                    newlist_day.add(i+"");
                }
                loopView_day.setItems(newlist_day);
            }
        });
        loopView_day.setListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(int index) {
                loopView_day.setCurrentIndex(index);
            }
        });

    }

    public void setClicklistener(ClickListenerInterface clickListenerInterface) {
        this.clickListenerInterface = clickListenerInterface;
    }
 /*   public void setItemSelectedListener(ItemSelectedListenerInterface itemSelectedListenerInterface) {//-----------滚动时 在页面刷新日期
        this.itemSelectedListenerInterface = itemSelectedListenerInterface;
    }*/
    private class clickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            int id = v.getId();
            switch (id) {
                case R.id.tv_true:
                    clickListenerInterface.doConfirm(loopView_year,loopView_month,loopView_day);
                    break;
                case R.id.tv_cancle:
                    clickListenerInterface.doCancel(loopView_year,loopView_month,loopView_day);
                    break;
            }
        }
    }
   /* private class itemSelectedListener implements OnItemSelectedListener {
        @Override
        public void onItemSelected(int index) {

        }
    }*/
    public interface ClickListenerInterface {
        void doConfirm(LoopView loopView_year, LoopView loopView_month, LoopView loopView_day);
        void doCancel(LoopView loopView_year, LoopView loopView_month, LoopView loopView_day);
    }
  /*  public interface ItemSelectedListenerInterface {
        void select();
    }
*/
    /**
     * 判断是否闰年
     *
     * @param year
     * @return
     */
    private static boolean isLeapYear(int year) {
        return (year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);
    }

    /**
     * 获取特定年月对应的天数
     *
     * @param year
     * @param month
     * @return
     */
    private static int getLastDay(int year, int month) {
        if (month == 2) {
            // 2月闰年的话返回29,防止28
            return isLeapYear(year) ? 29 : 28;
        }
        // 一三五七八十腊,三十一天永不差
        return month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ? 31 : 30;
    }
}

在Activity里代码实现:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    @BindView(R.id.start_time_year)
    TextView startTimeYear;
    @BindView(R.id.start_time_month)
    TextView startTimeMonth;
    @BindView(R.id.start_time_day)
    TextView startTimeDay;
    @BindView(R.id.start_time)
    LinearLayout startTime;
    @BindView(R.id.end_time_year)
    TextView endTimeYear;
    @BindView(R.id.end_time_month)
    TextView endTimeMonth;
    @BindView(R.id.end_time_day)
    TextView endTimeDay;
    @BindView(R.id.end_time)
    LinearLayout endTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);//绑定ButterKnife
        initData();
    }

    private void initData() {
        //----------初始化日期显示值 --当天年月日
        Calendar calendar = Calendar.getInstance();
        startTimeYear.setText(calendar.get(Calendar.YEAR) + "");
        startTimeMonth.setText((calendar.get(Calendar.MONTH) + 1) + "");
        startTimeDay.setText(calendar.get(Calendar.DAY_OF_MONTH) + "");
        endTimeYear.setText(calendar.get(Calendar.YEAR) + "");
        endTimeMonth.setText((calendar.get(Calendar.MONTH) + 1) + "");
        endTimeDay.setText(calendar.get(Calendar.DAY_OF_MONTH) + "");
    }


    @OnClick({R.id.start_time, R.id.end_time})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start_time:
                int id = 1;
                String before_start_year = startTimeYear.getText().toString().trim();
                String before_start_month = startTimeMonth.getText().toString().trim();
                String before_start_day = startTimeDay.getText().toString().trim();
                showTimeDialog(id, before_start_year, before_start_month, before_start_day);
                break;
            case R.id.end_time:
                int idd = 2;
                String before_end_year = endTimeYear.getText().toString().trim();
                String before_end_month = endTimeMonth.getText().toString().trim();
                String before_end_day = endTimeDay.getText().toString().trim();
                showTimeDialog(idd, before_end_year, before_end_month, before_end_day);
                break;
        }
    }

    private void showTimeDialog(final int id, final String before_year, final String before_month, final String before_day) {
        final DateDialog confirmDialog = new DateDialog(MainActivity.this);
        confirmDialog.show();
        confirmDialog.setClicklistener(new DateDialog.ClickListenerInterface() {
            @Override
            public void doConfirm(LoopView loopView_year, LoopView loopView_month, LoopView loopView_day) {
                switch (id) {
                    case 1:
                        startTimeYear.setText(loopView_year.getCurrentIndex() + 1900 + "");
                        startTimeMonth.setText(loopView_month.getCurrentIndex() + 1 + "");
                        startTimeDay.setText(loopView_day.getCurrentIndex() + 1 + "");
                        confirmDialog.dismiss();
                        break;
                    case 2:
                        endTimeYear.setText(loopView_year.getCurrentIndex() + 1900 + "");
                        endTimeMonth.setText(loopView_month.getCurrentIndex() + 1 + "");
                        endTimeDay.setText(loopView_day.getCurrentIndex() + 1 + "");
                        confirmDialog.dismiss();
                        break;
                }

            }

            @Override
            public void doCancel(LoopView loopView_year, LoopView loopView_month, LoopView loopView_day) {
                switch (id) {
                    case 1:
                        startTimeYear.setText(before_year);
                        startTimeMonth.setText(before_month);
                        startTimeDay.setText(before_day);
                        confirmDialog.dismiss();
                        break;
                    case 2:
                        endTimeYear.setText(before_year);
                        endTimeMonth.setText(before_month);
                        endTimeDay.setText(before_day);
                        confirmDialog.dismiss();
                        break;
                }

            }
        });
    }
}

源码地址:https://github.com/shaoyu00/DatePicker

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值