• 日期控件Android 自定义日历控件


    发一下牢骚和主题无关:

        

        有图有真像:

        

        日期和控件

        

        日历控件View:

    /**
     * 日历控件 功能:获得点选的日期区间
     * 
     */
    public class CalendarView extends View implements View.OnTouchListener {
    	private final static String TAG = "anCalendar";
    	private Date selectedStartDate;
    	private Date selectedEndDate;
    	private Date curDate; // 当前日历表现的月
    	private Date today; // 明天的日期文字表现红色
    	private Date downDate; // 手指按下状态时临时日期
    	private Date showFirstDate, showLastDate; // 日历表现的第一个日期和最后一个日期
    	private int downIndex; // 按下的格子索引
    	private Calendar calendar;
    	private Surface surface;
    	private int[] date = new int[42]; // 日历表现数字
    	private int curStartIndex, curEndIndex; // 当前表现的日历起始的索引
    	//private boolean completed = false; // 为false表示只选择了开始日期,true表示结束日期也选择了
    	//给控件设置监听事件
    	private OnItemClickListener onItemClickListener;
    	
    	public CalendarView(Context context) {
    		super(context);
    		init();
    	}
    
    	public CalendarView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		init();
    	}
    
    	private void init() {
    		curDate = selectedStartDate = selectedEndDate = today = new Date();
    		calendar = Calendar.getInstance();
    		calendar.setTime(curDate);
    		surface = new Surface();
    		surface.density = getResources().getDisplayMetrics().density;
    		setBackgroundColor(surface.bgColor);
    		setOnTouchListener(this);
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		surface.width = getResources().getDisplayMetrics().widthPixels;
    		surface.height = (int) (getResources().getDisplayMetrics().heightPixels*2/5);
    //		if (View.MeasureSpec.getMode(widthMeasureSpec) == View.MeasureSpec.EXACTLY) {
    //			surface.width = View.MeasureSpec.getSize(widthMeasureSpec);
    //		}
    //		if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.EXACTLY) {
    //			surface.height = View.MeasureSpec.getSize(heightMeasureSpec);
    //		}
    		widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.width,
    				View.MeasureSpec.EXACTLY);
    		heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.height,
    				View.MeasureSpec.EXACTLY);
    		setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    	}
    
    	@Override
    	protected void onLayout(boolean changed, int left, int top, int right,
    			int bottom) {
    		Log.d(TAG, "[onLayout] changed:"
    				+ (changed ? "new size" : "not change") + " left:" + left
    				+ " top:" + top + " right:" + right + " bottom:" + bottom);
    		if (changed) {
    			surface.init();
    		}
    		super.onLayout(changed, left, top, right, bottom);
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		Log.d(TAG, "onDraw");
    		// 画框
    		canvas.drawPath(surface.boxPath, surface.borderPaint);
    		// 年代
    		//String monthText = getYearAndmonth();
    		//float textWidth = surface.monthPaint.measureText(monthText);
    		//canvas.drawText(monthText, (surface.width - textWidth) / 2f,
    		//		surface.monthHeight * 3 / 4f, surface.monthPaint);
    		// 上一月/下一月
    		//canvas.drawPath(surface.preMonthBtnPath, surface.monthChangeBtnPaint);
    		//canvas.drawPath(surface.nextMonthBtnPath, surface.monthChangeBtnPaint);
    		// 礼拜
    		float weekTextY = surface.monthHeight + surface.weekHeight * 3 / 4f;
    		// 礼拜背景
    //		surface.cellBgPaint.setColor(surface.textColor);
    //		canvas.drawRect(surface.weekHeight, surface.width, surface.weekHeight, surface.width, surface.cellBgPaint);
    		for (int i = 0; i < surface.weekText.length; i++) {
    			float weekTextX = i
    					* surface.cellWidth
    					+ (surface.cellWidth - surface.weekPaint
    							.measureText(surface.weekText[i])) / 2f;
    			canvas.drawText(surface.weekText[i], weekTextX, weekTextY,
    					surface.weekPaint);
    		}
    		
    		// 计算日期
    		calculateDate();
    		// 按下状态,选择状态背景色
    		drawDownOrSelectedBg(canvas);
    		// write date number
    		// today index
    		int todayIndex = -1;
    		calendar.setTime(curDate);
    		String curYearAndMonth = calendar.get(Calendar.YEAR) + ""
    				+ calendar.get(Calendar.MONTH);
    		calendar.setTime(today);
    		String todayYearAndMonth = calendar.get(Calendar.YEAR) + ""
    				+ calendar.get(Calendar.MONTH);
    		if (curYearAndMonth.equals(todayYearAndMonth)) {
    			int todayNumber = calendar.get(Calendar.DAY_OF_MONTH);
    			todayIndex = curStartIndex + todayNumber - 1;
    		}
    		for (int i = 0; i < 42; i++) {
    			int color = surface.textColor;
    			if (isLastMonth(i)) {
    				color = surface.borderColor;
    			} else if (isNextMonth(i)) {
    				color = surface.borderColor;
    			}
    			if (todayIndex != -1 && i == todayIndex) {
    				color = surface.todayNumberColor;
    			}
    			drawCellText(canvas, i, date[i] + "", color);
    		}
    		super.onDraw(canvas);
    	}
    
    	private void calculateDate() {
    		calendar.setTime(curDate);
    		calendar.set(Calendar.DAY_OF_MONTH, 1);
    		int dayInWeek = calendar.get(Calendar.DAY_OF_WEEK);
    		Log.d(TAG, "day in week:" + dayInWeek);
    		int monthStart = dayInWeek;
    		if (monthStart == 1) {
    			monthStart = 8;
    		}
    		monthStart -= 1;  //以日为开头-1,以礼拜一为开头-2
    		curStartIndex = monthStart;
    		date[monthStart] = 1;
    		// last month
    		if (monthStart > 0) {
    			calendar.set(Calendar.DAY_OF_MONTH, 0);
    			int dayInmonth = calendar.get(Calendar.DAY_OF_MONTH);
    			for (int i = monthStart - 1; i >= 0; i--) {
    				date[i] = dayInmonth;
    				dayInmonth--;
    			}
    			calendar.set(Calendar.DAY_OF_MONTH, date[0]);
    		}
    		showFirstDate = calendar.getTime();
    		// this month
    		calendar.setTime(curDate);
    		calendar.add(Calendar.MONTH, 1);
    		calendar.set(Calendar.DAY_OF_MONTH, 0);
    		// Log.d(TAG, "m:" + calendar.get(Calendar.MONTH) + " d:" +
    		// calendar.get(Calendar.DAY_OF_MONTH));
    		int monthDay = calendar.get(Calendar.DAY_OF_MONTH);
    		for (int i = 1; i < monthDay; i++) {
    			date[monthStart + i] = i + 1;
    		}
    		curEndIndex = monthStart + monthDay;
    		// next month
    		for (int i = monthStart + monthDay; i < 42; i++) {
    			date[i] = i - (monthStart + monthDay) + 1;
    		}
    		if (curEndIndex < 42) {
    			// 表现了下一月的
    			calendar.add(Calendar.DAY_OF_MONTH, 1);
    		}
    		calendar.set(Calendar.DAY_OF_MONTH, date[41]);
    		showLastDate = calendar.getTime();
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 * @param index
    	 * @param text
    	 */
    	private void drawCellText(Canvas canvas, int index, String text, int color) {
    		int x = getXByIndex(index);
    		int y = getYByIndex(index);
    		surface.datePaint.setColor(color);
    		float cellY = surface.monthHeight + surface.weekHeight + (y - 1)
    				* surface.cellHeight + surface.cellHeight * 3 / 4f;
    		float cellX = (surface.cellWidth * (x - 1))
    				+ (surface.cellWidth - surface.datePaint.measureText(text))
    				/ 2f;
    		canvas.drawText(text, cellX, cellY, surface.datePaint);
    	}
    
    	/**
    	 * 
    	 * @param canvas
    	 * @param index
    	 * @param color
    	 */
    	private void drawCellBg(Canvas canvas, int index, int color) {
    		int x = getXByIndex(index);
    		int y = getYByIndex(index);
    		surface.cellBgPaint.setColor(color);
    		float left = surface.cellWidth * (x - 1) + surface.borderWidth;
    		float top = surface.monthHeight + surface.weekHeight + (y - 1)
    				* surface.cellHeight + surface.borderWidth;
    		canvas.drawRect(left, top, left + surface.cellWidth
    				- surface.borderWidth, top + surface.cellHeight
    				- surface.borderWidth, surface.cellBgPaint);
    	}
    
    	private void drawDownOrSelectedBg(Canvas canvas) {
    		// down and not up
    		if (downDate != null) {
    			drawCellBg(canvas, downIndex, surface.cellDownColor);
    		}
    		// selected bg color
    		if (!selectedEndDate.before(showFirstDate)
    				&& !selectedStartDate.after(showLastDate)) {
    			int[] section = new int[] { -1, -1 };
    			calendar.setTime(curDate);
    			calendar.add(Calendar.MONTH, -1);
    			findSelectedIndex(0, curStartIndex, calendar, section);
    			if (section[1] == -1) {
    				calendar.setTime(curDate);
    				findSelectedIndex(curStartIndex, curEndIndex, calendar, section);
    			}
    			if (section[1] == -1) {
    				calendar.setTime(curDate);
    				calendar.add(Calendar.MONTH, 1);
    				findSelectedIndex(curEndIndex, 42, calendar, section);
    			}
    			if (section[0] == -1) {
    				section[0] = 0;
    			}
    			if (section[1] == -1) {
    				section[1] = 41;
    			}
    			for (int i = section[0]; i <= section[1]; i++) {
    				drawCellBg(canvas, i, surface.cellSelectedColor);
    			}
    		}
    	}
    
    	private void findSelectedIndex(int startIndex, int endIndex,
    			Calendar calendar, int[] section) {
    		for (int i = startIndex; i < endIndex; i++) {
    			calendar.set(Calendar.DAY_OF_MONTH, date[i]);
    			Date temp = calendar.getTime();
    			// Log.d(TAG, "temp:" + temp.toLocaleString());
    			if (temp.compareTo(selectedStartDate) == 0) {
    				section[0] = i;
    			}
    			if (temp.compareTo(selectedEndDate) == 0) {
    				section[1] = i;
    				return;
    			}
    		}
    	}
    
    	public Date getSelectedStartDate() {
    		return selectedStartDate;
    	}
    
    	public Date getSelectedEndDate() {
    		return selectedEndDate;
    	}
    
    	private boolean isLastMonth(int i) {
    		if (i < curStartIndex) {
    			return true;
    		}
    		return false;
    	}
    
    	private boolean isNextMonth(int i) {
    		if (i >= curEndIndex) {
    			return true;
    		}
    		return false;
    	}
    
    	private int getXByIndex(int i) {
    		return i % 7 + 1; // 1 2 3 4 5 6 7
    	}
    
    	private int getYByIndex(int i) {
    		return i / 7 + 1; // 1 2 3 4 5 6
    	}
    
    	// 获得当前应该表现的年代
    	public String getYearAndmonth() {
    		calendar.setTime(curDate);
    		int year = calendar.get(Calendar.YEAR);
    		int month = calendar.get(Calendar.MONTH);
    		return year + "-" + surface.monthText[month];
    	}
    	
    	//上一月
    	public String clickLeftMonth(){
    		calendar.setTime(curDate);
    		calendar.add(Calendar.MONTH, -1);
    		curDate = calendar.getTime();
    		invalidate();
    		return getYearAndmonth();
    	}
    	//下一月
    	public String clickRightMonth(){
    		calendar.setTime(curDate);
    		calendar.add(Calendar.MONTH, 1);
    		curDate = calendar.getTime();
    		invalidate();
    		return getYearAndmonth();
    	}
    
    	private void setSelectedDateByCoor(float x, float y) {
    		// change month
    //		if (y < surface.monthHeight) {
    //			// pre month
    //			if (x < surface.monthChangeWidth) {
    //				calendar.setTime(curDate);
    //				calendar.add(Calendar.MONTH, -1);
    //				curDate = calendar.getTime();
    //			}
    //			// next month
    //			else if (x > surface.width - surface.monthChangeWidth) {
    //				calendar.setTime(curDate);
    //				calendar.add(Calendar.MONTH, 1);
    //				curDate = calendar.getTime();
    //			}
    //		}
    		// cell click down
    		if (y > surface.monthHeight + surface.weekHeight) {
    			int m = (int) (Math.floor(x / surface.cellWidth) + 1);
    			int n = (int) (Math
    					.floor((y - (surface.monthHeight + surface.weekHeight))
    							/ Float.valueOf(surface.cellHeight)) + 1);
    			downIndex = (n - 1) * 7 + m - 1;
    			Log.d(TAG, "downIndex:" + downIndex);
    			calendar.setTime(curDate);
    			if (isLastMonth(downIndex)) {
    				calendar.add(Calendar.MONTH, -1);
    			} else if (isNextMonth(downIndex)) {
    				calendar.add(Calendar.MONTH, 1);
    			}
    			calendar.set(Calendar.DAY_OF_MONTH, date[downIndex]);
    			downDate = calendar.getTime();
    		}
    		invalidate();
    	}
    
    	@Override
    	public boolean onTouch(View v, MotionEvent event) {
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			setSelectedDateByCoor(event.getX(), event.getY());
    			break;
    		case MotionEvent.ACTION_UP:
    			if (downDate != null) {
    //				if (!completed) {
    //					if (downDate.before(selectedStartDate)) {
    //						selectedEndDate = selectedStartDate;
    //						selectedStartDate = downDate;
    //					} else {
    //						selectedEndDate = downDate;
    //					}
    //					completed = true;
    //				} else {
    //					selectedStartDate = selectedEndDate = downDate;
    //					completed = false;
    //				}
    				selectedStartDate = selectedEndDate = downDate;
    				//响应监听事件
    				onItemClickListener.OnItemClick(selectedStartDate);
    				// Log.d(TAG, "downdate:" + downDate.toLocaleString());
    				//Log.d(TAG, "start:" + selectedStartDate.toLocaleString());
    				//Log.d(TAG, "end:" + selectedEndDate.toLocaleString());
    				downDate = null;
    				invalidate();
    			}
    			break;
    		}
    		return true;
    	}
    	
    	//给控件设置监听事件
    	public void setOnItemClickListener(OnItemClickListener onItemClickListener){
    		this.onItemClickListener =  onItemClickListener;
    	}
    	//监听接口
    	public interface OnItemClickListener {
    		void OnItemClick(Date date);
    	}
    
    	/**
    	 * 
    	 * 1. 布局尺寸 2. 文字颜色,大小 3. 当前日期的颜色,选择的日期颜色
    	 */
    	private class Surface {
    		public float density;
    		public int width; // 整个控件的宽度
    		public int height; // 整个控件的高度
    		public float monthHeight; // 表现月的高度
    		//public float monthChangeWidth; // 上一月、下一月按钮宽度
    		public float weekHeight; // 表现礼拜的高度
    		public float cellWidth; // 日期方框宽度
    		public float cellHeight; // 日期方框高度	
    		public float borderWidth;
    		public int bgColor = Color.parseColor("#FFFFFF");
    		private int textColor = Color.BLACK;
    		//private int textColorUnimportant = Color.parseColor("#666666");
    		private int btnColor = Color.parseColor("#666666");
    		private int borderColor = Color.parseColor("#CCCCCC");
    		public int todayNumberColor = Color.RED;
    		public int cellDownColor = Color.parseColor("#CCFFFF");
    		public int cellSelectedColor = Color.parseColor("#99CCFF");
    		public Paint borderPaint;
    		public Paint monthPaint;
    		public Paint weekPaint;
    		public Paint datePaint;
    		public Paint monthChangeBtnPaint;
    		public Paint cellBgPaint;
    		public Path boxPath; // 边框路径
    		//public Path preMonthBtnPath; // 上一月按钮三角形
    		//public Path nextMonthBtnPath; // 下一月按钮三角形
    		public String[] weekText = { "Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    		public String[] monthText = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
    		   
    		public void init() {
    			float temp = height / 7f;
    			monthHeight = 0;//(float) ((temp + temp * 0.3f) * 0.6);
    			//monthChangeWidth = monthHeight * 1.5f;
    			weekHeight = (float) ((temp + temp * 0.3f) * 0.7);
    			cellHeight = (height - monthHeight - weekHeight) / 6f;
    			cellWidth = width / 7f;
    			borderPaint = new Paint();
    			borderPaint.setColor(borderColor);
    			borderPaint.setStyle(Paint.Style.STROKE);
    			borderWidth = (float) (0.5 * density);
    			// Log.d(TAG, "border" + borderWidth);
    			borderWidth = borderWidth < 1 ? 1 : borderWidth;
    			borderPaint.setStrokeWidth(borderWidth);
    			monthPaint = new Paint();
    			monthPaint.setColor(textColor);
    			monthPaint.setAntiAlias(true);
    			float textSize = cellHeight * 0.4f;
    			Log.d(TAG, "text size:" + textSize);
    			monthPaint.setTextSize(textSize);
    			monthPaint.setTypeface(Typeface.DEFAULT_BOLD);
    			weekPaint = new Paint();
    			weekPaint.setColor(textColor);
    			weekPaint.setAntiAlias(true);
    			float weekTextSize = weekHeight * 0.6f;
    			weekPaint.setTextSize(weekTextSize);
    			weekPaint.setTypeface(Typeface.DEFAULT_BOLD);
    			datePaint = new Paint();
    			datePaint.setColor(textColor);
    			datePaint.setAntiAlias(true);
    			float cellTextSize = cellHeight * 0.5f;
    			datePaint.setTextSize(cellTextSize);
    			datePaint.setTypeface(Typeface.DEFAULT_BOLD);
    			boxPath = new Path();
    			//boxPath.addRect(0, 0, width, height, Direction.CW);
    			//boxPath.moveTo(0, monthHeight);
    			boxPath.rLineTo(width, 0);
    			boxPath.moveTo(0, monthHeight + weekHeight);
    			boxPath.rLineTo(width, 0);
    			for (int i = 1; i < 6; i++) {
    				boxPath.moveTo(0, monthHeight + weekHeight + i * cellHeight);
    				boxPath.rLineTo(width, 0);
    				boxPath.moveTo(i * cellWidth, monthHeight);
    				boxPath.rLineTo(0, height - monthHeight);
    			}
    			boxPath.moveTo(6 * cellWidth, monthHeight);
    			boxPath.rLineTo(0, height - monthHeight);
    			//preMonthBtnPath = new Path();
    			//int btnHeight = (int) (monthHeight * 0.6f);
    			//preMonthBtnPath.moveTo(monthChangeWidth / 2f, monthHeight / 2f);
    			//preMonthBtnPath.rLineTo(btnHeight / 2f, -btnHeight / 2f);
    			//preMonthBtnPath.rLineTo(0, btnHeight);
    			//preMonthBtnPath.close();
    			//nextMonthBtnPath = new Path();
    			//nextMonthBtnPath.moveTo(width - monthChangeWidth / 2f,
    			//		monthHeight / 2f);
    			//nextMonthBtnPath.rLineTo(-btnHeight / 2f, -btnHeight / 2f);
    			//nextMonthBtnPath.rLineTo(0, btnHeight);
    			//nextMonthBtnPath.close();
    			monthChangeBtnPaint = new Paint();
    			monthChangeBtnPaint.setAntiAlias(true);
    			monthChangeBtnPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    			monthChangeBtnPaint.setColor(btnColor);
    			cellBgPaint = new Paint();
    			cellBgPaint.setAntiAlias(true);
    			cellBgPaint.setStyle(Paint.Style.FILL);
    			cellBgPaint.setColor(cellSelectedColor);
    		}
    	}
    }
        每日一道理
    因为自信,在呀呀学语时,我靠着纤嫩的双腿,迈出人生的第一步;因为自信,我一次次将第一名的奖状高高举起;因为自信,我毫不吝惜地剪掉飘逸的长发,在运动场上展现风采……感谢自信,它给了我一双翅膀,让我在电闪雷鸣中去飞翔,在风雨中去搏击人生!

        实现日历控件:

    <com.techrare.view.CalendarView
                android:id="@+id/calendar"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" />

        日历控件中的一些功能(可以自己加):

    //获取日历控件对象
    calendar = (CalendarView)findViewById(R.id.calendar);
    //获取日历中年代 ya[0]为年,ya[1]为月(格式大家可以自行在日历控件中改)
    String[] ya = calendar.getYearAndmonth().split("-"); 
    //上一月 同样返回年代 
    String leftYearAndmonth = calendar.clickLeftMonth(); 
    String[] lya = leftYearAndmonth.split("-");
    //下一月
    String rightYearAndmonth = calendar.clickRightMonth(); 
    String[] rya = rightYearAndmonth.split("-");
    //设置控件监听,可以监听到点击的每一天(大家也可以在控件中自行设定)
    calendar.setOnItemClickListener(new calendarItemClickListener());
    class calendarItemClickListener implements OnItemClickListener{
    	@Override
    	public void OnItemClick(Date date) {
    		Toast.makeText(getApplicationContext(), date+"", Toast.LENGTH_SHORT).show();
    	}
     }

        这些功能只是配合项目中的需要来添加的,大家如有其他需求,可以自行在控件中添加,应该也不怎么困难!

        

        

    文章结束给大家分享下程序员的一些笑话语录: 现在社会太数字化了,所以最好是有一个集很多功能于一身的设备!

  • 相关阅读:
    Python第二
    Python第一讲以及计算机基础
    MySQL第五讲
    MySQL第四讲
    MySQL第三讲
    MySQL第一讲概论
    MySQL日常笔记第二讲
    Linux修改用户组
    XAMPP中proftpd的简明配置方法
    解决php configure: error: Cannot find ldap libraries in /usr/lib.错误
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3093660.html
Copyright © 2020-2023  润新知