소스 검색

完善足迹日历效果

zengjiebin 7 년 전
부모
커밋
b353fe362c

+ 0 - 3
app/src/main/AndroidManifest.xml

@@ -445,9 +445,6 @@
         <activity
             android:name="com.sheep.gamegroup.view.activity.ActInputAndPickerImg"
             android:theme="@style/AppTheme.translucent" />
-        <activity
-            android:name="com.sheep.gamegroup.view.activity.ActOverrideJsWeb"
-            android:screenOrientation="portrait"/>
 
         <!-- 友盟start -->
         <meta-data

+ 203 - 0
app/src/main/java/com/haibin/calendarviewproject/custom/CustomMonthView.java

@@ -0,0 +1,203 @@
+package com.haibin.calendarviewproject.custom;
+
+import android.content.Context;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.haibin.calendarview.Calendar;
+import com.haibin.calendarview.MonthView;
+
+/**
+ * 演示一个变态需求的月视图
+ * Created by huanghaibin on 2018/2/9.
+ */
+
+public class CustomMonthView extends MonthView {
+
+    private int mRadius;
+
+    /**
+     * 自定义魅族标记的文本画笔
+     */
+    private Paint mTextPaint = new Paint();
+
+
+    /**
+     * 24节气画笔
+     */
+    private Paint mSolarTermTextPaint = new Paint();
+
+    /**
+     * 背景圆点
+     */
+    private Paint mPointPaint = new Paint();
+
+    /**
+     * 今天的背景色
+     */
+    private Paint mCurrentDayPaint = new Paint();
+
+    /**
+     * 圆点半径
+     */
+    private float mPointRadius;
+
+    private int mPadding;
+
+    private float mCircleRadius;
+    /**
+     * 自定义魅族标记的圆形背景
+     */
+    private Paint mSchemeBasicPaint = new Paint();
+
+    private float mSchemeBaseLine;
+
+    public CustomMonthView(Context context) {
+        super(context);
+
+        mTextPaint.setTextSize(dipToPx(context, 8));
+        mTextPaint.setColor(0xffffffff);
+        mTextPaint.setAntiAlias(true);
+        mTextPaint.setFakeBoldText(true);
+
+
+        mSolarTermTextPaint.setColor(0xff489dff);
+        mSolarTermTextPaint.setAntiAlias(true);
+        mSolarTermTextPaint.setTextAlign(Paint.Align.CENTER);
+
+        mSchemeBasicPaint.setAntiAlias(true);
+        mSchemeBasicPaint.setStyle(Paint.Style.FILL);
+        mSchemeBasicPaint.setTextAlign(Paint.Align.CENTER);
+        mSchemeBasicPaint.setFakeBoldText(true);
+        mSchemeBasicPaint.setColor(Color.WHITE);
+
+
+        mCurrentDayPaint.setAntiAlias(true);
+        mCurrentDayPaint.setStyle(Paint.Style.FILL);
+        mCurrentDayPaint.setColor(0xFFeaeaea);
+
+        mPointPaint.setAntiAlias(true);
+        mPointPaint.setStyle(Paint.Style.FILL);
+        mPointPaint.setTextAlign(Paint.Align.CENTER);
+        mPointPaint.setColor(Color.RED);
+
+        mCircleRadius = dipToPx(getContext(), 7);
+
+        mPadding = dipToPx(getContext(), 3);
+
+        mPointRadius = dipToPx(context, 2);
+
+        Paint.FontMetrics metrics = mSchemeBasicPaint.getFontMetrics();
+        mSchemeBaseLine = mCircleRadius - metrics.descent + (metrics.bottom - metrics.top) / 2 + dipToPx(getContext(), 1);
+
+        //兼容硬件加速无效的代码
+        setLayerType(View.LAYER_TYPE_SOFTWARE, mSelectedPaint);
+        //4.0以上硬件加速会导致无效
+        mSelectedPaint.setMaskFilter(new BlurMaskFilter(28, BlurMaskFilter.Blur.SOLID));
+
+        setLayerType(View.LAYER_TYPE_SOFTWARE, mSchemeBasicPaint);
+        mSchemeBasicPaint.setMaskFilter(new BlurMaskFilter(28, BlurMaskFilter.Blur.SOLID));
+
+    }
+
+    @Override
+    protected void onPreviewHook() {
+        mSolarTermTextPaint.setTextSize(mCurMonthLunarTextPaint.getTextSize());
+        mRadius = Math.min(mItemWidth, mItemHeight) / 11 * 5;
+    }
+
+
+    @Override
+    protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) {
+        int cx = x + mItemWidth / 2;
+        int cy = y + mItemHeight / 2;
+        canvas.drawCircle(cx, cy, mRadius, mSelectedPaint);
+        return true;
+    }
+
+    @Override
+    protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) {
+
+        boolean isSelected = isSelected(calendar);
+        if (isSelected) {
+            mPointPaint.setColor(Color.WHITE);
+        } else {
+            mPointPaint.setColor(Color.RED);
+        }
+
+        canvas.drawCircle(x + mItemWidth / 2, y + mItemHeight - 3 * mPadding, mPointRadius, mPointPaint);
+    }
+
+    @Override
+    protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
+        int cx = x + mItemWidth / 2;
+        int cy = y + mItemHeight / 2;
+        int top = y - mItemHeight / 6;
+
+        if (calendar.isCurrentDay() && !isSelected) {
+            canvas.drawCircle(cx, cy, mRadius, mCurrentDayPaint);
+        }
+
+        if (hasScheme) {
+            canvas.drawCircle(x + mItemWidth - mPadding - mCircleRadius / 2, y + mPadding + mCircleRadius, mCircleRadius, mSchemeBasicPaint);
+            mTextPaint.setColor(calendar.getSchemeColor());
+            canvas.drawText(calendar.getScheme(), x + mItemWidth - mPadding - mCircleRadius, y + mPadding + mSchemeBaseLine, mTextPaint);
+        }
+
+        //当然可以换成其它对应的画笔就不麻烦,
+        if (calendar.isWeekend() && calendar.isCurrentMonth()) {
+            mCurMonthTextPaint.setColor(0xFF489dff);
+            mCurMonthLunarTextPaint.setColor(0xFF489dff);
+            mSchemeTextPaint.setColor(0xFF489dff);
+            mSchemeLunarTextPaint.setColor(0xFF489dff);
+            mOtherMonthLunarTextPaint.setColor(0xFF489dff);
+            mOtherMonthTextPaint.setColor(0xFF489dff);
+        } else {
+            mCurMonthTextPaint.setColor(0xff333333);
+            mCurMonthLunarTextPaint.setColor(0xffCFCFCF);
+            mSchemeTextPaint.setColor(0xff333333);
+            mSchemeLunarTextPaint.setColor(0xffCFCFCF);
+
+            mOtherMonthTextPaint.setColor(0xFFe1e1e1);
+            mOtherMonthLunarTextPaint.setColor(0xFFe1e1e1);
+        }
+
+        if (isSelected) {
+            canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
+                    mSelectTextPaint);
+            canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, mSelectedLunarTextPaint);
+        } else if (hasScheme) {
+
+            canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
+                    calendar.isCurrentMonth() ? mSchemeTextPaint : mOtherMonthTextPaint);
+
+            canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10,
+                    !TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint : mSchemeLunarTextPaint);
+        } else {
+            canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
+                    calendar.isCurrentDay() ? mCurDayTextPaint :
+                            calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
+
+            canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10,
+                    calendar.isCurrentDay() ? mCurDayLunarTextPaint :
+                            calendar.isCurrentMonth() ? !TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint  :
+                                    mCurMonthLunarTextPaint : mOtherMonthLunarTextPaint);
+        }
+    }
+
+    /**
+     * dp转px
+     *
+     * @param context context
+     * @param dpValue dp
+     * @return px
+     */
+    private static int dipToPx(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+}

+ 207 - 0
app/src/main/java/com/haibin/calendarviewproject/custom/CustomWeekView.java

@@ -0,0 +1,207 @@
+package com.haibin.calendarviewproject.custom;
+
+import android.content.Context;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.haibin.calendarview.Calendar;
+import com.haibin.calendarview.WeekView;
+
+/**
+ * 演示一个变态需求的周视图
+ * Created by huanghaibin on 2018/2/9.
+ */
+
+public class CustomWeekView extends WeekView {
+
+
+    private int mRadius;
+
+    /**
+     * 自定义魅族标记的文本画笔
+     */
+    private Paint mTextPaint = new Paint();
+
+
+    /**
+     * 24节气画笔
+     */
+    private Paint mSolarTermTextPaint = new Paint();
+
+    /**
+     * 背景圆点
+     */
+    private Paint mPointPaint = new Paint();
+
+    /**
+     * 今天的背景色
+     */
+    private Paint mCurrentDayPaint = new Paint();
+
+
+    /**
+     * 圆点半径
+     */
+    private float mPointRadius;
+
+    private int mPadding;
+
+    private float mCircleRadius;
+    /**
+     * 自定义魅族标记的圆形背景
+     */
+    private Paint mSchemeBasicPaint = new Paint();
+
+    private float mSchemeBaseLine;
+
+    public CustomWeekView(Context context) {
+        super(context);
+        mTextPaint.setTextSize(dipToPx(context, 8));
+        mTextPaint.setColor(0xffffffff);
+        mTextPaint.setAntiAlias(true);
+        mTextPaint.setFakeBoldText(true);
+
+
+        mSolarTermTextPaint.setColor(0xff489dff);
+        mSolarTermTextPaint.setAntiAlias(true);
+        mSolarTermTextPaint.setTextAlign(Paint.Align.CENTER);
+
+        mSchemeBasicPaint.setAntiAlias(true);
+        mSchemeBasicPaint.setStyle(Paint.Style.FILL);
+        mSchemeBasicPaint.setTextAlign(Paint.Align.CENTER);
+        mSchemeBasicPaint.setFakeBoldText(true);
+        mSchemeBasicPaint.setColor(Color.WHITE);
+
+        mPointPaint.setAntiAlias(true);
+        mPointPaint.setStyle(Paint.Style.FILL);
+        mPointPaint.setTextAlign(Paint.Align.CENTER);
+        mPointPaint.setColor(Color.RED);
+
+
+        mCurrentDayPaint.setAntiAlias(true);
+        mCurrentDayPaint.setStyle(Paint.Style.FILL);
+        mCurrentDayPaint.setColor(0xFFeaeaea);
+
+
+        mCircleRadius = dipToPx(getContext(), 7);
+
+        mPadding = dipToPx(getContext(), 3);
+
+        mPointRadius = dipToPx(context, 2);
+
+        Paint.FontMetrics metrics = mSchemeBasicPaint.getFontMetrics();
+        mSchemeBaseLine = mCircleRadius - metrics.descent + (metrics.bottom - metrics.top) / 2 + dipToPx(getContext(), 1);
+
+        //兼容硬件加速无效的代码
+        setLayerType(View.LAYER_TYPE_SOFTWARE, mSelectedPaint);
+        //4.0以上硬件加速会导致无效
+        mSelectedPaint.setMaskFilter(new BlurMaskFilter(28, BlurMaskFilter.Blur.SOLID));
+
+        setLayerType(View.LAYER_TYPE_SOFTWARE, mSchemeBasicPaint);
+        mSchemeBasicPaint.setMaskFilter(new BlurMaskFilter(28, BlurMaskFilter.Blur.SOLID));
+    }
+
+
+    @Override
+    protected void onPreviewHook() {
+        mSolarTermTextPaint.setTextSize(mCurMonthLunarTextPaint.getTextSize());
+        mRadius = Math.min(mItemWidth, mItemHeight) / 11 * 5;
+    }
+
+
+    @Override
+    protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, boolean hasScheme) {
+        int cx = x + mItemWidth / 2;
+        int cy = mItemHeight / 2;
+        canvas.drawCircle(cx, cy, mRadius, mSelectedPaint);
+        return true;
+    }
+
+    @Override
+    protected void onDrawScheme(Canvas canvas, Calendar calendar, int x) {
+
+        boolean isSelected = isSelected(calendar);
+        if (isSelected) {
+            mPointPaint.setColor(Color.WHITE);
+        } else {
+            mPointPaint.setColor(Color.GRAY);
+        }
+
+        canvas.drawCircle(x + mItemWidth / 2, mItemHeight - 3 * mPadding, mPointRadius, mPointPaint);
+    }
+
+    @Override
+    protected void onDrawText(Canvas canvas, Calendar calendar, int x, boolean hasScheme, boolean isSelected) {
+        int cx = x + mItemWidth / 2;
+        int cy = mItemHeight / 2;
+        int top = -mItemHeight / 6;
+
+        if (calendar.isCurrentDay() && !isSelected) {
+            canvas.drawCircle(cx, cy, mRadius, mCurrentDayPaint);
+        }
+
+        if(hasScheme){
+            canvas.drawCircle(x + mItemWidth - mPadding - mCircleRadius / 2, mPadding + mCircleRadius, mCircleRadius, mSchemeBasicPaint);
+
+            mTextPaint.setColor(calendar.getSchemeColor());
+
+            canvas.drawText(calendar.getScheme(), x + mItemWidth - mPadding - mCircleRadius, mPadding + mSchemeBaseLine, mTextPaint);
+        }
+
+        if (calendar.isWeekend() && calendar.isCurrentMonth()) {
+            mCurMonthTextPaint.setColor(0xFF489dff);
+            mCurMonthLunarTextPaint.setColor(0xFF489dff);
+            mSchemeTextPaint.setColor(0xFF489dff);
+            mSchemeLunarTextPaint.setColor(0xFF489dff);
+            mOtherMonthLunarTextPaint.setColor(0xFF489dff);
+            mOtherMonthTextPaint.setColor(0xFF489dff);
+        } else {
+            mCurMonthTextPaint.setColor(0xff333333);
+            mCurMonthLunarTextPaint.setColor(0xffCFCFCF);
+            mSchemeTextPaint.setColor(0xff333333);
+            mSchemeLunarTextPaint.setColor(0xffCFCFCF);
+
+            mOtherMonthTextPaint.setColor(0xFFe1e1e1);
+            mOtherMonthLunarTextPaint.setColor(0xFFe1e1e1);
+        }
+
+        if (isSelected) {
+            canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
+                    mSelectTextPaint);
+            canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10, mSelectedLunarTextPaint);
+        } else if (hasScheme) {
+
+            canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
+                    calendar.isCurrentMonth() ? mSchemeTextPaint : mOtherMonthTextPaint);
+
+            canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10,
+                    !TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint : mSchemeLunarTextPaint);
+        } else {
+            canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
+                    calendar.isCurrentDay() ? mCurDayTextPaint :
+                            calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
+
+            canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10,
+                    calendar.isCurrentDay() ? mCurDayLunarTextPaint :
+                            !TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint :
+                                    calendar.isCurrentMonth() ?
+                                            mCurMonthLunarTextPaint : mOtherMonthLunarTextPaint);
+        }
+    }
+
+    /**
+     * dp转px
+     *
+     * @param context context
+     * @param dpValue dp
+     * @return px
+     */
+    private static int dipToPx(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+}

+ 138 - 0
app/src/main/java/com/haibin/calendarviewproject/group/BaseRecyclerAdapter.java

@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 huanghaibin_dev <huanghaibin_dev@163.com>
+ * WebSite https://github.com/MiracleTimes-Dev
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.haibin.calendarviewproject.group;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 基本的适配器
+ */
+@SuppressWarnings("unused")
+public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter {
+
+    protected LayoutInflater mInflater;
+    protected List<T> mItems;
+    private OnItemClickListener onItemClickListener;
+    private OnClickListener onClickListener;
+
+   public BaseRecyclerAdapter(Context context) {
+        this.mItems = new ArrayList<>();
+        mInflater = LayoutInflater.from(context);
+        onClickListener = new OnClickListener() {
+            @Override
+            public void onClick(int position, long itemId) {
+                if (onItemClickListener != null)
+                    onItemClickListener.onItemClick(position, itemId);
+            }
+        };
+
+    }
+
+    @Override
+    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        final RecyclerView.ViewHolder holder = onCreateDefaultViewHolder(parent, viewType);
+        if (holder != null) {
+            holder.itemView.setTag(holder);
+            holder.itemView.setOnClickListener(onClickListener);
+        }
+        return holder;
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+        onBindViewHolder(holder, mItems.get(position), position);
+    }
+
+    protected abstract RecyclerView.ViewHolder onCreateDefaultViewHolder(ViewGroup parent, int type);
+
+    protected abstract void onBindViewHolder(RecyclerView.ViewHolder holder, T item, int position);
+
+    @Override
+    public int getItemCount() {
+        return mItems.size();
+    }
+
+    void setOnItemClickListener(OnItemClickListener onItemClickListener) {
+        this.onItemClickListener = onItemClickListener;
+    }
+
+    void addAll(List<T> items) {
+        if (items != null && items.size() > 0) {
+            mItems.addAll(items);
+            notifyItemRangeInserted(mItems.size(), items.size());
+        }
+    }
+
+    final void addItem(T item) {
+        if (item != null) {
+            this.mItems.add(item);
+            notifyItemChanged(mItems.size());
+        }
+    }
+
+    final List<T> getItems() {
+        return mItems;
+    }
+
+
+    final T getItem(int position) {
+        if (position < 0 || position >= mItems.size())
+            return null;
+        return mItems.get(position);
+    }
+
+    static abstract class OnClickListener implements View.OnClickListener {
+        @Override
+        public void onClick(View v) {
+            RecyclerView.ViewHolder holder = (RecyclerView.ViewHolder) v.getTag();
+            onClick(holder.getAdapterPosition(), holder.getItemId());
+        }
+
+        public abstract void onClick(int position, long itemId);
+    }
+
+
+    interface OnItemClickListener {
+        void onItemClick(int position, long itemId);
+    }
+
+    public final void removeItem(T item) {
+        if (this.mItems.contains(item)) {
+            int position = mItems.indexOf(item);
+            this.mItems.remove(item);
+            notifyItemRemoved(position);
+        }
+    }
+
+    protected final void removeItem(int position) {
+        if (this.getItemCount() > position) {
+            this.mItems.remove(position);
+            notifyItemRemoved(position);
+        }
+    }
+
+    protected final void clear(){
+        mItems.clear();
+        notifyDataSetChanged();
+    }
+}

+ 282 - 0
app/src/main/java/com/haibin/calendarviewproject/group/GroupItemDecoration.java

@@ -0,0 +1,282 @@
+package com.haibin.calendarviewproject.group;
+
+import android.annotation.SuppressLint;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.View;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 分组浮动的ItemDecoration
+ * Created by haibin on 2017/5/15.
+ */
+@SuppressWarnings("all")
+public class GroupItemDecoration<Group, Child> extends RecyclerView.ItemDecoration {
+    protected int mGroupHeight;
+    protected int mGroutBackground;
+    protected Paint mBackgroundPaint;
+    protected Paint mTextPaint;
+    protected float mTextBaseLine;
+    protected int mPaddingLeft, mPaddingRight;
+    protected boolean isCenter;
+    protected boolean isHasHeader;
+    protected int mChildItemOffset;
+    @SuppressLint("UseSparseArrays")
+    protected Map<Integer, Group> mGroup = new HashMap<>();
+
+    public GroupItemDecoration() {
+        super();
+        init();
+    }
+
+    private void init() {
+        mBackgroundPaint = new Paint();
+        mBackgroundPaint.setColor(0xFFf5f7f8);
+        mBackgroundPaint.setStyle(Paint.Style.FILL);
+        mBackgroundPaint.setAntiAlias(true);
+
+        mTextPaint = new Paint();
+        mTextPaint.setColor(0xFF353535);
+        mTextPaint.setAntiAlias(true);
+    }
+
+    /**
+     * 先于RecyclerView的Item onDraw调用
+     *
+     * @param c      RecyclerView canvas
+     * @param parent RecyclerView
+     * @param state  stare
+     */
+    @Override
+    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+        super.onDraw(c, parent, state);
+        onDrawGroup(c, parent);
+    }
+
+    /**
+     * 绘制分组Group
+     *
+     * @param c      Canvas
+     * @param parent RecyclerView
+     */
+    protected void onDrawGroup(Canvas c, RecyclerView parent) {
+        int paddingLeft = parent.getPaddingLeft();
+        int right = parent.getWidth() - parent.getPaddingRight();
+        int top, bottom;
+        int count = parent.getChildCount();
+        for (int i = 0; i < parent.getChildCount(); i++) {
+            View child = parent.getChildAt(i);
+            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+            int key = params.getViewLayoutPosition();
+            if (mGroup.containsKey(key)) {
+                top = child.getTop() - params.topMargin - mGroupHeight;
+                bottom = top + mGroupHeight;
+                c.drawRect(paddingLeft, top, right, bottom, mBackgroundPaint);
+                String group = mGroup.get(params.getViewLayoutPosition()).toString();
+                float x;
+                float y = top + mTextBaseLine;
+                if (isCenter) {
+                    x = parent.getMeasuredWidth() / 2 - getTextX(group);
+                } else {
+                    x = mPaddingLeft;
+                }
+                c.drawText(group, x, y, mTextPaint);
+            }
+        }
+    }
+
+    /**
+     * 后于RecyclerView的Item onDraw调用
+     *
+     * @param c      RecyclerView canvas
+     * @param parent RecyclerView
+     * @param state  stare
+     */
+    @Override
+    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+        super.onDrawOver(c, parent, state);
+        onDrawOverGroup(c, parent);
+    }
+
+    /**
+     * 绘制悬浮组
+     *
+     * @param c      Canvas
+     * @param parent RecyclerView
+     */
+    protected void onDrawOverGroup(Canvas c, RecyclerView parent) {
+        int firstVisiblePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
+        if (firstVisiblePosition == RecyclerView.NO_POSITION) {
+            return;
+        }
+        Group group = getCroup(firstVisiblePosition);
+        if (group == null)
+            return;
+        String groupTitle = group.toString();
+        if (TextUtils.isEmpty(groupTitle)) {
+            return;
+        }
+        boolean isRestore = false;
+        Group nextGroup = getCroup(firstVisiblePosition + 1);
+        if (nextGroup != null && !group.equals(nextGroup)) {
+            //说明是当前组最后一个元素,但不一定碰撞了
+            View child = parent.findViewHolderForAdapterPosition(firstVisiblePosition).itemView;
+            if (child.getTop() + child.getMeasuredHeight() < mGroupHeight) {
+                //进一步检测碰撞
+                c.save();//保存画布当前的状态
+                isRestore = true;
+                c.translate(0, child.getTop() + child.getMeasuredHeight() - mGroupHeight);
+            }
+        }
+        int left = parent.getPaddingLeft();
+        int right = parent.getWidth() - parent.getPaddingRight();
+        int top = parent.getPaddingTop();
+        int bottom = top + mGroupHeight;
+        c.drawRect(left, top, right, bottom, mBackgroundPaint);
+        float x;
+        float y = top + mTextBaseLine;
+        if (isCenter) {
+            x = parent.getMeasuredWidth() / 2 - getTextX(groupTitle);
+        } else {
+            x = mPaddingLeft;
+        }
+        c.drawText(groupTitle, x, y, mTextPaint);
+        if (isRestore) {
+            //还原画布为初始状态
+            c.restore();
+        }
+    }
+
+    /**
+     * 设置item的上下左右偏移量
+     *
+     * @param outRect rect
+     * @param view    item
+     * @param parent  RecyclerView
+     * @param state   stare
+     */
+    @Override
+    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+        super.getItemOffsets(outRect, view, parent, state);
+        getItemOffsets(outRect, view, parent, parent.getChildViewHolder(view).getAdapterPosition());
+    }
+
+    /**
+     * 设置item的上下左右偏移量,不做任何处理就是默认状态
+     *
+     * @param outRect         outRect
+     * @param view            view
+     * @param parent          RecyclerView
+     * @param adapterPosition position
+     */
+    protected void getItemOffsets(Rect outRect, View view, RecyclerView parent, int adapterPosition) {
+        if (mGroup.containsKey(adapterPosition)) {
+            outRect.set(0, mGroupHeight, 0, mGroup.containsKey(adapterPosition + 1) ? 0 : mChildItemOffset);
+        } else {
+            outRect.set(0, 0, 0, mGroup.containsKey(adapterPosition + 1) ? 0 : mChildItemOffset);
+        }
+    }
+
+    /**
+     * 获得当前ViewPosition所在的组
+     *
+     * @param position 当前View的position
+     * @return 当前ViewPosition所在的组
+     */
+    protected Group getCroup(int position) {
+        while (position >= 0) {
+            if (mGroup.containsKey(position)) {
+                return mGroup.get(position);
+            }
+            position--;
+        }
+        return null;
+    }
+
+    /**
+     * 通知更新分组信息
+     *
+     * @param adapter GroupRecyclerAdapter
+     */
+    public void notifyDataSetChanged(GroupRecyclerAdapter<Group, Child> adapter) {
+        mGroup.clear();
+        if (adapter == null) return;
+        int key = 0;
+        for (int i = 0; i < adapter.getGroupCount(); i++) {
+            if (i == 0) {
+                mGroup.put(isHasHeader ? 1 : 0, adapter.getGroup(i));
+                key += adapter.getChildCount(i) + (isHasHeader ? 1 : 0);
+                ;
+            } else {
+                mGroup.put(key, adapter.getGroup(i));
+                key += adapter.getChildCount(i);
+            }
+        }
+    }
+
+    public void setChildItemOffset(int childItemOffset){
+        this.mChildItemOffset = childItemOffset;
+    }
+
+    public void setBackground(int groupBackground) {
+        mBackgroundPaint.setColor(groupBackground);
+    }
+
+    public void setTextColor(int textColor) {
+        mTextPaint.setColor(textColor);
+    }
+
+    public void setTextSize(float textSize) {
+        mTextPaint.setTextSize(textSize);
+        Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
+        mTextBaseLine = mGroupHeight / 2 - metrics.descent + (metrics.bottom - metrics.top) / 2;
+    }
+
+    public void setGroupHeight(int groupHeight) {
+        mGroupHeight = groupHeight;
+        Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
+        mTextBaseLine = mGroupHeight / 2 - metrics.descent + (metrics.bottom - metrics.top) / 2;
+    }
+
+    public void setPadding(int mPaddingLeft, int mPaddingRight) {
+        this.mPaddingLeft = mPaddingLeft;
+        this.mPaddingRight = mPaddingRight;
+    }
+
+    public void setCenter(boolean isCenter) {
+        this.isCenter = isCenter;
+    }
+
+    public void setHasHeader(boolean hasHeader) {
+        isHasHeader = hasHeader;
+    }
+
+    /**
+     * 获取文本的x坐标起点
+     *
+     * @param str 文本
+     * @return x
+     */
+    protected float getTextX(String str) {
+        Rect bounds = new Rect();
+        mTextPaint.getTextBounds(str, 0, str.length(), bounds);
+        return bounds.width() / 2;
+    }
+
+    /**
+     * 获取文本的长度像素
+     * @param str 文本
+     * @return px
+     */
+    protected float getTextLenghtPx(String str) {
+        Rect bounds = new Rect();
+        mTextPaint.getTextBounds(str, 0, str.length(), bounds);
+        return bounds.width();
+    }
+}

+ 133 - 0
app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerAdapter.java

@@ -0,0 +1,133 @@
+package com.haibin.calendarviewproject.group;
+
+import android.content.Context;
+
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+
+/**
+ * 分组的RecyclerAdapter
+ * Created by haibin on 2017/5/15.
+ */
+@SuppressWarnings("unused")
+public abstract class GroupRecyclerAdapter<Parent, Child> extends BaseRecyclerAdapter<Child> {
+    private LinkedHashMap<Parent, List<Child>> mGroups;
+    private List<Parent> mGroupTitles;
+
+    public GroupRecyclerAdapter(Context context) {
+        super(context);
+        mGroups = new LinkedHashMap<>();
+        mGroupTitles = new ArrayList<>();
+    }
+
+    /**
+     * 返回特定的标题
+     */
+     Parent getGroup(int groupPosition) {
+        return mGroupTitles.get(groupPosition);
+    }
+
+    /**
+     * 获得分组的数量
+     *
+     * @return 组的数量
+     */
+     int getGroupCount() {
+        return mGroupTitles.size();
+    }
+
+    /**
+     * 获取某一组的数量
+     *
+     * @param groupPosition groupPosition
+     * @return 某一组的数量
+     */
+     int getChildCount(int groupPosition) {
+        if (mGroupTitles == null || mGroups.size() == 0)
+            return 0;
+        if (mGroups.get(mGroupTitles.get(groupPosition)) == null)
+            return 0;
+        return mGroups.get(mGroupTitles.get(groupPosition)).size();
+    }
+
+    /**
+     * 重置分组数据
+     *
+     * @param groups groups
+     * @param titles titles
+     */
+    protected void resetGroups(LinkedHashMap<Parent, List<Child>> groups, List<Parent> titles) {
+        if (groups == null || titles == null) {
+            return;
+        }
+        mGroups.clear();
+        mGroupTitles.clear();
+        mGroups.putAll(groups);
+        mGroupTitles.addAll(titles);
+        mItems.clear();
+        for (Parent key : mGroups.keySet()) {
+            mItems.addAll(mGroups.get(key));
+        }
+        notifyDataSetChanged();
+    }
+
+    /**
+     * 清除分组数据
+     */
+    public final void clearGroup() {
+        mGroupTitles.clear();
+        mGroups.clear();
+        clear();
+    }
+
+    /**
+     * 从分组移除数据
+     *
+     * @param position 下标
+     * @return 分组是否为空,要移除分组
+     */
+    public boolean removeGroupItem(int position) {
+        int group = getGroupIndex(position);
+        removeGroupChildren(group);
+        int count = getChildCount(group);
+        removeItem(position);
+        if (count <= 0) {
+            mGroupTitles.remove(group);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 获取所在分组
+     *
+     * @param position 下标
+     * @return 获取所在分组
+     */
+    private int getGroupIndex(int position) {
+        int count = 0;
+        if (position <= count)
+            return 0;
+        int i = 0;
+        for (Parent parent : mGroups.keySet()) {
+            count += mGroups.get(parent).size();
+            if (position < count) {
+                return i;
+            }
+            i++;
+        }
+        return 0;
+    }
+
+    private void removeGroupChildren(int groupPosition) {
+        if (groupPosition >= mGroupTitles.size())
+            return;
+        List<Child> childList = mGroups.get(mGroupTitles.get(groupPosition));
+        if (childList != null && childList.size() != 0) {
+            childList.remove(childList.size() - 1);
+        }
+    }
+}

+ 91 - 0
app/src/main/java/com/haibin/calendarviewproject/group/GroupRecyclerView.java

@@ -0,0 +1,91 @@
+package com.haibin.calendarviewproject.group;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+
+import com.sheep.jiuyan.samllsheep.R;
+
+
+/**
+ * 带分组浮动的RecyclerView
+ * Created by haibin on 2017/5/15.
+ */
+@SuppressWarnings("all")
+public class GroupRecyclerView extends RecyclerView {
+    private GroupItemDecoration mItemDecoration;
+    private int mGroupHeight;
+    private int mGroutBackground, mTextColor;
+    private int mTextSize;
+    private int mPaddingLeft, mPaddingRight;
+    private boolean isCenter;
+    protected int mChildItemOffset;
+    private boolean isHasHeader;
+    private OnGroupChangeListener mListener;
+
+    public GroupRecyclerView(Context context) {
+        super(context);
+    }
+
+    public GroupRecyclerView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GroupRecyclerView);
+        mTextSize = array.getDimensionPixelSize(R.styleable.GroupRecyclerView_group_text_size, 16);
+        mGroupHeight = (int) array.getDimension(R.styleable.GroupRecyclerView_group_height, 52);
+        mChildItemOffset = (int) array.getDimension(R.styleable.GroupRecyclerView_group_child_offset, 20);
+        mTextColor = array.getColor(R.styleable.GroupRecyclerView_group_text_color, 0xFFFFFFFF);
+        mGroutBackground = array.getColor(R.styleable.GroupRecyclerView_group_background, 0x80000000);
+        isCenter = array.getBoolean(R.styleable.GroupRecyclerView_group_center, false);
+        isHasHeader = array.getBoolean(R.styleable.GroupRecyclerView_group_has_header, true);
+        mPaddingLeft = (int) array.getDimension(R.styleable.GroupRecyclerView_group_padding_left, 16);
+        mPaddingRight = (int) array.getDimension(R.styleable.GroupRecyclerView_group_padding_right, 16);
+        array.recycle();
+    }
+
+
+    @Override
+    public void setAdapter(Adapter adapter) {
+        if (adapter instanceof GroupRecyclerAdapter) {
+            super.setAdapter(adapter);
+        } else {
+            throw new IllegalStateException("Adapter must instanceof " +
+                    "GroupRecyclerAdapter or extends GroupRecyclerAdapter");
+        }
+    }
+
+    @Override
+    public void addItemDecoration(ItemDecoration decor) {
+        if (decor instanceof GroupItemDecoration)
+            super.addItemDecoration(decor);
+        else
+            throw new IllegalStateException("ItemDecoration must instanceof " +
+                    "GroupItemDecoration or extends GroupItemDecoration");
+        mItemDecoration = (GroupItemDecoration) decor;
+        mItemDecoration.setTextSize(mTextSize);
+        mItemDecoration.setBackground(mGroutBackground);
+        mItemDecoration.setTextColor(mTextColor);
+        mItemDecoration.setGroupHeight(mGroupHeight);
+        mItemDecoration.setPadding(mPaddingLeft, mPaddingRight);
+        mItemDecoration.setCenter(isCenter);
+        mItemDecoration.setHasHeader(isHasHeader);
+        mItemDecoration.setChildItemOffset(mChildItemOffset);
+        //mItemDecoration.notifyDataSetChanged((GroupRecyclerAdapter) getAdapter());
+    }
+
+    public void notifyDataSetChanged() {
+        mItemDecoration.notifyDataSetChanged((GroupRecyclerAdapter) getAdapter());
+    }
+
+    public void setOnGroupChangeListener(OnGroupChangeListener listener) {
+        this.mListener = listener;
+    }
+
+    /**
+     * 分组最上面改变通知
+     */
+    public interface OnGroupChangeListener {
+        void onGroupChange(int groupPosition, String group);
+    }
+}

+ 5 - 5
app/src/main/java/com/sheep/gamegroup/util/Jump2View.java

@@ -79,7 +79,6 @@ import com.sheep.gamegroup.view.activity.ActMyWelfare;
 import com.sheep.gamegroup.view.activity.ActNewAboutUs;
 import com.sheep.gamegroup.view.activity.ActNewbieTaskList;
 import com.sheep.gamegroup.view.activity.ActNotice;
-import com.sheep.gamegroup.view.activity.ActOverrideJsWeb;
 import com.sheep.gamegroup.view.activity.ActPay;
 import com.sheep.gamegroup.view.activity.ActPlayGameList;
 import com.sheep.gamegroup.view.activity.ActPlayGameRecommendList;
@@ -2261,10 +2260,11 @@ public class Jump2View {
      * @param jsUrl
      */
     public void goActOverrideJsWeb(Activity activity, String title, String url, String jsUrl) {
-        Intent intent = new Intent(activity, ActOverrideJsWeb.class);
-        intent.putExtra("title", title);
-        intent.putExtra("url", url);
-        intent.putExtra("jsUrl", jsUrl);
+        Intent intent = new Intent(activity, ActWebX5.class);
+        intent.putExtra(IJumpWeb.KEY_TITLE, title);
+        intent.putExtra(IJumpWeb.KEY_URL, url);
+        intent.putExtra(IJumpWeb.KEY_JSURL, jsUrl);
+        intent.putExtra(IJumpWeb.KEY_NEEDJSINTERACT, true);
         activity.startActivity(intent);
     }
 

+ 74 - 41
app/src/main/java/com/sheep/gamegroup/util/TimeUtil.java

@@ -18,41 +18,38 @@ public class TimeUtil {
 
     private static TimeUtil timeUtil;
 
-    public static TimeUtil newInstance(){
+    public static TimeUtil newInstance() {
         if (timeUtil == null)
             timeUtil = new TimeUtil();
         return timeUtil;
     }
 
-    public static long getCurrentSeconds(){
-        long ls = System.currentTimeMillis()/1000;
+    public static long getCurrentSeconds() {
+        long ls = System.currentTimeMillis() / 1000;
         return ls;
     }
+
     public static String TimeStamp2Date(long time, String formats) {
         time = time < 10_000_000_000L ? time * 1000 : time;//秒的时间戳为10位数,要x1000  10_000_000_000L对应时间为2286-11-21 01:46:40
         String date = new SimpleDateFormat(formats, Locale.CHINA).format(new Date(time));
         return date;
     }
-    public static String[] getCalendarShowTime(long paramLong)
-    {
+
+    public static String[] getCalendarShowTime(long paramLong) {
         String[] localObject;
         String str = new SimpleDateFormat("yyyy:MM:dd", Locale.CHINA).format(new Date(paramLong));
-        try
-        {
+        try {
             String[] arrayOfString = str.split(":");
             localObject = arrayOfString;
-            if ((localObject != null) && (localObject.length == 3));
+            if ((localObject != null) && (localObject.length == 3)) ;
             return localObject;
-        }
-        catch (Exception localException)
-        {
+        } catch (Exception localException) {
             while (true)
                 localException.printStackTrace();
         }
     }
 
-    public static String[] getCalendarShowTime(String paramString)
-    {
+    public static String[] getCalendarShowTime(String paramString) {
         try {
             long l = Long.valueOf(paramString);
             Calendar localCalendar = Calendar.getInstance();
@@ -63,12 +60,22 @@ public class TimeUtil {
         }
         return null;
     }
-    public static String getDate(String format){
+
+    public static String getDate(String format) {
         return new SimpleDateFormat(format, Locale.CHINA).format(new Date());
     }
-    public static String getDate(String formate, long paramLong){
+
+    public static Calendar getCalendar(int year, int moth, int day) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.YEAR, year);
+        calendar.set(Calendar.MONTH, moth);
+        calendar.set(Calendar.DAY_OF_MONTH, day);
+        return calendar;
+    }
+
+    public static String getDate(String formate, long paramLong) {
         Calendar c = Calendar.getInstance();
-        c.setTimeInMillis(paramLong*1000);
+        c.setTimeInMillis(paramLong * 1000);
         Date date = c.getTime();
         String str = new SimpleDateFormat(formate, Locale.CHINA).format(date);
         return str;
@@ -76,6 +83,7 @@ public class TimeUtil {
 
     /**
      * 毫秒值
+     *
      * @param time
      * @return 时:分:秒
      */
@@ -114,9 +122,10 @@ public class TimeUtil {
 
     /**
      * 日期时间字符串转换成毫秒
+     *
      * @return
      */
-    public static long string2Long(String dateStr, String dateFormat){
+    public static long string2Long(String dateStr, String dateFormat) {
         Calendar calendar = Calendar.getInstance();
         try {
             calendar.setTime(new SimpleDateFormat(dateFormat).parse(dateStr));
@@ -130,8 +139,9 @@ public class TimeUtil {
 
     /**
      * time在x天内 x为正,代表x天前,为负,代表-x天后
+     *
      * @param time 判断的时间点
-     * @param x 从今天24点算起,x天内,x可以为负
+     * @param x    从今天24点算起,x天内,x可以为负
      * @return
      */
     public static boolean isTimeInXDay(long time, int x) {
@@ -141,31 +151,33 @@ public class TimeUtil {
         //今日24点的时间
         Calendar cur24Calendar = Calendar.getInstance();
         applyDayEnd(cur24Calendar);
-        if(x < 0) {
+        if (x < 0) {
             boolean isBeforeCur24 = timeCalendar.before(cur24Calendar);
-            if(TestUtil.isDev())
+            if (TestUtil.isDev())
                 LogUtil.println("isTimeInXDay", "isBeforeCur24", isBeforeCur24, cur24Calendar.getTimeInMillis());
             cur24Calendar.add(Calendar.DAY_OF_MONTH, x);
             boolean isAfterXDay = timeCalendar.after(cur24Calendar);
-            if(TestUtil.isDev())
+            if (TestUtil.isDev())
                 LogUtil.println("isTimeInXDay", "isAfterXDay", isAfterXDay, cur24Calendar.getTimeInMillis());
             return isBeforeCur24 && isAfterXDay;
-        } else if(x > 0) {
+        } else if (x > 0) {
             boolean isAfterCur24 = timeCalendar.after(cur24Calendar);
-            if(TestUtil.isDev())
+            if (TestUtil.isDev())
                 LogUtil.println("isTimeInXDay", "isAfterCur24", isAfterCur24, cur24Calendar.getTimeInMillis());
             cur24Calendar.add(Calendar.DAY_OF_MONTH, x);
             boolean isBeforeXDay = timeCalendar.before(cur24Calendar);
-            if(TestUtil.isDev())
+            if (TestUtil.isDev())
                 LogUtil.println("isTimeInXDay", "isBeforeXDay", isBeforeXDay, cur24Calendar.getTimeInMillis());
             return isBeforeXDay && isAfterCur24;
         }
         return false;
     }
+
     /**
      * time在x天前或者-x天后 x为正,代表x天前,为负,代表-x天后
+     *
      * @param time 判断的时间点
-     * @param x 从今天24点算起,x天内,x可以为负
+     * @param x    从今天24点算起,x天内,x可以为负
      * @return
      */
     public static boolean isTimeXDay(long time, int x) {
@@ -175,31 +187,33 @@ public class TimeUtil {
         //今日24点的时间
         Calendar cur24Calendar = Calendar.getInstance();
         applyDayEnd(cur24Calendar);
-        if(x > 0) {
+        if (x > 0) {
             cur24Calendar.add(Calendar.DAY_OF_MONTH, x);
             boolean isAfterXDay = timeCalendar.after(cur24Calendar);
-            if(TestUtil.isDev())
+            if (TestUtil.isDev())
                 LogUtil.println("isTimeXDay", "isAfterXDay", isAfterXDay, cur24Calendar.getTimeInMillis());
             return isAfterXDay;
-        } else if(x < 0) {
+        } else if (x < 0) {
             cur24Calendar.add(Calendar.DAY_OF_MONTH, x);
             boolean isBeforeXDay = timeCalendar.before(cur24Calendar);
-            if(TestUtil.isDev())
+            if (TestUtil.isDev())
                 LogUtil.println("isTimeXDay", "isBeforeXDay", isBeforeXDay, cur24Calendar.getTimeInMillis());
             return isBeforeXDay;
         }
         return false;
     }
+
     //时间转换为一天的开始,也是前一天的结束
-    public static Calendar applyDayBegin(Calendar calendar){
+    public static Calendar applyDayBegin(Calendar calendar) {
         calendar.set(Calendar.HOUR_OF_DAY, 0);
         calendar.set(Calendar.MINUTE, 0);
         calendar.set(Calendar.SECOND, 0);
         calendar.set(Calendar.MILLISECOND, 0);
         return calendar;
     }
+
     //时间转换为一天的结束,也是后一天的开始
-    public static Calendar applyDayEnd(Calendar calendar){
+    public static Calendar applyDayEnd(Calendar calendar) {
         calendar.set(Calendar.HOUR_OF_DAY, 24);
         calendar.set(Calendar.MINUTE, 0);
         calendar.set(Calendar.SECOND, 0);
@@ -207,24 +221,43 @@ public class TimeUtil {
         return calendar;
     }
 
+    //获取当月总天数
+    public static int getTotalDay(int month) {
+        switch (month) {
+            case 1:
+            case 3:
+            case 5:
+            case 7:
+            case 8:
+            case 10:
+            case 12:
+                return 31;
+            case 2:
+                return 28;
+            default:
+                return 30;
+        }
+    }
+
     /**
      * 是否大于今天
      */
-    public boolean big2Today(String dateStr, String dateFormat){
-        if(getDayBegin() == string2Long(dateStr, dateFormat)){
+    public boolean big2Today(String dateStr, String dateFormat) {
+        if (getDayBegin() == string2Long(dateStr, dateFormat)) {
             return true;
         }
         return false;
     }
+
     //获取当天的开始时间
-      public long getDayBegin() {
-                Calendar cal = new GregorianCalendar();
-                 cal.set(Calendar.HOUR_OF_DAY, 0);
-                 cal.set(Calendar.MINUTE, 0);
-                 cal.set(Calendar.SECOND, 0);
-                 cal.set(Calendar.MILLISECOND, 0);
-                 return (cal.getTime()).getTime();
-             }
+    public long getDayBegin() {
+        Calendar cal = new GregorianCalendar();
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return (cal.getTime()).getTime();
+    }
 
     // 将Unix时间戳转变为日期,如调用TimeStampToDate("1252639886", "yyyy-MM-dd
     // HH:mm:ss")返回值:2009-11-09 11:31:26

+ 0 - 167
app/src/main/java/com/sheep/gamegroup/view/activity/ActOverrideJsWeb.java

@@ -1,167 +0,0 @@
-package com.sheep.gamegroup.view.activity;
-
-import android.content.Intent;
-import android.os.Build;
-import android.view.View;
-import android.widget.TextView;
-
-import com.sheep.gamegroup.absBase.BaseActivity;
-import com.sheep.gamegroup.util.LogUtil;
-import com.sheep.gamegroup.util.ViewUtil;
-import com.sheep.gamegroup.util.WebViewJs;
-import com.sheep.jiuyan.samllsheep.BuildConfig;
-import com.sheep.jiuyan.samllsheep.R;
-import com.sheep.jiuyan.samllsheep.utils.G;
-import com.sheep.jiuyan.samllsheep.utils.TitleBarUtils;
-import com.tencent.smtt.sdk.WebChromeClient;
-import com.tencent.smtt.sdk.WebSettings;
-import com.tencent.smtt.sdk.WebView;
-import com.tencent.smtt.sdk.WebViewClient;
-import com.zhy.http.okhttp.OkHttpUtils;
-import com.zhy.http.okhttp.callback.StringCallback;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-
-import butterknife.BindView;
-import okhttp3.Call;
-
-
-/**
- * 覆盖js 的 web
- * Created by zengjiebin on 2018/11/21.
- */
-public class ActOverrideJsWeb extends BaseActivity {
-
-    @BindView(R.id.webview)
-    WebView mWebView;
-    @BindView(R.id.tv_next)
-    TextView tv_next;
-
-    private WebSettings webViewSettings;
-
-    @Override
-    protected int getLayoutId() {
-        return R.layout.activity_guide_on_hook;
-    }
-
-    @Override
-    public void initView() {
-        Intent intent = getIntent();
-        String title = intent.getStringExtra("title");
-        String url = intent.getStringExtra("url");
-        String jsUrl = intent.getStringExtra("jsUrl");
-        TitleBarUtils
-                .getInstance()
-                .setTitle(this, title)
-                .setTitleFinish(this);
-
-        webViewSettings = mWebView.getSettings();
-        webViewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-//            webViewSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
-        }
-        tv_next.setVisibility(View.GONE);
-        initJsData(url, jsUrl);
-    }
-
-    @Override
-    public void initListener() {
-
-    }
-
-    @Override
-    public void initData() {
-
-    }
-
-    private void initJsData(final String url, String jsUrl) {
-        OkHttpUtils.get()
-                .url(jsUrl)
-                .build()
-                .execute(new StringCallback() {
-                    @Override
-                    public void onError(Call call, Exception e, int id) {
-                        G.showToast( R.string.service_data_error);
-                    }
-
-                    @Override
-                    public void onResponse(String response, int id) {
-                        js = response;
-                        loadUrl(url);
-                    }
-                });
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        if (mWebView != null) {
-            mWebView.setVisibility(View.GONE);
-            mWebView.removeAllViews();
-            mWebView.destroy();
-        }
-    }
-
-    private void loadUrl(String url) {
-        mWebView.setWebChromeClient(new WebChromeClient(){
-            @Override
-            public void onReceivedTitle(WebView view, String title) {
-                super.onReceivedTitle(view, title);
-                TitleBarUtils
-                        .getInstance()
-                        .setTitle(ActOverrideJsWeb.this, title);
-            }
-        });
-        mWebView.setWebViewClient(new WebViewClient() {
-            @Override
-            public boolean shouldOverrideUrlLoading(WebView view, String url) {
-                try {
-                    view.loadUrl(url);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-                return true;
-            }
-            @Override
-            public void onPageFinished(WebView view, String url) {
-                super.onPageFinished(view, url);
-                try {
-                    LogUtil.println("ActOverrideJsWeb", "onPageFinished", "url", "=", url, "\ndecode_url", "=",  URLDecoder.decode(url, "utf-8"));
-                } catch (UnsupportedEncodingException e) {
-                    e.printStackTrace();
-                }
-                loadJs();
-//                loadTestJs();
-            }
-        });
-
-        // 开启DOM缓存,开启LocalStorage存储(html5的本地存储方式)
-        webViewSettings.setDomStorageEnabled(true);
-        webViewSettings.setDatabaseEnabled(true);
-        webViewSettings.setDatabasePath(getApplicationContext().getCacheDir().getAbsolutePath());
-
-        webViewSettings.setJavaScriptEnabled(true);
-        mWebView.addJavascriptInterface(new WebViewJs(), "kfzsjs");
-        mWebView.loadUrl(url);
-    }
-
-    @Override
-    public void onBackPressed() {
-        if(mWebView.canGoBack()){
-            mWebView.goBack();
-            return;
-        }
-        this.finish();
-    }
-    // 注入js函数监听
-    public void loadJs() {
-        ViewUtil.loadJs(mWebView, getJs());
-        LogUtil.println("ActOverrideJsWeb", "loadJs", js);
-    }
-    private String js;
-    private String getJs(){
-        String testJsStart = "alert('成功注入');";
-        return BuildConfig.DEBUG ? testJsStart + "\n" + js : js;
-    }
-}

+ 17 - 1
app/src/main/java/com/sheep/gamegroup/view/activity/ActSearchGame.java

@@ -28,7 +28,9 @@ import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.util.CommonUtil;
 import com.sheep.gamegroup.util.Jump2View;
 import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.LogUtil;
 import com.sheep.gamegroup.util.MyDbManager;
+import com.sheep.gamegroup.util.StringUtils;
 import com.sheep.gamegroup.util.TestUtil;
 import com.sheep.gamegroup.util.ViewHolder;
 import com.sheep.gamegroup.util.ViewUtil;
@@ -238,7 +240,11 @@ public class ActSearchGame extends BaseActivity {
 
             @Override
             public void afterTextChanged(Editable editable) {
-                if(editable.toString().startsWith("h") && TestUtil.isTest()){//测试用 http中的h开头
+                String text = editable.toString();
+                if(text.startsWith("h") && TestUtil.isTest()){//测试用 http中的h开头
+                    return;
+                }
+                if(text.startsWith("t") && TestUtil.isTest()){//测试用 task中的t开头
                     return;
                 }
                 search_game_input.removeCallbacks(autoSearchRunnable);
@@ -318,6 +324,16 @@ public class ActSearchGame extends BaseActivity {
             Jump2View.getInstance().goWeb(activity, inputText, "测试内部H5");
             return;
         }
+        if(inputText.startsWith("task") && inputText.length() > 6 && TestUtil.isTest()){//测试用
+            ArrayList<String> arrayList = StringUtils.getAllSatisfyStr(inputText, "\\d+");
+            ListUtil.forEach(arrayList, new Action1<String>() {
+                @Override
+                public void call(String s) {
+                    Jump2View.getInstance().goTaskDetailView(activity, Integer.parseInt(s));
+                }
+            });
+            return;
+        }
 
         if(type == 1){
             CommonUtil.getInstance()

+ 1 - 1
app/src/main/java/com/sheep/gamegroup/view/adapter/AdpMiDong.java

@@ -65,7 +65,7 @@ public class AdpMiDong extends AdbCommonRecycler<AdData> {
             CommonUtil.getInstance().setDownloadTvText(context,btnInstall, data);
         } else {
             String todayTask = data.getDate();
-            if (todayTask != null && todayTask.equals(TimeUtil.newInstance().TimeStamp2Date(System.currentTimeMillis(), "yyyy-MM-dd"))) {
+            if (todayTask != null && todayTask.equals(TimeUtil.TimeStamp2Date(System.currentTimeMillis(), "yyyy-MM-dd"))) {
                 CommonUtil.getInstance().setDownloadTvText(context,btnInstall, data);
                 btnInstall.setEnabled(true);
                 btnInstall.setBackground(context.getResources().getDrawable(R.drawable.sp_bg_gradient_rectangle_blue));

+ 209 - 0
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment4.java

@@ -0,0 +1,209 @@
+package com.sheep.gamegroup.view.fragment;
+
+import android.app.Activity;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.sheep.gamegroup.absBase.BaseRefreshLoadMoreFragment;
+import com.sheep.gamegroup.model.api.ApiService;
+import com.sheep.gamegroup.model.entity.BaseMessage;
+import com.sheep.gamegroup.model.util.SheepSubscriber;
+import com.sheep.gamegroup.util.CommonUtil;
+import com.sheep.gamegroup.util.Conversion;
+import com.sheep.gamegroup.util.DataUtil;
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.ViewUtil;
+import com.sheep.jiuyan.samllsheep.SheepApp;
+
+import java.util.List;
+
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by realicing on 2018/10/9.
+ * realicing@sina.com
+ * 使用普通的RecyclerView来显示列表,可配合SmartRefreshLayout和ViewPager使用(setSmartRefreshLayout和setViewPager)
+ */
+public abstract class BaseListFragment4<T> extends BaseRefreshLoadMoreFragment {
+
+    protected Activity activity;
+    protected View empty_view;
+    protected RecyclerView view_list;
+
+    @Override
+    public void onViewCreated() {
+        activity = getActivity();
+        initView();
+        initListener();
+        switch (refreshDataType()) {
+            case REFRESH_ON_CREATE:
+                refreshData();
+                break;
+            case REFRESH_ON_RESUME:
+                break;
+            case REFRESH_ON_YOURSELF:
+            default:
+                notifyDataSetChanged();
+                break;
+        }
+        if (!useSelfEmpty() && empty_view != null)
+            empty_view.setVisibility(View.GONE);
+    }
+
+
+    protected BaseMessage lastMessage;//最后一个网络获取的结果
+    protected int page = 1;//页数
+    protected int per_page = DataUtil.PER_PAGE;
+
+    public void initView() {
+
+    }
+
+    public void initListener() {
+
+    }
+
+    //加载更多数据
+    public void loadMoreData() {
+        if (ListUtil.size(list) >= per_page * page) {
+            page += 1;
+            initData();
+        } else {
+            setNoMore(true);
+            refreshOrLoadMoreComplete();
+        }
+    }
+
+    protected List<T> list = ListUtil.emptyList();
+    protected List<T> lastCacheList = ListUtil.emptyList();
+
+    //默认先获取缓存
+    protected boolean isFirstGetACache() {
+        return true;
+    }
+
+    //将baseMessage转化为list<T>
+    private Conversion<BaseMessage, List<T>> conversion = new Conversion<BaseMessage, List<T>>() {
+        @Override
+        public List<T> convert(BaseMessage baseMessage, int position) {
+            return resolveData(baseMessage, position);
+        }
+    };
+
+    //加载数据
+    public void initData() {
+        final String urlKey = getKey(page, per_page);
+        if (isFirstGetACache()) {
+            //先尝试获取缓存数据
+            lastCacheList = DataUtil.getInstance().getCacheList(urlKey, getTClass(), conversion, page);
+            loadList(lastCacheList);
+        }
+        getApi(SheepApp.getInstance().getNetComponent().getApiService())
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new SheepSubscriber<BaseMessage>(SheepApp.getInstance()) {
+                    @Override
+                    public void onNext(BaseMessage baseMessage) {
+                        lastMessage = baseMessage;
+                        boolean isNewData = DataUtil.getInstance().isNewData(urlKey);
+                        if (isNewData || !isFirstGetACache()) {
+                            if (isFirstGetACache())
+                                ListUtil.removeAll(list, lastCacheList);
+                            List<T> newList = conversion.convert(baseMessage, page);
+                            loadList(newList);
+                        } else {
+                            notifyDataSetChanged();
+                        }
+                    }
+
+                    @Override
+                    public void onError(BaseMessage baseMessage) {
+                        notifyDataSetChanged();
+                    }
+                });
+    }
+
+
+    //解析数据
+    protected List<T> resolveData(BaseMessage baseMessage, int page) {
+        return baseMessage.getDatas(getTClass());
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (refreshDataType() == REFRESH_ON_RESUME) {
+            refreshData();
+        }
+    }
+
+    //使用布局中自带的无数据空view
+    public boolean useSelfEmpty() {
+        return true;
+    }
+
+    public static final int REFRESH_ON_CREATE = 0;
+    public static final int REFRESH_ON_RESUME = 1;
+    public static final int REFRESH_ON_YOURSELF = -1;
+
+    /**
+     * 在哪里初始化数据:0 onViewCreated后, 1 onResume后, -1 不初始化
+     *
+     * @return
+     */
+    public int refreshDataType() {
+        return REFRESH_ON_CREATE;
+    }
+
+    public void clear() {
+        lastMessage = null;
+        setNoMore(false);
+
+        if (useSelfEmpty() && empty_view != null)
+            empty_view.setVisibility(View.INVISIBLE);
+        list.clear();
+        page = 1;
+    }
+
+    //通过刷新来重新加载数据
+    public void refreshData() {
+        clear();
+        ViewUtil.notifyDataSetChanged(view_list);
+        initData();
+    }
+
+    protected List<T> newList;
+
+    protected void loadList(List<T> addList) {
+        ListUtil.addAllItem(list, addList);
+        newList = addList;
+        notifyDataSetChanged();
+    }
+
+    //刷新数据
+    public void notifyDataSetChanged() {
+        if (view_list == null || empty_view == null) {
+            return;
+        }
+        updateEmptyView();
+        ViewUtil.notifyDataSetChanged(view_list);
+        refreshOrLoadMoreComplete();
+    }
+
+    //是否显示无数据占位图
+    protected void updateEmptyView() {
+        if (useSelfEmpty())
+            CommonUtil.getInstance().updateEmptyView(empty_view, list.isEmpty());
+    }
+
+    protected abstract RecyclerView.Adapter getAdapter();
+
+    protected abstract String getKey(int page, int per_page);
+
+    protected abstract Observable<BaseMessage> getApi(ApiService apiService);
+
+    protected abstract Class<T> getTClass();
+
+}

+ 141 - 45
app/src/main/java/com/sheep/gamegroup/view/fragment/FgtFootprint.java

@@ -1,33 +1,39 @@
 package com.sheep.gamegroup.view.fragment;
 
+import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
 import com.haibin.calendarview.Calendar;
+import com.haibin.calendarview.CalendarLayout;
 import com.haibin.calendarview.CalendarView;
+import com.haibin.calendarviewproject.custom.CustomMonthView;
+import com.haibin.calendarviewproject.custom.CustomWeekView;
 import com.kfzs.appstore.utils.adapter.recyclerview.RecyclerViewAdapter;
 import com.kfzs.appstore.utils.adapter.recyclerview.ViewHolder;
 import com.sheep.gamegroup.model.api.ApiService;
 import com.sheep.gamegroup.model.entity.BaseMessage;
-import com.sheep.gamegroup.model.entity.Lp;
-import com.sheep.gamegroup.model.entity.UserFocusLog;
 import com.sheep.gamegroup.model.entity.UserFootprint;
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.TimeUtil;
 import com.sheep.gamegroup.util.ViewUtil;
-import com.sheep.gamegroup.util.viewHelper.LayoutParamsUtil;
-import com.sheep.gamegroup.view.customview.CalendarMonthView2;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
-import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.TitleBarUtils;
 
 import org.afinal.simplecache.ApiKey;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
+import butterknife.BindView;
 import io.reactivex.Observable;
 
 /**
@@ -35,82 +41,124 @@ import io.reactivex.Observable;
  * realicing@sina.com
  * 小绵羊3.4.5新增--足迹
  */
-public class FgtFootprint extends BaseListFragment2<UserFootprint> {
-    private CalendarView calendarView;
-    private TextView header_foot_print_date_tv;
-    private ImageView header_foot_print_last_iv;
-    private View header_foot_print_last_v;
-    private ImageView header_foot_print_next_iv;
-    private View header_foot_print_next_v;
+public class FgtFootprint extends BaseListFragment4<UserFootprint> {
+    @BindView(R.id.header_foot_print_date_tv)
+    TextView header_foot_print_date_tv;
+    @BindView(R.id.header_foot_print_last_iv)
+    ImageView header_foot_print_last_iv;
+    @BindView(R.id.header_foot_print_last_v)
+    View header_foot_print_last_v;
+    @BindView(R.id.header_foot_print_next_iv)
+    ImageView header_foot_print_next_iv;
+    @BindView(R.id.header_foot_print_next_v)
+    View header_foot_print_next_v;
+
+    @BindView(R.id.fgt_foot_print_cv)
+    CalendarView mCalendarView;
+    @BindView(R.id.fgt_foot_print_cl)
+    CalendarLayout mCalendarLayout;
+    @BindView(R.id.fgt_foot_print_grv)
+    RecyclerView mRecyclerView;
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.fgt_foot_print;
+    }
 
     @Override
     public void initView() {
-        //添加 CalendarMonthView2 的引用,防止无引用,导致误删该类
-        CalendarMonthView2.class.getSimpleName();
+        CustomMonthView.class.getSimpleName();
+        CustomWeekView.class.getSimpleName();
         TitleBarUtils
                 .getInstance()
                 .setTitleFinish(getView(), activity)
                 .setTitle(getView(), "足迹");
-        LayoutParamsUtil.resetLayoutParams(empty_view, new Lp().setTopMargin(G.getRealPix(320)));
-        LayoutParamsUtil.resetLayoutParams(empty_view.findViewById(R.id.empty_view_msg), new Lp().setBottomMargin(0).setTopMargin(20));
-        per_page = 100;
-        view_list.setNestedScrollingEnabled(false);
-        View view = LayoutInflater.from(activity).inflate(R.layout.header_foot_print, null);
-        view_list.addHeaderView(view);
-        calendarView = view.findViewById(R.id.calendarView);
-        header_foot_print_date_tv = view.findViewById(R.id.header_foot_print_date_tv);
-        header_foot_print_last_iv = view.findViewById(R.id.header_foot_print_last_iv);
-        header_foot_print_last_v = view.findViewById(R.id.header_foot_print_last_v);
-        header_foot_print_next_iv = view.findViewById(R.id.header_foot_print_next_iv);
-        header_foot_print_next_v = view.findViewById(R.id.header_foot_print_next_v);
-        maxYear = calendarView.getCurYear();
-        maxYearMonth = calendarView.getCurMonth();
-        maxYearDay = calendarView.getCurDay();
-        calendarView.setRange(minYear, minYearMonth, minYearDay,
+
+        view_list = mRecyclerView;
+
+        mRecyclerView.setLayoutManager(new LinearLayoutManager(SheepApp.getInstance()));
+        mRecyclerView.setAdapter(getAdapter());
+
+        int maxYear = mCalendarView.getCurYear();
+        int maxYearMonth = mCalendarView.getCurMonth();
+        int maxYearDay = mCalendarView.getCurDay();
+        mCalendarView.setRange(2018, 10, 23,
                 maxYear, maxYearMonth, maxYearDay);
         header_foot_print_last_v.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 //翻到上一个月
-                calendarView.scrollToPre();
+                mCalendarView.scrollToPre(true);
             }
         });
         header_foot_print_next_v.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 //翻到下一个月
-                calendarView.scrollToNext();
+                mCalendarView.scrollToNext(true);
             }
         });
     }
-    private int minYear = 2018;
-    private int minYearMonth = 10;
-    private int minYearDay = 23;
-    private int maxYear;
-    private int maxYearMonth;
-    private int maxYearDay;
 
     private void checkHeaderView(int year, int month) {
         ViewUtil.setText(header_foot_print_date_tv, String.format(Locale.CHINA, "%d年%d月", year, month));
-        boolean canScrollToPre = year >= minYear && month > minYearMonth;
+        Calendar firstCalendar = new Calendar();
+        firstCalendar.setYear(year);
+        firstCalendar.setMonth(month);
+        firstCalendar.setDay(1);
+        Calendar lastCalendar = new Calendar();
+        lastCalendar.setYear(year);
+        lastCalendar.setMonth(month);
+        lastCalendar.setDay(TimeUtil.getTotalDay(month));
+        checkHeaderView(firstCalendar, lastCalendar);
+    }
+    private void checkHeaderView(Calendar firstCalendar, Calendar lastCalendar){
+        Calendar minCalendar = mCalendarView.getMinRangeCalendar();
+        Calendar maxCalendar = mCalendarView.getMaxRangeCalendar();
+        boolean canScrollToPre = minCalendar.compareTo(firstCalendar) < 0;
         ViewUtil.setEnabled(header_foot_print_last_iv, canScrollToPre);
         ViewUtil.setEnabled(header_foot_print_last_v, canScrollToPre);
-        boolean canScrollToNext = year <= maxYear && month < maxYearMonth;
+        boolean canScrollToNext = maxCalendar.compareTo(lastCalendar) > 0;
         ViewUtil.setEnabled(header_foot_print_next_iv, canScrollToNext);
         ViewUtil.setEnabled(header_foot_print_next_v, canScrollToNext);
     }
+    private void checkHeaderView(List<Calendar> weekCalendars) {
+        Calendar firstCalendar = ListUtil.getItem(weekCalendars, 0);
+        Calendar lastCalendar = ListUtil.getLast(weekCalendars);
+        if(firstCalendar != null && lastCalendar != null) {
+            int year = firstCalendar.getYear();
+            int month = firstCalendar.getMonth();
+            ViewUtil.setText(header_foot_print_date_tv, String.format(Locale.CHINA, "%d年%d月", year, month));
+            checkHeaderView(firstCalendar, lastCalendar);
+        }
+    }
 
 
     @Override
     public void initListener() {
-        super.initListener();
-        calendarView.setOnMonthChangeListener(new CalendarView.OnMonthChangeListener() {
+        mCalendarView.setOnMonthChangeListener(new CalendarView.OnMonthChangeListener() {
             @Override
             public void onMonthChange(int year, int month) {
                 checkHeaderView(year, month);
             }
         });
-        calendarView.setOnCalendarSelectListener(new CalendarView.OnCalendarSelectListener() {
+        mCalendarView.setOnWeekChangeListener(new CalendarView.OnWeekChangeListener() {
+            @Override
+            public void onWeekChange(List<Calendar> weekCalendars) {
+                checkHeaderView(weekCalendars);
+            }
+        });
+        mCalendarView.setOnViewChangeListener(new CalendarView.OnViewChangeListener() {
+            @Override
+            public void onViewChange(boolean isMonthView) {
+                if(isMonthView){
+                    checkHeaderView(mCalendarView.getCurYear(), mCalendarView.getCurMonth());
+                } else {
+                    checkHeaderView(mCalendarView.getCurrentWeekCalendars());
+                }
+            }
+        });
+        mCalendarView.setOnCalendarSelectListener(new CalendarView.OnCalendarSelectListener() {
             @Override
             public void onCalendarOutOfRange(Calendar calendar) {
 
@@ -125,10 +173,54 @@ public class FgtFootprint extends BaseListFragment2<UserFootprint> {
     }
 
     @Override
+    public void initData() {
+        super.initData();
+
+        int year = mCalendarView.getCurYear();
+        int month = mCalendarView.getCurMonth();
+
+        Map<String, Calendar> map = new HashMap<>();
+        map.put(getSchemeCalendar(year, month, 3, 0xFF40db25, "假").toString(),
+                getSchemeCalendar(year, month, 3, 0xFF40db25, "假"));
+        map.put(getSchemeCalendar(year, month, 6, 0xFFe69138, "事").toString(),
+                getSchemeCalendar(year, month, 6, 0xFFe69138, "事"));
+        map.put(getSchemeCalendar(year, month, 9, 0xFFdf1356, "议").toString(),
+                getSchemeCalendar(year, month, 9, 0xFFdf1356, "议"));
+        map.put(getSchemeCalendar(year, month, 13, 0xFFedc56d, "记").toString(),
+                getSchemeCalendar(year, month, 13, 0xFFedc56d, "记"));
+        map.put(getSchemeCalendar(year, month, 14, 0xFFedc56d, "记").toString(),
+                getSchemeCalendar(year, month, 14, 0xFFedc56d, "记"));
+        map.put(getSchemeCalendar(year, month, 15, 0xFFaacc44, "假").toString(),
+                getSchemeCalendar(year, month, 15, 0xFFaacc44, "假"));
+        map.put(getSchemeCalendar(year, month, 18, 0xFFbc13f0, "记").toString(),
+                getSchemeCalendar(year, month, 18, 0xFFbc13f0, "记"));
+        map.put(getSchemeCalendar(year, month, 25, 0xFF13acf0, "假").toString(),
+                getSchemeCalendar(year, month, 25, 0xFF13acf0, "假"));
+        map.put(getSchemeCalendar(year, month, 27, 0xFF13acf0, "多").toString(),
+                getSchemeCalendar(year, month, 27, 0xFF13acf0, "多"));
+        //此方法在巨大的数据量上不影响遍历性能,推荐使用
+        mCalendarView.setSchemeDate(map);
+
+    }
+
+    private Calendar getSchemeCalendar(int year, int month, int day, int color, String text) {
+        Calendar calendar = new Calendar();
+        calendar.setYear(year);
+        calendar.setMonth(month);
+        calendar.setDay(day);
+        calendar.setSchemeColor(color);//如果单独标记颜色、则会使用这个颜色
+        calendar.setScheme(text);
+        calendar.addScheme(new Calendar.Scheme());
+        calendar.addScheme(0xFF008800, "假");
+        calendar.addScheme(0xFF008800, "节");
+        return calendar;
+    }
+
+    @Override
     protected RecyclerView.Adapter getAdapter() {
-        return new RecyclerViewAdapter<UserFootprint>(SheepApp.getInstance(), R.layout.item_my_focus, list) {
+        BaseQuickAdapter<UserFootprint, BaseViewHolder> adapter = new BaseQuickAdapter<UserFootprint, BaseViewHolder>(R.layout.item_my_focus, list) {
             @Override
-            public void convert(ViewHolder holder, UserFootprint item, int position) {
+            protected void convert(BaseViewHolder holder, UserFootprint item) {
                 ImageView item_my_focus_iv = holder.itemView.findViewById(R.id.item_my_focus_iv);
                 TextView item_my_focus_info_tv = holder.itemView.findViewById(R.id.item_my_focus_info_tv);
                 TextView item_my_focus_tv = holder.itemView.findViewById(R.id.item_my_focus_tv);
@@ -138,9 +230,13 @@ public class FgtFootprint extends BaseListFragment2<UserFootprint> {
                 ViewUtil.setText(item_my_focus_info_tv, item.getInfo());
             }
         };
+        View headerView = LayoutInflater.from(SheepApp.getInstance()).inflate(R.layout.header_foot_print, null);
+        adapter.addHeaderView(headerView);
+        return adapter;
     }
 
     private String date;
+
     @Override
     protected String getKey(int page, int per_page) {
         return String.format(Locale.CHINA, "%s?page=%d&per_page=%d&date=%s", ApiKey.getUserFootPrintList, page, per_page, date);

+ 115 - 0
app/src/main/res/layout/fgt_foot_print.xml

@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/white">
+
+    <include
+        android:id="@+id/title"
+        layout="@layout/title"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize" />
+
+    <TextView
+        android:id="@+id/header_foot_print_date_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="15dp"
+        android:text="2018年11月"
+        android:textColor="#ff333333"
+        android:textSize="14sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/title" />
+
+    <ImageView
+        android:id="@+id/header_foot_print_last_iv"
+        android:layout_width="10dp"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="24dp"
+        android:adjustViewBounds="true"
+        android:rotation="270"
+        android:scaleType="fitXY"
+        android:src="@drawable/selector_tab_triangle_black_db"
+        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
+        app:layout_constraintEnd_toStartOf="@id/header_foot_print_date_tv"
+        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
+
+    <View
+        android:id="@+id/header_foot_print_last_v"
+        android:layout_width="60dp"
+        android:layout_height="40dp"
+        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
+        app:layout_constraintEnd_toStartOf="@id/header_foot_print_date_tv"
+        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
+
+    <ImageView
+        android:id="@+id/header_foot_print_next_iv"
+        android:layout_width="10dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:adjustViewBounds="true"
+        android:rotation="90"
+        android:scaleType="fitXY"
+        android:src="@drawable/selector_tab_triangle_black_db"
+        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
+        app:layout_constraintStart_toEndOf="@id/header_foot_print_date_tv"
+        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
+
+    <View
+        android:id="@+id/header_foot_print_next_v"
+        android:layout_width="60dp"
+        android:layout_height="40dp"
+        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
+        app:layout_constraintStart_toEndOf="@id/header_foot_print_date_tv"
+        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
+
+
+    <com.haibin.calendarview.CalendarLayout
+        android:id="@+id/fgt_foot_print_cl"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:background="#fff"
+        android:orientation="vertical"
+        app:calendar_content_view_id="@+id/fgt_foot_print_grv"
+        app:layout_constraintTop_toBottomOf="@id/header_foot_print_date_tv"
+        app:layout_constraintBottom_toBottomOf="parent">
+
+        <com.haibin.calendarview.CalendarView
+            android:id="@+id/fgt_foot_print_cv"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="#fff"
+            app:calendar_padding="10dp"
+            app:current_month_lunar_text_color="#CFCFCF"
+            app:current_month_text_color="#333333"
+            app:max_year="2020"
+            app:min_year="2004"
+            app:month_view="com.haibin.calendarviewproject.custom.CustomMonthView"
+            app:month_view_show_mode="mode_fix"
+            app:other_month_lunar_text_color="#e1e1e1"
+            app:other_month_text_color="#e1e1e1"
+            app:scheme_text="假"
+            app:scheme_text_color="#333"
+            app:scheme_theme_color="#128c4b"
+            app:selected_lunar_text_color="#fff"
+            app:selected_text_color="#fff"
+            app:selected_theme_color="#046cea"
+            app:week_background="#fff"
+            app:week_start_with="sun"
+            app:week_text_color="#e1e1e1"
+            app:week_view="com.haibin.calendarviewproject.custom.CustomWeekView"
+            app:year_view_day_text_color="#333333"
+            app:year_view_day_text_size="9sp"
+            app:year_view_month_text_color="#ff0000"
+            app:year_view_month_text_size="20sp"
+            app:year_view_scheme_color="#f17706" />
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/fgt_foot_print_grv"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+    </com.haibin.calendarview.CalendarLayout>
+</android.support.constraint.ConstraintLayout>

+ 1 - 86
app/src/main/res/layout/header_foot_print.xml

@@ -1,94 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
-
-    <TextView
-        android:id="@+id/header_foot_print_date_tv"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="15dp"
-        android:text="2018年11月"
-        android:textColor="#ff333333"
-        android:textSize="14sp"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <ImageView
-        android:id="@+id/header_foot_print_last_iv"
-        android:layout_width="10dp"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="24dp"
-        android:adjustViewBounds="true"
-        android:rotation="270"
-        android:scaleType="fitXY"
-        android:src="@drawable/selector_tab_triangle_black_db"
-        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
-        app:layout_constraintEnd_toStartOf="@id/header_foot_print_date_tv"
-        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
-
-    <View
-        android:id="@+id/header_foot_print_last_v"
-        android:layout_width="60dp"
-        android:layout_height="40dp"
-        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
-        app:layout_constraintEnd_toStartOf="@id/header_foot_print_date_tv"
-        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
-
-    <ImageView
-        android:id="@+id/header_foot_print_next_iv"
-        android:layout_width="10dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="24dp"
-        android:adjustViewBounds="true"
-        android:rotation="90"
-        android:scaleType="fitXY"
-        android:src="@drawable/selector_tab_triangle_black_db"
-        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
-        app:layout_constraintStart_toEndOf="@id/header_foot_print_date_tv"
-        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
-
-    <View
-        android:id="@+id/header_foot_print_next_v"
-        android:layout_width="60dp"
-        android:layout_height="40dp"
-        app:layout_constraintBottom_toBottomOf="@id/header_foot_print_date_tv"
-        app:layout_constraintStart_toEndOf="@id/header_foot_print_date_tv"
-        app:layout_constraintTop_toTopOf="@id/header_foot_print_date_tv" />
-
-    <com.haibin.calendarview.CalendarView
-        android:id="@+id/calendarView"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="5dp"
-        android:background="@color/white"
-        app:calendar_height="46dp"
-        app:current_day_lunar_text_color="#999999"
-        app:current_day_text_color="#333333"
-        app:current_month_lunar_text_color="#999999"
-        app:current_month_text_color="#333333"
-        app:day_text_size="12sp"
-        app:layout_constraintTop_toBottomOf="@id/header_foot_print_date_tv"
-        app:lunar_text_size="12sp"
-        app:min_year="2018"
-        app:month_view="com.sheep.gamegroup.view.customview.CalendarMonthView2"
-        app:month_view_scrollable="true"
-        app:month_view_show_mode="mode_all"
-        app:selected_theme_color="#4889FF"
-        app:selected_lunar_text_color="@color/white"
-        app:selected_text_color="@color/white"
-        app:scheme_lunar_text_color="#ffffff"
-        app:scheme_month_text_color="#ffffff"
-        app:week_background="@color/white"
-        app:week_bar_view="com.haibin.calendarview.WeekBar"
-        app:week_start_with="mon"
-        app:week_text_color="#111" />
-
     <View
         android:layout_width="match_parent"
         android:layout_height="5dp"
-        android:background="#F0F0F0"
-        app:layout_constraintTop_toBottomOf="@id/calendarView" />
+        android:background="#F0F0F0"/>
 </android.support.constraint.ConstraintLayout>

+ 15 - 0
app/src/main/res/values/haibin_group_attrs.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="GroupRecyclerView">
+        <attr name="group_height" format="dimension" />
+        <attr name="group_child_offset" format="dimension" />
+        <attr name="group_background" format="color" />
+        <attr name="group_text_color" format="color" />
+        <attr name="group_text_size" format="dimension" />
+        <attr name="group_center" format="boolean" />
+        <attr name="group_padding_left" format="dimension" />
+        <attr name="group_padding_right" format="dimension" />
+        <attr name="group_has_header" format="boolean" />
+    </declare-styleable>
+
+</resources>