android 自己实现日历功能

原创 2013年12月05日 20:59:17

好久没有写东西了,这两天自己联系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);
					
				}
			
	}
	
	
	}
	
}


大概就是这些了,如果有错误的地方希望指出   奋斗


android实现日历

日历的实现近期由于工作需要,对以前的日历控件进行重构和加强。 日历总体使用PopupWindow实现,日历view通过popupWindow.setContentView实现。原有日历使用的view...

Android日历开发详解

Android日历开发详解Android日历开发详解 基本实现思路 布局 结构 日历数据 Android日历开发日期工具类TimeUtils Android日历开发日历显示需要准备哪些数据 Andro...

Android 简单引导页实现

注意:该demo只能适应几张图片滑动。如果多了需要参考自定义viewgroup引导页实现 实现了动态添加小圆点,滑动到当前页设置选中,滑动到最后一页时显示立即进入按钮。 1.动态添加小圆点...

Android 自定义日历-实现签到订约功能

前言aiyang:公司项目需要做一个签到送积分的系统,要求app实现这种签到功能。先在网上找了一些资料,有些用自定义View画图实现,其实对于普通码农对绘图会没耐心看各自算法。所以自己动手撸一个通用型...

Android使用GridView实现日历功能(详细代码)

代码有点多,发个图先: 如果懒得往下看的,可以直接下载源码吧(0分的),最近一直有人要,由于时间太久了,懒得找出来整理,今天又看到有人要,正好没事就整理了一下 http://dow...

Android使用GridView实现日历功能(详细代码)

代码有点多,发个图先: 如果懒得往下看的,可以直接下载源码吧(0分的),最近一直有人要,由于时间太久了,懒得找出来整理,今天又看到有人要,正好没事就整理了一下 http://dow...

Android使用GridView实现日历功能(详细代码)

转自:http://blog.csdn.net/onlyonecoder/article/details/8481799#comments     代码有点多,发个图先: 布局...

Android功能强大的日历控件

  • 2015年09月25日 10:26
  • 195KB
  • 下载

调用Android自带日历功能

ortant; table-layout: fixed; width: 3186px;">ortant;">ortant;">ortant; zoom: 1 !important; filter: n...

Android中带签到功能的日历(积分)

利用gridview实现签到的日历
  • dailog
  • dailog
  • 2016年08月28日 10:05
  • 3724
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android 自己实现日历功能
举报原因:
原因补充:

(最多只允许输入30个字)