Canvas畫簡易的Calendar控件

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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_popupwindow);

    }

    @Override
    public 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);
    }

    @Override
    public 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() {
                    @Override
                    public void onSelectCalendar(Date downdate) {
                            ymd.setText(new SimpleDateFormat("yy-MM-dd").format(downdate));
                            date = downdate;
                            popupWindow.dismiss();

                    }
                });
                popupWindow.setTouchInterceptor(new View.OnTouchListener() {
                    @Override
                    public 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() {
                    @Override
                    public 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">

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/popupwindow"/>
    <TextView
        android: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">


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:layout_width="0.0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1.0"
            android:text="lastmonth"
            android:id="@+id/lastmonth"
            />
        <TextView
            android: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"/>
        <Button
            android: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.CanvasCalendar
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/layout_calendar"
       />


</LinearLayout>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章