private static final int TIME_PICKER_INTERVAL=15
private boolean mIgnoreEvent=false
private TimePicker.OnTimeChangedListener mTimePickerListener=new TimePicker.OnTimeChangedListener(){
public void onTimeChanged(TimePicker timePicker, int hourOfDay, int minute){
if (mIgnoreEvent)
return
if (minute%TIME_PICKER_INTERVAL!=0){
int minuteFloor=minute-(minute%TIME_PICKER_INTERVAL)
minute=minuteFloor + (minute==minuteFloor+1 ? TIME_PICKER_INTERVAL : 0)
if (minute==60)
minute=0
mIgnoreEvent=true
timePicker.setCurrentMinute(minute)
mIgnoreEvent=false
}
}
}
本主题介绍 TimePicker 控件的样式和模板。 你可以修改这些资源和默认 ControlTemplate 以便为该控件提供一个唯一的外观。视觉状态
TimePicker 默认样式不定义任何视觉状态。
主题资源
这些资源在该控件的默认样式中使用。
深色主题画笔
若要在深色主题下更改该控件的颜色,请在 App.xaml 中替代这些画笔。
XAML
<SolidColorBrush x:Key="TimePickerHeaderForegroundThemeBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="TimePickerForegroundThemeBrush" Color="#FF000000" />
浅色主题画笔
若要在浅色主题下更改该控件的颜色,请在 App.xaml 中替代这些画笔。
XAML
<SolidColorBrush x:Key="TimePickerHeaderForegroundThemeBrush" Color="#FF000000" />
<SolidColorBrush x:Key="TimePickerForegroundThemeBrush" Color="#FF000000" />
其他资源
XAML
<x:Double x:Key="TimePickerSelectorThemeMinWidth">80</x:Double>
<Thickness x:Key="TimePickerHeaderThemeMargin">0,0,0,6</Thickness>
<Thickness x:Key="TimePickerFirstHostThemeMargin">0,0,20,0</Thickness>
<Thickness x:Key="TimePickerThirdHostThemeMargin">20,0,0,0</Thickness>
<FontWeight x:Key="TimePickerHeaderThemeFontWeight">SemiLight</FontWeight>
共享资源
该控件模板使用这些与其他控件模板共享的资源。更改这些值将影响使用这些资源的其他控件。
XAML
<FontFamily x:Key="ContentControlThemeFontFamily">Segoe UI</FontFamily>
<x:Double x:Key="ControlContentThemeFontSize">14.667</x:Double>
有关主题资源的详细信息,包括用于 HighContrast 主题的值,请参阅 XAML 主题资源引用。
默认样式
XAML
<!-- Default style for Windows.UI.Xaml.Controls.TimePicker -->
<Style TargetType="TimePicker">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="Foreground" Value="{ThemeResource TimePickerForegroundThemeBrush}"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TimePicker">
<Border x:Name="LayoutRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Margin="{TemplateBinding Padding}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentPresenter x:Name="HeaderContentPresenter"
Foreground="{ThemeResource TimePickerHeaderForegroundThemeBrush}"
Margin="{ThemeResource TimePickerHeaderThemeMargin}"
FlowDirection="{TemplateBinding FlowDirection}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="{ThemeResource TimePickerHeaderThemeFontWeight}" />
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Border x:Name="FirstPickerHost" Margin="{ThemeResource TimePickerFirstHostThemeMargin}">
<ComboBox x:Name="HourPicker"
MinWidth="{ThemeResource TimePickerSelectorThemeMinWidth}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}"
Foreground="{TemplateBinding Foreground}"/>
</Border>
<Border x:Name="SecondPickerHost">
<ComboBox x:Name="MinutePicker"
MinWidth="{ThemeResource TimePickerSelectorThemeMinWidth}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}"
Foreground="{TemplateBinding Foreground}"/>
</Border>
<Border x:Name="ThirdPickerHost" Margin="{ThemeResource TimePickerThirdHostThemeMargin}">
<ComboBox x:Name="PeriodPicker"
MinWidth="{ThemeResource TimePickerSelectorThemeMinWidth}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}"
Foreground="{TemplateBinding Foreground}"/>
</Border>
</StackPanel>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--[if !supportLists]-->1. <!--[endif]-->TimePicker组件其实继承FrameLayout的,可以算的上是一个布局,就像那些TabHost等等的布局一样<!--[if !supportLists]-->2. <!--[endif]-->在TimePicker的构造函数里面,
public TimePicker(Context context, AttributeSet attrs, intdefStyle)
我们看到了这样的代码
LayoutInflater inflater =(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
inflater.inflate(R.layout.time_picker,this, // we are the parent
true)
一看我们就应该知道了,其实TimePicker也是一种布局,而且他有自己的布局文件R.layout.time_picker
其实在这个构造函数里面我们知道,android的底层其实也是调用java的
// initialize to current time
Calendar cal = Calendar.getInstance()
这个函数来获取时间的
// by default we're not in 24 hour mode
setCurrentHour(cal.get(Calendar.HOUR_OF_DAY))
setCurrentMinute(cal.get(Calendar.MINUTE))
初始化时间
<!--[if !supportLists]-->3. <!--[endif]-->关于在TimePicker的构造函数里加载的R.layout.time_picker我们打开android的平台文件夹
如:
F:\android-sdk-windows\platforms\android-8\data\res\layout在此文件夹下面我们找到了time_picker.xml文件,打开此布局文件我们看到了两个NumberPicker元属和一个Button元属,此控件的效果图就是这样的(注意此处截图没上,如果需要请下载附件的文档)
用过TimePicker控件的朋友应该知道,此控件会自动生成一个按钮,此按钮是显示AM/PM的,其实我们也可以通过函数
TimePicker.setIs24HourView(true)//设置时间格式为24小时制
来设置TimePicker的时间显示方法,默认情况下此属性值为false
<!--[if !supportLists]-->4. <!--[endif]-->分析NumberPicker组件,我们找到android的源码找到NumberPicker.java在此类里面我们看到了此类其实是继承LinearLayout由此可知,其实NumberPicker组件也是一个布局元属
在NumberPicker的构造函数里面我们同样看到了
LayoutInflater inflater=(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
inflater.inflate(R.layout.number_picker, this, true)
这样的代码,由此我们找到R.layout.number_picker布局文件
<!--[if !supportLists]-->5. <!--[endif]-->分析R.layout.number_picker文件
如:F:\android-sdk-windows\platforms\android-8\data\res\layout在这样的路径下面我们可以找到R.layout.number_picker.xml布局文件打开此布局文件,我们看到这样的代码
有两个NumberPickerButton和一个EditText其实分析我们不难知道其实这个布局文件生成的样式就是这样的
<!--[if !supportLists]-->6. <!--[endif]-->说了这么多下面我来说重点了,其实我们每次点击+或-都会触发这个监听函数
setOnTimeChangedListener所以如果我们需要对时间进行定制的话,我们可以使用此监听器来做一些事情此监听器会插入三个参数很好的是他把TimePicker对象也传入进来了
public void onTimeChanged(TimePickerview, int hourOfDay, int minute)
下面我来说个业务需求
我们要为用户提供一个选择时间的界面,但用户选择时间秒的时候用户只有两个选择要是秒是00,如
要么秒是30,如
我们该如何来做出这样的应用了,下面我就告诉大家我是如何做出这样的应用的
通过上面我们对TimePicker的源码架构分析可以知道其实我们只要通过java强大的反射机制来修改源码里面的一些属性值就可以做到了
<!--[if !supportLists]-->1.<!--[endif]-->在TimePicker类里面我们找到private
final NumberPicker mMinutePicker属性因为第3步我们分析了TimePicker的布局构成。是由两个NumberPicker元属和一个Button元属构成的布局文件,我们为什么要反射这个属性了,因为这个属性实现的布局文件里面用到了NumberPicker而NumberPicker是我们设置时间的小时和分钟的组件通过反射mMinutePicker属性我们可以拿到mMinutePicker的实例对象然后通过此对象我们需要反射出NumberPicker里面的mCurrent属性和mCurrentMinute,然后我们重新对这两个属性赋值就可以了下面来看我的代码实现
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePickerview, int hourOfDay,
int minute) {
try {
Field mMinutePicker =view.getClass().getDeclaredField("mMinutePicker")
mMinutePicker.setAccessible(true)
Object value = mMinutePicker.get(view)
Log.i(TAG,value.getClass()+"")
//反射NumberPicker里面的mCurrent此属性值是显示给用户看的
Field mCurrent = value.getClass().getDeclaredField("mCurrent")
mCurrent.setAccessible(true)
//反射TimePicker类里面的mCurrentMinute属性,此属性是保存用户设置的时间
Field mCurrentMinute = view.getClass().getDeclaredField("mCurrentMinute")
mCurrentMinute.setAccessible(true)
if(minute>0&&minute<30){
mCurrent.set(value, 30)
mCurrentMinute.set(view, 30)
}
else{
mCurrent.set(value, 0)
mCurrentMinute.set(view, 0)
}
//判断用户是否点击了减按钮
if(minute==59){//如果点击了时间的减按钮那么minute值为00---->59或30---->29
//00---->59
mCurrent.set(value, 30)
mCurrentMinute.set(view, 30)
}
else if(minute == 29){//30---->29
mCurrent.set(value, 0)
mCurrentMinute.set(view, 0)
}
} catch (Exception e) {
e.printStackTrace()
}
}
})
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)