編輯:關於Android編程
IDE版本:AndroidStudio2.0
物理機版本:Win7旗艦版(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 ListmOptionalDates; /** * 以選日期數據 */ private List 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 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 getSelectedDates(){ return mSelectedDates; } /** * 設置已選日期數據 */ public void setSelectedDates(List 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,初始化自定義日歷View:
CalendarView mCalendarView = (CalendarView) findViewById(R.id.calendarView);
2,初始化可以被選擇的天數數據:
ListmDatas = 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(); // 獲取已選擇日期 Listdates = mCalendarView.getSelectedDates(); for (String date : dates) { Log.e("test", "date: " + date); } } });
如果只需要進行數據展示,而不需要點擊,可以設置:
// 設置已選日期 mCalendarView.setSelectedDates(mDatas); // 設置不可以被點擊 mCalendarView.setClickable(false);
一.Universal-Image-Loader概述:Android-Universal-Image-Loader是一個開源的圖片加載框架,這個項目的目的是提供一個可重復
效果如圖中藍框所框 0){ editText.setText(defaultText); } editText.setEnabled(isReadOnl
概述整個View樹的繪圖流程是在ViewRoot.java類的performTraversals()函數展開的,該函數做的執行過程可簡單概況為:- 判斷是否需要重新計算視
OPPO R9是OPPO發布的最新款手機,對於它的操作使用,還有人不大清楚,如oppo r9怎麼截圖?下面小編就跟大家介紹一下oppo r9截圖方法,有需要