安卓:一个简单的日期选择控件

 效果如图:

安卓:一个简单的日期选择控件_第1张图片

代码如下:

package com.example.listpickerdialog;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

/**
 * Created by nlx on 2018-09-18, at 14:19
 * 

* date picker */ public class DatePickerPop extends PopupWindow { private static ContentType[] mContentType; private ArrayList mDayListData; private MyAdapter mDayListAdapter; private Calendar mCurrentCalendar; private onConfirmListener mListener; private ListView mDayListView; private String[] mDefaultDate; public enum ContentType { YEAR, DAY, MONTH; } //btn public static final int BACKGRO_COLOR_BTN = Color.parseColor("#b6bbc2"); //title public static final int BACKGRO_COLOR_TITLE = Color.parseColor("#D7DCDF"); //item public static final int HEIGHT = 700; public static final int ITEM_COUNT = 5; public static final int ITEM_HEIGHT = HEIGHT / (ITEM_COUNT + 1) + 10; //text public static final int TEXT_SIZE_FOCUSING = 28; public static final int TEXT_SIZE_DEFAULT = 22; public static final int TEXT_COLOT_DEFAULT = Color.parseColor("#b6bbc2"); public static final int TEXT_COLOR_FOCUSING = Color.parseColor("#1a1a1a"); //content public static final int YEAR_OFFSET = 50; private Context mContext; private TextView mCurrentFocusingViewInMonthList; private TextView mCurrentFocusingViewInYearList; private TextView mCurrentFocusingViewInDayList; public DatePickerPop(Context context) { super(context); mContext = context; setHeight(HEIGHT); setOutsideTouchable(true); } /** * 内容显示什么,参数顺序决定内容布局 * * @param type */ public DatePickerPop setContentType(ContentType... type) { mContentType = type; initView(); return this; } /** * 点击确定的listener * * @param listener * @return */ public DatePickerPop setOnConfirmListener(onConfirmListener listener) { mListener = listener; return this; } /** * 设置弹出时默认选中的时间,注意与{@link #setContentType(ContentType...)}要匹配 *

* 如果为空那么默认选中当前日期 *

* 如果超过日期范围那么会选中最后一个 * * @param defaultDate * @return */ public DatePickerPop setDefaultDate(String... defaultDate) { mDefaultDate = defaultDate; return this; } /** * 如果使用popWindow的showXXX方法,可能需要将{@linkplain #initView()}的位置放在重写后的方法中 * * @param parentView */ public void showPop(View parentView) { initView(); this.showAtLocation(parentView, Gravity.BOTTOM, 0, 0); } //addChildView private void initView() { LinearLayout view = new LinearLayout(mContext); view.setOrientation(LinearLayout.VERTICAL); FrameLayout contentPar = new FrameLayout(mContext); LinearLayout ll_main = new LinearLayout(mContext); ll_main.setOrientation(LinearLayout.HORIZONTAL); if (null == mContentType || mContentType.length < 0) { TextView child = new TextView(mContext); child.setText("没有设置该显示什么内容,请调用setContentType(...)"); child.setTextColor(Color.RED); child.setGravity(Gravity.CENTER); ll_main.addView(child); } //set current day mCurrentCalendar = Calendar.getInstance(); mCurrentCalendar.setTime(new Date()); for (int i = 0; null != mContentType && i < mContentType.length; i++) { if (mContentType[i] == ContentType.MONTH) { //MONTH ArrayList monthLists = new ArrayList<>(); //前后加空item,以便可以选到所有的item for (int i1 = 0; i1 < ITEM_COUNT / 2; i1++) { monthLists.add(""); } for (int j = 1; j < 13; j++) { monthLists.add(j + ""); } //前后加空item,以便可以选到所有的item for (int i1 = 0; i1 < ITEM_COUNT / 2; i1++) { monthLists.add(""); } ListView monthListView = new ListView(mContext); monthListView.setVerticalScrollBarEnabled(false); monthListView.setDivider(null); final MyAdapter monthAdapter = new MyAdapter(monthLists, ITEM_HEIGHT); monthListView.setAdapter(monthAdapter); LinearLayout.LayoutParams param0 = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT); param0.weight = 1; ll_main.addView(monthListView, param0); monthListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { //when stop scrolling if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { refreshDayList(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mCurrentFocusingViewInMonthList = setFocusingViewStyle(firstVisibleItem, visibleItemCount, monthAdapter, mCurrentFocusingViewInMonthList); } }); if (null != mDefaultDate && i < mDefaultDate.length && !TextUtils.isEmpty(mDefaultDate[i])) { int position = 0; try { position = Integer.parseInt(mDefaultDate[i]) - 1; } catch (Exception e) { e.printStackTrace(); } monthListView.setSelection(position); } else { //current day as default position monthListView.setSelection(mCurrentCalendar.get(Calendar.MONTH)); } } else if (mContentType[i] == ContentType.YEAR) { //YEAR ArrayList yearList = new ArrayList<>(); int currentYear = mCurrentCalendar.get(Calendar.YEAR); for (int k = 0; k < YEAR_OFFSET; k++) { yearList.add(currentYear - YEAR_OFFSET + k + ""); } for (int l = 0; l < YEAR_OFFSET; l++) { yearList.add(currentYear + l + ""); } ListView yearListView = new ListView(mContext); yearListView.setVerticalScrollBarEnabled(false); final MyAdapter yearAdapter = new MyAdapter(yearList, ITEM_HEIGHT); yearListView.setAdapter(yearAdapter); yearListView.setDivider(null); LinearLayout.LayoutParams param1 = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT); param1.weight = 1; ll_main.addView(yearListView, param1); yearListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { //when stop scrolling if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { refreshDayList(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mCurrentFocusingViewInYearList = setFocusingViewStyle(firstVisibleItem, visibleItemCount, yearAdapter, mCurrentFocusingViewInYearList); } }); if (null != mDefaultDate && i < mDefaultDate.length && !TextUtils.isEmpty(mDefaultDate[i])) { int defaultValue = 0; try { defaultValue = Integer.parseInt(mDefaultDate[i]) - currentYear + YEAR_OFFSET; } catch (Exception e) { e.printStackTrace(); } yearListView.setSelection(defaultValue - ITEM_COUNT / 2); } else { //current day as default position yearListView.setSelection(YEAR_OFFSET - ITEM_COUNT / 2); } } else if (mContentType[i] == ContentType.DAY) { //DAY mDayListView = new ListView(mContext); mDayListData = new ArrayList<>(); mDayListAdapter = new MyAdapter(mDayListData, ITEM_HEIGHT); mDayListView.setAdapter(mDayListAdapter); mDayListView.setDivider(null); mDayListView.setVerticalScrollBarEnabled(false); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT); params.weight = 1; ll_main.addView(mDayListView, params); mDayListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mCurrentFocusingViewInDayList = setFocusingViewStyle(firstVisibleItem, visibleItemCount, mDayListAdapter, mCurrentFocusingViewInDayList); } }); } } //default set day list if (null != mDayListData && null != mDayListAdapter) { refreshDayList(); boolean setDefaultDay; for (int i = 0; null != mContentType && i < mContentType.length; i++) { if (ContentType.DAY == mContentType[i]) { setDefaultDay = true; int position = 0; if (setDefaultDay && null != mDefaultDate && !TextUtils.isEmpty(mDefaultDate[i])) { try { position = Integer.parseInt(mDefaultDate[i]) - 1; } catch (Exception e) { e.printStackTrace(); } } else { //current day as default position position = mCurrentCalendar.get(Calendar.DAY_OF_MONTH) - ITEM_COUNT / 2 + 1; } if (position < 0) { position = 0; } if (position > mDayListData.size()) { position = mDayListData.size() - 1; } mDayListView.setSelection(position); break; } } } contentPar.addView(ll_main); contentPar.addView(new PickerHintView(mContext, ITEM_HEIGHT)); RelativeLayout titleRl = new RelativeLayout(mContext); Button btn = new Button(mContext); btn.setText("确定"); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != mListener) { StringBuilder builder = new StringBuilder(); for (int i = 0; null != mContentType && i < mContentType.length; i++) { if (mContentType[i] == ContentType.DAY) { if (null != mCurrentFocusingViewInDayList) { builder.append(mCurrentFocusingViewInDayList.getText()); } else { builder.append(""); } } else if (mContentType[i] == ContentType.MONTH) { if (null != mCurrentFocusingViewInMonthList) { builder.append(mCurrentFocusingViewInMonthList.getText()); } else { builder.append(""); } } else if (mContentType[i] == ContentType.YEAR) { if (null != mCurrentFocusingViewInYearList) { builder.append(mCurrentFocusingViewInYearList.getText()); } else { builder.append(""); } } if (i != mContentType.length - 1) { builder.append("-"); } } mListener.onConfirmClicked(builder.toString()); } DatePickerPop.this.dismiss(); } }); btn.setGravity(Gravity.CENTER); RelativeLayout.LayoutParams paramBtn = new RelativeLayout.LayoutParams(150, RelativeLayout.LayoutParams.MATCH_PARENT); btn.setBackgroundColor(BACKGRO_COLOR_BTN); paramBtn.addRule(RelativeLayout.ALIGN_PARENT_END); btn.setGravity(Gravity.CENTER); paramBtn.setMargins(0, 0, 20, 0); btn.setTextSize(15 ); titleRl.addView(btn, paramBtn); titleRl.setBackgroundColor(BACKGRO_COLOR_TITLE); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0); layoutParams.weight = 1; view.addView(titleRl, layoutParams); LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0); layoutParams1.weight = (float) (ITEM_COUNT - 0.1); view.addView(contentPar, layoutParams1); setContentView(view); setBackgroundDrawable(null); } @Nullable private TextView setFocusingViewStyle(int firstVisibleItem, int visibleItemCount, MyAdapter adapter, TextView lastFocusedView) { //加深选中区域的条目显示 int focusingIndex = firstVisibleItem + visibleItemCount / 2; TextView focusingView = (TextView) adapter.getViewReference(focusingIndex); if (null != focusingView) { focusingView.setTextSize(TEXT_SIZE_FOCUSING); focusingView.setTextColor(TEXT_COLOR_FOCUSING); } //revert the style of last focused item if (null != lastFocusedView && lastFocusedView != focusingView) { lastFocusedView.setTextColor(TEXT_COLOT_DEFAULT); lastFocusedView.setTextSize(TEXT_SIZE_DEFAULT); } return focusingView; } /** * show days according to current month and year; */ private void refreshDayList() { if (mDayListData == null || mDayListData.size() == 1 || mDayListData.size() == 1 || mDayListAdapter == null) { return; } mDayListData.clear(); Calendar calendar = Calendar.getInstance(); if (null != mCurrentFocusingViewInMonthList) { String text = (String) mCurrentFocusingViewInMonthList.getText(); int value = 0; if (!"".equals(text)) { try { value = Integer.parseInt(text) - 1; } catch (Exception e) { e.printStackTrace(); } } calendar.set(calendar.MONTH, value); } if (null != mCurrentFocusingViewInYearList) { String text = (String) mCurrentFocusingViewInYearList.getText(); int value = 0; if (!"".equals(text)) { try { value = Integer.parseInt(text); } catch (Exception e) { e.printStackTrace(); } } calendar.set(Calendar.YEAR, value); } int maximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); //前后加空item,以便可以选到所有的item for (int i = 0; i < ITEM_COUNT / 2; i++) { mDayListData.add(""); } for (int i = 1; i <= maximum; i++) { mDayListData.add(i + ""); } for (int i = 0; i < ITEM_COUNT / 2; i++) { mDayListData.add(""); } mDayListAdapter.notifyDataSetChanged(); } static class MyAdapter extends BaseAdapter { private int mItemHeight; ArrayList mDatas; HashMap mViewMap = new HashMap<>(); public MyAdapter(ArrayList mDatas, int itemHeight) { this.mDatas = mDatas; this.mItemHeight = itemHeight; } @Override public int getCount() { return mDatas.size(); } @Override public String getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = new TextView(parent.getContext()); convertView.setTag(convertView); } TextView tv = (TextView) convertView.getTag(); tv.setText(mDatas.get(position)); tv.setGravity(Gravity.CENTER); tv.setMinHeight(mItemHeight); tv.setBackgroundColor(Color.WHITE); tv.setTextColor(TEXT_COLOT_DEFAULT); tv.setTextSize(TEXT_SIZE_DEFAULT); mViewMap.put(position, tv); return convertView; } View getViewReference(int position) { return mViewMap.get(position); } } //两条横线作为选中提示框 static class PickerHintView extends View { public static final int LINE_PADDING = 25; private int mItemHeight; private int mWidth; private int mHeight; public PickerHintView(Context context, int itemHeight) { super(context); setBackgroundColor(Color.TRANSPARENT); mItemHeight = itemHeight; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //center y int line1Y = mHeight / 2 - mItemHeight / 2; int line2Y = line1Y + mItemHeight; Paint paint = new Paint(); paint.setColor(Color.GRAY); paint.setStrokeWidth(3); if (mContentType.length == 2) { //left line1 int endXLeft = mWidth / 2 - LINE_PADDING; canvas.drawLine(LINE_PADDING, line1Y, endXLeft, line1Y, paint); //left line2 canvas.drawLine(LINE_PADDING, line2Y, endXLeft, line2Y, paint); //right line1 canvas.drawLine(endXLeft + LINE_PADDING, line1Y, mWidth - LINE_PADDING, line1Y, paint); //right line2 canvas.drawLine(endXLeft + LINE_PADDING, line2Y, mWidth - LINE_PADDING, line2Y, paint); } else if (mContentType.length == 3) { //left line1 int stopXLine1 = mWidth / 3 - LINE_PADDING; canvas.drawLine(LINE_PADDING, line1Y, stopXLine1, line1Y, paint); //left line2 canvas.drawLine(LINE_PADDING, line2Y, stopXLine1, line2Y, paint); //middle line1 canvas.drawLine(stopXLine1 + 2 * LINE_PADDING, line1Y, stopXLine1 + LINE_PADDING + mWidth / 3, line1Y, paint); //middle lin2 canvas.drawLine(stopXLine1 + 2 * LINE_PADDING, line2Y, stopXLine1 + LINE_PADDING + mWidth / 3, line2Y, paint); //right line1 canvas.drawLine(mWidth / 3 * 2 + LINE_PADDING, line1Y, mWidth - LINE_PADDING, line1Y, paint); //right line2 canvas.drawLine(mWidth / 3 * 2 + LINE_PADDING, line2Y, mWidth - LINE_PADDING, line2Y, paint); } else if (mContentType.length == 1) { //line1 canvas.drawLine(LINE_PADDING, line1Y, mWidth - LINE_PADDING, line1Y, paint); //line2 canvas.drawLine(LINE_PADDING, line2Y, mWidth - LINE_PADDING, line2Y, paint); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; } } public interface onConfirmListener { /** * 按照传入的contentType 返回字符串 用-分隔! * @param string */ void onConfirmClicked(String string); } }

 

你可能感兴趣的:(安卓:一个简单的日期选择控件)