好久没有写东西了,这两天自己联系android小项目的时候,就想到了自己做一个日历。最简单的功能,当前日期能够突出显示,能够选择月份和年份 。上图
下面来说实现思路
首先:日期的确定主要是采用java中Calendar这个类,有了这个类,所有日期的获取都是浮云了。
其次:布局,看到这个布局很容易想到的就是表格布局了,最外部的线性布局加上里面的表格布局,采用表格布局的还有一个好处就是里面的选项都自动的对齐了,不要自己来控制。
第三:用来显示每一个日期项的组件,很简单就是一个TextView ,因为需要在布局中区分出每一个日期项,所以我的处理是自己重写了TextView的onDraw方法,为其添加上边框。
第四:里面这么多控件采用什么方法来实现布局呢?如果采用xml的方法来布局,那么真是手都要写断了,这里采用了代码的方式来实现布局,布局的表格采用两层循环就能解决。
因为没有考虑优化和耦合性问题,所以代码写出来了不是很好看。
首先是自己定义的TextView
public class CalendarElement extends TextView {
public CalendarElement(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CalendarElement(Context context) {
super(context);
}
public CalendarElement(Context context, AttributeSet attrs,int res) {
super(context, attrs,res);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
int startX = this.getWidth();
int stopX = startX;
int stopY = this.getHeight();
//画边框
canvas.drawLine(0, 0, this.getWidth() - 1, 0, paint);
canvas.drawLine(0, 0, 0, this.getHeight() - 1, paint);
canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1, this.getHeight() - 1, paint);
canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1, this.getHeight() - 1, paint);
}
}
下面是日历的主界面,日历实现的逻辑也夹在里面了
public class CalendarActivity extends Activity {
private TextView currentCalendar;
private LinearLayout linear;
private Resources res;
private TableLayout tablayout ;
private TextView [][] dateViews;
private Calendar calendar = Calendar.getInstance();
private Calendar current = Calendar.getInstance();
private int rowIndex; //当前日期所在的行索引
private int colIndex; //当前日期所在的列索引
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
res = this.getResources();
tablayout = new TableLayout(this);
calendar.set(Calendar.DAY_OF_MONTH, 1); //作为日期的设定的第一天
linear = new LinearLayout(this);
linear.setBackgroundColor(Color.WHITE);
this.initBasicActivity();
this.setContentView(linear);
}
private void initBasicActivity()
{
// 初始化表示星期的第一行
linear.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
linear.setOrientation(LinearLayout.VERTICAL);
currentCalendar = new TextView(this);
currentCalendar.setText(current.get(Calendar.YEAR)+ "年" + (current.get(Calendar.MONTH)+1)+"月");
currentCalendar.setGravity(0x11);//设置文本居中放置
linear.addView(currentCalendar);
TableRow row1 = new TableRow(this); //第一行来显示星期
String weeks [] = res.getStringArray(R.array.week);
for(int i = 0 ; i < weeks.length ;i++)
{
TextView view = new TextView(this);
view.setText(weeks[i]);
view.setGravity(0x11);
view.setPadding(0, 0,7, 28);
row1.addView(view, new TableRow.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
}
tablayout.addView(row1,new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
//初始化日历界面
this.intiCalendar();
//添加下上月的按钮
LinearLayout chooseLayout = new LinearLayout(this);
chooseLayout.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
chooseLayout.setGravity(Gravity.CENTER_HORIZONTAL);
ImageButton nextMonth = new ImageButton(this);
nextMonth.setTag("next");
nextMonth.setImageDrawable(this.getResources().getDrawable(R.drawable.next_year));
ImageButton preMonth = new ImageButton(this);
preMonth.setTag("pre");
preMonth.setImageDrawable(this.getResources().getDrawable(R.drawable.pre_year));
Button nextYear = new Button(this);
nextYear.setText("明年");
nextYear.setTag("next");
Button preYear = new Button(this);
preYear.setText("去年");
preYear.setTag("pre");
LinearLayout.LayoutParams nyParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
nextMonth.setLayoutParams(nyParams);
preMonth.setLayoutParams(nyParams);
nextYear.setLayoutParams(nyParams);
preYear.setLayoutParams(nyParams);
MyOnClickListener listener = new MyOnClickListener(this.dateViews);
nextMonth.setOnClickListener(listener);
nextYear.setOnClickListener(listener);
preMonth.setOnClickListener(listener);
preYear.setOnClickListener(listener);
chooseLayout.addView(preYear);
chooseLayout.addView(preMonth);
chooseLayout.addView(nextMonth);
chooseLayout.addView(nextYear);
linear.addView(chooseLayout);
}
private void intiCalendar()
{
CalendarElementListener elementListener = new CalendarElementListener();
dateViews = new CalendarElement[6][7] ; //需要显示出所有的日期项,一共需要6*7个格子。
int week = calendar.get(Calendar.DAY_OF_WEEK);
int day = 0;
boolean thisMonthEnd = false;
for(int i = 0; i < dateViews.length;i++)
{
TableRow dateRow = new TableRow(this);
for(int j = week-1; j < dateViews[i].length;j++)//因为每一个月的第一天不一定就是星期日,所以需要跳过
{
day = calendar.get(Calendar.DAY_OF_MONTH);
dateViews[i][j] = new CalendarElement(this);
dateViews[i][j].setText(String.valueOf(day));
/*
* 因为采用roll方法来改变日期的时候,会不断的循环,所以可能出现两个相同的日期。例如,出现了 一个
*12月1号 ,roll方法增加到31号之后,再调用一次roll方法会继续变成当年的12月1号,那么就出现了两次
*十二月一号,所以在31号出现之后,就认定这个月已经结束了。
*/
if(calendar.get(Calendar.DAY_OF_YEAR) == current.get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.YEAR)==current.get(Calendar.YEAR) && !thisMonthEnd)
{
dateViews[i][j].setBackgroundColor(getResources().getColor(R.color.ground)); //当天的背景颜色加深
rowIndex = i; //保存当前日期所在TextVIew的索引,后面其他日期需要去掉背景
colIndex = j;
}
dateRow.addView(dateViews[i][j], new TableRow.LayoutParams(LayoutParams.WRAP_CONTENT,75));
if(thisMonthEnd)
{
dateViews[i][j].setVisibility(View.INVISIBLE); //如果当前月份完了,那么继续添加的日期控件就不显示出来
}
if(calendar.get(Calendar.DAY_OF_MONTH) == calendar.getActualMaximum(Calendar.DAY_OF_MONTH))
{
thisMonthEnd = true;
}
calendar.roll(Calendar.DAY_OF_MONTH, true);
}
week=1; //下一行是从星期天开始的
tablayout.addView(dateRow,new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
linear.addView(tablayout,new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
//实现四个按钮对日期的控制
class MyOnClickListener implements OnClickListener
{
private TextView dateviews [][];
public MyOnClickListener(TextView [][] dateViews)
{
this.dateviews = dateViews;
}
@Override
public void onClick(View v) {
String tag = (String) v.getTag();
int filed = 0;
//判断按的是什么键
if(v instanceof ImageButton)
{
filed = Calendar.MONTH;
}
else
{
filed = Calendar.YEAR;
}
calendar.roll(filed, tag.equals("next")); //如果相同就表示是下个月,不相同就是上个月。
calendar.set(Calendar.DAY_OF_MONTH, 1);
currentCalendar.setText(calendar.get(Calendar.YEAR)+ "年" +(calendar.get(Calendar.MONTH)+1)+"月");
int week = calendar.get(Calendar.DAY_OF_WEEK);
boolean isFirstWeek = true;
boolean thisMonthEnd = false;
for(int i = 0 ; i < dateviews.length ;i++)
{
for(int j = week-1; j < dateviews[i].length;j++)
{
//每月的第一天所在那个那个星期,在第一天之前的几天不显示出来
if(isFirstWeek)
{
for(int temp = 0;temp < j;temp++)
{
dateviews[i][temp].setVisibility(View.INVISIBLE);
}
isFirstWeek = false;
}
if(thisMonthEnd)
{
dateviews[i][j].setVisibility(View.INVISIBLE);
}
dateviews[i][j].setText(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)));
if(!thisMonthEnd )
{
dateviews[i][j].setVisibility(View.VISIBLE);
}
if(calendar.get(Calendar.DAY_OF_MONTH) == calendar.getActualMaximum(Calendar.DAY_OF_MONTH))
{
thisMonthEnd = true;
}
calendar.roll(Calendar.DAY_OF_MONTH, true);
}
week = 1;
}
//如果不是当前日期,那么日期的背景需要取消掉
if(calendar.get(Calendar.MONTH) == current.get(Calendar.MONTH) && calendar.get(Calendar.YEAR) == current.get(Calendar.YEAR))
{
dateviews[rowIndex][colIndex].setBackgroundColor(getResources().getColor(R.color.ground));
}
else
{
dateviews[rowIndex][colIndex].setBackgroundColor(Color.WHITE);
}
}
}
}
