小米日历详解

来源:互联网 发布:ubuntu 16.04搭建lnmp 编辑:程序博客网 时间:2024/04/30 00:14



    今天  我们来解释一下 如图所示日历是怎么构建的

   well  首先 我们要了解  图上日历其实是自定义Dateview的一种,所以我们要了解它需要些什么 参考 http://blog.csdn.net/mr_dsw/article/details/48755993

  我们需要实现:
             (1)视图周一到周六

             (2)视图阴农历转换

             (3)视图日期

             (4)事务圆圈

             (5)主界面分层

             (6)对选中日期进行点击事件的处理。   

      接下来 通过发现我们需要一个myLibrary类库,方便程序的再利用,好不多说上类库代码:


      

  1.CaledarAdapter
package com.codbking.calendar;import android.view.View;import android.view.ViewGroup;import com.codbking.calendar.CalendarBean;/** * Created by codbking on 2016/12/22. * email:codbking@gmail.com * github:https://github.com/codbking * blog:http://www.jianshu.com/users/49d47538a2dd/latest_articles */public interface CaledarAdapter {     View getView(View convertView, ViewGroup parentView, CalendarBean bean);}
2.CaledarTopViewChangeListener
package com.codbking.calendar;/** * Created by codbking on 2016/12/23. * email:codbking@gmail.com * github:https://github.com/codbking * blog:http://www.jianshu.com/users/49d47538a2dd/latest_articles */public interface CaledarTopViewChangeListener {    void onLayoutChange(CalendarTopView topView);}

CalendarBean
package com.codbking.calendar;public class CalendarBean {    public int year;    public int moth;    public int day;    public int week;    //-1,0,1    public int mothFlag;    //显示    public String chinaMonth;    public String chinaDay;    public CalendarBean(int year, int moth, int day) {        this.year = year;        this.moth = moth;        this.day = day;    }    public String getDisplayWeek(){        String s="";         switch(week){             case 1:                 s="星期日";          break;             case 2:                 s="星期一";          break;             case 3:                 s="星期二";                 break;             case 4:                 s="星期三";                 break;             case 5:                 s="星期四";                 break;             case 6:                 s="星期五";                 break;             case 7:                 s="星期六";                 break;         }        return s ;    }    @Override    public String toString() {//        String s=year+"/"+moth+"/"+day+"\t"+getDisplayWeek()+"\t农历"+":"+chinaMonth+"/"+chinaDay;        String s=year+"/"+moth+"/"+day;        return s;    }}
4.CalendarDateView
package com.codbking.calendar;import android.content.Context;import android.content.res.TypedArray;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import java.util.Date;import java.util.HashMap;import java.util.LinkedList;import static com.codbking.calendar.CalendarFactory.getMonthOfDayList;/** * Created by codbking on 2016/12/18. * email:codbking@gmail.com * github:https://github.com/codbking * blog:http://www.jianshu.com/users/49d47538a2dd/latest_articles */public class CalendarDateView extends ViewPager implements CalendarTopView {    HashMap<Integer, CalendarView> views = new HashMap<>();    private CaledarTopViewChangeListener mCaledarLayoutChangeListener;    private CalendarView.OnItemClickListener onItemClickListener;    private LinkedList<CalendarView> cache = new LinkedList();    private int MAXCOUNT=6;    private int row = 6;    private CaledarAdapter mAdapter;    private int calendarItemHeight = 0;    public void setAdapter(CaledarAdapter adapter) {        mAdapter = adapter;        initData();    }    public void setOnItemClickListener(CalendarView.OnItemClickListener onItemClickListener) {        this.onItemClickListener = onItemClickListener;    }    public CalendarDateView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CalendarDateView);        row = a.getInteger(R.styleable.CalendarDateView_cbd_calendar_row, 6);        a.recycle();        init();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int calendarHeight = 0;        if (getAdapter() != null) {            CalendarView view = (CalendarView) getChildAt(0);            if (view != null) {                calendarHeight = view.getMeasuredHeight();                calendarItemHeight = view.getItemHeight();            }        }        setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec(calendarHeight, MeasureSpec.EXACTLY));    }    private void init() {       final int[] dateArr= CalendarUtil.getYMD(new Date());        setAdapter(new PagerAdapter() {            @Override            public int getCount() {                return Integer.MAX_VALUE;            }            @Override            public boolean isViewFromObject(View view, Object object) {                return view == object;            }            @Override            public Object instantiateItem(ViewGroup container, final int position) {                CalendarView view;                if (!cache.isEmpty()) {                    view = cache.removeFirst();                } else {                    view = new CalendarView(container.getContext(), row);                }                view.setOnItemClickListener(onItemClickListener);                view.setAdapter(mAdapter);                view.setData(getMonthOfDayList(dateArr[0],dateArr[1]+position-Integer.MAX_VALUE/2),position==Integer.MAX_VALUE/2);                container.addView(view);                views.put(position, view);                return view;            }            @Override            public void destroyItem(ViewGroup container, int position, Object object) {                container.removeView((View) object);                cache.addLast((CalendarView) object);                views.remove(position);            }        });        addOnPageChangeListener(new SimpleOnPageChangeListener() {            @Override            public void onPageSelected(int position) {                super.onPageSelected(position);                if (onItemClickListener != null) {                    CalendarView view = views.get(position);                    Object[] obs = view.getSelect();                    onItemClickListener.onItemClick((View) obs[0], (int) obs[1], (CalendarBean) obs[2]);                }                mCaledarLayoutChangeListener.onLayoutChange(CalendarDateView.this);            }        });    }    private void initData() {        setCurrentItem(Integer.MAX_VALUE/2, false);        getAdapter().notifyDataSetChanged();    }    @Override    public int[] getCurrentSelectPositon() {        CalendarView view = views.get(getCurrentItem());        if (view == null) {            view = (CalendarView) getChildAt(0);        }        if (view != null) {            return view.getSelectPostion();        }        return new int[4];    }    @Override    public int getItemHeight() {        return calendarItemHeight;    }    @Override    public void setCaledarTopViewChangeListener(CaledarTopViewChangeListener listener) {        mCaledarLayoutChangeListener = listener;    }}
5.CalendarFactory
import java.util.ArrayList;import java.util.Arrays;import java.util.Calendar;import java.util.HashMap;import java.util.List;import static android.R.attr.listDivider;import static android.R.attr.max;import static android.R.attr.y;import static android.R.id.list;import static com.codbking.calendar.CalendarUtil.getDayOfWeek;/** * Created by codbking on 2016/12/16. */public class CalendarFactory {    private static HashMap<String, List<CalendarBean>> cache = new HashMap<>();    //获取一月中的集合    public static List<CalendarBean> getMonthOfDayList(int y, int m) {        String key=y+""+m;        if(cache.containsKey(key)){            List<CalendarBean> list=cache.get(key);            if(list==null){                cache.remove(key);            }else{                return list;            }        }        List<CalendarBean> list = new ArrayList<CalendarBean>();        cache.put(key,list);        //计算出一月第一天是星期几        int fweek = getDayOfWeek(y, m, 1);        int total = CalendarUtil.getDayOfMaonth(y, m);        //根据星期推出前面还有几个显示        for (int i = fweek - 1; i > 0; i--) {            CalendarBean bean = geCalendarBean(y, m, 1 - i);            bean.mothFlag = -1;            list.add(bean);        }        //获取当月的天数        for (int i = 0; i < total; i++) {            CalendarBean bean = geCalendarBean(y, m, i + 1);            list.add(bean);        }        //为了塞满42个格子,显示多出当月的天数        for (int i = 0; i < 42 - (fweek - 1) - total; i++) {            CalendarBean bean = geCalendarBean(y, m, total + i + 1);            bean.mothFlag = 1;            list.add(bean);        }        return list;    }    public static CalendarBean geCalendarBean(int year, int month, int day) {        Calendar calendar = Calendar.getInstance();        calendar.set(year, month - 1, day);        year = calendar.get(Calendar.YEAR);        month = calendar.get(Calendar.MONTH) + 1;        day = calendar.get(Calendar.DATE);        CalendarBean bean = new CalendarBean(year, month, day);        bean.week = CalendarUtil.getDayOfWeek(year, month, day);        String[] chinaDate = ChinaDate.getChinaDate(year, month, day);        bean.chinaMonth = chinaDate[0];        bean.chinaDay = chinaDate[1];        return bean;    }    public static void main(String[] args) {    }}
6.CalendarLayout


package com.codbking.calendar;import android.content.Context;import android.graphics.Rect;import android.support.v4.view.VelocityTrackerCompat;import android.support.v4.view.ViewCompat;import android.support.v4.widget.ScrollerCompat;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewGroup;import android.view.animation.Interpolator;import android.widget.AbsListView;import android.widget.FrameLayout;import android.widget.ListView;/** * Created by codbking on 2016/12/18. * email:codbking@gmail.com * github:https://github.com/codbking * blog:http://www.jianshu.com/users/49d47538a2dd/latest_articles */public class CalendarLayout extends FrameLayout {    private static final String TAG = "CalendarLayout";    private View view1;    private ViewGroup view2;    private CalendarTopView mTopView;    //展开    public static final int TYPE_OPEN = 0;    //折叠    public static final int TYPE_FOLD = 1;    public int type = TYPE_FOLD;    //是否处于滑动中    private boolean isSilde = false;    private int topHeigth;    private int itemHeight;    private int bottomViewTopHeight;    private int maxDistance;    private ScrollerCompat mScroller;    private float mMaxVelocity;    private float mMinVelocity;    private int activitPotionerId;    private static final Interpolator sInterpolator = new Interpolator() {        @Override        public float getInterpolation(float t) {            t -= 1.0f;            return t * t * t * t * t + 1.0f;        }    };    public CalendarLayout(Context context) {        super(context);        init();    }    public CalendarLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        final CalendarTopView viewPager = (CalendarTopView) getChildAt(0);        mTopView = viewPager;        view1 = (View) viewPager;        view2 = (ViewGroup) getChildAt(1);        mTopView.setCaledarTopViewChangeListener(new CaledarTopViewChangeListener() {            @Override            public void onLayoutChange(CalendarTopView topView) {                CalendarLayout.this.requestLayout();            }        });    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        itemHeight=mTopView.getItemHeight();        topHeigth=view1.getMeasuredHeight();        maxDistance = topHeigth - itemHeight;        switch (type) {            case TYPE_FOLD:                bottomViewTopHeight = itemHeight;                break;            case TYPE_OPEN:                bottomViewTopHeight = topHeigth;                break;        }        view2.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - mTopView.getItemHeight(), MeasureSpec.EXACTLY));    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        view2.offsetTopAndBottom(bottomViewTopHeight);        int [] selectRct=getSelectRect();        if(type==TYPE_FOLD){            view1.offsetTopAndBottom(-selectRct[1]);        }    }    private void init() {        final ViewConfiguration vc = ViewConfiguration.get(getContext());        mMaxVelocity = vc.getScaledMaximumFlingVelocity();        mMinVelocity = vc.getScaledMinimumFlingVelocity();        mScroller = ScrollerCompat.create(getContext(), sInterpolator);    }    float oy, ox;    boolean isClickBtottomView = false;    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {//        mViewDragHelper.shouldInterceptTouchEvent(ev);        boolean isflag = false;        //上下运动进行拦截        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                oy = ev.getY();                ox = ev.getX();                isClickBtottomView = isClickView(view2, ev);                cancel();                activitPotionerId = ev.getPointerId(0);                int top = view2.getTop();                if (top < topHeigth) {                    type = TYPE_FOLD;                } else {                    type = TYPE_OPEN;                }                break;            case MotionEvent.ACTION_MOVE:                float y = ev.getY();                float x = ev.getX();                float xdiff = x - ox;                float ydiff = y - oy;                if (Math.abs(ydiff) > 5 && Math.abs(ydiff) > Math.abs(xdiff)) {                    isflag = true;                    if (isClickBtottomView) {                        boolean isScroll = isScroll(view2);                        if (ydiff > 0) {                            //向下                            if (type == TYPE_OPEN) {                                return super.onInterceptTouchEvent(ev);                            } else {                                if (isScroll) {                                    return super.onInterceptTouchEvent(ev);                                }                            }                        } else {                            //向上                            if (type == TYPE_FOLD) {                                return super.onInterceptTouchEvent(ev);                            } else {                                if (isScroll) {                                    return super.onInterceptTouchEvent(ev);                                }                            }                        }                    }                }                ox = x;                oy = y;                break;            case MotionEvent.ACTION_UP:                break;        }        return isSilde || isflag || super.onInterceptTouchEvent(ev);    }    private boolean isScroll(ViewGroup view2) {        View fistChildView = view2.getChildAt(0);        if (fistChildView == null) {            return false;        }        if (view2 instanceof ListView) {            AbsListView list = (AbsListView) view2;            if (fistChildView.getTop() != 0) {                return true;            } else {                if (list.getPositionForView(fistChildView) != 0) {                    return true;                }            }        }        return false;    }    public boolean isClickView(View view, MotionEvent ev) {        Rect rect = new Rect();        view.getHitRect(rect);        boolean isClick = rect.contains((int) ev.getX(), (int) ev.getY());        Log.d(TAG, "isClickView() called with: isClick = [" + isClick + "]");        return isClick;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        processTouchEvent(event);        return true;    }    private VelocityTracker mVelocityTracker;    public void processTouchEvent(MotionEvent event) {        if (mVelocityTracker == null) {            mVelocityTracker = VelocityTracker.obtain();        }        mVelocityTracker.addMovement(event);        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                break;            case MotionEvent.ACTION_MOVE:                if (isSilde) {                    return;                }                float cy = event.getY();                int dy = (int) (cy - oy);                if (dy == 0) {                    return;                }                oy = cy;                move(dy);                break;            case MotionEvent.ACTION_UP:                if (isSilde) {                    cancel();                    return;                }                //判断速度                final int pointerId = activitPotionerId;                mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);                float crrentV = VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId);                if (Math.abs(crrentV) > 2000) {                    if (crrentV > 0) {                        open();                    } else {                        flod();                    }                    cancel();                    return;                }                int top = view2.getTop() - topHeigth;                int maxd = maxDistance;                if (Math.abs(top) < maxd / 2) {                    open();                } else {                    flod();                }                cancel();                break;            case MotionEvent.ACTION_CANCEL:                cancel();                break;        }    }    public void open() {        startScroll(view2.getTop(), topHeigth);    }    public void flod() {        startScroll(view2.getTop(), topHeigth - maxDistance);    }    private int[] getSelectRect() {        return mTopView.getCurrentSelectPositon();    }    private void move(int dy) {        int []selectRect = getSelectRect();        int itemHeight=mTopView.getItemHeight();        int dy1 = getAreaValue(view1.getTop(), dy, -selectRect[1], 0);        int dy2 = getAreaValue(view2.getTop() - topHeigth, dy, -(topHeigth - itemHeight), 0);        if (dy1 != 0) {            ViewCompat.offsetTopAndBottom(view1, dy1);        }        if (dy2 != 0) {            ViewCompat.offsetTopAndBottom(view2, dy2);        }    }    private int getAreaValue(int top, int dy, int minValue, int maxValue) {        if (top + dy < minValue) {            return minValue - top;        }        if (top + dy > maxValue) {            return maxValue - top;        }        return dy;    }    private void startScroll(int starty, int endY) {        float distance = endY - starty;        float t = distance / maxDistance * 600;        mScroller.startScroll(0, 0, 0, endY - starty, (int) Math.abs(t));        postInvalidate();    }    int oldY = 0;    @Override    public void computeScroll() {        super.computeScroll();        bottomViewTopHeight = view2.getTop();        if (mScroller.computeScrollOffset()) {            isSilde = true;            int cy = mScroller.getCurrY();            int dy = cy - oldY;            move(dy);            oldY = cy;            postInvalidate();        } else {            oldY = 0;            isSilde = false;        }    }    public void cancel() {        if (mVelocityTracker != null) {            mVelocityTracker.recycle();            mVelocityTracker = null;        }    }}

    这个类主要实现滚动还有滑屏 继承FrameLayout   

    onInterceptTouchEvent监听上下进行拦截

   CalendarLayout()用来加载布局

      布局加载完成回调onFinishInflate()方法

      重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象

7.CalendarUti

public class CalendarUtil {    //获取一月的第一天是星期几    public static int getDayOfWeek(int y, int m, int day) {        Calendar calendar = Calendar.getInstance();        calendar.set(y, m - 1, day);        return calendar.get(Calendar.DAY_OF_WEEK);    }    //获取一月最大天数    public static int getDayOfMaonth(int y, int m) {        Calendar cal = Calendar.getInstance();        cal.set(y, m - 1, 1);        int dateOfMonth = cal.getActualMaximum(Calendar.DATE);        return dateOfMonth;    }    public static int getMothOfMonth(int y, int m) {        Calendar cal = Calendar.getInstance();        cal.set(y, m - 1, 1);        int dateOfMonth = cal.get(Calendar.MONTH);        return dateOfMonth + 1;    }    public static int[] getYMD(Date date) {        Calendar cal = Calendar.getInstance();        cal.setTime(date);        return new int[]{cal.get(Calendar.YEAR),cal.get(Calendar.MONTH)+1,cal.get(Calendar.DATE)};    }}


8.CalendarTopView
package com.codbking.calendar;/** * Created by codbking on 2016/12/23. * email:codbking@gmail.com * github:https://github.com/codbking * blog:http://www.jianshu.com/users/49d47538a2dd/latest_articles */public interface CalendarTopView {    int[] getCurrentSelectPositon();    int getItemHeight();    void setCaledarTopViewChangeListener(CaledarTopViewChangeListener listener);}
9.CalendarView
package com.codbking.calendar;import android.content.Context;import android.graphics.Canvas;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;import java.util.Date;import java.util.List;/** * Created by codbking on 2016/12/18. * email:codbking@gmail.com * github:https://github.com/codbking * blog:http://www.jianshu.com/users/49d47538a2dd/latest_articles */public class CalendarView extends ViewGroup {    private static final String TAG = "CalendarView";    private int selectPostion = -1;    private CaledarAdapter adapter;    private List<CalendarBean> data;    private OnItemClickListener onItemClickListener;    private int row = 6;    private int column = 7;    private int itemWidth;    private int itemHeight;    private boolean isToday;    public interface OnItemClickListener {        void onItemClick(View view, int postion, CalendarBean bean);    }    public CalendarView(Context context, int row) {        super(context);        this.row = row;    }    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {        this.onItemClickListener = onItemClickListener;    }    public int getItemHeight() {        return itemHeight;    }    public CalendarView(Context context, AttributeSet attrs) {        super(context, attrs);        setWillNotDraw(false);    }    public void setAdapter(CaledarAdapter adapter) {        this.adapter = adapter;    }    public void setData(List<CalendarBean> data,boolean isToday) {        this.data = data;        this.isToday=isToday;        setItem();        requestLayout();    }    private void setItem() {        selectPostion = -1;        if (adapter == null) {            throw new RuntimeException("adapter is null,please setadapter");        }        for (int i = 0; i < data.size(); i++) {            CalendarBean bean = data.get(i);            View view = getChildAt(i);            View chidView = adapter.getView(view, this, bean);            if (view == null || view != chidView) {                addViewInLayout(chidView, i, chidView.getLayoutParams(), true);            }            if(isToday&&selectPostion==-1){                int[]date=CalendarUtil.getYMD(new Date());                if(bean.year==date[0]&&bean.moth==date[1]&&bean.day==date[2]){                     selectPostion=i;                }            }else {                if (selectPostion == -1 && bean.day == 1) {                    selectPostion = i;                }            }            chidView.setSelected(selectPostion==i);            setItemClick(chidView, i, bean);        }    }    public Object[] getSelect(){         return new Object[]{getChildAt(selectPostion),selectPostion,data.get(selectPostion)};    }    public void setItemClick(final View view, final int potsion, final CalendarBean bean) {        view.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (selectPostion != -1) {                    getChildAt(selectPostion).setSelected(false);                    getChildAt(potsion).setSelected(true);                }                selectPostion = potsion;                if (onItemClickListener != null) {                    onItemClickListener.onItemClick(view, potsion, bean);                }            }        });    }    public int[] getSelectPostion() {        Rect rect = new Rect();        try {            getChildAt(selectPostion).getHitRect(rect);        } catch (Exception e) {            e.printStackTrace();        }        return new int[]{rect.left, rect.top, rect.right, rect.top};    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int parentWidth = MeasureSpec.getSize(MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY));        itemWidth = parentWidth / column;        itemHeight = itemWidth;        View view = getChildAt(0);        if (view == null) {            return;        }        ViewGroup.LayoutParams params = view.getLayoutParams();        if (params != null && params.height > 0) {            itemHeight = params.height;        }        setMeasuredDimension(parentWidth, itemHeight * row);        for(int i=0;i<getChildCount();i++){            View childView=getChildAt(i);            childView.measure(MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY));        }        Log.i(TAG, "onMeasure() called with: itemHeight = [" + itemHeight + "], itemWidth = [" + itemWidth + "]");    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        for (int i = 0; i <getChildCount(); i++) {            layoutChild(getChildAt(i), i, l, t, r, b);        }    }    private void layoutChild(View view, int postion, int l, int t, int r, int b) {        int cc = postion % column;        int cr = postion / column;        int itemWidth = view.getMeasuredWidth();        int itemHeight = view.getMeasuredHeight();        l = cc * itemWidth;        t = cr * itemHeight;        r = l + itemWidth;        b = t + itemHeight;        view.layout(l, t, r, b);    }}
 继承extends  用来实现显示网格状的日历内容
  实现CaledarAdapter接口 CalendarBean list 用来 获取或者说显示日期
10.ChinaDate
package com.codbking.calendar;import java.text.SimpleDateFormat;import java.util.Arrays;import java.util.HashMap;import java.util.Locale;import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;import static android.media.CamcorderProfile.get;public class ChinaDate {    private static SimpleDateFormat sdf = new SimpleDateFormat(            "yyyy年M月d日 EEEEE");    private final static long[] lunarInfo = new long[]{0x04bd8, 0x04ae0,            0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0,            0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,            0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5,            0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,            0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3,            0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0,            0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0,            0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8,            0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570,            0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5,            0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0,            0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50,            0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0,            0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,            0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7,            0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50,            0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954,            0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260,            0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0,            0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0,            0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20,            0x0ada0};    final private static int[] year20 = new int[]{1, 4, 1, 2, 1, 2, 1, 1, 2,            1, 2, 1};    final private static int[] year19 = new int[]{0, 3, 0, 1, 0, 1, 0, 0, 1,            0, 1, 0};    final private static int[] year2000 = new int[]{0, 3, 1, 2, 1, 2, 1, 1,            2, 1, 2, 1};    public final static String[] nStr1 = new String[]{"", "正", "二", "三", "四",            "五", "六", "七", "八", "九", "十", "冬月", "腊月"};    private final static String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊",            "己", "庚", "辛", "壬", "癸"};    private final static String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰",            "巳", "午", "未", "申", "酉", "戌", "亥"};    private final static String[] Animals = new String[]{"鼠", "牛", "虎", "兔",            "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};    private final static String[] solarTerm = new String[]{"小寒", "大寒", "立春",            "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑",            "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};    private final static String[] sFtv = new String[]{"0101*元旦", "0214 情人节",            "0308 妇女节", "0312 植树节", "0315 消费者权益日", "0401 愚人节", "0501 劳动节",            "0504 青年节", "0512 护士节", "0601 儿童节", "0701 建党节", "0801 建军节",            "0808 父亲节", "0909 mzd逝世纪念", "0910 教师节", "0928 孔子诞辰", "1001*国庆节",            "1006 老人节", "1024 联合国日", "1112 孙中山诞辰", "1220 澳门回归", "1225 圣诞节",            "1226 mzd诞辰"};    private final static String[] lFtv = new String[]{"0101*农历春节",            "0115 元宵节", "0505 端午节", "0707 七夕情人节", "0815 中秋节", "0909 重阳节",            "1208 腊八节", "1224 小年", "0100*除夕"};    /**     * 传回农历 y年的总天数     *     * @param y     * @return     */    final private static int lYearDays(int y) {        int i, sum = 348;        for (i = 0x8000; i > 0x8; i >>= 1) {            if ((lunarInfo[y - 1900] & i) != 0)                sum += 1;        }        return (sum + leapDays(y));    }    /**     * 传回农历 y年闰月的天数     *     * @param y     * @return     */    final private static int leapDays(int y) {        if (leapMonth(y) != 0) {            if ((lunarInfo[y - 1900] & 0x10000) != 0)                return 30;            else                return 29;        } else            return 0;    }    /**     * 传回农历 y年闰哪个月 1-12 , 没闰传回 0     *     * @param y     * @return     */    final private static int leapMonth(int y) {        return (int) (lunarInfo[y - 1900] & 0xf);    }    /**     * 传回农历 y年m月的总天数     *     * @param y     * @param m     * @return     */    final private static int monthDays(int y, int m) {        if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)            return 29;        else            return 30;    }    /**     * 传回农历 y年的生肖     *     * @param y     * @return     */    final public static String AnimalsYear(int y) {        return Animals[(y - 4) % 12];    }    /**     * 传入 月日的offset 传回干支,0=甲子     *     * @param num     * @return     */    final private static String cyclicalm(int num) {        return (Gan[num % 10] + Zhi[num % 12]);    }    /**     * 传入 offset 传回干支, 0=甲子     *     * @param y     * @return     */    final public static String cyclical(int y) {        int num = y - 1900 + 36;        return (cyclicalm(num));    }    /**     * 传出农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6     *     * @param y     * @param m     * @return     */    final private long[] Lunar(int y, int m) {        long[] nongDate = new long[7];        int i = 0, temp = 0, leap = 0;        Date baseDate = new GregorianCalendar(1900 + 1900, 1, 31).getTime();        Date objDate = new GregorianCalendar(y + 1900, m, 1).getTime();        long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L;        if (y < 2000)            offset += year19[m - 1];        if (y > 2000)            offset += year20[m - 1];        if (y == 2000)            offset += year2000[m - 1];        nongDate[5] = offset + 40;        nongDate[4] = 14;        for (i = 1900; i < 2050 && offset > 0; i++) {            temp = lYearDays(i);            offset -= temp;            nongDate[4] += 12;        }        if (offset < 0) {            offset += temp;            i--;            nongDate[4] -= 12;        }        nongDate[0] = i;        nongDate[3] = i - 1864;        leap = leapMonth(i); // 闰哪个月        nongDate[6] = 0;        for (i = 1; i < 13 && offset > 0; i++) {            // 闰月            if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) {                --i;                nongDate[6] = 1;                temp = leapDays((int) nongDate[0]);            } else {                temp = monthDays((int) nongDate[0], i);            }            // 解除闰月            if (nongDate[6] == 1 && i == (leap + 1))                nongDate[6] = 0;            offset -= temp;            if (nongDate[6] == 0)                nongDate[4]++;        }        if (offset == 0 && leap > 0 && i == leap + 1) {            if (nongDate[6] == 1) {                nongDate[6] = 0;            } else {                nongDate[6] = 1;                --i;                --nongDate[4];            }        }        if (offset < 0) {            offset += temp;            --i;            --nongDate[4];        }        nongDate[1] = i;        nongDate[2] = offset + 1;        return nongDate;    }    /**     * 传出y年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6     *     * @param y     * @param m     * @param d     * @return     */    final public static long[] calElement(int y, int m, int d) {        long[] nongDate = new long[7];        int i = 0, temp = 0, leap = 0;        Date baseDate = new GregorianCalendar(0 + 1900, 0, 31).getTime();        Date objDate = new GregorianCalendar(y, m - 1, d).getTime();        long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L;        nongDate[5] = offset + 40;        nongDate[4] = 14;        for (i = 1900; i < 2050 && offset > 0; i++) {            temp = lYearDays(i);            offset -= temp;            nongDate[4] += 12;        }        if (offset < 0) {            offset += temp;            i--;            nongDate[4] -= 12;        }        nongDate[0] = i;        nongDate[3] = i - 1864;        leap = leapMonth(i); // 闰哪个月        nongDate[6] = 0;        for (i = 1; i < 13 && offset > 0; i++) {            // 闰月            if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) {                --i;                nongDate[6] = 1;                temp = leapDays((int) nongDate[0]);            } else {                temp = monthDays((int) nongDate[0], i);            }            // 解除闰月            if (nongDate[6] == 1 && i == (leap + 1))                nongDate[6] = 0;            offset -= temp;            if (nongDate[6] == 0)                nongDate[4]++;        }        if (offset == 0 && leap > 0 && i == leap + 1) {            if (nongDate[6] == 1) {                nongDate[6] = 0;            } else {                nongDate[6] = 1;                --i;                --nongDate[4];            }        }        if (offset < 0) {            offset += temp;            --i;            --nongDate[4];        }        nongDate[1] = i;        nongDate[2] = offset + 1;        return nongDate;    }    public final static String getChinaDate(int day) {        String a = "";        if (day == 10)            return "初十";        if (day == 20)            return "二十";        if (day == 30)            return "三十";        int two = (int) ((day) / 10);        if (two == 0)            a = "初";        if (two == 1)            a = "十";        if (two == 2)            a = "廿";        if (two == 3)            a = "三";        int one = (int) (day % 10);        switch (one) {            case 1:                a += "一";                break;            case 2:                a += "二";                break;            case 3:                a += "三";                break;            case 4:                a += "四";                break;            case 5:                a += "五";                break;            case 6:                a += "六";                break;            case 7:                a += "七";                break;            case 8:                a += "八";                break;            case 9:                a += "九";                break;        }        return a;    }    public static String today() {        Calendar today = Calendar.getInstance(Locale.SIMPLIFIED_CHINESE);        int year = today.get(Calendar.YEAR);        int month = today.get(Calendar.MONTH) + 1;        int date = today.get(Calendar.DATE);        long[] l = calElement(year, month, date);        StringBuffer sToday = new StringBuffer();        try {            sToday.append(sdf.format(today.getTime()));            sToday.append(" 农历");            sToday.append(cyclical(year));            sToday.append('(');            sToday.append(AnimalsYear(year));            sToday.append(")年");            sToday.append(nStr1[(int) l[1]]);            sToday.append("月");            sToday.append(getChinaDate((int) (l[2])));            return sToday.toString();        } finally {            sToday = null;        }    }    //获取农历的月与日的显示    public static String[] getChinaDate(int year, int month, int day) {        long[] l = calElement(year, month, day);        return new String[]{nStr1[(int) l[1]], getChinaDate((int) (l[2]))};    }    public static String oneDay(int year, int month, int day) {        Calendar today = Calendar.getInstance(Locale.SIMPLIFIED_CHINESE);        today.set(year, month - 1, day);        long[] l = calElement(year, month, day);        StringBuffer sToday = new StringBuffer();        try {            sToday.append(sdf.format(today.getTime()));            sToday.append(" 农历");            sToday.append(cyclical(year));            sToday.append('(');            sToday.append(AnimalsYear(year));            sToday.append(")年");            sToday.append(nStr1[(int) l[1]]);            sToday.append("月");            sToday.append(getChinaDate((int) (l[2])));            return sToday.toString();        } finally {            sToday = null;        }    }    /**     * 农历日历工具使用演示     *     * @param args     */    public static void main(String[] args) {    }//    //[0-4]、[5-10]//    private static int[] getData(int z) {//        //判断区间//        int j = z / 5;//        int[] arr = map.get(j);//        if (arr == null) {//            arr = new int[5];//            map.put(j, arr);//            for (int a = 0, b = j * 5; a < 5; a++, b++) {//                arr[a] = b;//            }//        }else {//            System.out.println("arr!=null");//        }//        return arr;//////    }} 

   好 我们的类库已经给大家了 现在哪 我想给他们分一下类 方便理解

   接口类:1.2.7

   工具类: 8.5.3

   视图类 :9.6

   阴农历转换类:10

      因为我们所实现的日历是一种 自定义控件 所以我们比较关心view视图的实现(此处请看8.6)

    大体了解了日历布局的网格状(6.CalendarLayout)上下运动(8.CalendarView是通过哪些类来实现

    然后来了解一下他是怎么工作的 

  1.CaledarAdapter适配器接口    适配器就我自己来看我感觉应该是将各种数据以合适的形式显示在View中给用户看。 这里实现3.CalendarBean与视图类(9.6)之间
的适配 方便最后Mainactivity获取显示时间
5CalendarFactory主要用来对本月 的天数,月初第一天是哪天,还有考虑到美观占满网格

8CalendarUtil 用来显示一个月的第一天是星期及,一个月有几天

  好关于类库  他基本实现的什么我们已经了解了现在来看布局

  1.activity_calendar

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true">    <LinearLayout        android:id="@+id/weeks"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:paddingBottom="8dp"        android:paddingTop="8dp" />    <View        android:id="@+id/weekline"        android:layout_width="match_parent"        android:layout_height="1px"        android:layout_below="@+id/weeks"        android:background="#dddddd"        />    <com.ucg.app.calendar.view.CalendarLayout        android:id="@+id/calendarLayout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_below="@+id/weekline">        <android.support.v4.view.ViewPager            android:id="@+id/pager"            android:layout_width="match_parent"            android:layout_height="200dp" />        <FrameLayout            android:id="@+id/selectZoomLayout"            android:layout_width="match_parent"            android:layout_height="100dp"            android:background="#66ff0000"            />        <com.ucg.app.calendar.view.ScrollerLayout            android:layout_below="@+id/selectZoomLayout"            android:id="@+id/workContentLayout"            android:layout_width="match_parent"            android:layout_height="match_parent">            <LinearLayout                android:id="@+id/linearLayout"                android:layout_width="match_parent"                android:layout_height="match_parent">                <ScrollView                    android:id="@+id/workContent"                    android:layout_width="match_parent"                    android:layout_height="match_parent">                    <FrameLayout                        android:layout_width="match_parent"                        android:layout_height="wrap_content">                        <LinearLayout                            android:id="@+id/content"                            android:layout_width="match_parent"                            android:layout_height="wrap_content"                            android:orientation="vertical" />                    </FrameLayout>                </ScrollView>            </LinearLayout>        </com.ucg.app.calendar.view.ScrollerLayout>    </com.ucg.app.calendar.view.CalendarLayout>
2.activity_main

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@drawable/background_main"    android:orientation="vertical"    tools:context="com.codbking.calendar.exaple.DingdingActivity">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="48dp"        android:gravity="center_vertical"        android:orientation="horizontal"        >        <ImageView            android:id="@+id/back"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:background="@drawable/actbar_home_up_indicator_white_normal"            android:scaleType="fitCenter"            />        <TextView            android:id="@+id/title"            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="2016/10/10"            android:textColor="#ffffff"            />        <View            android:layout_width="48dp"            android:layout_height="0dp"            />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="28dp"        android:orientation="horizontal"        >        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="日"            android:textColor="#ffffff"            />        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="一"            android:textColor="#ffffff"            />        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="二"            android:textColor="#ffffff"            />        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="三"            android:textColor="#ffffff"            />        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="四"            android:textColor="#ffffff"            />        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="五"            android:textColor="#ffffff"            />        <TextView            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center"            android:text="六"            android:textColor="#ffffff"            />    </LinearLayout>    <com.codbking.calendar.CalendarLayout        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        >        <com.codbking.calendar.CalendarDateView            android:id="@+id/calendarDateView"            android:layout_width="match_parent"            android:layout_height="wrap_content"/>        <ListView            android:id="@+id/list"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="#ffffff"            />    </com.codbking.calendar.CalendarLayout></LinearLayout>
Mainactivity
import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import com.codbking.calendar.CaledarAdapter;import com.codbking.calendar.CalendarBean;import com.codbking.calendar.CalendarDateView;import com.codbking.calendar.CalendarUtil;import com.codbking.calendar.CalendarView;import java.util.Date;import butterknife.BindView;import butterknife.ButterKnife;import butterknife.OnClick;public class XiaomiActivity extends AppCompatActivity {    @BindView(R.id.title)    TextView mTitle;    @BindView(R.id.calendarDateView)    CalendarDateView mCalendarDateView;    @BindView(R.id.list)    ListView mList;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_xiaomi);        ButterKnife.bind(this);        initView();        initList();    }    private void initList() {        mList.setAdapter(new BaseAdapter() {            @Override            public int getCount() {                return 100;            }            @Override            public Object getItem(int position) {                return null;            }            @Override            public long getItemId(int position) {                return 0;            }            @Override            public View getView(int position, View convertView, ViewGroup parent) {                if (convertView == null) {                    convertView = LayoutInflater.from(XiaomiActivity.this).inflate(android.R.layout.simple_list_item_1, null);                }                TextView textView = (TextView) convertView;                textView.setText("position:" + position);                return convertView;            }        });    }    private void initView() {        mCalendarDateView.setAdapter(new CaledarAdapter() {            @Override            public View getView(View convertView, ViewGroup parentView, CalendarBean bean) {                if (convertView == null) {                    convertView = LayoutInflater.from(parentView.getContext()).inflate(R.layout.item_xiaomi, null);                }                TextView chinaText = (TextView) convertView.findViewById(R.id.chinaText);                TextView text = (TextView) convertView.findViewById(R.id.text);                text.setText("" + bean.day);                if (bean.mothFlag != 0) {                    text.setTextColor(0xff9299a1);                } else {                    text.setTextColor(0xff444444);                }                chinaText.setText(bean.chinaDay);                return convertView;            }        });        mCalendarDateView.setOnItemClickListener(new CalendarView.OnItemClickListener() {            @Override            public void onItemClick(View view, int postion, CalendarBean bean) {                mTitle.setText(bean.year + "/" + bean.moth + "/" + bean.day);            }        });        int[] data = CalendarUtil.getYMD(new Date());        mTitle.setText(data[0] + "/" + data[1] + "/" + data[2]);    }    @OnClick(R.id.back)    public void onClick() {        finish();    }}



原创粉丝点击