接上一篇文章chenglei1986/DatePicker源码解析(一),我们继续将剩余的部分讲完,其实剩余的内容,就是利用Numberpicker来组成一个datePicker,代码非常的简单
为了实现自定义布局的效果,我们给Datepciker定制了一个layout,大家可以定制自己的layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:app1="http://schemas.android.com/apk/res/com.example.androidtest"> <LinearLayout android:layout_width="fill_parent" android:layout_height="48dp" android:orientation="vertical" android:background="@color/base_color_gray_bg" android:gravity="center_vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="@color/base_color_text_black" android:layout_marginLeft="10dp" android:text="@string/bday" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="18dp" android:background="@color/base_color_text_white" android:orientation="horizontal" > <com.example.androidtest.NumberPicker android:id="@+id/day_picker" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="16dp" app:flagText="asdasd" app:flagTextSize="30dp" app:flagTextColor="#abcdef" app:startNumber="1" app:endNumber="31" app:currentNumber="11" app:textColorNormal="#000000" app:textSizeHighLight="24dp" app:textColorHighLight="#abcdef" app:textSizeNormal="22dp" app:verticalSpacing="50dp" app:lines="3" /> <LinearLayout android:layout_width="0dp" android:layout_height="fill_parent" android:orientation="vertical" android:layout_weight="0.7" ></LinearLayout> <com.example.androidtest.NumberPicker android:id="@+id/month_picker" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="16dp" app:startNumber="1" app:endNumber="12" app:currentNumber="16" app:textSizeHighLight="24dp" app:textSizeNormal="22dp" app:verticalSpacing="50dp" app:lines="3" /> <LinearLayout android:layout_width="0dp" android:layout_height="fill_parent" android:orientation="vertical" android:layout_weight="0.7" ></LinearLayout> <com.example.androidtest.NumberPicker android:id="@+id/year_picker" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="16dp" app:startNumber="1970" app:endNumber="2050" app:currentNumber="2005" app:textSizeHighLight="24dp" app:textSizeNormal="22dp" app:verticalSpacing="50dp" app:lines="3" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="48dp" android:orientation="vertical" android:background="@color/base_color_header_green" > <Button android:id="@+id/finish" android:layout_width="fill_parent" android:layout_height="48dp" android:text="@string/finish" android:background="@null" android:textSize="18sp" android:textColor="@color/base_color_text_white" /> </LinearLayout> </LinearLayout>
在datepicker的初始化中,我们加载这个布局就可以了
public DatePicker(Context context, AttributeSet attrs) { super(context, attrs); mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); init(); }
我们有三个numberpicker
public class DatePicker extends LinearLayout implements NumberPicker.OnValueChangeListener { //日期选择器 private NumberPicker mYearPicker; private NumberPicker mMonthPicker; private NumberPicker mDayOfMonthPicker; private Calendar mCalendar; //日期监听器 private OnDateChangedListener mOnDateChangedListener; private LayoutInflater mLayoutInflater;
在init函数了,设置一些基本属性,监听等
private void init() { mLayoutInflater.inflate(R.layout.date_picker_layout, this, true); mYearPicker = (NumberPicker) findViewById(R.id.year_picker); mMonthPicker = (NumberPicker) findViewById(R.id.month_picker); mDayOfMonthPicker = (NumberPicker) findViewById(R.id.day_picker); //为每个numberpicker设置监听器(统一监听) mYearPicker.setOnValueChangeListener(this); mMonthPicker.setOnValueChangeListener(this); mDayOfMonthPicker.setOnValueChangeListener(this); //获取自定义选项数组 if (!getResources().getConfiguration().locale.getCountry().equals("CN") && !getResources().getConfiguration().locale.getCountry().equals("TW")) { String[] monthNames = getResources().getStringArray(R.array.month_name); mMonthPicker.setCustomTextArray(monthNames); } mCalendar = Calendar.getInstance(); setDate(mCalendar.getTime()); }
注意到日期格式不是一成不变的,例如2月,有可能是28,29天,我们利用Calendar类来为我们提供这个范围
/** * 设置日期默认值 * @param date */ public void setDate(Date date) { mCalendar.setTime(date); mDayOfMonthPicker.setEndNumber(mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); mYearPicker.setCurrentNumber(mCalendar.get(Calendar.YEAR)); mMonthPicker.setCurrentNumber(mCalendar.get(Calendar.MONTH) + 1); mDayOfMonthPicker.setCurrentNumber(mCalendar.get(Calendar.DAY_OF_MONTH)); }
最后是监听器的设置,只要有一个numberpicker改变,就应该通知监听器
@Override /** * 三个numberpicker,有一个改变,就产生通知 */ public void onValueChange(final NumberPicker picker, final int oldVal, final int newVal) { if (picker == mYearPicker) { mCalendar.set(Calendar.YEAR, newVal); mDayOfMonthPicker.setEndNumber(mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); } else if (picker == mMonthPicker) { mCalendar.set(Calendar.MONTH, newVal - 1); mDayOfMonthPicker.setEndNumber(mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); } else if (picker == mDayOfMonthPicker) { mCalendar.set(Calendar.DAY_OF_WEEK, newVal); } notifyDateChanged(); }
最后还有剩余的播放,我直接贴出Sound类
package com.example.androidtest; import android.content.Context; import android.media.AudioManager; import android.media.SoundPool; public class Sound { private SoundPool mSoundPool; private AudioManager mAudioManager; private float mCurrVolume; private Context mContext; private int mSoundId; public Sound(Context context) { mContext = context; mSoundPool = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); } /** * 播放声音 */ public void playSoundEffect() { mCurrVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM); if (mSoundId != 0) { mSoundPool.play(mSoundId, mCurrVolume, mCurrVolume, 0, 0, 1); } else { mAudioManager.playSoundEffect(AudioManager.FX_KEY_CLICK, mCurrVolume); } } /** * 设置声音 * @param resId */ public void setCustomSound(int resId) { mSoundId = mSoundPool.load(mContext, resId, 1); } }
这个类会产生系统的默认声音,我们使用声音之前,要为datepicker设置
public void setSoundEffect(Sound sound) { mYearPicker.setSoundEffect(sound); mMonthPicker.setSoundEffect(sound); mDayOfMonthPicker.setSoundEffect(sound); } @Override public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { super.setSoundEffectsEnabled(soundEffectsEnabled); mYearPicker.setSoundEffectsEnabled(soundEffectsEnabled); mMonthPicker.setSoundEffectsEnabled(soundEffectsEnabled); mDayOfMonthPicker.setSoundEffectsEnabled(soundEffectsEnabled); }
以上的代码都非常简单,更重要的Numberpicker的理解,搭建好numberpicker,datepciker自然就出来了
最后贴出datepicker完整代码
package com.example.androidtest; import java.util.Calendar; import java.util.Date; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.LinearLayout; public class DatePicker extends LinearLayout implements NumberPicker.OnValueChangeListener { //日期选择器 private NumberPicker mYearPicker; private NumberPicker mMonthPicker; private NumberPicker mDayOfMonthPicker; private Calendar mCalendar; //日期监听器 private OnDateChangedListener mOnDateChangedListener; private LayoutInflater mLayoutInflater; public DatePicker(Context context) { this(context, null); } public DatePicker(Context context, AttributeSet attrs) { super(context, attrs); mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); init(); } private void init() { mLayoutInflater.inflate(R.layout.date_picker_layout, this, true); mYearPicker = (NumberPicker) findViewById(R.id.year_picker); mMonthPicker = (NumberPicker) findViewById(R.id.month_picker); mDayOfMonthPicker = (NumberPicker) findViewById(R.id.day_picker); //为每个numberpicker设置监听器(统一监听) mYearPicker.setOnValueChangeListener(this); mMonthPicker.setOnValueChangeListener(this); mDayOfMonthPicker.setOnValueChangeListener(this); //获取自定义选项数组 if (!getResources().getConfiguration().locale.getCountry().equals("CN") && !getResources().getConfiguration().locale.getCountry().equals("TW")) { String[] monthNames = getResources().getStringArray(R.array.month_name); mMonthPicker.setCustomTextArray(monthNames); } mCalendar = Calendar.getInstance(); setDate(mCalendar.getTime()); } /** * 设置日期默认值 * @param date */ public void setDate(Date date) { mCalendar.setTime(date); mDayOfMonthPicker.setEndNumber(mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); mYearPicker.setCurrentNumber(mCalendar.get(Calendar.YEAR)); mMonthPicker.setCurrentNumber(mCalendar.get(Calendar.MONTH) + 1); mDayOfMonthPicker.setCurrentNumber(mCalendar.get(Calendar.DAY_OF_MONTH)); } @Override /** * 三个numberpicker,有一个改变,就产生通知 */ public void onValueChange(final NumberPicker picker, final int oldVal, final int newVal) { if (picker == mYearPicker) { mCalendar.set(Calendar.YEAR, newVal); mDayOfMonthPicker.setEndNumber(mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); } else if (picker == mMonthPicker) { mCalendar.set(Calendar.MONTH, newVal - 1); mDayOfMonthPicker.setEndNumber(mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); } else if (picker == mDayOfMonthPicker) { mCalendar.set(Calendar.DAY_OF_WEEK, newVal); } notifyDateChanged(); } /** * The callback used to indicate the user changes\d the date. */ public interface OnDateChangedListener { /** * Called upon a date change. * * @param view The view associated with this listener. * @param year The year that was set. * @param monthOfYear The month that was set (0-11) for compatibility * with {@link java.util.Calendar}. * @param dayOfMonth The day of the month that was set. */ void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth); } public void setOnDateChangedListener(OnDateChangedListener l) { mOnDateChangedListener = l; } private void notifyDateChanged() { if (mOnDateChangedListener != null) { mOnDateChangedListener.onDateChanged(this, getYear(), getMonth(), getDayOfMonth()); } } public int getYear() { return mCalendar.get(Calendar.YEAR); } public int getMonth() { return mCalendar.get(Calendar.MONTH) + 1; } public int getDayOfMonth() { return mCalendar.get(Calendar.DAY_OF_MONTH); } public void setSoundEffect(Sound sound) { mYearPicker.setSoundEffect(sound); mMonthPicker.setSoundEffect(sound); mDayOfMonthPicker.setSoundEffect(sound); } @Override public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { super.setSoundEffectsEnabled(soundEffectsEnabled); mYearPicker.setSoundEffectsEnabled(soundEffectsEnabled); mMonthPicker.setSoundEffectsEnabled(soundEffectsEnabled); mDayOfMonthPicker.setSoundEffectsEnabled(soundEffectsEnabled); } }
时间: 2024-11-07 21:35:13