一直都是在博客园和csdn上看各种大牛的技术博客,终于忍不住要开始自己写博客,希望一起成长,我会把自己的学习的过程放到博客里,但同时我更愿意贴出的是我碰到的错误。也欢迎网友来指导与纠正,大家一起进步,更希望的是自己能够坚持写博客。
废话不多说,直接进入正题,最近在学习android开发,对于这些界面的开发,最重要的就是一堆控件的使用了。今天登场的就是DatePicker和TimePicker。既然要学习,那就需要有学习的资料。碰到一个新的东西最自然的想法就是去搜一下。网上相关的文章也是一大堆。再有了资料之后就可以入手设计了,对于日期和时间选择控件,最常用的大概就是获得选择结果。所以一个demo的功能就出来了:
1.程序启动进入主界面,看到一个最简单的布局,提示用户选择开始时间和结束时间。
2.用户触摸EditText时,触发onTouch事件。弹出datepicker dialog。
3.用户选择日期和时间并确定。
4.结果返回到EditText。
有了程序的流程,接下来就来设计界面。首先是主界面activity_main.xml的布局文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" 6 android:padding="10dip" 7 tools:context=".MainActivity" > 8 <RelativeLayout 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content"> 11 <TextView 12 android:id="@+id/startTextView" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:gravity="center_vertical" 16 android:text="@string/start" /> 17 <EditText 18 android:id="@+id/startEditText" 19 android:layout_width="fill_parent" 20 android:layout_height="wrap_content" 21 android:singleLine="true" 22 android:layout_toRightOf="@id/startTextView"/> 23 </RelativeLayout> 24 <RelativeLayout 25 android:layout_width="fill_parent" 26 android:layout_height="wrap_content"> 27 <TextView 28 android:id="@+id/endTextView" 29 android:layout_width="wrap_content" 30 android:layout_height="wrap_content" 31 android:gravity="center_vertical" 32 android:text="@string/end" /> 33 <EditText 34 android:id="@+id/endEditText" 35 android:layout_width="fill_parent" 36 android:layout_height="wrap_content" 37 android:singleLine="true" 38 android:layout_toRightOf="@id/endTextView"/> 39 </RelativeLayout> 40 </LinearLayout>
界面效果如下:
接下来是datepicker dialog的view布局datepicker.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" 6 android:scrollbars="vertical"> 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:textSize="16sp" 11 android:text="@string/datepicker"/> 12 <DatePicker 13 android:id="@+id/myDatePicker" 14 android:layout_width="fill_parent" 15 android:layout_height="wrap_content" 16 android:layout_marginTop="5dip"/> 17 <TextView 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:textSize="16sp" 21 android:text="@string/timepicker"/> 22 <TimePicker 23 android:id="@+id/myTimePicker" 24 android:layout_width="fill_parent" 25 android:layout_height="wrap_content" 26 android:layout_marginTop="5dip" /> 27 28 </LinearLayout>
界面效果如下:
这效果,吓我一跳。怎么这样子。算了先不管了。等运行再看看。现在布局文件都有了那么就要开始程序的功能部分了。
1 package com.example.datepickertest; 2 3 import java.util.Calendar; 4 5 import android.app.Activity; 6 import android.app.AlertDialog; 7 import android.content.DialogInterface; 8 import android.os.Bundle; 9 import android.text.InputType; 10 import android.view.Menu; 11 import android.view.MotionEvent; 12 import android.view.View; 13 import android.widget.DatePicker; 14 import android.widget.EditText; 15 import android.widget.TimePicker; 16 17 public class MainActivity extends Activity { 18 //定义控件变量 19 private EditText startEdit,endEdit; 20 @Override 21 protected void onCreate(Bundle savedInstanceState) { 22 super.onCreate(savedInstanceState); 23 setContentView(R.layout.activity_main); 24 startEdit = (EditText) findViewById(R.id.startEditText); 25 endEdit = (EditText) findViewById(R.id.endEditText); 26 startEdit.setOnTouchListener(new MyTouchListener()); 27 endEdit.setOnTouchListener(new MyTouchListener()); 28 } 29 class MyTouchListener implements View.OnTouchListener{ 30 @Override 31 public boolean onTouch(View v, MotionEvent event) { 32 // TODO Auto-generated method stub 33 if(event.getAction() == MotionEvent.ACTION_DOWN){ 34 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 35 View view = View.inflate(MainActivity.this,R.layout.datepicker,null); 36 //获取datepicker和timepicker,在这里要注意. 37 //如果是直接通过datepicker = (DatePicker) findViewById(R.id.myDatePicker);或者 38 //datepicker = (DatePicker) this.findViewById(R.id.myDatePicker);来获取控件 39 //会出现空指针异常,因为当前的this指的是MyTouchListener的实例。所以在这里通过view来取得控件 40 final DatePicker datepicker = (DatePicker) view.findViewById(R.id.myDatePicker); 41 final TimePicker timepicker = (TimePicker) view.findViewById(R.id.myTimePicker); 42 //设置对话框的布局文件 43 builder.setView(view); 44 //获取Calendar实例来初始化datepicker和设置timepicker的初始值 45 Calendar cal = Calendar.getInstance(); 46 cal.setTimeInMillis(System.currentTimeMillis()); 47 datepicker.init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 48 cal.get(Calendar.DAY_OF_MONTH), null); 49 timepicker.setIs24HourView(true); 50 timepicker.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY)); 51 timepicker.setCurrentMinute(cal.get(Calendar.MINUTE)); 52 //判断事件的对象 53 if(v.getId() == R.id.startEditText){ 54 final int inType = startEdit.getInputType(); 55 startEdit.setInputType(InputType.TYPE_NULL); 56 startEdit.onTouchEvent(event); 57 startEdit.setInputType(inType); 58 //设置对话框属性 59 builder.setTitle(R.string.starttitle); 60 builder.setPositiveButton("确 定", new DialogInterface.OnClickListener() 61 { 62 63 @Override 64 public void onClick(DialogInterface dialog, int which) { 65 // TODO Auto-generated method stub 66 StringBuffer sb = new StringBuffer(); 67 sb.append(String.format("%d-%02d-%02d", 68 datepicker.getYear(), 69 datepicker.getMonth()+1, 70 datepicker.getDayOfMonth())); 71 sb.append(" "); 72 sb.append(timepicker.getCurrentHour()) 73 .append(":") 74 .append(timepicker.getCurrentMinute()); 75 startEdit.setText(sb); 76 dialog.cancel(); 77 } 78 } 79 ); 80 } 81 if(v.getId() == R.id.endEditText){ 82 final int inType = endEdit.getInputType(); 83 endEdit.setInputType(InputType.TYPE_NULL); 84 endEdit.onTouchEvent(event); 85 endEdit.setInputType(inType); 86 //设置对话框属性 87 builder.setTitle(R.string.endtitle); 88 builder.setPositiveButton("确 定", new DialogInterface.OnClickListener() 89 { 90 91 @Override 92 public void onClick(DialogInterface dialog, int which) { 93 // TODO Auto-generated method stub 94 StringBuffer sb = new StringBuffer(); 95 sb.append(String.format("%d-%02d-%02d", 96 datepicker.getYear(), 97 datepicker.getMonth() + 1, 98 datepicker.getDayOfMonth())); 99 sb.append(" "); 100 sb.append(timepicker.getCurrentHour()) 101 .append(":").append(timepicker.getCurrentMinute()); 102 endEdit.setText(sb); 103 dialog.cancel(); 104 } 105 } 106 ); 107 } 108 //创建对话框,并显示 109 AlertDialog dialog = builder.create(); 110 dialog.show(); 111 } 112 return true; 113 } 114 115 } 116 @Override 117 public boolean onCreateOptionsMenu(Menu menu) { 118 // Inflate the menu; this adds items to the action bar if it is present. 119 getMenuInflater().inflate(R.menu.main, menu); 120 return true; 121 } 122 123 }
接下来运行程序:发现界面丑的简直不能忍啊。
连时间都看不到,让我怎么选。上面那个日历也是大的可以。既然涉及到外观那么说不定在XML文件里能找到些许的影子。抱着试一试的想法去XML文件中找,但是看了那茫茫多的属性就在想这么找何时才能找到。想到android通常在XML中出现的属性,就会有相似的set和get方法。于是乎,直接看SDK文档,找到set开头的那些函数。果然很快就定位在setCalendarViewShown上。看了一下的介绍感觉八九不离十,实验才是检验真理的标准。于是乎在程序中添加一行代码
1 //获取Calendar实例来初始化datepicker和设置timepicker的初始值 2 Calendar cal = Calendar.getInstance(); 3 cal.setTimeInMillis(System.currentTimeMillis()); 4 datepicker.setCalendarViewShown(false); 5 datepicker.init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 6 cal.get(Calendar.DAY_OF_MONTH), null);
运行一下程序,果然。界面瞬间不一样。
然后试验一下发现程序和我们想的一样正常工作。但是到这里就完了吗?反过来想想既然有set方法去设置,那么会不会有这个属性呢,我们再一次来到XML文件,这一次有了目标。属性可能是带CalendarViewShown这类字样的,很快我们发现确实有这个属性。立马尝试了一下,将它设为false,并删掉之前的那一句代码。程序依然正常运行。所以这个属性是正确的。好像到这里就该去睡觉了,但是细心的人已经发现在上面的代码中有一个地方有点怪,我们看到这个getMonth()在返回后还加了1,那么我们把这个加1去掉呢,再次运行程序发现,显示的月份总比选择的月份小1,天天和程序打交道的话就会立即反应一下:"难道月份也是从0计数的?",还是老套路,碰到怪问题就去问SDK,但是发现getmonth这个函数的解释只有一句话,返回选择的月,于是我们望上看,突然发现了Calendar的常量字段。发现果然是从0开始:
public static final int JANUARY
Added in API level 1
Value of the MONTH field indicating the first month of the year.
Constant Value: 0 (0x00000000)。那么既然是这样,反过来我们去设置月份的时候也一样,当我们通过函数这是对应参数为8的时候其实是9.所以要注意程序在参数的处理。今天就写到这儿吧,该睡觉了。
1 sb.append(String.format("%d-%02d-%02d", 2 datepicker.getYear(), 3 datepicker.getMonth()+1, 4 datepicker.getDayOfMonth()));