擼一個Android高效能日曆控制項,高仿魅族,android高仿

來源:互聯網
上載者:User

擼一個Android高效能日曆控制項,高仿魅族,android高仿

Android原生的CalendarView根本無法滿足我們日常開發的需要,在開發吾記APP的過程中,我覺得需要來一款高效能且美觀簡潔的日曆控制項,覺得魅族的日曆風格十分適合,於是打算擼一款。

github地址:https://github.com/huanghaibin-dev/CalendarView

 

compile 'com.haibin:calendarview:1.0.2'

 

先上:

 

動手之前我們需要分析一下魅族是怎麼設計如此高效能的日曆的,我們開啟開發人員選項中的顯示布局邊界:

 

好吧,一開始我以為日曆介面是ViewPager+RecyclerView的,但是這麼一看明顯就不是了,如果是RecyclerView,那麼我們假設每個月的卡片都有5*7=35個item,每個item根布局是RelativeLayout+3個TextView,我們大概估算一下日曆初始化時要載入的控制項:

3個ViewPager的item * 35個RecyclerView的Item * 4(每個item的控制項數) + 8 (星期欄)= 420+ 

我的天,這可不能這麼幹,明顯效能大打折扣,我們再來看看月份控制項:

好吧,這裡看上去就是ViewPager+RecyclerView來做的,每個RecyclerView的item都只是一個控制項,裡面繪製了文本 ,這裡大概就分析清楚了。

我們採取折中的方式,日曆介面和月份卡介面均採用ViewPager+RecyclerView的方式,不同的是所有的item我們都採用自訂ViewCanvas繪製的方式來做,這樣效能雖然比不上魅族,但速度體驗基本差不多,下面先看日曆介面的item代碼:只需要繪製3個文本即可

 

public class CellView extends View {    private int mDay = 20;    private String mLunar;    private String mScheme;    private Paint mDayPaint = new Paint();    private Paint mLunarPaint = new Paint();    private Paint mSchemePaint = new Paint();    private Paint mCirclePaint = new Paint();    private int mRadius;    private int mCirclePadding;    private int mCircleColor;    public CellView(Context context) {        this(context, null);    }    public CellView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        mDayPaint.setAntiAlias(true);        mDayPaint.setColor(Color.BLACK);        mDayPaint.setFakeBoldText(true);        mDayPaint.setTextAlign(Paint.Align.CENTER);        mLunarPaint.setAntiAlias(true);        mLunarPaint.setColor(Color.GRAY);        mLunarPaint.setTextAlign(Paint.Align.CENTER);        mSchemePaint.setAntiAlias(true);        mSchemePaint.setColor(Color.WHITE);        mSchemePaint.setFakeBoldText(true);        mSchemePaint.setTextAlign(Paint.Align.CENTER);        mCirclePaint.setAntiAlias(true);        mCirclePaint.setStyle(Paint.Style.FILL);        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CellView);        mDayPaint.setTextSize(array.getDimensionPixelSize(R.styleable.CellView_cell_day_text_size, 18));        mLunarPaint.setTextSize(array.getDimensionPixelSize(R.styleable.CellView_cell_lunar_text_size, 12));        mRadius = (int) array.getDimension(R.styleable.CellView_cell_scheme_radius, 8);        mSchemePaint.setTextSize(array.getDimensionPixelSize(R.styleable.CellView_cell_scheme_text_size, 6));        mCirclePadding = array.getDimensionPixelSize(R.styleable.CellView_cell_circle_padding, 4);        mCirclePaint.setColor(array.getColor(R.styleable.CellView_cell_circle_color, 0xff16BB7F));        array.recycle();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        int w = (width - getPaddingLeft() - getPaddingRight());        int h = (height - getPaddingTop() - getPaddingBottom()) / 4;        canvas.drawText(String.valueOf(mDay), w / 2, 2 * h + getPaddingTop(), mDayPaint);        canvas.drawText(mLunar, w / 2, 4 * h + getPaddingTop(), mLunarPaint);        if (!TextUtils.isEmpty(mScheme)) {            canvas.drawCircle(w / 2 + mCirclePadding + mDayPaint.getTextSize(), getPaddingTop() + h, mRadius, mCirclePaint);            canvas.drawText(mScheme, w / 2 + mCirclePadding + mDayPaint.getTextSize(), getPaddingTop() + mRadius / 2 + h, mSchemePaint);        }    }    /**     * 初始化日曆     * @param day 天     * @param lunar 農曆     * @param scheme 事件標記     */    void init(int day, String lunar, String scheme) {        this.mDay = day;        this.mLunar = lunar;        this.mScheme = scheme;    }    void setTextColor(int textColor) {        mDayPaint.setColor(textColor);        mLunarPaint.setColor(textColor);    }    void setCircleColor(int circleColor) {        mCirclePaint.setColor(circleColor);        invalidate();    }}

月份卡自訂View

 

public class MonthView extends View {    private int mDiff;//第一天偏離周日多少天    private int mCount;//總數    private int mLastCount;//最後一行的天數    private int mLine;//多少行    private Paint mPaint = new Paint();    private Paint mSchemePaint = new Paint();    private List<Calendar> mSchemes;    private Calendar mCalendar;    public MonthView(Context context) {        this(context, null);    }    public MonthView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        mPaint.setAntiAlias(true);        mPaint.setTextAlign(Paint.Align.CENTER);        mSchemePaint.setAntiAlias(true);        mSchemePaint.setTextAlign(Paint.Align.CENTER);        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MonthView);        mPaint.setTextSize(array.getDimensionPixelSize(R.styleable.MonthView_month_view_text_size, 12));        mSchemePaint.setTextSize(array.getDimensionPixelSize(R.styleable.MonthView_month_view_text_size, 12));        mPaint.setColor(array.getColor(R.styleable.MonthView_month_view_text_color, Color.BLACK));        mSchemePaint.setColor(array.getColor(R.styleable.MonthView_month_view_remark_color, Color.RED));        array.recycle();        measureLine();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        int pLeft = getPaddingLeft();        int w = (width - getPaddingLeft() - getPaddingRight()) / 7;        int h = (height - getPaddingTop() - getPaddingBottom()) / 6;        int d = 0;        for (int i = 0; i < mLine; i++) {            if (i == 0) {//第一行                for (int j = 0; j < (7 - mDiff); j++) {                    ++d;                    canvas.drawText(String.valueOf(j + 1), mDiff * w + j * w + pLeft + w / 2, h, isScheme(d) ? mSchemePaint : mPaint);                }            } else if (i == mLine - 1 && mLastCount != 0) {                int first = mCount - mLastCount + 1;                for (int j = 0; j < mLastCount; j++) {                    ++d;                    canvas.drawText(String.valueOf(first), j * w + pLeft + w / 2, (i + 1) * h, isScheme(d) ? mSchemePaint : mPaint);                    ++first;                }            } else {                int first = i * 7 - mDiff + 1;                for (int j = 0; j < 7; j++) {                    ++d;                    canvas.drawText(String.valueOf(first), j * w + pLeft + w / 2, (i + 1) * h, isScheme(d) ? mSchemePaint : mPaint);                    ++first;                }            }        }    }    /**     * 計算行數     */    private void measureLine() {        int offset = mCount - (7 - mDiff);        mLine = 1 + (offset % 7 == 0 ? 0 : 1) + offset / 7;        mLastCount = offset % 7;    }    /**     * 初始化月份卡     * @param mDiff 偏離天數     * @param mCount 當月總天數     * @param mYear 哪一年     * @param mMonth 哪一月     */     void init(int mDiff, int mCount, int mYear, int mMonth) {        this.mDiff = mDiff;        this.mCount = mCount;        mCalendar = new Calendar();        mCalendar.setYear(mYear);        mCalendar.setMonth(mMonth);        measureLine();        invalidate();    }    void setSchemes(List<Calendar> mSchemes) {        this.mSchemes = mSchemes;    }    void setSchemeColor(int schemeColor) {        if (schemeColor != 0)            mSchemePaint.setColor(schemeColor);        if(schemeColor == 0xff30393E)            mSchemePaint.setColor(Color.RED);    }    private boolean isScheme(int day) {        if (mSchemes == null || mSchemes.size() == 0)            return false;        mCalendar.setDay(day);        return mSchemes.contains(mCalendar);    }}

  

其它代碼沒有什麼難度,日曆演算法是github上找的,更多詳情請看倉庫地址:https://github.com/huanghaibin-dev/CalendarView

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.