文章目录

  • 重复造轮子?
  • 说一说实现过程
    • 集成WheelView库
    • DatePicker的实现
      • DatePicker
      • Builder
      • OnDatePickedListener
      • WheelView
    • DatePicker的使用
  • 附以完整源码
    • DatePicker.class
    • layout_datepicker.xml

明日复明日,明日何其多————困了,但不能把工作推到明天了,拭心大佬是我学习的榜样。

重复造轮子?

也不算是。
Bigkoo的Android-PickerView库,很好的支持了日期、时间、地区等各种类型的联动选择。目前的需求是只需要年月二级联动查询,不想集成整个Android-PickerView,毕竟大部分功能用不到,白白增加代码量,于是就基于Bigkoo的WheelView库实现了一个简便的年月选择器DatePicker。

说一说实现过程

集成WheelView库

implementation 'com.contrarywind:wheelview:4.0.9'

Bigkoo的Github地址:Bigkoo Github
他的Android-PickerView库写的很棒,功能全,性能好,单看看Star数,就知道此库得到了Android开发者的广泛认可。
WheelView内置于Android-PickerView,也可单独集成。它是一个自定义View,800行源码,立一个flag:读它的源码,下周内出一篇源码分析的文章。

DatePicker的实现

DatePicker

DatePicker继承于DialogFragment。采用Fragment弹出框,更便于自定义DatePicker布局,以及在任意页面进行调用,并可像管理Fragment一样管理DatePicker,很方便。

Builder

在DatePicker中用了一个静态内部类Builder,用于构建DatePicker及初始化。在Builder中开放了几个方法:

  1. setYearRange(int minYear, int maxYear)
    设定年份可选择的范围
  2. setCancelable(boolean cancelable)
    设定点击DatePicker外区域是否可取消DatePicker
  3. loopYear(boolean loop)
    设置年份是否可循环展示,默认为true
  4. loopMonth(boolean loop)
    设置月份是否可循环展示,默认为true
  5. build()
    构建并初始化DatePicker
public static class Builder {        private OnDatePickedListener listener;        public Builder(OnDatePickedListener listener) {            this.listener = listener;        }        private int minYear;        private int maxYear;        private boolean loopYear;        private boolean loopMonth;        private boolean cancelable;        public Builder setYearRange(int minYear, int maxYear) {            this.minYear = minYear;            this.maxYear = maxYear;            return this;        }        public Builder setCancelable(boolean cancelable) {            this.cancelable = cancelable;            return this;        }        public Builder loopYear(boolean loop) {            this.loopYear = loop;            return this;        }        public Builder loopMonth(boolean loop) {            this.loopMonth = loop;            return this;        }        public DatePicker build() {            if (minYear > maxYear) {                throw new IllegalArgumentException();//不允许minYear > maxYear            }            return DatePicker.newInstance(this);        }    }

OnDatePickedListener

DatePicker的监听接口,内有一回调方法onDatePickCompleted(int year, int month),用于年月选择后的选择值回传。

public interface OnDatePickedListener {   void onDatePickCompleted(int year, int month);}

WheelView

xml布局:

Java代码:

WheelView wheelView = findViewById(R.id.wheelview);        wheelView.setCyclic(false); //是否循环展示        final List mOptionsItems = new ArrayList<>();        mOptionsItems.add("item0");        mOptionsItems.add("item1");        mOptionsItems.add("item2");          wheelView.setAdapter(new ArrayWheelAdapter(mOptionsItems));        wheelView.setOnItemSelectedListener(new OnItemSelectedListener() {            @Override            public void onItemSelected(int index) {                Toast.makeText(MainActivity.this, "" + mOptionsItems.get(index), Toast.LENGTH_SHORT).show();            }        });

DatePicker的使用

private String TAG = DemoActivity.class.getName();
DatePicker datePicker = new DatePicker.Builder(new DatePicker.OnDatePickedListener() {                    @Override                    public void onDatePickCompleted(int year, int month) {                        Toast.makeText(LoginStatisticsActivity.this, "selectedYear:" + year + "--selectedMonth" + month, Toast.LENGTH_SHORT).show();                    }                })                  .setYearRange(1990, Calendar.getInstance().get(Calendar.YEAR))//1990——当前年份                  .setCancelable(true)                  .loopYear(false)                  .loopMonth(false)                  .build();datePicker.showPicker(DemoActivity.this, TAG);

附以完整源码

DatePicker.class

package com.gd.terminalmanager.view;import android.app.Activity;import android.app.DialogFragment;import android.graphics.Color;import android.graphics.drawable.ColorDrawable;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.util.DisplayMetrics;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.widget.TextView;import com.contrarywind.adapter.WheelAdapter;import com.contrarywind.listener.OnItemSelectedListener;import com.contrarywind.view.WheelView;import com.gd.terminalmanager.R;import java.util.ArrayList;import java.util.Calendar;import java.util.List;/** * 只提供年和月的选择 * * @author ZuoHailong * @date 2019/3/19. */public class DatePicker extends DialogFragment {    private static final int DEFAULT_MAX_YEAR = 2050;    private static final int DEFAULT_MIN_YEAR = 1900;    private WheelView wheelViewYear, wheelViewMonth;    private TextView tv_sure, tv_cancle;    private int minYear; // min year    private int maxYear; // max year    private boolean cancelable, loopYear, loopMonth;    private OnDatePickedListener listener;    private int selectedYear, selectedMonth;    private static Calendar calendar;    //private,只允许通过Builder构建DatePicker    private static DatePicker newInstance(Builder builder) {        calendar = Calendar.getInstance();        DatePicker datePicker = new DatePicker();        datePicker.minYear = builder.minYear < DatePicker.DEFAULT_MIN_YEAR ? DatePicker.DEFAULT_MIN_YEAR : builder.minYear;        datePicker.maxYear = builder.maxYear > DatePicker.DEFAULT_MAX_YEAR ? DatePicker.DEFAULT_MAX_YEAR : builder.maxYear;        datePicker.cancelable = builder.cancelable;        datePicker.loopYear = builder.loopYear;        datePicker.loopMonth = builder.loopMonth;        datePicker.listener = builder.listener;        return datePicker;    }    @Override    public void onStart() {        super.onStart();        DisplayMetrics dm = new DisplayMetrics();        getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);        getDialog().getWindow().setLayout(dm.widthPixels, getDialog().getWindow().getAttributes().height);    }    @Nullable    @Override    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.layout_datepicker, container);        tv_cancle = view.findViewById(R.id.tv_cancle);        tv_cancle.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dismiss();            }        });        tv_sure = view.findViewById(R.id.tv_sure);        tv_sure.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                listener.onDatePickCompleted(selectedYear, selectedMonth);                dismiss();            }        });        wheelViewYear = view.findViewById(R.id.wheelViewYear);        wheelViewMonth = view.findViewById(R.id.wheelViewMonth);        //设置DialogFragment所在窗口的背景透明        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);        initView();        return view;    }    private void initView() {        setCancelable(cancelable);        initYear(minYear, maxYear);        initMonth();        //默认选择当前年份        selectedYear = calendar.get(Calendar.YEAR);        //position = 当前年份 - minYear        wheelViewYear.setCurrentItem(selectedYear - minYear);        //设置是否循环显示年份        wheelViewYear.setCyclic(loopYear);        wheelViewYear.setOnItemSelectedListener(new OnItemSelectedListener() {            @Override            public void onItemSelected(int position) {                selectedYear = yearList.get(position);            }        });        //月份是从0到11,实际选择月份要+1        selectedMonth = calendar.get(Calendar.MONTH) + 1;        //position = 实际选择月份 - 1        wheelViewMonth.setCurrentItem(selectedMonth - 1);        //设置是否循环显示月份        wheelViewMonth.setCyclic(loopMonth);        wheelViewMonth.setOnItemSelectedListener(new OnItemSelectedListener() {            @Override            public void onItemSelected(int position) {                selectedMonth = monthList.get(position);            }        });    }    //存储可供选择的 年份/月份 集合    private List yearList, monthList;    private void initYear(int minYear, int maxYear) {        //避免传入顺序有误        minYear = Math.min(minYear, maxYear);        maxYear = Math.max(minYear, maxYear);        yearList = new ArrayList<>();        for (int i = 0; i < maxYear + 1 - minYear; i++) {            yearList.add(minYear + i);        }        wheelViewYear.setAdapter(new WheelAdapter() {            @Override            public int getItemsCount() {                return yearList.size();            }            @Override            public Object getItem(int index) {                return yearList.get(index);            }            @Override            public int indexOf(Object o) {                return yearList.indexOf(o);            }        });    }    private void initMonth() {        monthList = new ArrayList<>();        monthList.add(1);        monthList.add(2);        monthList.add(3);        monthList.add(4);        monthList.add(5);        monthList.add(6);        monthList.add(7);        monthList.add(8);        monthList.add(9);        monthList.add(10);        monthList.add(11);        monthList.add(12);        wheelViewMonth.setAdapter(new WheelAdapter() {            @Override            public int getItemsCount() {                return monthList.size();            }            @Override            public Object getItem(int index) {                return monthList.get(index);            }            @Override            public int indexOf(Object o) {                return monthList.indexOf(o);            }        });    }    //显示DatePicker    public void showPicker(Activity mActivity, String TAG) {        show(mActivity.getFragmentManager(), TAG);    }    public interface OnDatePickedListener {        void onDatePickCompleted(int year, int month);    }    public static class Builder {        private OnDatePickedListener listener;        public Builder(OnDatePickedListener listener) {            this.listener = listener;        }        private int minYear;        private int maxYear;        private boolean loopYear;        private boolean loopMonth;        private boolean cancelable;        public Builder setYearRange(int minYear, int maxYear) {            this.minYear = minYear;            this.maxYear = maxYear;            return this;        }        public Builder setCancelable(boolean cancelable) {            this.cancelable = cancelable;            return this;        }        public Builder loopYear(boolean loop) {            this.loopYear = loop;            return this;        }        public Builder loopMonth(boolean loop) {            this.loopMonth = loop;            return this;        }        public DatePicker build() {            if (minYear > maxYear) {                throw new IllegalArgumentException();//不允许minYear > maxYear            }            return DatePicker.newInstance(this);        }    }}

layout_datepicker.xml

<?xml version="1.0" encoding="utf-8"?>                                                                                                

更多相关文章

  1. [置顶] Android源码分享
  2. android 中如何获取radiogroup 中那个radiobutton被选择
  3. Android应用程序对话框大合集
  4. android 短信:电信运营商给你的号码可能是+86开头
  5. 第三方Android(安卓)模拟器流畅速度快,适合开发人员(2)
  6. [Android]Fragment源码分析(二) 状态
  7. Mac下Android(安卓)Studio 使用git版本控制个人心得
  8. 序列化原理(二):从源码理解Parcelable
  9. Android(安卓)实现音乐播放器【源码+注释】— MediaPlayer

随机推荐

  1. Android6.0 按键流程(三)InputDispatcher分
  2. Android错误提示:IMGSRV::0: gralloc_modu
  3. Android飞行模式的打开与关闭
  4. 国内四个不错的技术团体博客
  5. Windows下快速搭建安卓开发环境Android(
  6. android/bitmap.h 详解
  7. 开发技术前线 第十一期
  8. Android(安卓)Tint使用
  9. Android(安卓)截取手机屏幕两种实现方法
  10. android ActivityGroup使用简单步骤