您的位置:首页 > 移动开发 > Android开发

Canvas画简易的Calendar控件

2015-11-13 10:33 513 查看
package com.example.lshan.canvascalendar;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class CanvasCalendar extends View implements View.OnTouchListener,GestureDetector.OnGestureListener{
private float width = 0f,radius = 0f;
private Paint circlep,textp,todayp;
private int monthday = 0;
private int year = 0,month = 0;
private Map<String,String> date = new HashMap<String,String>();
private SelectCalendarListener selectCalendarListener;
private FlingCalendarListener flingCalendarListener;
private Date curDate = new Date();
private Calendar mcalendar;
private GestureDetector gd = new GestureDetector(this);
private float upx = 0f, upy = 0f;
private float downx =0f,downy = 0f;

public CanvasCalendar(Context context) {
super(context);
initDate(curDate);

}

public CanvasCalendar(Context context, AttributeSet attrs) {
super(context, attrs);
initDate(curDate);
}

public CanvasCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDate(curDate);
}

public void setDate(Date mdate){
this.curDate = mdate;
initDate(mdate);
}
public void setWidth(float width){
this.width = width;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawCircle(canvas);
setMonth(mcalendar.get(Calendar.YEAR), mcalendar.get(Calendar.MONTH) + 1);
drawText(canvas);
setOnTouchListener(this);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().widthPixels * 6 / 7);
}

public void drawCircle(Canvas canvas){
for(int x = 0; x < 7;x++){
for(int y = 0; y < 6; y++){
canvas.drawCircle((x+1/2f)*width/7f,(y+1/2f)*width/7f,radius,circlep);
}
}
invalidate();
}

public void drawText(Canvas canvas){
//选中日期
mcalendar.setTime(curDate);
int today = mcalendar.get(Calendar.DAY_OF_MONTH);
int todaymonth = mcalendar.get(Calendar.MONTH);
int todayyear = mcalendar.get(Calendar.YEAR);
int selectx = mcalendar.get(Calendar.DAY_OF_WEEK) - 1;
int selecty = mcalendar.get(Calendar.WEEK_OF_MONTH)-1;

//当前日期
Date tdate = new Date();
mcalendar.setTime(tdate);
int today2 = mcalendar.get(Calendar.DAY_OF_MONTH);
int today2month = mcalendar.get(Calendar.MONTH);
int today2year = mcalendar.get(Calendar.YEAR);

//当月日期
for(int i = 1; i <= monthday; i++){
mcalendar.set(year, month-1, i);
int x = mcalendar.get(Calendar.DAY_OF_WEEK) - 1;
int y = mcalendar.get(Calendar.WEEK_OF_MONTH)-1;
canvas.drawText("" + i, (x + 1 / 2f) * width / 7f - textp.measureText("" + i) / 2f, (y + 1 / 2f) * width / 7f + textp.measureText("" + i) / 2f, textp);
if(i == today){
canvas.drawCircle((selectx+1/2f)*width/7f,(selecty+1/2f)*width/7f,radius,textp);
canvas.drawText(""+today,(selectx+1/2f)*width/7f - circlep.measureText(""+i)/2f,(selecty+1/2f)*width/7f + circlep.measureText(""+i)/2f,circlep);
}else if (i == today2 && today2month == todaymonth && today2year == todayyear){
canvas.drawCircle((x+1/2f)*width/7f,(y+1/2f)*width/7f,radius,todayp);
} else{
canvas.drawText(""+i,(x+1/2f)*width/7f - textp.measureText(""+i)/2f,(y+1/2f)*width/7f + textp.measureText(""+i)/2f,textp);
}
date.put(""+x+y,month+","+i);
}
//上个月日期
mcalendar.set(year,month-1,1);
int lx = mcalendar.get(Calendar.DAY_OF_WEEK) - 2;
int mons = getMonthday(month - 1);
for(int j = lx ; j >= 0 ;j--,mons--){
canvas.drawText(""+mons,(j+1/2f)*width/7f - textp.measureText(""+mons)/2f,(1/2f)*width/7f + textp.measureText(""+mons)/2f,textp);
date.put("" + j + 0, (month - 1) + "," + mons);
}
//下个月日期
mcalendar.set(year, month - 1, monthday);
int nx = mcalendar.get(Calendar.DAY_OF_WEEK)+1;
int ny = mcalendar.get(Calendar.WEEK_OF_MONTH);
int day = 1;
for(int ni = ny; ni < 7 ; ni++){
for(int nj = nx; nj <8;nj++,day++){
canvas.drawText(""+day,(nj - 1 + 1/2f)*width/7f - textp.measureText(""+day)/2f,(ni - 1 + 1/2f)*width/7f + textp.measureText(""+day)/2f,textp);
date.put("" + (nj - 1) + (ni - 1), (month + 1) + "," + day);
}
nx = 1;
}
invalidate();

}

public void setMonth(int year,int mon){
this.year = year;
this.month = mon;
monthday = getMonthday(mon);

}

public Date lastMonth() {
mcalendar.setTime(curDate);
mcalendar.add(Calendar.MONTH, -1);
curDate = mcalendar.getTime();
invalidate();
return curDate;
}

public Date nextMonth() {
mcalendar.setTime(curDate);
mcalendar.add(Calendar.MONTH, 1);
curDate = mcalendar.getTime();
invalidate();
return curDate;
}

public int getMonthday(int mon){
int days = 0;
if(mon == 1 || mon == 3 || mon == 5 || mon == 7 || mon == 8 || mon == 10 || mon == 12){
days = 31;
}else if(mon == 2){
if((year/4==0&&year/100!=0)|| year/400 == 0){
days = 29;
}else{
days = 28;
}
}else{
days = 30;
}
return days;
}

@Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean fling = true;
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
downx = event.getX();
downy = event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
upx = event.getX();
upy = event.getY();
if(Math.abs(downx - upx) > 50 || Math.abs(downy - upy) > 50){
fling = true;
}else{
fling = false;
}
break;
}
if(x< width && y < 6*width/7f && !fling){
String[] s = date.get(getXRY(x)+getXRY(y)).split(",");
Calendar d = Calendar.getInstance();
d.set(year, Integer.parseInt(s[0]) - 1, Integer.parseInt(s[1]));
selectCalendarListener.onSelectCalendar(d.getTime());

if(curDate.getMonth() == (Integer.parseInt(s[0])-1)){
curDate = d.getTime();
}
}
return gd.onTouchEvent(event);
}

public void setCalendarListener(SelectCalendarListener selectCalendarListener){
this.selectCalendarListener = selectCalendarListener;
}

public void setFlingCalendarListener(FlingCalendarListener flingCalendarListener){
this.flingCalendarListener = flingCalendarListener;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}

@Override
public void onShowPress(MotionEvent e) {

}

@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}

@Override
public void onLongPress(MotionEvent e) {

}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(velocityX > 20){
flingCalendarListener.onFlingCalendar(lastMonth());
}else if(velocityX < -20){
flingCalendarListener.onFlingCalendar(nextMonth());
}
return false;
}

public interface SelectCalendarListener{
public void onSelectCalendar(Date downdate);
}

public interface FlingCalendarListener{
public void onFlingCalendar(Date flingdate);
}

public String getXRY(float point){
String key = "";
int keyx = (int)(point/((1/2f)*width/7f));
switch(keyx){
case 0:
key = "0";
break;
case 1:
key = "0";
break;
case 2:
key = "1";
break;
case 3:
key = "1";
break;
case 4:
key = "2";
break;
case 5:
key = "2";
break;
case 6:
key = "3";
break;
case 7:
key = "3";
break;
case 8:
key = "4";
break;
case 9:
key = "4";
break;
case 10:
key = "5";
break;
case 11:
key = "5";
break;
case 12:
key = "6";
break;
case 13:
key = "6";
break;

}
return key;
}

private void initDate(Date date){
radius = width/14f-10;

circlep = new Paint();
circlep.setColor(Color.parseColor("#ffffff"));
circlep.setAntiAlias(true);
circlep.setTextSize(18);

textp = new Paint();
textp.setColor(Color.parseColor("#e23086"));
textp.setAntiAlias(true);
textp.setTextSize(18);

todayp = new Paint();
todayp.setColor(Color.parseColor("#e23086"));
todayp.setAntiAlias(true);
todayp.setStyle(Paint.Style.STROKE);

curDate = date;
mcalendar = Calendar.getInstance();
mcalendar.setTime(curDate);
}

}
实现使用
package com.example.lshan.canvascalendar;import android.app.Activity;import android.graphics.drawable.BitmapDrawable;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.DisplayMetrics;import android.util.Log;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.View;import android.widget.Button;import android.widget.LinearLayout;import android.widget.PopupWindow;import android.widget.TextView;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;public class MainActivity extends Activity implements View.OnClickListener{private Button popupbtn;private TextView tv_date;private View contextView;private CanvasCalendar canvasCalendar;private Date date;private Date today;private Date LastNext;private Button lastmonth,nextmonth;private TextView ymd;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_popupwindow);}@Overridepublic void onContentChanged() {super.onContentChanged();popupbtn = (Button)findViewById(R.id.popupwindow);popupbtn.setOnClickListener(this);tv_date = (TextView)findViewById(R.id.date);contextView  = LayoutInflater.from(this).inflate(R.layout.activity_main,null);lastmonth = (Button)contextView.findViewById(R.id.lastmonth);lastmonth.setOnClickListener(this);nextmonth = (Button)contextView.findViewById(R.id.nextmonth);nextmonth.setOnClickListener(this);canvasCalendar = (CanvasCalendar)contextView.findViewById(R.id.layout_calendar);ymd = (TextView)contextView.findViewById(R.id.ymd);date = new Date();today = new Date();ymd.setText(new SimpleDateFormat("yy-MM-dd").format(date));DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);canvasCalendar.setWidth(dm.widthPixels);}@Overridepublic void onClick(View v) {switch(v.getId()){case R.id.popupwindow:canvasCalendar.setDate(date);DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);final PopupWindow popupWindow = new PopupWindow(contextView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT,true);popupWindow.setOutsideTouchable(true);popupWindow.setBackgroundDrawable(new BitmapDrawable());popupWindow.setFocusable(true);popupWindow.showAsDropDown(popupbtn);LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(dm.widthPixels,(int)Math.ceil(dm.widthPixels*6/7.0));canvasCalendar.setCalendarListener(new CanvasCalendar.SelectCalendarListener() {@Overridepublic void onSelectCalendar(Date downdate) {ymd.setText(new SimpleDateFormat("yy-MM-dd").format(downdate));date = downdate;popupWindow.dismiss();}});popupWindow.setTouchInterceptor(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {Log.i("hima","touch");if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {popupWindow.dismiss();}return false;}});canvasCalendar.setFlingCalendarListener(new CanvasCalendar.FlingCalendarListener() {@Overridepublic void onFlingCalendar(Date flingdate) {ymd.setText(new SimpleDateFormat("yy-MM-dd").format(flingdate));date = flingdate;}});break;case R.id.lastmonth:LastNext = canvasCalendar.lastMonth();ymd.setText(new SimpleDateFormat("yy-MM-dd").format(LastNext));date = LastNext;break;case R.id.nextmonth:LastNext = canvasCalendar.nextMonth();ymd.setText(new SimpleDateFormat("yy-MM-dd").format(LastNext));date = LastNext;break;}}}
布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent" android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/popupwindow"/><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/date"/></LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:layout_width="0.0dip"android:layout_height="wrap_content"android:layout_weight="1.0"android:text="lastmonth"android:id="@+id/lastmonth"/><TextViewandroid:layout_width="0.0dip"android:layout_height="wrap_content"android:layout_weight="2.0"android:layout_gravity="center"android:gravity="center"android:id="@+id/ymd"/><Buttonandroid:layout_width="0.0dip"android:layout_height="wrap_content"android:layout_weight="1.0"android:text="nextmonth"android:id="@+id/nextmonth"/></LinearLayout><com.example.lshan.canvascalendar.CanvasCalendarandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/layout_calendar"/></LinearLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android canvas calendar