版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ShenQiXiaYang/article/details/83151034
对于PopupWindow不了解的,请自行移步到Android PopupWindow详解
对于NumberPicker不了解的,请自行移步到android NumberPicker 全面解析
本次Demo总共有四种样式。由于全部贴出本文篇幅较长,所以只贴关于月日时分样式选择器代码。
下面直接看我们的自定义View,上代码:
SelectTimePop .java
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.PopupWindow;
import com.maigu.yang.datetimepickerdemo.R;
import java.util.Calendar;
public class SelectTimePop extends PopupWindow implements OnClickListener {
private Button btnCancel, btnConfirm;
private DateTimePicker mDateTimePicker;
private Calendar mDate = Calendar.getInstance();
private OnDateTimeSetListener mOnDateTimeSetListener;
private Activity context;
public SelectTimePop(final Activity context, View parent) {
super(context);
this.context = context;
mDateTimePicker = new DateTimePicker(context);
mDateTimePicker.setOnDateTimeChangedListener(new DateTimePicker.OnDateTimeChangedListener() {
@Override
public void onDateTimeChanged(DateTimePicker view, int year, int month, int day, int hour, int minute) {
mDate.set(Calendar.YEAR, year);
mDate.set(Calendar.MONTH, month);
mDate.set(Calendar.DAY_OF_MONTH, day);
mDate.set(Calendar.HOUR_OF_DAY, hour);
mDate.set(Calendar.MINUTE, minute);
mDate.set(Calendar.SECOND, 0);
}
});
btnCancel = (Button) mDateTimePicker.findViewById(R.id.btn_cancel);
btnConfirm = (Button) mDateTimePicker.findViewById(R.id.btn_ok);
btnCancel.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dismiss();
}
});
btnConfirm.setOnClickListener(this);
// 设置SelectTimePop的View
this.setContentView(mDateTimePicker);
// 设置SelectTimePop弹出窗体的宽
this.setWidth(LayoutParams.MATCH_PARENT);
// 设置SelectTimePop弹出窗体的高
this.setHeight(LayoutParams.WRAP_CONTENT);
// 设置SelectTimePop弹出窗体可点击
this.setFocusable(true);
// 设置SelectTimePop弹出窗体动画效果
this.setAnimationStyle(R.style.animation);
// 设置SelectTimePop弹出窗体的背景
ColorDrawable dw = new ColorDrawable(0xffffffff);
this.setBackgroundDrawable(dw);
// 在指定位置的弹出窗口中显示内容视图。
showAtLocation(parent, Gravity.BOTTOM, 0, 0);
anseBg();
this.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
baiseBg();
}
});
}
private void anseBg() {
WindowManager.LayoutParams params = context.getWindow()
.getAttributes();
params.alpha = 0.7f;
context.getWindow().setAttributes(params);
}
private void baiseBg() {
WindowManager.LayoutParams params = context.getWindow()
.getAttributes();
params.alpha = 1.0f;
context.getWindow().setAttributes(params);
}
@Override
public void onClick(View v) {
this.dismiss();
if (mOnDateTimeSetListener != null) {
mOnDateTimeSetListener.OnDateTimeSet(mDate.getTimeInMillis());
}
}
public interface OnDateTimeSetListener {
void OnDateTimeSet(long date);
}
public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) {
mOnDateTimeSetListener = callBack;
}
}
上文代码中使用到的dialog_datedialog.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_title2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="0.8dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ffffff"
android:text="取消"
android:textColor="@android:color/black"
android:textSize="14sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_type"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:gravity="center"
android:text="确认时间"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/btn_ok"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ffffff"
android:text="确定"
android:textColor="@android:color/black"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
<NumberPicker
android:id="@+id/np_date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5" />
<NumberPicker
android:id="@+id/np_hour"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_weight="2"
tools:ignore="RtlHardcoded" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=":"
android:textSize="20sp"
tools:ignore="HardcodedText" />
<NumberPicker
android:id="@+id/np_minute"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2" />
</LinearLayout>
</LinearLayout>
DateTimePicker.java
import java.util.Calendar;
import android.content.Context;
import android.text.format.DateFormat;
import android.widget.FrameLayout;
import android.widget.NumberPicker;
import android.widget.NumberPicker.OnValueChangeListener;
import com.maigu.yang.datetimepickerdemo.R;
public class DateTimePicker extends FrameLayout {
private final NumberPicker mDateSpinner;
private final NumberPicker mHourSpinner;
private final NumberPicker mMinuteSpinner;
private Calendar mDate;
private int mHour, mMinute;
private String[] mDateDisplayValues = new String[7];
private OnDateTimeChangedListener mOnDateTimeChangedListener;
public DateTimePicker(Context context) {
super(context);
mDate = Calendar.getInstance();
mHour = mDate.get(Calendar.HOUR_OF_DAY);
mMinute = mDate.get(Calendar.MINUTE);
inflate(context, R.layout.dialog_datedialog, this);
mDateSpinner = (NumberPicker) this.findViewById(R.id.np_date);
(mDateSpinner.getChildAt(0)).setFocusable(false);
// Sets the min value of the picker.——设置最小值
mDateSpinner.setMinValue(0);
// Sets the max value of the picker.——设置最大值
mDateSpinner.setMaxValue(6);
updateDateControl();
// Sets the listener to be notified on change of the current value.——设置要在更改当前值时通知监听器。
mDateSpinner.setOnValueChangedListener(mOnDateChangedListener);
mHourSpinner = (NumberPicker) this.findViewById(R.id.np_hour);
(mHourSpinner.getChildAt(0)).setFocusable(false);
mHourSpinner.setMaxValue(23);
mHourSpinner.setMinValue(0);
// Set the current value for the number picker.——设置数字选择器的当前值。
mHourSpinner.setValue(mHour);
mHourSpinner.setOnValueChangedListener(mOnHourChangedListener);
mMinuteSpinner = (NumberPicker) this.findViewById(R.id.np_minute);
(mMinuteSpinner.getChildAt(0)).setFocusable(false);
mMinuteSpinner.setMaxValue(59);
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setValue(mMinute);
mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener);
}
private OnValueChangeListener mOnDateChangedListener = new OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
updateDateControl();
onDateTimeChanged();
}
};
private OnValueChangeListener mOnHourChangedListener = new OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mHour = mHourSpinner.getValue();
onDateTimeChanged();
}
};
private OnValueChangeListener mOnMinuteChangedListener = new OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mMinute = mMinuteSpinner.getValue();
onDateTimeChanged();
}
};
private void updateDateControl() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(mDate.getTimeInMillis());
cal.add(Calendar.DAY_OF_YEAR, -7 / 2 - 1);
mDateSpinner.setDisplayedValues(null);
for (int i = 0; i < 7; ++i) {
cal.add(Calendar.DAY_OF_YEAR, 1);
mDateDisplayValues[i] = (String) DateFormat.format("MM月dd日", cal);
}
mDateSpinner.setDisplayedValues(mDateDisplayValues);
// Sets the values to be displayed.——设置要显示的值。
mDateSpinner.setValue(7 / 2);
mDateSpinner.invalidate();
}
public interface OnDateTimeChangedListener {
void onDateTimeChanged(DateTimePicker view, int year, int month, int day, int hour, int minute);
}
public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) {
mOnDateTimeChangedListener = callback;
}
private void onDateTimeChanged() {
if (mOnDateTimeChangedListener != null) {
mOnDateTimeChangedListener.onDateTimeChanged(this, mDate.get(Calendar.YEAR),
mDate.get(Calendar.MONTH), mDate.get(Calendar.DAY_OF_MONTH), mHour, mMinute);
}
}
}
在MainActivity.java文件中的使用
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import com.maigu.yang.datetimepickerdemo.timepicker.SelectDateTimePop;
import com.maigu.yang.datetimepickerdemo.timepicker.SelectTimePop;
import com.maigu.yang.datetimepickerdemo.timepicker.SelectYearTimePop;
import com.maigu.yang.datetimepickerdemo.util.DateUtils;
import java.text.ParseException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btn_date_type_one;
private Button btn_date_type_two;
private Button btn_date_type_three;
private Button btn_date_type_four;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
btn_date_type_one = (Button) findViewById(R.id.btn_date_type_one);
btn_date_type_one.setOnClickListener(this);
btn_date_type_two = (Button) findViewById(R.id.btn_date_type_two);
btn_date_type_two.setOnClickListener(this);
btn_date_type_three = (Button) findViewById(R.id.btn_date_type_three);
btn_date_type_three.setOnClickListener(this);
btn_date_type_four = (Button) findViewById(R.id.btn_date_type_four);
btn_date_type_four.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_date_type_one:
SelectTimePop selectTimePop = new SelectTimePop(MainActivity.this, btn_date_type_one);
selectTimePop.setOnDateTimeSetListener(new SelectTimePop.OnDateTimeSetListener() {
@Override
public void OnDateTimeSet(long date) {
String time = null;
try {
time = DateUtils.longToString(date, "MM月dd日 HH时:mm分");
} catch (ParseException e) {
e.printStackTrace();
}
btn_date_type_one.setText(time);
}
});
break;
case R.id.btn_date_type_two:
SelectYearTimePop selectYearTimePop = new SelectYearTimePop(MainActivity.this, btn_date_type_two, true);
selectYearTimePop.setOnDateTimeSetListener(new SelectYearTimePop.OnDateTimeSetListener() {
@Override
public void OnDateTimeSet(long date, int i, View v) throws ParseException {
String time = null;
try {
time = DateUtils.longToString(date, "yyyy年");
} catch (ParseException e) {
e.printStackTrace();
}
btn_date_type_two.setText(time);
}
});
break;
case R.id.btn_date_type_three:
SelectDateTimePop selectDateTimePop = new SelectDateTimePop(MainActivity.this, btn_date_type_three, true, false);
selectDateTimePop.setOnDateTimeSetListener(new SelectDateTimePop.OnDateTimeSetListener() {
@Override
public void OnDateTimeSet(long date, int i, View v) throws ParseException {
String time = null;
try {
time = DateUtils.longToString(date, "yyyy年MM月dd日");
} catch (ParseException e) {
e.printStackTrace();
}
btn_date_type_three.setText(time);
}
});
break;
case R.id.btn_date_type_four:
SelectDateTimePop selectDateTimePopLast = new SelectDateTimePop(MainActivity.this, btn_date_type_three, true, true);
selectDateTimePopLast.setOnDateTimeSetListener(new SelectDateTimePop.OnDateTimeSetListener() {
@Override
public void OnDateTimeSet(long date, int i, View v) throws ParseException {
String time = null;
try {
time = DateUtils.longToString(date, "yyyy年MM月dd日");
if (i == 0) {
btn_date_type_four.setText(time + " 上午");
} else {
btn_date_type_four.setText(time + " 下午");
}
} catch (ParseException e) {
e.printStackTrace();
}
}
});
break;
default:
break;
}
}
}
MainActivity.java中使用的activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_date_type_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="点击弹出月日时分选择器"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/btn_date_type_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btn_date_type_one"
android:layout_centerInParent="true"
android:text="点击弹出年选择器"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/btn_date_type_three"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btn_date_type_two"
android:layout_centerInParent="true"
android:text="点击弹出年月日选择器"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/btn_date_type_four"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btn_date_type_three"
android:layout_centerInParent="true"
android:text="点击弹出年月日上下午选择器"
tools:ignore="HardcodedText" />
</RelativeLayout>
运行效果图:
样式一:月日时分选择器(上面代码运行后就是此效果图)
样式二:年选择器
样式三:年月日选择器
样式四:年月日上下午选择器
项目中的代码可以自定义改动,定制自己想要的日历选择器。