小米日历详解
来源:互联网 发布: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
因为我们所实现的日历是一种 自定义控件 所以我们比较关心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(); }}
- 小米日历详解
- 仿小米日历
- 高仿小米日历
- 小米3 日历 同步google日历
- 仿魅族日历,乐视日历,小米日历等效果
- android高仿钉钉和小米的日历控件
- 高仿钉钉和小米的日历控件
- NSCalendar日历使用详解
- 日历控件--MaterialCalendarView 详解
- Android日历开发详解
- 关于产品的一些思考——小米之日历
- 仿小米,Cal日历的周月切换
- 仿小米和iphone日历效果,基于Android week view
- android 仿小米日历 周视图 月视图切换
- 仿小米、华为、滴答清单、365、钉钉自定义日历
- 高仿钉钉和小米的日历控件,很实用
- 高仿可伸缩小米日历 支持添加自定义提示数据
- 日历控件开发详解0
- web.xml详解
- 直播系统如何设置多码率输出
- FlytestingToolkit工具派送,懒人的测试思考
- Android之添加第三方下拉刷新PullToRefresh操作
- Linux shell 中的快捷键
- 小米日历详解
- 动起手来,自己搭建HBase分布式数据库
- python 对list的常用操作
- 每天一个Linux命令(40):wc命令
- JMeter 非用户界面模式
- git学习笔记
- 我们一起走,寻找自己的答案
- Merge Two Binary Trees
- JavaMVC分层模式