Android(安卓)年月选择器,基于必酷公司的竖直滑动选择器WheelView进行实现
16lz
2021-01-26
文章目录
- 重复造轮子?
- 说一说实现过程
- 集成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中开放了几个方法:
- setYearRange(int minYear, int maxYear)
设定年份可选择的范围 - setCancelable(boolean cancelable)
设定点击DatePicker外区域是否可取消DatePicker - loopYear(boolean loop)
设置年份是否可循环展示,默认为true - loopMonth(boolean loop)
设置月份是否可循环展示,默认为true - 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"?>
更多相关文章
- [置顶] Android源码分享
- android 中如何获取radiogroup 中那个radiobutton被选择
- Android应用程序对话框大合集
- android 短信:电信运营商给你的号码可能是+86开头
- 第三方Android(安卓)模拟器流畅速度快,适合开发人员(2)
- [Android]Fragment源码分析(二) 状态
- Mac下Android(安卓)Studio 使用git版本控制个人心得
- 序列化原理(二):从源码理解Parcelable
- Android(安卓)实现音乐播放器【源码+注释】— MediaPlayer