Android 사용자 정의 컨트롤 로 다 중 선택 가능 한 과정 달력 CalendarView 구현

다 중 선택 가능 한 달력 CalendarView 효과 그림

개발 환경
IDE 버 전:Android Studio 2.0
물리 기기 버 전:Win 7 플래그 십 버 전(64 비트)
머리말
최근 프로젝트 에 서 는 한 과정 에서 선택 한 달력 View 를 사 용 했 습 니 다.그래서 인터넷 에서 사용자 정의 달력 View 를 검색 한 결과 대체적으로 단일 선택 으로 프로젝트 의 수 요 를 만족 시 키 지 못 했 습 니 다.그래서 스스로 바퀴 를 다시 만 들 고 선택 할 수 있 는 사용자 정의 달력 View 를 썼 습 니 다.맨 뒤에 GitHub 주소 가 나 옵 니 다.
코드 구현

package widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

import com.arisaid.calendarview.R;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * Created by zhouyou on 2016/7/25.
 * Class desc:
 *
 *      View,   
 */
public class CalendarView extends View {

  //     
  private static final int NUM_COLUMNS  =  7;
  //     
  private static final int NUM_ROWS    =  6;

  /**
   *       
   */
  private List<String> mOptionalDates;

  /**
   *       
   */
  private List<String> mSelectedDates = new ArrayList<>();

  //     
  private int mBgColor = Color.parseColor("#F7F7F7");
  //       
  private int mDayNormalColor = Color.parseColor("#0070F8");
  //        
  private int mDayNotOptColor = Color.parseColor("#CBCBCB");
  //        
  private int mDayPressedColor = Color.WHITE;
  //       
  private int mDayTextSize = 14;
  //          
  private boolean mClickable = true;

  private DisplayMetrics mMetrics;
  private Paint mPaint;
  private int mCurYear;
  private int mCurMonth;
  private int mCurDate;

  private int mSelYear;
  private int mSelMonth;
  private int mSelDate;
  private int mColumnSize;
  private int mRowSize;
  private int[][] mDays;

  //         
  private int mMonthDays;
  //          
  private int mWeekNumber;
  //      Bitmap
  private Bitmap mBgOptBitmap;
  //      Bitmap
  private Bitmap mBgNotOptBitmap;

  public CalendarView(Context context) {
    super(context);
    init();
  }

  public CalendarView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  public CalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }

  private void init() {
    //         
    mMetrics = getResources().getDisplayMetrics();
    //     
    mPaint = new Paint();
    //       
    Calendar calendar = Calendar.getInstance();
    mCurYear  =  calendar.get(Calendar.YEAR);
    mCurMonth  =  calendar.get(Calendar.MONTH);
    mCurDate  =  calendar.get(Calendar.DATE);
    setSelYTD(mCurYear, mCurMonth, mCurDate);

    //     Bitmap
    mBgOptBitmap  = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_bg_course_optional);
    mBgNotOptBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_bg_course_not_optional);
  }

  @Override
  public void invalidate() {
    //         
    if(hasWindowFocus()) super.invalidate();
  }

  @Override
  protected void onDraw(Canvas canvas) {
    initSize();

    //     
    mPaint.setColor(mBgColor);
    canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mPaint);

    mDays = new int[6][7];
    //         
    mPaint.setTextSize(mDayTextSize * mMetrics.scaledDensity);
    //         

    String dayStr;
    //           
    mMonthDays = DateUtils.getMonthDays(mSelYear, mSelMonth);
    //            
    mWeekNumber = DateUtils.getFirstDayWeek(mSelYear, mSelMonth);

    for(int day = 0; day < mMonthDays; day++){
      dayStr = String.valueOf(day + 1);
      int column = (day + mWeekNumber - 1) % 7;
      int row   = (day + mWeekNumber - 1) / 7;
      mDays[row][column] = day + 1;
      int startX = (int) (mColumnSize * column + (mColumnSize - mPaint.measureText(dayStr)) / 2);
      int startY = (int) (mRowSize * row + mRowSize / 2 - (mPaint.ascent() + mPaint.descent()) / 2);

      //           
      if(mOptionalDates.contains(getSelData(mSelYear, mSelMonth, mDays[row][column]))){
        //   ,           
        if(!mSelectedDates.contains(getSelData(mSelYear, mSelMonth, mDays[row][column]))){
          //      ,      
          canvas.drawBitmap(mBgNotOptBitmap, startX - 22, startY - 55, mPaint);
          mPaint.setColor(mDayNormalColor);
        }else{
          //    ,        
          canvas.drawBitmap(mBgOptBitmap, startX - 22, startY - 55, mPaint);
          mPaint.setColor(mDayPressedColor);
        }
        //     
        canvas.drawText(dayStr, startX, startY - 10, mPaint);
      }else{
        mPaint.setColor(mDayNotOptColor);
        canvas.drawText(dayStr, startX, startY, mPaint);
      }
    }
  }

  private int downX = 0,downY = 0;

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    int eventCode = event.getAction();
    switch(eventCode){
      case MotionEvent.ACTION_DOWN:
        downX = (int) event.getX();
        downY = (int) event.getY();
        break;
      case MotionEvent.ACTION_MOVE:
        break;
      case MotionEvent.ACTION_UP:
        if(!mClickable) return true;

        int upX = (int) event.getX();
        int upY = (int) event.getY();
        if(Math.abs(upX - downX) < 10 && Math.abs(upY - downY) < 10){
          performClick();
          onClick((upX + downX) / 2, (upY + downY) / 2);
        }
        break;
    }
    return true;
  }

  /**
   *     
   */
  private void onClick(int x, int y){
    int row = y / mRowSize;
    int column = x / mColumnSize;
    setSelYTD(mSelYear, mSelMonth, mDays[row][column]);

    //        
    boolean isSelected = mSelectedDates.contains(getSelData(mSelYear, mSelMonth, mSelDate));
    if(isSelected){
      mSelectedDates.remove(getSelData(mSelYear, mSelMonth, mSelDate));
    }else{
      mSelectedDates.add(getSelData(mSelYear, mSelMonth, mSelDate));
    }

    invalidate();
    if(mListener != null){
      //     
      mListener.onClickDateListener(mSelYear, (mSelMonth + 1), mSelDate);
    }
  }

  /**
   *        
   */
  private void initSize() {
    //         
    mColumnSize = getWidth() / NUM_COLUMNS;
    //         
    mRowSize = getHeight() / NUM_ROWS;
  }

  /**
   *        
   * @param dates     
   */
  public void setOptionalDate(List<String> dates){
    this.mOptionalDates = dates;
  }

  /**
   *      
   * @param year  
   * @param month  
   * @param date  
   */
  public void setSelYTD(int year, int month, int date){
    this.mSelYear  =  year;
    this.mSelMonth =  month;
    this.mSelDate  =  date;
  }

  /**
   *         
   */
  public void setLastMonth(){
    int year  =  mSelYear;
    int month  =  mSelMonth;
    int day   =  mSelDate;
    //    1  ,   12  
    if(month == 0){
      year = mSelYear-1;
      month = 11;
    }else if(DateUtils.getMonthDays(year, month) == day){
      //              ,       ,          
      month = month-1;
      day = DateUtils.getMonthDays(year, month);
    }else{
      month = month-1;
    }
    setSelYTD(year,month,day);
    invalidate();
  }

  /**
   *        
   */
  public void setNextMonth(){
    int year  =  mSelYear;
    int month  =  mSelMonth;
    int day   =  mSelDate;
    //    12  ,   1  
    if(month == 11){
      year = mSelYear+1;
      month = 0;
    }else if(DateUtils.getMonthDays(year, month) == day){
      //              ,       ,          
      month = month + 1;
      day = DateUtils.getMonthDays(year, month);
    }else{
      month = month + 1;
    }
    setSelYTD(year,month,day);
    invalidate();
  }

  /**
   *            
   * @return   :2016-06
   */
  public String getDate(){
    String data;
    if((mSelMonth + 1) < 10){
      data = mSelYear + "-0" + (mSelMonth + 1);
    }else{
      data = mSelYear + "-" + (mSelMonth + 1);
    }
    return data;
  }

  /**
   *          
   * @return   :20160606
   */
  private String getSelData(int year, int month, int date){
    String monty, day;
    month = (month + 1);

    //         0  
    if((month) < 10) {
      monty = "0" + month;
    }else{
      monty = String.valueOf(month);
    }

    //         0  
    if((date) < 10){
      day = "0" + (date);
    }else{
      day = String.valueOf(date);
    }
    return year + monty + day;
  }

  /**
   *         
   */
  public List<String> getSelectedDates(){
    return mSelectedDates;
  }

  /**
   *         
   */
  public void setSelectedDates(List<String> dates){
    this.mSelectedDates = dates;
  }

  /**
   *           
   */
  @Override
  public void setClickable(boolean clickable) {
    this.mClickable = clickable;
  }

  private OnClickListener mListener;

  public interface OnClickListener{
    void onClickDateListener(int year, int month, int day);
  }

  /**
   *       
   */
  public void setOnClickDate(OnClickListener listener){
    this.mListener = listener;
  }

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    recyclerBitmap(mBgOptBitmap);
    recyclerBitmap(mBgNotOptBitmap);
  }

  /**
   *   Bitmap  
   */
  private void recyclerBitmap(Bitmap bitmap) {
    if(bitmap != null && !bitmap.isRecycled()){
      bitmap.recycle();
    }
  }
}

사용 절차
1.사용자 정의 달력 보기 초기 화:
CalendarView mCalendarView = (CalendarView) findViewById(R.id.calendarView);
2.선택 할 수 있 는 일수 데이터 초기 화:

List<String> mDatas = new ArrayList<>();
mDatas.add("20160801");
mDatas.add("20160802");
mDatas.add("20160803");
mDatas.add("20160816");
mDatas.add("20160817");
mDatas.add("20160826");
mDatas.add("20160910");
mDatas.add("20160911");
mDatas.add("20160912");
3.사용자 정의 달력 View 에 설정:

//       
mCalendarView.setOptionalDate(mDatas);
설정 클릭 감청

mCalendarView.setOnClickDate(new CalendarView.OnClickListener() {
  @Override
  public void onClickDateListener(int year, int month, int day) {
    Toast.makeText(getApplication(), year + " " + month + " " + day + " ", Toast.LENGTH_SHORT).show();

    //        
    List<String> dates = mCalendarView.getSelectedDates();
    for (String date : dates) {
      Log.e("test", "date: " + date);
    }

  }
});

클릭 하지 않 고 데이터 전시 만 하면 설정 할 수 있 습 니 다.

//       
mCalendarView.setSelectedDates(mDatas);
//         
mCalendarView.setClickable(false);
원본 다운로드:
GitHub 주소:https://github.com/Airsaid/CalendarView환영 스타~!
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기