From b16846e666afe648d943d26bd2c5fc41d09a3fc0 Mon Sep 17 00:00:00 2001 From: "marunjar@aon.at" Date: Tue, 6 Jan 2015 17:51:06 +0100 Subject: [PATCH 01/39] dynamic time column width --- .../main/java/com/alamkanak/weekview/WeekView.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..05dc1b892 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -276,9 +276,9 @@ private void init() { mTimeTextPaint.setColor(mHeaderColumnTextColor); Rect rect = new Rect(); mTimeTextPaint.getTextBounds("00 PM", 0, "00 PM".length(), rect); - mTimeTextWidth = mTimeTextPaint.measureText("00 PM"); mTimeTextHeight = rect.height(); mHeaderMarginBottom = mTimeTextHeight / 2; + initTextTimeWidth(); // Measure settings for header row. mHeaderTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -333,6 +333,14 @@ private void init() { mDefaultEventColor = Color.parseColor("#9fc6e7"); } + /** + * Initialize time column width. Calculate value with latest possible hour (supposed widest text) + */ + private void initTextTimeWidth() { + String timeSample = getDateTimeInterpreter().interpretTime(23); + mTimeTextWidth = mTimeTextPaint.measureText(timeSample); + } + @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -991,6 +999,9 @@ public String interpretTime(int hour) { */ public void setDateTimeInterpreter(DateTimeInterpreter dateTimeInterpreter){ this.mDateTimeInterpreter = dateTimeInterpreter; + + // refresh time column width + initTextTimeWidth(); } From 4915b9434516c725a1dd7bce65142653a1e60011 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Tue, 3 Feb 2015 17:35:49 +0100 Subject: [PATCH 02/39] Add location field to WeekViewEvents (Copied most of the code from the AOSP: http://www.javased.com/index.php?source_dir=packages_apps_Calendar/src/com/android/calendar/DayView.java) --- .../java/com/alamkanak/weekview/WeekView.java | 24 ++++++++++++++----- .../com/alamkanak/weekview/WeekViewEvent.java | 24 ++++++++++++++++++- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..8a28eb24c 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -12,9 +12,11 @@ import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.ViewCompat; import android.text.Layout; +import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.text.style.StyleSpan; import android.util.AttributeSet; import android.util.TypedValue; import android.view.GestureDetector; @@ -555,7 +557,7 @@ eventRectF.top < getHeight() && mEventRects.get(i).rectF = eventRectF; mEventBackgroundPaint.setColor(mEventRects.get(i).event.getColor() == 0 ? mDefaultEventColor : mEventRects.get(i).event.getColor()); canvas.drawRect(mEventRects.get(i).rectF, mEventBackgroundPaint); - drawText(mEventRects.get(i).event.getName(), mEventRects.get(i).rectF, canvas, originalTop, originalLeft); + drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, originalTop, originalLeft); } else mEventRects.get(i).rectF = null; @@ -567,17 +569,27 @@ eventRectF.top < getHeight() && /** * Draw the name of the event on top of the event rectangle. - * @param text The text to draw. + * @param event The event of which the title (and location) should be drawn. * @param rect The rectangle on which the text is to be drawn. * @param canvas The canvas to draw upon. * @param originalTop The original top position of the rectangle. The rectangle may have some of its portion outside of the visible area. * @param originalLeft The original left position of the rectangle. The rectangle may have some of its portion outside of the visible area. */ - private void drawText(String text, RectF rect, Canvas canvas, float originalTop, float originalLeft) { + private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, float originalTop, float originalLeft) { if (rect.right - rect.left - mEventPadding * 2 < 0) return; + SpannableStringBuilder bob = new SpannableStringBuilder(); + if (event.getName() != null) { + bob.append(event.getName()); + bob.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,bob.length(),0); + bob.append(' '); + } + if (event.getLocation() != null) { + bob.append(event.getLocation()); + } + // Get text dimensions - StaticLayout textLayout = new StaticLayout(text, mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + StaticLayout textLayout = new StaticLayout(bob, mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); // Crop height int availableHeight = (int) (rect.bottom - originalTop - mEventPadding * 2); @@ -586,11 +598,11 @@ private void drawText(String text, RectF rect, Canvas canvas, float originalTop, int lineCount = textLayout.getLineCount(); int availableLineCount = (int) Math.floor(lineCount * availableHeight / textLayout.getHeight()); float widthAvailable = (rect.right - originalLeft - mEventPadding * 2) * availableLineCount; - textLayout = new StaticLayout(TextUtils.ellipsize(text, mEventTextPaint, widthAvailable, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, widthAvailable, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } else if (lineHeight >= availableHeight) { int width = (int) (rect.right - originalLeft - mEventPadding * 2); - textLayout = new StaticLayout(TextUtils.ellipsize(text, mEventTextPaint, width, TextUtils.TruncateAt.END), mEventTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 1.0f, false); + textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, width, TextUtils.TruncateAt.END), mEventTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 1.0f, false); } // Draw text diff --git a/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java b/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java index ce1f15c76..e6638a875 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java @@ -11,6 +11,7 @@ public class WeekViewEvent { private Calendar mStartTime; private Calendar mEndTime; private String mName; + private String mLocation; private int mColor; public WeekViewEvent(){ @@ -56,16 +57,29 @@ public WeekViewEvent(long id, String name, int startYear, int startMonth, int st * Initializes the event for week view. * @param id The id of the event. * @param name Name of the event. + * @param location The location of the event. * @param startTime The time when the event starts. * @param endTime The time when the event ends. */ - public WeekViewEvent(long id, String name, Calendar startTime, Calendar endTime) { + public WeekViewEvent(long id, String name, String location, Calendar startTime, Calendar endTime) { this.mId = id; this.mName = name; + this.mLocation = location; this.mStartTime = startTime; this.mEndTime = endTime; } + /** + * Initializes the event for week view. + * @param id The id of the event. + * @param name Name of the event. + * @param startTime The time when the event starts. + * @param endTime The time when the event ends. + */ + public WeekViewEvent(long id, String name, Calendar startTime, Calendar endTime) { + this(id, name, null, startTime, endTime); + } + public Calendar getStartTime() { return mStartTime; @@ -91,6 +105,14 @@ public void setName(String name) { this.mName = name; } + public String getLocation() { + return mLocation; + } + + public void setLocation(String location) { + this.mLocation = location; + } + public int getColor() { return mColor; } From d2fd12fa478ddf438d953b7d35e9e0005fe8af30 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Wed, 4 Feb 2015 16:26:11 +0100 Subject: [PATCH 03/39] Bug with view getting stuck between days. There was a bug where the weekview would get stuck between days. This is fixed with this commit. --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..7fded494c 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -139,7 +139,6 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { mScroller.forceFinished(true); - mStickyScroller.forceFinished(true); if (mCurrentFlingDirection == Direction.HORIZONTAL){ mScroller.fling((int) mCurrentOrigin.x, 0, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); @@ -1288,6 +1287,10 @@ public boolean onTouchEvent(MotionEvent event) { if (mCurrentScrollDirection == Direction.HORIZONTAL) { float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)); + if(mDistanceX > 0) + leftDays--; + else + leftDays++; int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap)); mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0); ViewCompat.postInvalidateOnAnimation(WeekView.this); From 07d329a0ced3869a01a645457ecc901a1c9e18d5 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Wed, 4 Feb 2015 11:45:03 +0100 Subject: [PATCH 04/39] Provide a new way of coloring the weekview. Solves #48, solves #49 Provides 4 new background colors: past and future (and optional past and future colors for the weekend, so they stand out). Today is rendered as partially past and partially future (based on the hour). There's also a line drawn at the current hour (on today's view). --- .../java/com/alamkanak/weekview/WeekView.java | 105 ++++++++++++++---- library/src/main/res/values/attrs.xml | 7 ++ 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..f1e07b9eb 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -43,8 +43,6 @@ public class WeekView extends View { @Deprecated public static final int LENGTH_LONG = 2; private final Context mContext; - private Calendar mToday; - private Calendar mStartDate; private Paint mTimeTextPaint; private float mTimeTextWidth; private float mTimeTextHeight; @@ -60,6 +58,11 @@ public class WeekView extends View { private Paint mHourSeparatorPaint; private float mHeaderMarginBottom; private Paint mTodayBackgroundPaint; + private Paint mFutureBackgroundPaint; + private Paint mPastBackgroundPaint; + private Paint mFutureWeekendBackgroundPaint; + private Paint mPastWeekendBackgroundPaint; + private Paint mNowLinePaint; private Paint mTodayHeaderTextPaint; private Paint mEventBackgroundPaint; private float mHeaderColumnWidth; @@ -84,6 +87,13 @@ public class WeekView extends View { private int mHeaderRowPadding = 10; private int mHeaderRowBackgroundColor = Color.WHITE; private int mDayBackgroundColor = Color.rgb(245, 245, 245); + private int mPastBackgroundColor = Color.rgb(227, 227, 227); + private int mFutureBackgroundColor = Color.rgb(245, 245, 245); + private int mPastWeekendBackgroundColor = 0; + private int mFutureWeekendBackgroundColor = 0; + private int mNowLineColor = Color.rgb(102, 102, 102); + private int mNowLineThickness = 5; + private boolean mUseNewColoring = false; private int mHourSeparatorColor = Color.rgb(230, 230, 230); private int mTodayBackgroundColor = Color.rgb(239, 247, 254); private int mHourSeparatorHeight = 2; @@ -238,6 +248,13 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { mHeaderRowPadding = a.getDimensionPixelSize(R.styleable.WeekView_headerRowPadding, mHeaderRowPadding); mHeaderRowBackgroundColor = a.getColor(R.styleable.WeekView_headerRowBackgroundColor, mHeaderRowBackgroundColor); mDayBackgroundColor = a.getColor(R.styleable.WeekView_dayBackgroundColor, mDayBackgroundColor); + mFutureBackgroundColor = a.getColor(R.styleable.WeekView_futureBackgroundColor, mFutureBackgroundColor); + mPastBackgroundColor = a.getColor(R.styleable.WeekView_pastBackgroundColor, mPastBackgroundColor); + mFutureWeekendBackgroundColor = a.getColor(R.styleable.WeekView_futureWeekendBackgroundColor, mFutureBackgroundColor); // If not set, use the same color as in the week + mPastWeekendBackgroundColor = a.getColor(R.styleable.WeekView_pastWeekendBackgroundColor, mPastBackgroundColor); + mNowLineColor = a.getColor(R.styleable.WeekView_nowLineColor, mNowLineColor); + mNowLineThickness = a.getDimensionPixelSize(R.styleable.WeekView_nowLineThickness, mNowLineThickness); + mUseNewColoring = a.getBoolean(R.styleable.WeekView_useNewColoringStyle, mUseNewColoring); mHourSeparatorColor = a.getColor(R.styleable.WeekView_hourSeparatorColor, mHourSeparatorColor); mTodayBackgroundColor = a.getColor(R.styleable.WeekView_todayBackgroundColor, mTodayBackgroundColor); mHourSeparatorHeight = a.getDimensionPixelSize(R.styleable.WeekView_hourSeparatorHeight, mHourSeparatorHeight); @@ -258,12 +275,6 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { } private void init() { - // Get the date today. - mToday = Calendar.getInstance(); - mToday.set(Calendar.HOUR_OF_DAY, 0); - mToday.set(Calendar.MINUTE, 0); - mToday.set(Calendar.SECOND, 0); - // Scrolling initialization. mGestureDetector = new GestureDetectorCompat(mContext, mGestureListener); mScroller = new OverScroller(mContext); @@ -296,6 +307,14 @@ private void init() { // Prepare day background color paint. mDayBackgroundPaint = new Paint(); mDayBackgroundPaint.setColor(mDayBackgroundColor); + mFutureBackgroundPaint = new Paint(); + mFutureBackgroundPaint.setColor(mFutureBackgroundColor); + mPastBackgroundPaint = new Paint(); + mPastBackgroundPaint.setColor(mPastBackgroundColor); + mFutureWeekendBackgroundPaint = new Paint(); + mFutureWeekendBackgroundPaint.setColor(mFutureWeekendBackgroundColor); + mPastWeekendBackgroundPaint = new Paint(); + mPastWeekendBackgroundPaint.setColor(mPastWeekendBackgroundColor); // Prepare hour separator color paint. mHourSeparatorPaint = new Paint(); @@ -303,6 +322,11 @@ private void init() { mHourSeparatorPaint.setStrokeWidth(mHourSeparatorHeight); mHourSeparatorPaint.setColor(mHourSeparatorColor); + // Prepare the "now" line color paint + mNowLinePaint = new Paint(); + mNowLinePaint.setStrokeWidth(mNowLineThickness); + mNowLinePaint.setColor(mNowLineColor); + // Prepare today background color paint. mTodayBackgroundPaint = new Paint(); mTodayBackgroundPaint.setColor(mTodayBackgroundColor); @@ -327,7 +351,6 @@ private void init() { mEventTextPaint.setStyle(Paint.Style.FILL); mEventTextPaint.setColor(mEventTextColor); mEventTextPaint.setTextSize(mEventTextSize); - mStartDate = (Calendar) mToday.clone(); // Set default event color. mDefaultEventColor = Color.parseColor("#9fc6e7"); @@ -378,10 +401,12 @@ private void drawHeaderRowAndEvents(Canvas canvas) { mWidthPerDay = getWidth() - mHeaderColumnWidth - mColumnGap * (mNumberOfVisibleDays - 1); mWidthPerDay = mWidthPerDay/mNumberOfVisibleDays; + Calendar today = today(); + // If the week view is being drawn for the first time, then consider the first day of week. if (mIsFirstDraw && mNumberOfVisibleDays >= 7) { - if (mToday.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) { - int difference = 7 + (mToday.get(Calendar.DAY_OF_WEEK) - mFirstDayOfWeek); + if (today.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) { + int difference = 7 + (today.get(Calendar.DAY_OF_WEEK) - mFirstDayOfWeek); mCurrentOrigin.x += (mWidthPerDay + mColumnGap) * difference; } mIsFirstDraw = false; @@ -395,7 +420,7 @@ private void drawHeaderRowAndEvents(Canvas canvas) { float startPixel = startFromPixel; // Prepare to iterate for each day. - Calendar day = (Calendar) mToday.clone(); + Calendar day = (Calendar) today.clone(); day.add(Calendar.HOUR, 6); // Prepare to iterate for each hour to draw the hour lines. @@ -412,18 +437,18 @@ private void drawHeaderRowAndEvents(Canvas canvas) { } // Iterate through each day. - mFirstVisibleDay = (Calendar) mToday.clone(); + mFirstVisibleDay = (Calendar) today.clone(); mFirstVisibleDay.add(Calendar.DATE, leftDaysWithGaps); for (int dayNumber = leftDaysWithGaps + 1; dayNumber <= leftDaysWithGaps + mNumberOfVisibleDays + 1; dayNumber++) { // Check if the day is today. - day = (Calendar) mToday.clone(); + day = (Calendar) today.clone(); mLastVisibleDay = (Calendar) day.clone(); day.add(Calendar.DATE, dayNumber - 1); mLastVisibleDay.add(Calendar.DATE, dayNumber - 2); - boolean sameDay = isSameDay(day, mToday); + boolean sameDay = isSameDay(day, today); // Get more events if necessary. We want to store the events 3 months beforehand. Get // events only when it is the first iteration of the loop. @@ -434,8 +459,27 @@ private void drawHeaderRowAndEvents(Canvas canvas) { // Draw background color for each day. float start = (startPixel < mHeaderColumnWidth ? mHeaderColumnWidth : startPixel); - if (mWidthPerDay + startPixel - start> 0) - canvas.drawRect(start, mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom, startPixel + mWidthPerDay, getHeight(), sameDay ? mTodayBackgroundPaint : mDayBackgroundPaint); + if (mWidthPerDay + startPixel - start> 0){ + if(mUseNewColoring){ + boolean isWeekend = (day.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || day.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY); + Paint pastPaint = isWeekend ? mPastWeekendBackgroundPaint : mPastBackgroundPaint; + Paint futurePaint = isWeekend ? mFutureWeekendBackgroundPaint : mFutureBackgroundPaint; + float startY = mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom + mCurrentOrigin.y; + + if(sameDay){ + Calendar now = Calendar.getInstance(); + float beforeNow = (now.get(Calendar.HOUR_OF_DAY)+now.get(Calendar.MINUTE)/60.0f)*mHourHeight; + canvas.drawRect(start, startY, startPixel + mWidthPerDay, startY+beforeNow, pastPaint); + canvas.drawRect(start, startY+beforeNow, startPixel + mWidthPerDay, getHeight(), futurePaint); + } else if(day.before(today)) { + canvas.drawRect(start, startY, startPixel + mWidthPerDay, getHeight(), pastPaint); + } else { + canvas.drawRect(start, startY, startPixel + mWidthPerDay, getHeight(), futurePaint); + } + }else{ + canvas.drawRect(start, mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom, startPixel + mWidthPerDay, getHeight(), sameDay ? mTodayBackgroundPaint : mDayBackgroundPaint); + } + } // Prepare the separator lines for hours. int i = 0; @@ -456,6 +500,14 @@ private void drawHeaderRowAndEvents(Canvas canvas) { // Draw the events. drawEvents(day, startPixel, canvas); + //Draw the line at the current time + if(mUseNewColoring && sameDay){ + float startY = mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom + mCurrentOrigin.y; + Calendar now = Calendar.getInstance(); + float beforeNow = (now.get(Calendar.HOUR_OF_DAY)+now.get(Calendar.MINUTE)/60.0f)*mHourHeight; + canvas.drawLine(start, startY+beforeNow, startPixel + mWidthPerDay, startY+beforeNow, mNowLinePaint); + } + // In the next iteration, start from the next day. startPixel += mWidthPerDay + mColumnGap; } @@ -467,9 +519,9 @@ private void drawHeaderRowAndEvents(Canvas canvas) { startPixel = startFromPixel; for (int dayNumber=leftDaysWithGaps+1; dayNumber <= leftDaysWithGaps + mNumberOfVisibleDays + 1; dayNumber++) { // Check if the day is today. - day = (Calendar) mToday.clone(); + day = (Calendar) today.clone(); day.add(Calendar.DATE, dayNumber - 1); - boolean sameDay = isSameDay(day, mToday); + boolean sameDay = isSameDay(day, today); // Draw the day labels. String dayLabel = getDateTimeInterpreter().interpretDate(day); @@ -497,7 +549,7 @@ private Calendar getTimeFromPoint(float x, float y){ float start = (startPixel < mHeaderColumnWidth ? mHeaderColumnWidth : startPixel); if (mWidthPerDay + startPixel - start> 0 && x>start && x + + + + + + + From c36b8a851d2cf844bddfaddcbc745f9925616090 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Thu, 15 Jan 2015 16:16:09 +0100 Subject: [PATCH 05/39] Fixes to goToHour and goToDate(). Allow goToDate to be called before the weekview is drawn for the first time. goToDate relies on mWidthPerDay, which itself relies on View#getWidth() which can't be called during initialisation. Therefore the goToDate variable is cached until the first time the weekview is drawn. Fixes #45: 1. Date is cloned before use (in goToDate) 2. goToHour doesn't throw errors anymore Fixes #55: goToDate now uses an animation Fixes #65: If a dimension is altered and is followed by a goToDate or goToHour, then the hour or date to go to, is cached. --- .../java/com/alamkanak/weekview/WeekView.java | 49 ++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..9d8baa073 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -94,12 +94,15 @@ public class WeekView extends View { private int mHeaderColumnBackgroundColor = Color.WHITE; private int mDefaultEventColor; private boolean mIsFirstDraw = true; + private boolean mAreDimensionsInvalid = true; @Deprecated private int mDayNameLength = LENGTH_LONG; private int mOverlappingEventGap = 0; private int mEventMarginVertical = 0; private float mXScrollingSpeed = 1f; private Calendar mFirstVisibleDay; private Calendar mLastVisibleDay; + private Calendar mScrollToDay = null; + private double mScrollToHour = -1; // Listeners. private EventClickListener mEventClickListener; @@ -378,13 +381,22 @@ private void drawHeaderRowAndEvents(Canvas canvas) { mWidthPerDay = getWidth() - mHeaderColumnWidth - mColumnGap * (mNumberOfVisibleDays - 1); mWidthPerDay = mWidthPerDay/mNumberOfVisibleDays; - // If the week view is being drawn for the first time, then consider the first day of week. - if (mIsFirstDraw && mNumberOfVisibleDays >= 7) { - if (mToday.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) { + if (mAreDimensionsInvalid) { + mAreDimensionsInvalid = false; + + if(mScrollToDay != null) + goToDate(mScrollToDay); + if(mScrollToHour >= 0) + goToHour(mScrollToHour); + } + if (mIsFirstDraw){ + mIsFirstDraw = false; + + // If the week view is being drawn for the first time, then consider the first day of the week. + if(mNumberOfVisibleDays >= 7 && mToday.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) { int difference = 7 + (mToday.get(Calendar.DAY_OF_WEEK) - mFirstDayOfWeek); mCurrentOrigin.x += (mWidthPerDay + mColumnGap) * difference; } - mIsFirstDraw = false; } // Consider scroll offset. @@ -904,6 +916,13 @@ private void deleteFarMonths(Calendar currentDay) { mEventRects.addAll(newEvents); } + @Override + public void invalidate() { + super.invalidate(); + mAreDimensionsInvalid = true; + mScrollToDay = null; + mScrollToHour = -1; + } ///////////////////////////////////////////////////////////////// // @@ -1351,6 +1370,11 @@ public void goToDate(Calendar date) { date.set(Calendar.SECOND, 0); date.set(Calendar.MILLISECOND, 0); + if(mAreDimensionsInvalid) { + mScrollToDay = date; + return; + } + mRefreshEvents = true; Calendar today = Calendar.getInstance(); @@ -1360,8 +1384,7 @@ public void goToDate(Calendar date) { today.set(Calendar.MILLISECOND, 0); int dateDifference = (int) ((date.getTimeInMillis() - today.getTimeInMillis()) / (1000 * 60 * 60 * 24)); - mCurrentOrigin.x = - dateDifference * (mWidthPerDay + mColumnGap); - + mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, (int) (-dateDifference*(mWidthPerDay + mColumnGap)-mCurrentOrigin.x), 0); invalidate(); } @@ -1378,14 +1401,18 @@ public void notifyDatasetChanged(){ * @param hour The hour to scroll to in 24-hour format. Supported values are 0-24. */ public void goToHour(double hour){ + int verticalOffset = (int) (mHourHeight * hour); if (hour < 0) - throw new IllegalArgumentException("Cannot scroll to an hour of negative value."); + verticalOffset = 0; else if (hour > 24) - throw new IllegalArgumentException("Cannot scroll to an hour of value greater than 24."); - else if (hour * mHourHeight > mHourHeight * 24 - getHeight() + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom) - throw new IllegalArgumentException("Cannot scroll to an hour which will result the calendar to go off the screen."); + verticalOffset = mHourHeight * 24; + + if (mAreDimensionsInvalid) { + mScrollToHour = hour; + return; + } else if (verticalOffset > mHourHeight * 24 - getHeight() + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom) + verticalOffset = (int)(mHourHeight * 24 - getHeight() + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom); - int verticalOffset = (int) (mHourHeight * hour); mCurrentOrigin.y = -verticalOffset; invalidate(); } From 3219991a94428f1d79d28d3253274c659caf5840 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Wed, 4 Feb 2015 21:14:24 +0100 Subject: [PATCH 06/39] Possible fix voor #54 I fixed an issue with going to the next day. It doesn't seem to be related to getFirstVisibleDay but to goToDate. Not sure if it fixes the original issue. --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..ead516013 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1359,7 +1359,8 @@ public void goToDate(Calendar date) { today.set(Calendar.SECOND, 0); today.set(Calendar.MILLISECOND, 0); - int dateDifference = (int) ((date.getTimeInMillis() - today.getTimeInMillis()) / (1000 * 60 * 60 * 24)); + long day = 1000L * 60L * 60L * 24L; + long dateDifference = (date.getTimeInMillis()/day) - (today.getTimeInMillis()/day); mCurrentOrigin.x = - dateDifference * (mWidthPerDay + mColumnGap); invalidate(); From 6621e8365436fb4c7833fc812d83c1b21a5f674b Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sun, 8 Feb 2015 23:08:19 +0100 Subject: [PATCH 07/39] Vertical zoom on weekview. Fixes #8 Based on code from @sylvaindd. The min and maxHourHeight are configurable via attributes. --- .../java/com/alamkanak/weekview/WeekView.java | 92 +++++++++++++++---- library/src/main/res/values/attrs.xml | 2 + 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 34dfdb907..ad0199508 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -22,6 +22,7 @@ import android.view.GestureDetector; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; +import android.view.ScaleGestureDetector; import android.view.SoundEffectConstants; import android.view.View; import android.widget.OverScroller; @@ -80,6 +81,10 @@ public class WeekView extends View { // Attributes and their default values. private int mHourHeight = 50; + private int mNewHourHeight = -1; + private int mMinHourHeight = 0; //no minimum specified (will be dynamic, based on screen) + private int mEffectiveMinHourHeight = mMinHourHeight; //compensates for the fact that you can't keep zooming out. + private int mMaxHourHeight = 250; private int mColumnGap = 10; private int mFirstDayOfWeek = Calendar.MONDAY; private int mTextSize = 12; @@ -115,6 +120,8 @@ public class WeekView extends View { private Calendar mLastVisibleDay; private Calendar mScrollToDay = null; private double mScrollToHour = -1; + private ScaleGestureDetector mScaleDetector; + private boolean mIsZooming; // Listeners. private EventClickListener mEventClickListener; @@ -136,6 +143,8 @@ public boolean onDown(MotionEvent e) { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if(mIsZooming) + return true; if (mCurrentScrollDirection == Direction.NONE) { if (Math.abs(distanceX) > Math.abs(distanceY)){ mCurrentScrollDirection = Direction.HORIZONTAL; @@ -245,6 +254,9 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { try { mFirstDayOfWeek = a.getInteger(R.styleable.WeekView_firstDayOfWeek, mFirstDayOfWeek); mHourHeight = a.getDimensionPixelSize(R.styleable.WeekView_hourHeight, mHourHeight); + mMinHourHeight = a.getDimensionPixelSize(R.styleable.WeekView_minHourHeight, mMinHourHeight); + mEffectiveMinHourHeight = mMinHourHeight; + mMaxHourHeight = a.getDimensionPixelSize(R.styleable.WeekView_maxHourHeight, mMaxHourHeight); mTextSize = a.getDimensionPixelSize(R.styleable.WeekView_textSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mTextSize, context.getResources().getDisplayMetrics())); mHeaderColumnPadding = a.getDimensionPixelSize(R.styleable.WeekView_headerColumnPadding, mHeaderColumnPadding); mColumnGap = a.getDimensionPixelSize(R.styleable.WeekView_columnGap, mColumnGap); @@ -359,6 +371,33 @@ private void init() { // Set default event color. mDefaultEventColor = Color.parseColor("#9fc6e7"); + + mScaleDetector = new ScaleGestureDetector(mContext, new ScaleGestureDetector.OnScaleGestureListener() { + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + mIsZooming = false; + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + mIsZooming = true; + mScroller.forceFinished(true); + mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; + goToNearestOrigin(); + return true; + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + mNewHourHeight = Math.round(mHourHeight * detector.getScaleFactor()); + if(mNewHourHeight < mEffectiveMinHourHeight) + mNewHourHeight = mEffectiveMinHourHeight; + else if(mNewHourHeight > mMaxHourHeight) + mNewHourHeight = mMaxHourHeight; + invalidate(); + return true; + } + }); } /** @@ -387,13 +426,6 @@ protected void onDraw(Canvas canvas) { } private void drawTimeColumnAndAxes(Canvas canvas) { - // Do not let the view go above/below the limit due to scrolling. Set the max and min limit of the scroll. - if (mCurrentScrollDirection == Direction.VERTICAL) { - if (mCurrentOrigin.y - mDistanceY > 0) mCurrentOrigin.y = 0; - else if (mCurrentOrigin.y - mDistanceY < -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 - getHeight())) mCurrentOrigin.y = -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 - getHeight()); - else mCurrentOrigin.y -= mDistanceY; - } - // Draw the background color for the header column. canvas.drawRect(0, mHeaderTextHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, getHeight(), mHeaderColumnBackgroundPaint); @@ -418,6 +450,7 @@ private void drawHeaderRowAndEvents(Canvas canvas) { if (mAreDimensionsInvalid) { mAreDimensionsInvalid = false; + mEffectiveMinHourHeight= Math.max(mMinHourHeight, (int) ((getHeight() - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) / 24)); if(mScrollToDay != null) goToDate(mScrollToDay); @@ -434,6 +467,25 @@ private void drawHeaderRowAndEvents(Canvas canvas) { } } + // Do not let the view go above/below the limit due to scrolling. Set the max and min limit of the scroll. + if (mCurrentScrollDirection == Direction.VERTICAL) + mCurrentOrigin.y -= mDistanceY; + + + //Calculate the new height due to the zooming. + if (mNewHourHeight > 0){ + mCurrentOrigin.y = (mCurrentOrigin.y/mHourHeight)*mNewHourHeight; + mHourHeight = mNewHourHeight; + mNewHourHeight = -1; + } + + //if the new mCurrentOrigin.y is invalid, make it valid. + if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) + mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom; + //Don't put an else if because it will trigger a glitch when completly zoomed out and scrolling vertically. + if(mCurrentOrigin.y > 0) + mCurrentOrigin.y = 0; + // Consider scroll offset. if (mCurrentScrollDirection == Direction.HORIZONTAL) mCurrentOrigin.x -= mDistanceX; int leftDaysWithGaps = (int) -(Math.ceil(mCurrentOrigin.x / (mWidthPerDay + mColumnGap))); @@ -1389,23 +1441,29 @@ public void setXScrollingSpeed(float xScrollingSpeed) { @Override public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP) { - + if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming) { if (mCurrentScrollDirection == Direction.HORIZONTAL) { - float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)); - if(mDistanceX > 0) - leftDays--; - else - leftDays++; - int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap)); - mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0); - ViewCompat.postInvalidateOnAnimation(WeekView.this); + goToNearestOrigin(); } mCurrentScrollDirection = Direction.NONE; } + mScaleDetector.onTouchEvent(event); return mGestureDetector.onTouchEvent(event); } + private void goToNearestOrigin(){ + float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)); + if(!mIsZooming){ + if(mDistanceX > 0) + leftDays--; + else + leftDays++; + } + int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap)); + mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0); + ViewCompat.postInvalidateOnAnimation(WeekView.this); + } + @Override public void computeScroll() { diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 6f77350ad..5ae26b19c 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -11,6 +11,8 @@ + + From e56c1f4783b088e18f2b3d83c537528d555882fe Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sat, 21 Feb 2015 15:57:04 +0100 Subject: [PATCH 08/39] Dynamic prefetch range. --- .../com/alamkanak/weekview/MonthLoader.java | 31 ++++ .../java/com/alamkanak/weekview/WeekView.java | 147 ++++++++---------- .../alamkanak/weekview/WeekViewLoader.java | 23 +++ 3 files changed, 123 insertions(+), 78 deletions(-) create mode 100644 library/src/main/java/com/alamkanak/weekview/MonthLoader.java create mode 100644 library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java diff --git a/library/src/main/java/com/alamkanak/weekview/MonthLoader.java b/library/src/main/java/com/alamkanak/weekview/MonthLoader.java new file mode 100644 index 000000000..c77c76e3a --- /dev/null +++ b/library/src/main/java/com/alamkanak/weekview/MonthLoader.java @@ -0,0 +1,31 @@ +package com.alamkanak.weekview; + +import java.util.Calendar; +import java.util.List; + +public class MonthLoader implements WeekViewLoader { + + private WeekView.MonthChangeListener mOnMonthChangeListener; + public MonthLoader(WeekView.MonthChangeListener listener){ + this.mOnMonthChangeListener = listener; + } + + @Override + public double toWeekViewPeriodIndex(Calendar instance){ + return instance.get(Calendar.YEAR)*12 + instance.get(Calendar.MONTH) + (instance.get(Calendar.DAY_OF_MONTH)-1)/30.0; + } + + @Override + public List onLoad(int periodIndex){ + return mOnMonthChangeListener.onMonthChange(periodIndex/12,periodIndex%12+1); + } + + + public WeekView.MonthChangeListener getOnMonthChangeListener() { + return mOnMonthChangeListener; + } + + public void setOnMonthChangeListener(WeekView.MonthChangeListener onMonthChangeListener) { + this.mOnMonthChangeListener = onMonthChangeListener; + } +} diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5e039d60b..e49b08a80 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -64,10 +64,13 @@ public class WeekView extends View { private Paint mEventBackgroundPaint; private float mHeaderColumnWidth; private List mEventRects; + private List mPreviousPeriodEvents; + private List mCurrentPeriodEvents; + private List mNextPeriodEvents; private TextPaint mEventTextPaint; private Paint mHeaderColumnBackgroundPaint; private Scroller mStickyScroller; - private int mFetchedMonths[] = new int[3]; + private int mFetchedPeriod = -1; // the middle period the calendar has fetched. private boolean mRefreshEvents = false; private float mDistanceY = 0; private float mDistanceX = 0; @@ -104,7 +107,7 @@ public class WeekView extends View { // Listeners. private EventClickListener mEventClickListener; private EventLongPressListener mEventLongPressListener; - private MonthChangeListener mMonthChangeListener; + private WeekViewLoader mWeekViewLoader; private EmptyViewClickListener mEmptyViewClickListener; private EmptyViewLongPressListener mEmptyViewLongPressListener; private DateTimeInterpreter mDateTimeInterpreter; @@ -427,7 +430,9 @@ private void drawHeaderRowAndEvents(Canvas canvas) { // Get more events if necessary. We want to store the events 3 months beforehand. Get // events only when it is the first iteration of the loop. - if (mEventRects == null || mRefreshEvents || (dayNumber == leftDaysWithGaps + 1 && mFetchedMonths[1] != day.get(Calendar.MONTH)+1 && day.get(Calendar.DAY_OF_MONTH) == 15)) { + if (mEventRects == null || mRefreshEvents || + (dayNumber == leftDaysWithGaps + 1 && mFetchedPeriod != (int) mWeekViewLoader.toWeekViewPeriodIndex(day) && + Math.abs(mFetchedPeriod - mWeekViewLoader.toWeekViewPeriodIndex(day)) > 0.5)) { getMoreEvents(day); mRefreshEvents = false; } @@ -644,59 +649,60 @@ public EventRect(WeekViewEvent event, WeekViewEvent originalEvent, RectF rectF) * @param day The day where the user is currently is. */ private void getMoreEvents(Calendar day) { - - // Delete all events if its not current month +- 1. - deleteFarMonths(day); - // Get more events if the month is changed. if (mEventRects == null) mEventRects = new ArrayList(); - if (mMonthChangeListener == null && !isInEditMode()) + if (mWeekViewLoader == null && !isInEditMode()) throw new IllegalStateException("You must provide a MonthChangeListener"); // If a refresh was requested then reset some variables. if (mRefreshEvents) { mEventRects.clear(); - mFetchedMonths = new int[3]; + mPreviousPeriodEvents = null; + mCurrentPeriodEvents = null; + mNextPeriodEvents = null; + mFetchedPeriod = -1; } - // Get events of previous month. - int previousMonth = (day.get(Calendar.MONTH) == 0?12:day.get(Calendar.MONTH)); - int nextMonth = (day.get(Calendar.MONTH)+2 == 13 ?1:day.get(Calendar.MONTH)+2); - int[] lastFetchedMonth = mFetchedMonths.clone(); - if (mFetchedMonths[0] < 1 || mFetchedMonths[0] != previousMonth || mRefreshEvents) { - if (!containsValue(lastFetchedMonth, previousMonth) && !isInEditMode()){ - List events = mMonthChangeListener.onMonthChange((previousMonth==12)?day.get(Calendar.YEAR)-1:day.get(Calendar.YEAR), previousMonth); - sortEvents(events); - for (WeekViewEvent event: events) { - cacheEvent(event); - } - } - mFetchedMonths[0] = previousMonth; - } - - // Get events of this month. - if (mFetchedMonths[1] < 1 || mFetchedMonths[1] != day.get(Calendar.MONTH)+1 || mRefreshEvents) { - if (!containsValue(lastFetchedMonth, day.get(Calendar.MONTH)+1) && !isInEditMode()) { - List events = mMonthChangeListener.onMonthChange(day.get(Calendar.YEAR), day.get(Calendar.MONTH) + 1); - sortEvents(events); - for (WeekViewEvent event : events) { - cacheEvent(event); - } - } - mFetchedMonths[1] = day.get(Calendar.MONTH)+1; - } - - // Get events of next month. - if (mFetchedMonths[2] < 1 || mFetchedMonths[2] != nextMonth || mRefreshEvents) { - if (!containsValue(lastFetchedMonth, nextMonth) && !isInEditMode()) { - List events = mMonthChangeListener.onMonthChange(nextMonth == 1 ? day.get(Calendar.YEAR) + 1 : day.get(Calendar.YEAR), nextMonth); - sortEvents(events); - for (WeekViewEvent event : events) { - cacheEvent(event); + if(mWeekViewLoader != null){ + int periodToFetch = (int) mWeekViewLoader.toWeekViewPeriodIndex(day); + if (!isInEditMode() && (mFetchedPeriod < 0 || mFetchedPeriod != periodToFetch || mRefreshEvents)) { + List previousPeriodEvents = null; + List currentPeriodEvents = null; + List nextPeriodEvents = null; + + if(mPreviousPeriodEvents != null && mCurrentPeriodEvents != null && mNextPeriodEvents != null){ + if(periodToFetch == mFetchedPeriod-1){ + currentPeriodEvents = mPreviousPeriodEvents; + nextPeriodEvents = mCurrentPeriodEvents; + }else if(periodToFetch == mFetchedPeriod){ + previousPeriodEvents = mPreviousPeriodEvents; + currentPeriodEvents = mCurrentPeriodEvents; + nextPeriodEvents = mNextPeriodEvents; + }else if(periodToFetch == mFetchedPeriod+1){ + previousPeriodEvents = mCurrentPeriodEvents; + currentPeriodEvents = mNextPeriodEvents; + } } + if(currentPeriodEvents == null) + currentPeriodEvents = mWeekViewLoader.onLoad(periodToFetch); + if(previousPeriodEvents == null) + previousPeriodEvents = mWeekViewLoader.onLoad(periodToFetch-1); + if(nextPeriodEvents == null) + nextPeriodEvents = mWeekViewLoader.onLoad(periodToFetch+1); + + + //clear events + mEventRects.clear(); + sortAndCacheEvents(previousPeriodEvents); + sortAndCacheEvents(currentPeriodEvents); + sortAndCacheEvents(nextPeriodEvents); + + mPreviousPeriodEvents = previousPeriodEvents; + mCurrentPeriodEvents = currentPeriodEvents; + mNextPeriodEvents = nextPeriodEvents; + mFetchedPeriod = periodToFetch; } - mFetchedMonths[2] = nextMonth; } // Prepare to calculate positions of each events. @@ -745,6 +751,13 @@ private void cacheEvent(WeekViewEvent event) { mEventRects.add(new EventRect(event, event, null)); } + private void sortAndCacheEvents(List events){ + sortEvents(events); + for(WeekViewEvent event : events){ + cacheEvent(event); + } + } + /** * Sorts the events in ascending order. * @param events The events to be sorted. @@ -873,38 +886,6 @@ private boolean isTimeAfterOrEquals(Calendar time1, Calendar time2) { return !(time1 == null || time2 == null) && time1.getTimeInMillis() >= time2.getTimeInMillis(); } - /** - * Deletes the events of the months that are too far away from the current month. - * @param currentDay The current day. - */ - private void deleteFarMonths(Calendar currentDay) { - - if (mEventRects == null) return; - - Calendar nextMonth = (Calendar) currentDay.clone(); - nextMonth.add(Calendar.MONTH, 1); - nextMonth.set(Calendar.DAY_OF_MONTH, nextMonth.getActualMaximum(Calendar.DAY_OF_MONTH)); - nextMonth.set(Calendar.HOUR_OF_DAY, 12); - nextMonth.set(Calendar.MINUTE, 59); - nextMonth.set(Calendar.SECOND, 59); - - Calendar prevMonth = (Calendar) currentDay.clone(); - prevMonth.add(Calendar.MONTH, -1); - prevMonth.set(Calendar.DAY_OF_MONTH, 1); - prevMonth.set(Calendar.HOUR_OF_DAY, 0); - prevMonth.set(Calendar.MINUTE, 0); - prevMonth.set(Calendar.SECOND, 0); - - List newEvents = new ArrayList(); - for (EventRect eventRect : mEventRects) { - boolean isFarMonth = eventRect.event.getStartTime().getTimeInMillis() > nextMonth.getTimeInMillis() || eventRect.event.getEndTime().getTimeInMillis() < prevMonth.getTimeInMillis(); - if (!isFarMonth) newEvents.add(eventRect); - } - mEventRects.clear(); - mEventRects.addAll(newEvents); - } - - ///////////////////////////////////////////////////////////////// // // Functions related to setting and getting the properties. @@ -920,11 +901,21 @@ public EventClickListener getEventClickListener() { } public MonthChangeListener getMonthChangeListener() { - return mMonthChangeListener; + if(mWeekViewLoader instanceof MonthLoader) + return ((MonthLoader) mWeekViewLoader).getOnMonthChangeListener(); + return null; } public void setMonthChangeListener(MonthChangeListener monthChangeListener) { - this.mMonthChangeListener = monthChangeListener; + this.mWeekViewLoader = new MonthLoader(monthChangeListener); + } + + public WeekViewLoader getWeekViewLoader(){ + return mWeekViewLoader; + } + + public void setWeekViewLoader(WeekViewLoader loader){ + this.mWeekViewLoader = loader; } public EventLongPressListener getEventLongPressListener() { diff --git a/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java b/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java new file mode 100644 index 000000000..c6c4b4b27 --- /dev/null +++ b/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java @@ -0,0 +1,23 @@ +package com.alamkanak.weekview; + +import java.util.Calendar; +import java.util.List; + +public interface WeekViewLoader { + /** + * Convert a date into a double that will be used to reference when you're loading data. + * + * All periods that have the same integer part, define one period. Dates that are later in time should have a greater return value. + * + * @param instance the date + * @return The period index in which the date falls (floating point number). + */ + public double toWeekViewPeriodIndex(Calendar instance); + + /** + * Load the events within the period + * @param periodIndex the period to load + * @return A list with the events of this period + */ + public List onLoad(int periodIndex); +} From 2f428cb5bafaf0d84c5c6ac9fb27ac54162e98e4 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sat, 28 Feb 2015 20:10:25 +0100 Subject: [PATCH 09/39] Small improvement --- .../main/java/com/alamkanak/weekview/WeekView.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index ad0199508..0b1aace79 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -390,10 +390,6 @@ public boolean onScaleBegin(ScaleGestureDetector detector) { @Override public boolean onScale(ScaleGestureDetector detector) { mNewHourHeight = Math.round(mHourHeight * detector.getScaleFactor()); - if(mNewHourHeight < mEffectiveMinHourHeight) - mNewHourHeight = mEffectiveMinHourHeight; - else if(mNewHourHeight > mMaxHourHeight) - mNewHourHeight = mMaxHourHeight; invalidate(); return true; } @@ -474,6 +470,11 @@ private void drawHeaderRowAndEvents(Canvas canvas) { //Calculate the new height due to the zooming. if (mNewHourHeight > 0){ + if(mNewHourHeight < mEffectiveMinHourHeight) + mNewHourHeight = mEffectiveMinHourHeight; + else if(mNewHourHeight > mMaxHourHeight) + mNewHourHeight = mMaxHourHeight; + mCurrentOrigin.y = (mCurrentOrigin.y/mHourHeight)*mNewHourHeight; mHourHeight = mNewHourHeight; mNewHourHeight = -1; @@ -1175,7 +1176,7 @@ public int getHourHeight() { } public void setHourHeight(int hourHeight) { - mHourHeight = hourHeight; + mNewHourHeight = hourHeight; invalidate(); } From 9461d55fe06822ab3fd4b818a58abedbba3b5670 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sat, 28 Feb 2015 21:21:31 +0100 Subject: [PATCH 10/39] finally fixed #54 (hopefully) --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index ead516013..6d11de255 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -413,7 +413,7 @@ private void drawHeaderRowAndEvents(Canvas canvas) { // Iterate through each day. mFirstVisibleDay = (Calendar) mToday.clone(); - mFirstVisibleDay.add(Calendar.DATE, leftDaysWithGaps); + mFirstVisibleDay.add(Calendar.DATE, -(Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)))); for (int dayNumber = leftDaysWithGaps + 1; dayNumber <= leftDaysWithGaps + mNumberOfVisibleDays + 1; dayNumber++) { From 94230c57155ae4f5f249b0c755c2107b7093c48f Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sat, 11 Apr 2015 17:04:35 +0200 Subject: [PATCH 11/39] =?UTF-8?q?PR=20#105=20re=C3=AFmplemented=20on=20cur?= =?UTF-8?q?rent=20code.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 8a940c0f0..3a1d9917a 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1529,7 +1529,9 @@ public void goToDate(Calendar date) { today.set(Calendar.MILLISECOND, 0); long day = 1000L * 60L * 60L * 24L; - long dateDifference = (date.getTimeInMillis()/day) - (today.getTimeInMillis()/day); + long dateInMillis = date.getTimeInMillis() + date.getTimeZone().getOffset(date.getTimeInMillis()); + long todayInMillis = today.getTimeInMillis() + today.getTimeZone().getOffset(today.getTimeInMillis()); + long dateDifference = (dateInMillis/day) - (todayInMillis/day); mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, (int) (-dateDifference*(mWidthPerDay + mColumnGap)-mCurrentOrigin.x), 0); invalidate(); } From 7341ef34ae889ed5ea94c7c1a6a19430d78da890 Mon Sep 17 00:00:00 2001 From: marunjar Date: Tue, 2 Jun 2015 10:39:10 +0200 Subject: [PATCH 12/39] change goToHour shuffle code a little bit: return immediately if mAreDimensionsInvalid calculate verticalOffset only if necessary --- .../java/com/alamkanak/weekview/WeekView.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 486b41df5..b3d571c04 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1420,16 +1420,18 @@ public void notifyDatasetChanged(){ * @param hour The hour to scroll to in 24-hour format. Supported values are 0-24. */ public void goToHour(double hour){ - int verticalOffset = (int) (mHourHeight * hour); - if (hour < 0) - verticalOffset = 0; - else if (hour > 24) - verticalOffset = mHourHeight * 24; - if (mAreDimensionsInvalid) { mScrollToHour = hour; return; - } else if (verticalOffset > mHourHeight * 24 - getHeight() + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom) + } + + int verticalOffset = 0; + if (hour > 24) + verticalOffset = mHourHeight * 24; + else if (hour > 0) + verticalOffset = (int) (mHourHeight * hour); + + if (verticalOffset > mHourHeight * 24 - getHeight() + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom) verticalOffset = (int)(mHourHeight * 24 - getHeight() + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom); mCurrentOrigin.y = -verticalOffset; From 354bb2357f8bdac3f42bbe0c30796bfff10477ea Mon Sep 17 00:00:00 2001 From: Laurent Meyer Date: Tue, 16 Jun 2015 11:53:52 +0200 Subject: [PATCH 13/39] Documented the interfaces --- .../java/com/alamkanak/weekview/WeekView.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5a9281b32..ee8e906ea 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1457,22 +1457,46 @@ public double getFirstVisibleHour(){ ///////////////////////////////////////////////////////////////// public interface EventClickListener { + /** + * Triggered when clicked on one existing event + * @param event: event clicked. + * @param eventRect: view containing the clicked event. + */ public void onEventClick(WeekViewEvent event, RectF eventRect); } public interface MonthChangeListener { + /** + * Very important interface, it's the base to load events in the calendar. + * @param newYear: year of the events required by the view. + * @param newMonth: month of the events required by the view. + * @return a list of the events happening during the specified month. + */ public List onMonthChange(int newYear, int newMonth); } public interface EventLongPressListener { + /** + * Similar to #EventClickListener but with a long press. + * @param event: event clicked. + * @param eventRect: view containing the clicked event. + */ public void onEventLongPress(WeekViewEvent event, RectF eventRect); } public interface EmptyViewClickListener { + /** + * Triggered when the users clicks on a empty space of the calendar. + * @param time: #Calendar object set with the date and time of the clicked position on the view. + */ public void onEmptyViewClicked(Calendar time); } public interface EmptyViewLongPressListener { + /** + * Similar to EmptyViewClickListener but with long press. + * @param time: #Calendar object set with the date and time of the long pressed position on the view. + */ public void onEmptyViewLongPress(Calendar time); } From 0e422b54088eb4e69b86d5dfc8298edfe05628ec Mon Sep 17 00:00:00 2001 From: Laurent Meyer Date: Tue, 16 Jun 2015 12:19:46 +0200 Subject: [PATCH 14/39] Corrected mistakes on links --- .../src/main/java/com/alamkanak/weekview/WeekView.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index ee8e906ea..d03a7f1e6 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1477,7 +1477,7 @@ public interface MonthChangeListener { public interface EventLongPressListener { /** - * Similar to #EventClickListener but with a long press. + * Similar to {@link com.alamkanak.weekview.WeekView.EventClickListener} but with a long press. * @param event: event clicked. * @param eventRect: view containing the clicked event. */ @@ -1487,15 +1487,15 @@ public interface EventLongPressListener { public interface EmptyViewClickListener { /** * Triggered when the users clicks on a empty space of the calendar. - * @param time: #Calendar object set with the date and time of the clicked position on the view. + * @param time: {@link Calendar} object set with the date and time of the clicked position on the view. */ public void onEmptyViewClicked(Calendar time); } public interface EmptyViewLongPressListener { /** - * Similar to EmptyViewClickListener but with long press. - * @param time: #Calendar object set with the date and time of the long pressed position on the view. + * Similar to {@link com.alamkanak.weekview.WeekView.EmptyViewClickListener} but with long press. + * @param time: {@link Calendar} object set with the date and time of the long pressed position on the view. */ public void onEmptyViewLongPress(Calendar time); } From f8a541a821283077398d095c3e49e419f1af3dbf Mon Sep 17 00:00:00 2001 From: Laurent Meyer Date: Tue, 16 Jun 2015 13:22:06 +0200 Subject: [PATCH 15/39] Corrected the docs following @caske33 advices --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index d03a7f1e6..b3e7b28dd 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1468,8 +1468,10 @@ public interface EventClickListener { public interface MonthChangeListener { /** * Very important interface, it's the base to load events in the calendar. + * This method is called three times: once to load the previous month, once to load the next month and once to load the current month. + * That's why you can have three times the same event at the same place if you mess up with the configuration * @param newYear: year of the events required by the view. - * @param newMonth: month of the events required by the view. + * @param newMonth: month of the events required by the view 1 based (not like JAVA API) --> January = 1 and December = 12. * @return a list of the events happening during the specified month. */ public List onMonthChange(int newYear, int newMonth); From 32726eccabcc1a784ba87447eeeed8142fc5ea52 Mon Sep 17 00:00:00 2001 From: Laurent Meyer Date: Tue, 16 Jun 2015 13:24:01 +0200 Subject: [PATCH 16/39] Changed tiny things --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index b3e7b28dd..4354917f4 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1468,10 +1468,10 @@ public interface EventClickListener { public interface MonthChangeListener { /** * Very important interface, it's the base to load events in the calendar. - * This method is called three times: once to load the previous month, once to load the next month and once to load the current month. + * This method is called three times: once to load the previous month, once to load the next month and once to load the current month.
* That's why you can have three times the same event at the same place if you mess up with the configuration * @param newYear: year of the events required by the view. - * @param newMonth: month of the events required by the view 1 based (not like JAVA API) --> January = 1 and December = 12. + * @param newMonth: month of the events required by the view
1 based (not like JAVA API) --> January = 1 and December = 12. * @return a list of the events happening during the specified month. */ public List onMonthChange(int newYear, int newMonth); From 9a83618103134978dd48ce6a81f2162b1cca2dc2 Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 10 Oct 2015 20:14:21 +0200 Subject: [PATCH 17/39] fix compile error mScrollListener vs. mScrolledListener --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 593febb4c..030339cac 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -524,8 +524,8 @@ else if(mNewHourHeight > mMaxHourHeight) Calendar oldFirstVisibleDay = mFirstVisibleDay; mFirstVisibleDay = (Calendar) today.clone(); mFirstVisibleDay.add(Calendar.DATE, -(Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)))); - if(!mFirstVisibleDay.equals(oldFirstVisibleDay) && mScrolledListener != null){ - mScrolledListener.onFirstVisibleDayChanged(mFirstVisibleDay, oldFirstVisibleDay); + if(!mFirstVisibleDay.equals(oldFirstVisibleDay) && mScrollListener != null){ + mScrollListener.onFirstVisibleDayChanged(mFirstVisibleDay, oldFirstVisibleDay); } for (int dayNumber = leftDaysWithGaps + 1; dayNumber <= leftDaysWithGaps + mNumberOfVisibleDays + 1; From 5dd30d75f6e18fd2dee4bbf69a325f4b1f8ed372 Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 10 Oct 2015 20:22:00 +0200 Subject: [PATCH 18/39] fix cacheEvent cacheEvent(WeekViewEvent event) didn't preserve location for events longer than a day --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 593febb4c..a57ccbe9f 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -887,9 +887,9 @@ private void cacheEvent(WeekViewEvent event) { Calendar startTime = (Calendar) event.getEndTime().clone(); startTime.set(Calendar.HOUR_OF_DAY, 0); startTime.set(Calendar.MINUTE, 0); - WeekViewEvent event1 = new WeekViewEvent(event.getId(), event.getName(), event.getStartTime(), endTime); + WeekViewEvent event1 = new WeekViewEvent(event.getId(), event.getName(), event.getLocation(), event.getStartTime(), endTime); event1.setColor(event.getColor()); - WeekViewEvent event2 = new WeekViewEvent(event.getId(), event.getName(), startTime, event.getEndTime()); + WeekViewEvent event2 = new WeekViewEvent(event.getId(), event.getName(), event.getLocation(), startTime, event.getEndTime()); event2.setColor(event.getColor()); mEventRects.add(new EventRect(event1, event, null)); mEventRects.add(new EventRect(event2, event, null)); From 9474070afd52c4851d8e1676faffeccf1e529911 Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 10 Oct 2015 21:17:30 +0200 Subject: [PATCH 19/39] dynamic time column width --- .../main/java/com/alamkanak/weekview/WeekView.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 593febb4c..bc9803064 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -400,11 +400,17 @@ public boolean onScale(ScaleGestureDetector detector) { } /** - * Initialize time column width. Calculate value with latest possible hour (supposed widest text) + * Initialize time column width. Calculate value with all possible hours (supposed widest text) */ private void initTextTimeWidth() { - String timeSample = getDateTimeInterpreter().interpretTime(23); - mTimeTextWidth = mTimeTextPaint.measureText(timeSample); + mTimeTextWidth = 0; + for (int i = 0; i < 24; i++) { + // measure time string and get max width + String time = getDateTimeInterpreter().interpretTime(i); + if (time == null) + throw new IllegalStateException("A DateTimeInterpreter must not return null time"); + mTimeTextWidth = Math.max(mTimeTextWidth, mTimeTextPaint.measureText(time)); + } } @Override From c09624d644bb11a88c7b400aa71a2f2fec75ddce Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 10 Oct 2015 22:04:12 +0200 Subject: [PATCH 20/39] add option for event corner radius optional round corners for events, default = 0 can be changed by attr eventCornerRadius in layout file by setter setEventCornerRadius --- .../java/com/alamkanak/weekview/WeekView.java | 26 +++++++++++++------ library/src/main/res/values/attrs.xml | 1 + 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 593febb4c..ca540b43a 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -125,6 +125,7 @@ public class WeekView extends View { private double mScrollToHour = -1; private ScaleGestureDetector mScaleDetector; private boolean mIsZooming; + private int mEventCornerRadius = 0; // Listeners. private EventClickListener mEventClickListener; @@ -287,6 +288,7 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { mOverlappingEventGap = a.getDimensionPixelSize(R.styleable.WeekView_overlappingEventGap, mOverlappingEventGap); mEventMarginVertical = a.getDimensionPixelSize(R.styleable.WeekView_eventMarginVertical, mEventMarginVertical); mXScrollingSpeed = a.getFloat(R.styleable.WeekView_xScrollingSpeed, mXScrollingSpeed); + mEventCornerRadius = a.getDimensionPixelSize(R.styleable.WeekView_eventCornerRadius, mEventCornerRadius); } finally { a.recycle(); } @@ -421,7 +423,7 @@ protected void onDraw(Canvas canvas) { canvas.drawRect(0, 0, mTimeTextWidth + mHeaderColumnPadding * 2, mHeaderTextHeight + mHeaderRowPadding * 2, mHeaderBackgroundPaint); // Hide anything that is in the bottom margin of the header row. - canvas.drawRect(mHeaderColumnWidth, mHeaderTextHeight + mHeaderRowPadding * 2, getWidth(), mHeaderRowPadding * 2 + mHeaderTextHeight + mHeaderMarginBottom + mTimeTextHeight/2 - mHourSeparatorHeight / 2, mHeaderColumnBackgroundPaint); + canvas.drawRect(mHeaderColumnWidth, mHeaderTextHeight + mHeaderRowPadding * 2, getWidth(), mHeaderRowPadding * 2 + mHeaderTextHeight + mHeaderMarginBottom + mTimeTextHeight/2, mHeaderColumnBackgroundPaint); } private void drawTimeColumnAndAxes(Canvas canvas) { @@ -667,9 +669,6 @@ private void drawEvents(Calendar date, float startFromPixel, Canvas canvas) { // Calculate top. float top = mHourHeight * 24 * mEventRects.get(i).top / 1440 + mCurrentOrigin.y + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 + mEventMarginVertical; - float originalTop = top; - if (top < mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2) - top = mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2; // Calculate bottom. float bottom = mEventRects.get(i).bottom; @@ -679,11 +678,9 @@ private void drawEvents(Calendar date, float startFromPixel, Canvas canvas) { float left = startFromPixel + mEventRects.get(i).left * mWidthPerDay; if (left < startFromPixel) left += mOverlappingEventGap; - float originalLeft = left; float right = left + mEventRects.get(i).width * mWidthPerDay; if (right < startFromPixel + mWidthPerDay) right -= mOverlappingEventGap; - if (left < mHeaderColumnWidth) left = mHeaderColumnWidth; // Draw the event and the event name on top of it. RectF eventRectF = new RectF(left, top, right, bottom); @@ -696,8 +693,8 @@ eventRectF.top < getHeight() && ) { mEventRects.get(i).rectF = eventRectF; mEventBackgroundPaint.setColor(mEventRects.get(i).event.getColor() == 0 ? mDefaultEventColor : mEventRects.get(i).event.getColor()); - canvas.drawRect(mEventRects.get(i).rectF, mEventBackgroundPaint); - drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, originalTop, originalLeft); + canvas.drawRoundRect(mEventRects.get(i).rectF, mEventCornerRadius, mEventCornerRadius, mEventBackgroundPaint); + drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, top, left); } else mEventRects.get(i).rectF = null; @@ -1389,6 +1386,19 @@ public void setOverlappingEventGap(int overlappingEventGap) { invalidate(); } + public int getEventCornerRadius() { + return mEventCornerRadius; + } + + /** + * Set corner radius for event rect. + * + * @param eventCornerRadius the radius in px. + */ + public void setEventCornerRadius(int eventCornerRadius) { + mEventCornerRadius = eventCornerRadius; + } + public int getEventMarginVertical() { return mEventMarginVertical; } diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 5ae26b19c..77229ead3 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -43,5 +43,6 @@ + \ No newline at end of file From 2e8a9a5644414a3f6e7112af4b8ad512f4959306 Mon Sep 17 00:00:00 2001 From: marunjar Date: Sat, 10 Oct 2015 23:25:55 +0200 Subject: [PATCH 21/39] improve default time formatting uses DateFormat for formatting day and hour format time according to locale or system settings: If 24h format is enabled then use format "HH:mm" else use format "hh a" like before. --- .../java/com/alamkanak/weekview/WeekView.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 593febb4c..33d600979 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -16,6 +16,7 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.text.format.DateFormat; import android.text.style.StyleSpan; import android.util.AttributeSet; import android.util.TypedValue; @@ -34,6 +35,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Locale; /** * Created by Raquib-ul-Alam Kanak on 7/21/2014. @@ -1115,12 +1117,10 @@ public DateTimeInterpreter getDateTimeInterpreter() { mDateTimeInterpreter = new DateTimeInterpreter() { @Override public String interpretDate(Calendar date) { - SimpleDateFormat sdf; - sdf = mDayNameLength == LENGTH_SHORT ? new SimpleDateFormat("EEEEE") : new SimpleDateFormat("EEE"); - try{ - String dayName = sdf.format(date.getTime()).toUpperCase(); - return String.format("%s %d/%02d", dayName, date.get(Calendar.MONTH) + 1, date.get(Calendar.DAY_OF_MONTH)); - }catch (Exception e){ + try { + SimpleDateFormat sdf = mDayNameLength == LENGTH_SHORT ? new SimpleDateFormat("EEEEE M/dd", Locale.getDefault()) : new SimpleDateFormat("EEE M/dd", Locale.getDefault()); + return sdf.format(date.getTime()).toUpperCase(); + } catch (Exception e) { e.printStackTrace(); return ""; } @@ -1128,12 +1128,17 @@ public String interpretDate(Calendar date) { @Override public String interpretTime(int hour) { - String amPm; - if (hour >= 0 && hour < 12) amPm = "AM"; - else amPm = "PM"; - if (hour == 0) hour = 12; - if (hour > 12) hour -= 12; - return String.format("%02d %s", hour, amPm); + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, 0); + + try { + SimpleDateFormat sdf = DateFormat.is24HourFormat(getContext()) ? new SimpleDateFormat("HH:mm", Locale.getDefault()) : new SimpleDateFormat("hh a", Locale.getDefault()); + return sdf.format(calendar.getTime()); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } } }; } From fec85ae27d46fdf8e2c6dc4717b1f724ce6c1002 Mon Sep 17 00:00:00 2001 From: marunjar Date: Mon, 12 Oct 2015 22:44:11 +0200 Subject: [PATCH 22/39] fix height of last hour addresses #163 onDraw: add missing height for checking minimum of mCurrentOrigin.y scroller.fling: add missing height to minY in so fling can scroll to full last hour --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 8e387a315..6c0206a3a 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -175,7 +175,7 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve mScroller.fling((int) mCurrentOrigin.x, 0, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); } else if (mCurrentFlingDirection == Direction.VERTICAL){ - mScroller.fling(0, (int) mCurrentOrigin.y, 0, (int) velocityY, 0, 0, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 - getHeight()), 0); + mScroller.fling(0, (int) mCurrentOrigin.y, 0, (int) velocityY, 0, 0, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 - getHeight()), 0); } ViewCompat.postInvalidateOnAnimation(WeekView.this); @@ -500,8 +500,8 @@ else if(mNewHourHeight > mMaxHourHeight) } //if the new mCurrentOrigin.y is invalid, make it valid. - if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) - mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom; + if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom - mTimeTextHeight/2) + mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom - mTimeTextHeight/2; //Don't put an else if because it will trigger a glitch when completly zoomed out and scrolling vertically. if(mCurrentOrigin.y > 0) mCurrentOrigin.y = 0; From 3f7404f1e5b6173aacca3f102b678e3eeb6d5c5a Mon Sep 17 00:00:00 2001 From: marunjar Date: Sun, 11 Oct 2015 14:48:22 +0200 Subject: [PATCH 23/39] improve scroll/fling performance i tried to change it to be more like the examples in android doc 1: https://developer.android.com/training/gestures/scale.html 2: https://developer.android.com/training/gestures/scroll.html less calculations in computeScroll() scrolling now is done in onScroll() and not in onDraw() anymore no more lagging when swiping horizontal and fling is triggered only one scroller left --- .../java/com/alamkanak/weekview/WeekView.java | 133 ++++++++++-------- library/src/main/res/values/attrs.xml | 1 + 2 files changed, 72 insertions(+), 62 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index a4a65bdf2..5fb24c7f1 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -27,7 +27,6 @@ import android.view.SoundEffectConstants; import android.view.View; import android.widget.OverScroller; -import android.widget.Scroller; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -77,11 +76,8 @@ public class WeekView extends View { private List mNextPeriodEvents; private TextPaint mEventTextPaint; private Paint mHeaderColumnBackgroundPaint; - private Scroller mStickyScroller; private int mFetchedPeriod = -1; // the middle period the calendar has fetched. private boolean mRefreshEvents = false; - private float mDistanceY = 0; - private float mDistanceX = 0; private Direction mCurrentFlingDirection = Direction.NONE; // Attributes and their default values. @@ -127,6 +123,7 @@ public class WeekView extends View { private double mScrollToHour = -1; private ScaleGestureDetector mScaleDetector; private boolean mIsZooming; + private int mEventCornerRadius = 0; // Listeners. private EventClickListener mEventClickListener; @@ -141,8 +138,7 @@ public class WeekView extends View { @Override public boolean onDown(MotionEvent e) { - mScroller.forceFinished(true); - mStickyScroller.forceFinished(true); + goToNearestOrigin(); return true; } @@ -151,18 +147,28 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d if(mIsZooming) return true; if (mCurrentScrollDirection == Direction.NONE) { + // allow scrolling only in one direction if (Math.abs(distanceX) > Math.abs(distanceY)){ mCurrentScrollDirection = Direction.HORIZONTAL; - mCurrentFlingDirection = Direction.HORIZONTAL; } else { - mCurrentFlingDirection = Direction.VERTICAL; mCurrentScrollDirection = Direction.VERTICAL; } } - mDistanceX = distanceX * mXScrollingSpeed; - mDistanceY = distanceY; - invalidate(); + + switch (mCurrentScrollDirection) { + case HORIZONTAL: + mCurrentOrigin.x -= distanceX * mXScrollingSpeed; + ViewCompat.postInvalidateOnAnimation(WeekView.this); + + break; + case VERTICAL: + mCurrentOrigin.y -= distanceY; + ViewCompat.postInvalidateOnAnimation(WeekView.this); + + break; + } + return true; } @@ -170,11 +176,12 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { mScroller.forceFinished(true); + mCurrentFlingDirection = mCurrentScrollDirection; if (mCurrentFlingDirection == Direction.HORIZONTAL){ - mScroller.fling((int) mCurrentOrigin.x, 0, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); + mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 - getHeight()), 0); } else if (mCurrentFlingDirection == Direction.VERTICAL){ - mScroller.fling(0, (int) mCurrentOrigin.y, 0, (int) velocityY, 0, 0, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 - getHeight()), 0); + mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, 0, (int) velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE, (int) -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 - getHeight()), 0); } ViewCompat.postInvalidateOnAnimation(WeekView.this); @@ -289,6 +296,7 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { mOverlappingEventGap = a.getDimensionPixelSize(R.styleable.WeekView_overlappingEventGap, mOverlappingEventGap); mEventMarginVertical = a.getDimensionPixelSize(R.styleable.WeekView_eventMarginVertical, mEventMarginVertical); mXScrollingSpeed = a.getFloat(R.styleable.WeekView_xScrollingSpeed, mXScrollingSpeed); + mEventCornerRadius = a.getDimensionPixelSize(R.styleable.WeekView_eventCornerRadius, mEventCornerRadius); } finally { a.recycle(); } @@ -300,7 +308,6 @@ private void init() { // Scrolling initialization. mGestureDetector = new GestureDetectorCompat(mContext, mGestureListener); mScroller = new OverScroller(mContext); - mStickyScroller = new Scroller(mContext); // Measure settings for time column. mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -386,8 +393,6 @@ public void onScaleEnd(ScaleGestureDetector detector) { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { mIsZooming = true; - mScroller.forceFinished(true); - mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; goToNearestOrigin(); return true; } @@ -429,7 +434,7 @@ protected void onDraw(Canvas canvas) { canvas.drawRect(0, 0, mTimeTextWidth + mHeaderColumnPadding * 2, mHeaderTextHeight + mHeaderRowPadding * 2, mHeaderBackgroundPaint); // Hide anything that is in the bottom margin of the header row. - canvas.drawRect(mHeaderColumnWidth, mHeaderTextHeight + mHeaderRowPadding * 2, getWidth(), mHeaderRowPadding * 2 + mHeaderTextHeight + mHeaderMarginBottom + mTimeTextHeight/2 - mHourSeparatorHeight / 2, mHeaderColumnBackgroundPaint); + canvas.drawRect(mHeaderColumnWidth, mHeaderTextHeight + mHeaderRowPadding * 2, getWidth(), mHeaderRowPadding * 2 + mHeaderTextHeight + mHeaderMarginBottom + mTimeTextHeight/2, mHeaderColumnBackgroundPaint); } private void drawTimeColumnAndAxes(Canvas canvas) { @@ -480,11 +485,6 @@ private void drawHeaderRowAndEvents(Canvas canvas) { } } - // Do not let the view go above/below the limit due to scrolling. Set the max and min limit of the scroll. - if (mCurrentScrollDirection == Direction.VERTICAL) - mCurrentOrigin.y -= mDistanceY; - - //Calculate the new height due to the zooming. if (mNewHourHeight > 0){ if(mNewHourHeight < mEffectiveMinHourHeight) @@ -498,14 +498,14 @@ else if(mNewHourHeight > mMaxHourHeight) } //if the new mCurrentOrigin.y is invalid, make it valid. - if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) - mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom; + if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom - mTimeTextHeight/2) + mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom - mTimeTextHeight/2; //Don't put an else if because it will trigger a glitch when completly zoomed out and scrolling vertically. - if(mCurrentOrigin.y > 0) + if(mCurrentOrigin.y > 0) { mCurrentOrigin.y = 0; + } // Consider scroll offset. - if (mCurrentScrollDirection == Direction.HORIZONTAL) mCurrentOrigin.x -= mDistanceX; int leftDaysWithGaps = (int) -(Math.ceil(mCurrentOrigin.x / (mWidthPerDay + mColumnGap))); float startFromPixel = mCurrentOrigin.x + (mWidthPerDay + mColumnGap) * leftDaysWithGaps + mHeaderColumnWidth; @@ -675,9 +675,6 @@ private void drawEvents(Calendar date, float startFromPixel, Canvas canvas) { // Calculate top. float top = mHourHeight * 24 * mEventRects.get(i).top / 1440 + mCurrentOrigin.y + mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2 + mEventMarginVertical; - float originalTop = top; - if (top < mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2) - top = mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight/2; // Calculate bottom. float bottom = mEventRects.get(i).bottom; @@ -687,11 +684,9 @@ private void drawEvents(Calendar date, float startFromPixel, Canvas canvas) { float left = startFromPixel + mEventRects.get(i).left * mWidthPerDay; if (left < startFromPixel) left += mOverlappingEventGap; - float originalLeft = left; float right = left + mEventRects.get(i).width * mWidthPerDay; if (right < startFromPixel + mWidthPerDay) right -= mOverlappingEventGap; - if (left < mHeaderColumnWidth) left = mHeaderColumnWidth; // Draw the event and the event name on top of it. RectF eventRectF = new RectF(left, top, right, bottom); @@ -704,8 +699,8 @@ eventRectF.top < getHeight() && ) { mEventRects.get(i).rectF = eventRectF; mEventBackgroundPaint.setColor(mEventRects.get(i).event.getColor() == 0 ? mDefaultEventColor : mEventRects.get(i).event.getColor()); - canvas.drawRect(mEventRects.get(i).rectF, mEventBackgroundPaint); - drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, originalTop, originalLeft); + canvas.drawRoundRect(mEventRects.get(i).rectF, mEventCornerRadius, mEventCornerRadius, mEventBackgroundPaint); + drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, top, left); } else mEventRects.get(i).rectF = null; @@ -1400,6 +1395,19 @@ public void setOverlappingEventGap(int overlappingEventGap) { invalidate(); } + public int getEventCornerRadius() { + return mEventCornerRadius; + } + + /** + * Set corner radius for event rect. + * + * @param eventCornerRadius the radius in px. + */ + public void setEventCornerRadius(int eventCornerRadius) { + mEventCornerRadius = eventCornerRadius; + } + public int getEventMarginVertical() { return mEventMarginVertical; } @@ -1453,55 +1461,54 @@ public void setXScrollingSpeed(float xScrollingSpeed) { @Override public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming) { + mScaleDetector.onTouchEvent(event); + boolean val = mGestureDetector.onTouchEvent(event); + + // check after call of mGestureDetector, so mCurrentFlingDirection and mCurrentScrollDirection are set + if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming && mCurrentFlingDirection == Direction.NONE) { if (mCurrentScrollDirection == Direction.HORIZONTAL) { goToNearestOrigin(); } mCurrentScrollDirection = Direction.NONE; } - mScaleDetector.onTouchEvent(event); - return mGestureDetector.onTouchEvent(event); + + return val; } private void goToNearestOrigin(){ float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)); - if(!mIsZooming){ - if(mDistanceX > 0) - leftDays--; - else - leftDays++; + + int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay + mColumnGap)); + + if (nearestOrigin != 0) { + // stop current animation + mScroller.forceFinished(true); + // snap to date + mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0); + ViewCompat.postInvalidateOnAnimation(WeekView.this); } - int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap)); - mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0); - ViewCompat.postInvalidateOnAnimation(WeekView.this); + // reset scrolling and fling direction + mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; } @Override public void computeScroll() { super.computeScroll(); - if (mScroller.computeScrollOffset()) { - if (Math.abs(mScroller.getFinalX() - mScroller.getCurrX()) < mWidthPerDay + mColumnGap && Math.abs(mScroller.getFinalX() - mScroller.getStartX()) != 0) { - mScroller.forceFinished(true); - float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)); - if(mScroller.getFinalX() < mScroller.getCurrX()) - leftDays--; - else - leftDays++; - int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap)); - mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0); - ViewCompat.postInvalidateOnAnimation(WeekView.this); + + if (mScroller.isFinished()) { + if (mCurrentFlingDirection != Direction.NONE) { + // snap to day after fling is finished + goToNearestOrigin(); } - else { - if (mCurrentFlingDirection == Direction.VERTICAL) mCurrentOrigin.y = mScroller.getCurrY(); - else mCurrentOrigin.x = mScroller.getCurrX(); + } else { + if (mScroller.computeScrollOffset()) { + mCurrentOrigin.y = mScroller.getCurrY(); + mCurrentOrigin.x = mScroller.getCurrX(); + ViewCompat.postInvalidateOnAnimation(this); } } - if (mStickyScroller.computeScrollOffset()) { - mCurrentOrigin.x = mStickyScroller.getCurrX(); - ViewCompat.postInvalidateOnAnimation(this); - } } @@ -1525,6 +1532,8 @@ public void goToToday() { */ public void goToDate(Calendar date) { mScroller.forceFinished(true); + mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; + date.set(Calendar.HOUR_OF_DAY, 0); date.set(Calendar.MINUTE, 0); date.set(Calendar.SECOND, 0); diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 5ae26b19c..77229ead3 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -43,5 +43,6 @@ + \ No newline at end of file From 2a67bdb87eb44d4e2c1aae0d088ac7cba916bb0f Mon Sep 17 00:00:00 2001 From: marunjar Date: Mon, 19 Oct 2015 00:37:00 +0200 Subject: [PATCH 24/39] improve scroll performance another improvement for #139 there is no need to iterate over all days for 2 months to collect and calculate eventRects, it works if u just check all days with events --- .../java/com/alamkanak/weekview/WeekView.java | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 6c0206a3a..880426a2b 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -858,25 +858,29 @@ private void getMoreEvents(Calendar day) { } // Prepare to calculate positions of each events. - ArrayList tempEvents = new ArrayList(mEventRects); + List tempEvents = mEventRects; mEventRects = new ArrayList(); - Calendar dayCounter = (Calendar) day.clone(); - dayCounter.add(Calendar.MONTH, -1); - dayCounter.set(Calendar.DAY_OF_MONTH, 1); - Calendar maxDay = (Calendar) day.clone(); - maxDay.add(Calendar.MONTH, 1); - maxDay.set(Calendar.DAY_OF_MONTH, maxDay.getActualMaximum(Calendar.DAY_OF_MONTH)); - - // Iterate through each day to calculate the position of the events. - while (dayCounter.getTimeInMillis() <= maxDay.getTimeInMillis()) { - ArrayList eventRects = new ArrayList(); - for (EventRect eventRect : tempEvents) { - if (isSameDay(eventRect.event.getStartTime(), dayCounter)) - eventRects.add(eventRect); - } + // Iterate through each day with events to calculate the position of the events. + while (tempEvents.size() > 0) { + ArrayList eventRects = new ArrayList<>(tempEvents.size()); + + // get first event for a day + EventRect eventRect1 = tempEvents.remove(0); + eventRects.add(eventRect1); + + int i = 0; + while (i < tempEvents.size()) { + // collect all other events for same day + EventRect eventRect2 = tempEvents.get(i); + if (isSameDay(eventRect1.event.getStartTime(), eventRect2.event.getStartTime())) { + tempEvents.remove(i); + eventRects.add(eventRect2); + } else { + i++; + } + } computePositionOfEvents(eventRects); - dayCounter.add(Calendar.DATE, 1); } } From eb6580625c4988294a44d809066dcde1210f7bca Mon Sep 17 00:00:00 2001 From: Francisco Madrid Date: Thu, 29 Oct 2015 16:57:19 -0300 Subject: [PATCH 25/39] fixing orientation changes --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 7 +++++++ 1 file changed, 7 insertions(+) mode change 100644 => 100755 library/src/main/java/com/alamkanak/weekview/WeekView.java diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java old mode 100644 new mode 100755 index 6c0206a3a..f476399d7 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -403,6 +403,13 @@ public boolean onScale(ScaleGestureDetector detector) { }); } + // fix rotation changes + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mAreDimensionsInvalid = true; + } + /** * Initialize time column width. Calculate value with all possible hours (supposed widest text) */ From 3724c54e0f2ec0a5f9b65fa8e37999eb71db0e20 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Thu, 29 Oct 2015 21:12:05 +0100 Subject: [PATCH 26/39] Add duration for scroll snapping --- library/src/main/java/com/alamkanak/weekview/WeekView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 5fb24c7f1..2789e2710 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -1484,7 +1484,7 @@ private void goToNearestOrigin(){ // stop current animation mScroller.forceFinished(true); // snap to date - mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0); + mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, 50); ViewCompat.postInvalidateOnAnimation(WeekView.this); } // reset scrolling and fling direction From 853ca78eedc25dcdfe52fa5685f5c16157d5b50c Mon Sep 17 00:00:00 2001 From: Van Fan Date: Wed, 1 Jul 2015 11:29:55 +0800 Subject: [PATCH 27/39] Support event over three days. Conflicts: library/src/main/java/com/alamkanak/weekview/WeekView.java --- .../java/com/alamkanak/weekview/WeekView.java | 43 ++++++++++++++++--- .../com/alamkanak/weekview/WeekViewEvent.java | 16 +++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index a45e64b47..402295735 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -894,31 +894,64 @@ private void getMoreEvents(Calendar day) { * @param event The event to cache. */ private void cacheEvent(WeekViewEvent event) { + // do not cache twice + if (alreadyCached(event)) return; + if (!isSameDay(event.getStartTime(), event.getEndTime())) { + // add first day Calendar endTime = (Calendar) event.getStartTime().clone(); endTime.set(Calendar.HOUR_OF_DAY, 23); endTime.set(Calendar.MINUTE, 59); + WeekViewEvent event1 = new WeekViewEvent(event.getId(), event.getName(), event.getLocation(), event.getStartTime(), endTime); + event1.setColor(event.getColor()); + mEventRects.add(new EventRect(event1, event, null)); + + // add over days + Calendar otherDay = (Calendar) event.getStartTime().clone(); + otherDay.add(Calendar.DATE, 1); + while (!isSameDay(otherDay, event.getEndTime())) { + Calendar overDay = (Calendar) otherDay.clone(); + overDay.set(Calendar.HOUR_OF_DAY, 0); + overDay.set(Calendar.MINUTE, 0); + Calendar endOfOverDay = (Calendar) overDay.clone(); + endOfOverDay.set(Calendar.HOUR_OF_DAY, 23); + endOfOverDay.set(Calendar.MINUTE, 59); + WeekViewEvent eventMore = new WeekViewEvent(event.getId(), event.getName(), overDay, endOfOverDay); + eventMore.setColor(event.getColor()); + mEventRects.add(new EventRect(eventMore, event, null)); + + // next day + otherDay.add(Calendar.DATE, 1); + } + + // add last day Calendar startTime = (Calendar) event.getEndTime().clone(); startTime.set(Calendar.HOUR_OF_DAY, 0); startTime.set(Calendar.MINUTE, 0); - WeekViewEvent event1 = new WeekViewEvent(event.getId(), event.getName(), event.getLocation(), event.getStartTime(), endTime); - event1.setColor(event.getColor()); WeekViewEvent event2 = new WeekViewEvent(event.getId(), event.getName(), event.getLocation(), startTime, event.getEndTime()); event2.setColor(event.getColor()); - mEventRects.add(new EventRect(event1, event, null)); mEventRects.add(new EventRect(event2, event, null)); } else mEventRects.add(new EventRect(event, event, null)); } - private void sortAndCacheEvents(List events){ + private void sortAndCacheEvents(List events) { sortEvents(events); - for(WeekViewEvent event : events){ + for (WeekViewEvent event : events) { cacheEvent(event); } } + private boolean alreadyCached(WeekViewEvent event) { + for (EventRect eventRect : mEventRects) { + if (eventRect.originalEvent.getId() == event.getId()) { + return true; + } + } + return false; + } + /** * Sorts the events in ascending order. * @param events The events to be sorted. diff --git a/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java b/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java index e6638a875..e0d4765a8 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekViewEvent.java @@ -128,4 +128,20 @@ public long getId() { public void setId(long id) { this.mId = id; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + WeekViewEvent that = (WeekViewEvent) o; + + return mId == that.mId; + + } + + @Override + public int hashCode() { + return (int) (mId ^ (mId >>> 32)); + } } From 3396a814584959a8e5ef6e36cf7a8ba254274e6f Mon Sep 17 00:00:00 2001 From: marunjar Date: Mon, 2 Nov 2015 20:23:39 +0100 Subject: [PATCH 28/39] Fix ellipsize bug Fixes #206 --- .../java/com/alamkanak/weekview/WeekView.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 402295735..2485b35a7 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -727,6 +727,7 @@ eventRectF.top < getHeight() && */ private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, float originalTop, float originalLeft) { if (rect.right - rect.left - mEventPadding * 2 < 0) return; + if (rect.bottom - rect.top - mEventPadding * 2 < 0) return; SpannableStringBuilder bob = new SpannableStringBuilder(); if (event.getName() != null) { @@ -738,28 +739,31 @@ private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, floa bob.append(event.getLocation()); } + int availableHeight = (int) (rect.bottom - originalTop - mEventPadding * 2); + int availableWidth = (int) (rect.right - originalLeft - mEventPadding * 2); + // Get text dimensions - StaticLayout textLayout = new StaticLayout(bob, mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + StaticLayout textLayout = new StaticLayout(bob, mEventTextPaint, availableWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - // Crop height - int availableHeight = (int) (rect.bottom - originalTop - mEventPadding * 2); int lineHeight = textLayout.getHeight() / textLayout.getLineCount(); - if (lineHeight < availableHeight && textLayout.getHeight() > rect.height() - mEventPadding * 2) { - int lineCount = textLayout.getLineCount(); - int availableLineCount = (int) Math.floor(lineCount * availableHeight / textLayout.getHeight()); - float widthAvailable = (rect.right - originalLeft - mEventPadding * 2) * availableLineCount; - textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, widthAvailable, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - } - else if (lineHeight >= availableHeight) { - int width = (int) (rect.right - originalLeft - mEventPadding * 2); - textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, width, TextUtils.TruncateAt.END), mEventTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 1.0f, false); - } - // Draw text - canvas.save(); - canvas.translate(originalLeft + mEventPadding, originalTop + mEventPadding); - textLayout.draw(canvas); - canvas.restore(); + if (availableHeight >= lineHeight) { + // calculate available lines + int availableLineCount = availableHeight / lineHeight; + do { + // ellipsize text to fit into event rect + textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, availableLineCount * availableWidth, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + // reduce line count + availableLineCount--; + // and repeat until text is short enough + } while (textLayout.getHeight() > availableHeight); + + // Draw text + canvas.save(); + canvas.translate(originalLeft + mEventPadding, originalTop + mEventPadding); + textLayout.draw(canvas); + canvas.restore(); + } } From dbf464efcbfdcc19291f6e990d96fce89930ba54 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sun, 8 Nov 2015 22:10:34 +0100 Subject: [PATCH 29/39] Don't check if already cached --- .../main/java/com/alamkanak/weekview/WeekView.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 2485b35a7..4c8473d6e 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -898,9 +898,6 @@ private void getMoreEvents(Calendar day) { * @param event The event to cache. */ private void cacheEvent(WeekViewEvent event) { - // do not cache twice - if (alreadyCached(event)) return; - if (!isSameDay(event.getStartTime(), event.getEndTime())) { // add first day Calendar endTime = (Calendar) event.getStartTime().clone(); @@ -947,15 +944,6 @@ private void sortAndCacheEvents(List events) { } } - private boolean alreadyCached(WeekViewEvent event) { - for (EventRect eventRect : mEventRects) { - if (eventRect.originalEvent.getId() == event.getId()) { - return true; - } - } - return false; - } - /** * Sorts the events in ascending order. * @param events The events to be sorted. From 24913dfcbb5ae84912f1bde1c0f39d398981e19c Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Sun, 8 Nov 2015 22:21:45 +0100 Subject: [PATCH 30/39] Remove tag from manifest Fixes #198 --- library/src/main/AndroidManifest.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml index 1c9d5b1a7..c7707cff5 100644 --- a/library/src/main/AndroidManifest.xml +++ b/library/src/main/AndroidManifest.xml @@ -1,7 +1,3 @@ - - - - From 6137a282b01acfe07979bafa49aee9af362cf4b0 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Wed, 21 Oct 2015 14:35:13 +0600 Subject: [PATCH 31/39] Update SDKs and tools --- build.gradle | 2 +- library/build.gradle | 8 ++++---- sample/build.gradle | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 23167e28c..010afe941 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:1.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/library/build.gradle b/library/build.gradle index 9453d1cdd..2ece4ff92 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -5,17 +5,17 @@ repositories { } android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 23 + buildToolsVersion "23.0.1" defaultConfig { minSdkVersion 9 - targetSdkVersion 22 + targetSdkVersion 23 } } dependencies { - compile 'com.android.support:appcompat-v7:22.0.0' + compile 'com.android.support:appcompat-v7:23.0.1' } apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index 9e37c882e..62228588d 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 - buildToolsVersion "21.1.1" + compileSdkVersion 23 + buildToolsVersion "23.0.1" defaultConfig { applicationId "com.alamkanak.weekview" minSdkVersion 9 - targetSdkVersion 21 + targetSdkVersion 23 versionCode 1 versionName "1.0" } @@ -22,5 +22,5 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':library') - compile 'com.android.support:appcompat-v7:19.1.0' + compile 'com.android.support:appcompat-v7:23.0.1' } From bec4a2b900765165fd4bb5fd82fef786bfc0e687 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Sun, 22 Nov 2015 03:19:04 +0600 Subject: [PATCH 32/39] Organize some of the code --- .../java/com/alamkanak/weekview/WeekView.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index 4c8473d6e..b9a48b76d 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -144,8 +144,10 @@ public boolean onDown(MotionEvent e) { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - if(mIsZooming) + if (mIsZooming) return true; + + // Calculate the direction to scroll. if (mCurrentScrollDirection == Direction.NONE) { // allow scrolling only in one direction if (Math.abs(distanceX) > Math.abs(distanceY)){ @@ -156,19 +158,17 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d } } + // Calculate the new origin after scroll. switch (mCurrentScrollDirection) { case HORIZONTAL: mCurrentOrigin.x -= distanceX * mXScrollingSpeed; ViewCompat.postInvalidateOnAnimation(WeekView.this); - break; case VERTICAL: mCurrentOrigin.y -= distanceY; ViewCompat.postInvalidateOnAnimation(WeekView.this); - break; } - return true; } @@ -564,14 +564,14 @@ else if(mNewHourHeight > mMaxHourHeight) // Draw background color for each day. float start = (startPixel < mHeaderColumnWidth ? mHeaderColumnWidth : startPixel); - if (mWidthPerDay + startPixel - start> 0){ - if(mUseNewColoring){ + if (mWidthPerDay + startPixel - start > 0){ + if (mUseNewColoring){ boolean isWeekend = (day.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || day.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY); Paint pastPaint = isWeekend ? mPastWeekendBackgroundPaint : mPastBackgroundPaint; Paint futurePaint = isWeekend ? mFutureWeekendBackgroundPaint : mFutureBackgroundPaint; float startY = mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom + mCurrentOrigin.y; - if(sameDay){ + if (sameDay){ Calendar now = Calendar.getInstance(); float beforeNow = (now.get(Calendar.HOUR_OF_DAY)+now.get(Calendar.MINUTE)/60.0f)*mHourHeight; canvas.drawRect(start, startY, startPixel + mWidthPerDay, startY+beforeNow, pastPaint); @@ -582,7 +582,7 @@ else if(mNewHourHeight > mMaxHourHeight) canvas.drawRect(start, startY, startPixel + mWidthPerDay, getHeight(), futurePaint); } }else{ - canvas.drawRect(start, mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom, startPixel + mWidthPerDay, getHeight(), sameDay ? mTodayBackgroundPaint : mDayBackgroundPaint); + canvas.drawRect(start, mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight / 2 + mHeaderMarginBottom, startPixel + mWidthPerDay, getHeight(), sameDay ? mTodayBackgroundPaint : mDayBackgroundPaint); } } @@ -1189,7 +1189,7 @@ public String interpretTime(int hour) { public void setDateTimeInterpreter(DateTimeInterpreter dateTimeInterpreter){ this.mDateTimeInterpreter = dateTimeInterpreter; - // refresh time column width + // Refresh time column width. initTextTimeWidth(); } From f4b4e67709a0a443dcbfd8a444a6291be39c5511 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Fri, 11 Dec 2015 13:06:01 +0600 Subject: [PATCH 33/39] Correct some comments --- .../java/com/alamkanak/weekview/WeekView.java | 140 +++++++++--------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index b9a48b76d..ec4bb82c9 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -144,6 +144,7 @@ public boolean onDown(MotionEvent e) { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + // Check if view is zoomed. if (mIsZooming) return true; @@ -414,12 +415,12 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { } /** - * Initialize time column width. Calculate value with all possible hours (supposed widest text) + * Initialize time column width. Calculate value with all possible hours (supposed widest text). */ private void initTextTimeWidth() { mTimeTextWidth = 0; for (int i = 0; i < 24; i++) { - // measure time string and get max width + // Measure time string and get max width. String time = getDateTimeInterpreter().interpretTime(i); if (time == null) throw new IllegalStateException("A DateTimeInterpreter must not return null time"); @@ -492,11 +493,11 @@ private void drawHeaderRowAndEvents(Canvas canvas) { } } - //Calculate the new height due to the zooming. + // Calculate the new height due to the zooming. if (mNewHourHeight > 0){ - if(mNewHourHeight < mEffectiveMinHourHeight) + if (mNewHourHeight < mEffectiveMinHourHeight) mNewHourHeight = mEffectiveMinHourHeight; - else if(mNewHourHeight > mMaxHourHeight) + else if (mNewHourHeight > mMaxHourHeight) mNewHourHeight = mMaxHourHeight; mCurrentOrigin.y = (mCurrentOrigin.y/mHourHeight)*mNewHourHeight; @@ -504,11 +505,13 @@ else if(mNewHourHeight > mMaxHourHeight) mNewHourHeight = -1; } - //if the new mCurrentOrigin.y is invalid, make it valid. + // If the new mCurrentOrigin.y is invalid, make it valid. if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom - mTimeTextHeight/2) mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom - mTimeTextHeight/2; - //Don't put an else if because it will trigger a glitch when completly zoomed out and scrolling vertically. - if(mCurrentOrigin.y > 0) { + + // Don't put an "else if" because it will trigger a glitch when completely zoomed out and + // scrolling vertically. + if (mCurrentOrigin.y > 0) { mCurrentOrigin.y = 0; } @@ -573,15 +576,18 @@ else if(mNewHourHeight > mMaxHourHeight) if (sameDay){ Calendar now = Calendar.getInstance(); - float beforeNow = (now.get(Calendar.HOUR_OF_DAY)+now.get(Calendar.MINUTE)/60.0f)*mHourHeight; + float beforeNow = (now.get(Calendar.HOUR_OF_DAY) + now.get(Calendar.MINUTE)/60.0f) * mHourHeight; canvas.drawRect(start, startY, startPixel + mWidthPerDay, startY+beforeNow, pastPaint); canvas.drawRect(start, startY+beforeNow, startPixel + mWidthPerDay, getHeight(), futurePaint); - } else if(day.before(today)) { + } + else if (day.before(today)) { canvas.drawRect(start, startY, startPixel + mWidthPerDay, getHeight(), pastPaint); - } else { + } + else { canvas.drawRect(start, startY, startPixel + mWidthPerDay, getHeight(), futurePaint); } - }else{ + } + else { canvas.drawRect(start, mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight / 2 + mHeaderMarginBottom, startPixel + mWidthPerDay, getHeight(), sameDay ? mTodayBackgroundPaint : mDayBackgroundPaint); } } @@ -605,12 +611,12 @@ else if(mNewHourHeight > mMaxHourHeight) // Draw the events. drawEvents(day, startPixel, canvas); - //Draw the line at the current time - if(mUseNewColoring && sameDay){ + // Draw the line at the current time. + if (mUseNewColoring && sameDay){ float startY = mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom + mCurrentOrigin.y; Calendar now = Calendar.getInstance(); - float beforeNow = (now.get(Calendar.HOUR_OF_DAY)+now.get(Calendar.MINUTE)/60.0f)*mHourHeight; - canvas.drawLine(start, startY+beforeNow, startPixel + mWidthPerDay, startY+beforeNow, mNowLinePaint); + float beforeNow = (now.get(Calendar.HOUR_OF_DAY) + now.get(Calendar.MINUTE)/60.0f) * mHourHeight; + canvas.drawLine(start, startY + beforeNow, startPixel + mWidthPerDay, startY + beforeNow, mNowLinePaint); } // In the next iteration, start from the next day. @@ -652,8 +658,7 @@ private Calendar getTimeFromPoint(float x, float y){ dayNumber <= leftDaysWithGaps + mNumberOfVisibleDays + 1; dayNumber++) { float start = (startPixel < mHeaderColumnWidth ? mHeaderColumnWidth : startPixel); - if (mWidthPerDay + startPixel - start> 0 - && x>start && x 0 && x > start && x < startPixel + mWidthPerDay){ Calendar day = today(); day.add(Calendar.DATE, dayNumber - 1); float pixelsFromZero = y - mCurrentOrigin.y - mHeaderTextHeight @@ -729,12 +734,15 @@ private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, floa if (rect.right - rect.left - mEventPadding * 2 < 0) return; if (rect.bottom - rect.top - mEventPadding * 2 < 0) return; + // Prepare the name of the event. SpannableStringBuilder bob = new SpannableStringBuilder(); if (event.getName() != null) { bob.append(event.getName()); - bob.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,bob.length(),0); + bob.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, bob.length(), 0); bob.append(' '); } + + // Prepare the location of the event. if (event.getLocation() != null) { bob.append(event.getLocation()); } @@ -742,23 +750,25 @@ private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, floa int availableHeight = (int) (rect.bottom - originalTop - mEventPadding * 2); int availableWidth = (int) (rect.right - originalLeft - mEventPadding * 2); - // Get text dimensions + // Get text dimensions. StaticLayout textLayout = new StaticLayout(bob, mEventTextPaint, availableWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); int lineHeight = textLayout.getHeight() / textLayout.getLineCount(); if (availableHeight >= lineHeight) { - // calculate available lines + // Calculate available number of line counts. int availableLineCount = availableHeight / lineHeight; do { - // ellipsize text to fit into event rect + // Ellipsize text to fit into event rect. textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, availableLineCount * availableWidth, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - // reduce line count + + // Reduce line count. availableLineCount--; - // and repeat until text is short enough + + // Repeat until text is short enough. } while (textLayout.getHeight() > availableHeight); - // Draw text + // Draw text. canvas.save(); canvas.translate(originalLeft + mEventPadding, originalTop + mEventPadding); textLayout.draw(canvas); @@ -810,6 +820,7 @@ public EventRect(WeekViewEvent event, WeekViewEvent originalEvent, RectF rectF) * @param day The day where the user is currently is. */ private void getMoreEvents(Calendar day) { + // Get more events if the month is changed. if (mEventRects == null) mEventRects = new ArrayList(); @@ -825,35 +836,37 @@ private void getMoreEvents(Calendar day) { mFetchedPeriod = -1; } - if(mWeekViewLoader != null){ + if (mWeekViewLoader != null){ int periodToFetch = (int) mWeekViewLoader.toWeekViewPeriodIndex(day); if (!isInEditMode() && (mFetchedPeriod < 0 || mFetchedPeriod != periodToFetch || mRefreshEvents)) { List previousPeriodEvents = null; List currentPeriodEvents = null; List nextPeriodEvents = null; - if(mPreviousPeriodEvents != null && mCurrentPeriodEvents != null && mNextPeriodEvents != null){ - if(periodToFetch == mFetchedPeriod-1){ + if (mPreviousPeriodEvents != null && mCurrentPeriodEvents != null && mNextPeriodEvents != null){ + if (periodToFetch == mFetchedPeriod-1){ currentPeriodEvents = mPreviousPeriodEvents; nextPeriodEvents = mCurrentPeriodEvents; - }else if(periodToFetch == mFetchedPeriod){ + } + else if (periodToFetch == mFetchedPeriod){ previousPeriodEvents = mPreviousPeriodEvents; currentPeriodEvents = mCurrentPeriodEvents; nextPeriodEvents = mNextPeriodEvents; - }else if(periodToFetch == mFetchedPeriod+1){ + } + else if (periodToFetch == mFetchedPeriod+1){ previousPeriodEvents = mCurrentPeriodEvents; currentPeriodEvents = mNextPeriodEvents; } } - if(currentPeriodEvents == null) + if (currentPeriodEvents == null) currentPeriodEvents = mWeekViewLoader.onLoad(periodToFetch); - if(previousPeriodEvents == null) + if (previousPeriodEvents == null) previousPeriodEvents = mWeekViewLoader.onLoad(periodToFetch-1); - if(nextPeriodEvents == null) + if (nextPeriodEvents == null) nextPeriodEvents = mWeekViewLoader.onLoad(periodToFetch+1); - //clear events + // Clear events. mEventRects.clear(); sortAndCacheEvents(previousPeriodEvents); sortAndCacheEvents(currentPeriodEvents); @@ -874,13 +887,13 @@ private void getMoreEvents(Calendar day) { while (tempEvents.size() > 0) { ArrayList eventRects = new ArrayList<>(tempEvents.size()); - // get first event for a day + // Get first event for a day. EventRect eventRect1 = tempEvents.remove(0); eventRects.add(eventRect1); int i = 0; while (i < tempEvents.size()) { - // collect all other events for same day + // Collect all other events for same day. EventRect eventRect2 = tempEvents.get(i); if (isSameDay(eventRect1.event.getStartTime(), eventRect2.event.getStartTime())) { tempEvents.remove(i); @@ -899,7 +912,7 @@ private void getMoreEvents(Calendar day) { */ private void cacheEvent(WeekViewEvent event) { if (!isSameDay(event.getStartTime(), event.getEndTime())) { - // add first day + // Add first day. Calendar endTime = (Calendar) event.getStartTime().clone(); endTime.set(Calendar.HOUR_OF_DAY, 23); endTime.set(Calendar.MINUTE, 59); @@ -907,7 +920,7 @@ private void cacheEvent(WeekViewEvent event) { event1.setColor(event.getColor()); mEventRects.add(new EventRect(event1, event, null)); - // add over days + // Add other days. Calendar otherDay = (Calendar) event.getStartTime().clone(); otherDay.add(Calendar.DATE, 1); while (!isSameDay(otherDay, event.getEndTime())) { @@ -921,11 +934,11 @@ private void cacheEvent(WeekViewEvent event) { eventMore.setColor(event.getColor()); mEventRects.add(new EventRect(eventMore, event, null)); - // next day + // Add next day. otherDay.add(Calendar.DATE, 1); } - // add last day + // Add last day. Calendar startTime = (Calendar) event.getEndTime().clone(); startTime.set(Calendar.HOUR_OF_DAY, 0); startTime.set(Calendar.MINUTE, 0); @@ -933,10 +946,15 @@ private void cacheEvent(WeekViewEvent event) { event2.setColor(event.getColor()); mEventRects.add(new EventRect(event2, event, null)); } - else + else { mEventRects.add(new EventRect(event, event, null)); + } } + /** + * Sort and cache events. + * @param events The events to be sorted and cached. + */ private void sortAndCacheEvents(List events) { sortEvents(events); for (WeekViewEvent event : events) { @@ -1097,7 +1115,7 @@ public EventClickListener getEventClickListener() { } public MonthChangeListener getMonthChangeListener() { - if(mWeekViewLoader instanceof MonthLoader) + if (mWeekViewLoader instanceof MonthLoader) return ((MonthLoader) mWeekViewLoader).getOnMonthChangeListener(); return null; } @@ -1145,6 +1163,7 @@ public void setScrollListener(ScrollListener scrolledListener){ public ScrollListener getScrollListener(){ return mScrollListener; } + /** * Get the interpreter which provides the text to show in the header column and the header row. * @return The date, time interpreter. @@ -1500,7 +1519,7 @@ public boolean onTouchEvent(MotionEvent event) { mScaleDetector.onTouchEvent(event); boolean val = mGestureDetector.onTouchEvent(event); - // check after call of mGestureDetector, so mCurrentFlingDirection and mCurrentScrollDirection are set + // Check after call of mGestureDetector, so mCurrentFlingDirection and mCurrentScrollDirection are set. if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming && mCurrentFlingDirection == Direction.NONE) { if (mCurrentScrollDirection == Direction.HORIZONTAL) { goToNearestOrigin(); @@ -1517,13 +1536,13 @@ private void goToNearestOrigin(){ int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay + mColumnGap)); if (nearestOrigin != 0) { - // stop current animation + // Stop current animation. mScroller.forceFinished(true); - // snap to date + // Snap to date. mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, 50); ViewCompat.postInvalidateOnAnimation(WeekView.this); } - // reset scrolling and fling direction + // Reset scrolling and fling direction. mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; } @@ -1534,14 +1553,13 @@ public void computeScroll() { if (mScroller.isFinished()) { if (mCurrentFlingDirection != Direction.NONE) { - // snap to day after fling is finished + // Snap to day after fling is finished. goToNearestOrigin(); } } else { if (mScroller.computeScrollOffset()) { mCurrentOrigin.y = mScroller.getCurrY(); mCurrentOrigin.x = mScroller.getCurrX(); - ViewCompat.postInvalidateOnAnimation(this); } } @@ -1649,7 +1667,7 @@ public interface EventClickListener { * @param event: event clicked. * @param eventRect: view containing the clicked event. */ - public void onEventClick(WeekViewEvent event, RectF eventRect); + void onEventClick(WeekViewEvent event, RectF eventRect); } public interface MonthChangeListener { @@ -1661,7 +1679,7 @@ public interface MonthChangeListener { * @param newMonth: month of the events required by the view
1 based (not like JAVA API) --> January = 1 and December = 12. * @return a list of the events happening during the specified month. */ - public List onMonthChange(int newYear, int newMonth); + List onMonthChange(int newYear, int newMonth); } public interface EventLongPressListener { @@ -1670,7 +1688,7 @@ public interface EventLongPressListener { * @param event: event clicked. * @param eventRect: view containing the clicked event. */ - public void onEventLongPress(WeekViewEvent event, RectF eventRect); + void onEventLongPress(WeekViewEvent event, RectF eventRect); } public interface EmptyViewClickListener { @@ -1678,7 +1696,7 @@ public interface EmptyViewClickListener { * Triggered when the users clicks on a empty space of the calendar. * @param time: {@link Calendar} object set with the date and time of the clicked position on the view. */ - public void onEmptyViewClicked(Calendar time); + void onEmptyViewClicked(Calendar time); } public interface EmptyViewLongPressListener { @@ -1686,7 +1704,7 @@ public interface EmptyViewLongPressListener { * Similar to {@link com.alamkanak.weekview.WeekView.EmptyViewClickListener} but with long press. * @param time: {@link Calendar} object set with the date and time of the long pressed position on the view. */ - public void onEmptyViewLongPress(Calendar time); + void onEmptyViewLongPress(Calendar time); } public interface ScrollListener { @@ -1697,7 +1715,7 @@ public interface ScrollListener { * @param newFirstVisibleDay The new first visible day * @param oldFirstVisibleDay The old first visible day (is null on the first call). */ - public void onFirstVisibleDayChanged(Calendar newFirstVisibleDay, Calendar oldFirstVisibleDay); + void onFirstVisibleDayChanged(Calendar newFirstVisibleDay, Calendar oldFirstVisibleDay); } @@ -1707,20 +1725,6 @@ public interface ScrollListener { // ///////////////////////////////////////////////////////////////// - /** - * Checks if an integer array contains a particular value. - * @param list The haystack. - * @param value The needle. - * @return True if the array contains the value. Otherwise returns false. - */ - private boolean containsValue(int[] list, int value) { - for (int i = 0; i < list.length; i++){ - if (list[i] == value) - return true; - } - return false; - } - /** * Checks if two times are on the same day. * @param dayOne The first day. From 99d8918679e6e0bf0de9a9dfc83d31caf0a4125b Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Fri, 11 Dec 2015 13:43:09 +0600 Subject: [PATCH 34/39] Update some attributes for coloring days --- .../java/com/alamkanak/weekview/WeekView.java | 31 ++++++++++++------- library/src/main/res/values/attrs.xml | 17 ++++++++-- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index ec4bb82c9..cec604914 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -79,6 +79,11 @@ public class WeekView extends View { private int mFetchedPeriod = -1; // the middle period the calendar has fetched. private boolean mRefreshEvents = false; private Direction mCurrentFlingDirection = Direction.NONE; + private ScaleGestureDetector mScaleDetector; + private boolean mIsZooming; + private Calendar mFirstVisibleDay; + private Calendar mLastVisibleDay; + private int mDefaultEventColor; // Attributes and their default values. private int mHourHeight = 50; @@ -101,7 +106,6 @@ public class WeekView extends View { private int mFutureWeekendBackgroundColor = 0; private int mNowLineColor = Color.rgb(102, 102, 102); private int mNowLineThickness = 5; - private boolean mUseNewColoring = false; private int mHourSeparatorColor = Color.rgb(230, 230, 230); private int mTodayBackgroundColor = Color.rgb(239, 247, 254); private int mHourSeparatorHeight = 2; @@ -110,20 +114,20 @@ public class WeekView extends View { private int mEventTextColor = Color.BLACK; private int mEventPadding = 8; private int mHeaderColumnBackgroundColor = Color.WHITE; - private int mDefaultEventColor; private boolean mIsFirstDraw = true; private boolean mAreDimensionsInvalid = true; @Deprecated private int mDayNameLength = LENGTH_LONG; private int mOverlappingEventGap = 0; private int mEventMarginVertical = 0; private float mXScrollingSpeed = 1f; - private Calendar mFirstVisibleDay; - private Calendar mLastVisibleDay; private Calendar mScrollToDay = null; private double mScrollToHour = -1; - private ScaleGestureDetector mScaleDetector; - private boolean mIsZooming; private int mEventCornerRadius = 0; + private boolean mUseDifferentPastBackgroundColor = false; + private boolean mUseDifferentFutureWeekendBackgroundColor = false; + private boolean mShowDistinctWeekendColor = false; + private boolean mShowNowLine = false; + private boolean mShowDistinctPastFutureColor = false; // Listeners. private EventClickListener mEventClickListener; @@ -284,7 +288,6 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { mPastWeekendBackgroundColor = a.getColor(R.styleable.WeekView_pastWeekendBackgroundColor, mPastBackgroundColor); mNowLineColor = a.getColor(R.styleable.WeekView_nowLineColor, mNowLineColor); mNowLineThickness = a.getDimensionPixelSize(R.styleable.WeekView_nowLineThickness, mNowLineThickness); - mUseNewColoring = a.getBoolean(R.styleable.WeekView_useNewColoringStyle, mUseNewColoring); mHourSeparatorColor = a.getColor(R.styleable.WeekView_hourSeparatorColor, mHourSeparatorColor); mTodayBackgroundColor = a.getColor(R.styleable.WeekView_todayBackgroundColor, mTodayBackgroundColor); mHourSeparatorHeight = a.getDimensionPixelSize(R.styleable.WeekView_hourSeparatorHeight, mHourSeparatorHeight); @@ -298,6 +301,10 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) { mEventMarginVertical = a.getDimensionPixelSize(R.styleable.WeekView_eventMarginVertical, mEventMarginVertical); mXScrollingSpeed = a.getFloat(R.styleable.WeekView_xScrollingSpeed, mXScrollingSpeed); mEventCornerRadius = a.getDimensionPixelSize(R.styleable.WeekView_eventCornerRadius, mEventCornerRadius); + mShowDistinctPastFutureColor = a.getBoolean(R.styleable.WeekView_showDistinctPastFutureColor, mShowDistinctPastFutureColor); + mShowDistinctWeekendColor = a.getBoolean(R.styleable.WeekView_showDistinctWeekendColor, mShowDistinctWeekendColor); + mShowNowLine = a.getBoolean(R.styleable.WeekView_showNowLine, mShowNowLine); + } finally { a.recycle(); } @@ -568,10 +575,10 @@ else if (mNewHourHeight > mMaxHourHeight) // Draw background color for each day. float start = (startPixel < mHeaderColumnWidth ? mHeaderColumnWidth : startPixel); if (mWidthPerDay + startPixel - start > 0){ - if (mUseNewColoring){ - boolean isWeekend = (day.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || day.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY); - Paint pastPaint = isWeekend ? mPastWeekendBackgroundPaint : mPastBackgroundPaint; - Paint futurePaint = isWeekend ? mFutureWeekendBackgroundPaint : mFutureBackgroundPaint; + if (mShowDistinctPastFutureColor){ + boolean isWeekend = day.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || day.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY; + Paint pastPaint = isWeekend && mShowDistinctWeekendColor ? mPastWeekendBackgroundPaint : mPastBackgroundPaint; + Paint futurePaint = isWeekend && mShowDistinctWeekendColor ? mFutureWeekendBackgroundPaint : mFutureBackgroundPaint; float startY = mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom + mCurrentOrigin.y; if (sameDay){ @@ -612,7 +619,7 @@ else if (day.before(today)) { drawEvents(day, startPixel, canvas); // Draw the line at the current time. - if (mUseNewColoring && sameDay){ + if (mShowNowLine && sameDay){ float startY = mHeaderTextHeight + mHeaderRowPadding * 2 + mTimeTextHeight/2 + mHeaderMarginBottom + mCurrentOrigin.y; Calendar now = Calendar.getInstance(); float beforeNow = (now.get(Calendar.HOUR_OF_DAY) + now.get(Calendar.MINUTE)/60.0f) * mHourHeight; diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 77229ead3..0c355528a 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -26,9 +26,6 @@ - - - @@ -44,5 +41,19 @@ + + + + + + + + + + + + + + \ No newline at end of file From 3a97dfe8f23b164dd231812173ee50a7d6618b37 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Fri, 11 Dec 2015 13:46:08 +0600 Subject: [PATCH 35/39] Remove unused codes --- library/src/main/res/values/attrs.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 0c355528a..3ca02ab99 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -46,14 +46,5 @@ - - - - - - - - - \ No newline at end of file From c265c9d23e26debc22d6bc748a97c88b6e12a059 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Fri, 11 Dec 2015 14:01:32 +0600 Subject: [PATCH 36/39] Add getter and setter for new attributes --- README.md | 9 ++ .../java/com/alamkanak/weekview/WeekView.java | 99 ++++++++++++++++++- library/src/main/res/values/attrs.xml | 8 +- 3 files changed, 110 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7d3ceca73..db2d162e3 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,15 @@ You can customize the look of the `WeekView` in xml. Use the following attribute - `textSize` - `todayBackgroundColor` - `todayHeaderTextColor` +- `showDistinctPastFutureColor` +- `futureBackgroundColor` +- `pastBackgroundColor` +- `showDistinctWeekendColor` +- `futureWeekendBackgroundColor` +- `pastWeekendBackgroundColor` +- `showNowLine` +- `nowLineColor` +- `nowLineThickness` Interfaces ---------- diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index cec604914..d4f34f080 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -123,8 +123,6 @@ public class WeekView extends View { private Calendar mScrollToDay = null; private double mScrollToHour = -1; private int mEventCornerRadius = 0; - private boolean mUseDifferentPastBackgroundColor = false; - private boolean mUseDifferentFutureWeekendBackgroundColor = false; private boolean mShowDistinctWeekendColor = false; private boolean mShowNowLine = false; private boolean mShowDistinctPastFutureColor = false; @@ -1515,6 +1513,103 @@ public float getXScrollingSpeed() { public void setXScrollingSpeed(float xScrollingSpeed) { this.mXScrollingSpeed = xScrollingSpeed; } + + /** + * Whether weekends should have a background color different from the normal day background + * color. The weekend background colors are defined by the attributes + * `futureWeekendBackgroundColor` and `pastWeekendBackgroundColor`. + * @return True if weekends should have different background colors. + */ + public boolean isShowDistinctWeekendColor() { + return mShowDistinctWeekendColor; + } + + /** + * Set whether weekends should have a background color different from the normal day background + * color. The weekend background colors are defined by the attributes + * `futureWeekendBackgroundColor` and `pastWeekendBackgroundColor`. + * @param showDistinctWeekendColor True if weekends should have different background colors. + */ + public void setShowDistinctWeekendColor(boolean showDistinctWeekendColor) { + this.mShowDistinctWeekendColor = showDistinctWeekendColor; + invalidate(); + } + + /** + * Whether past and future days should have two different background colors. The past and + * future day colors are defined by the attributes `futureBackgroundColor` and + * `pastBackgroundColor`. + * @return True if past and future days should have two different background colors. + */ + public boolean isShowDistinctPastFutureColor() { + return mShowDistinctPastFutureColor; + } + + /** + * Set whether weekends should have a background color different from the normal day background + * color. The past and future day colors are defined by the attributes `futureBackgroundColor` + * and `pastBackgroundColor`. + * @param showDistinctPastFutureColor True if past and future should have two different + * background colors. + */ + public void setShowDistinctPastFutureColor(boolean showDistinctPastFutureColor) { + this.mShowDistinctPastFutureColor = showDistinctPastFutureColor; + invalidate(); + } + + /** + * Get whether "now" line should be displayed. "Now" line is defined by the attributes + * `nowLineColor` and `nowLineThickness`. + * @return True if "now" line should be displayed. + */ + public boolean isShowNowLine() { + return mShowNowLine; + } + + /** + * Set whether "now" line should be displayed. "Now" line is defined by the attributes + * `nowLineColor` and `nowLineThickness`. + * @param showNowLine True if "now" line should be displayed. + */ + public void setShowNowLine(boolean showNowLine) { + this.mShowNowLine = showNowLine; + invalidate(); + } + + /** + * Get the "now" line color. + * @return The color of the "now" line. + */ + public int getNowLineColor() { + return mNowLineColor; + } + + /** + * Set the "now" line color. + * @param nowLineColor The color of the "now" line. + */ + public void setNowLineColor(int nowLineColor) { + this.mNowLineColor = nowLineColor; + invalidate(); + } + + /** + * Get the "now" line thickness. + * @return The thickness of the "now" line. + */ + public int getNowLineThickness() { + return mNowLineThickness; + } + + /** + * Set the "now" line thickness. + * @param nowLineThickness The thickness of the "now" line. + */ + public void setNowLineThickness(int nowLineThickness) { + this.mNowLineThickness = nowLineThickness; + invalidate(); + } + ///////////////////////////////////////////////////////////////// // // Functions related to scrolling. diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml index 3ca02ab99..fccad1635 100644 --- a/library/src/main/res/values/attrs.xml +++ b/library/src/main/res/values/attrs.xml @@ -22,10 +22,6 @@ - - - - @@ -43,6 +39,10 @@ + + + + From 724646f5ceb153252f314b57b96437d620205496 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Sat, 12 Dec 2015 18:27:19 +0600 Subject: [PATCH 37/39] Update week view loader --- README.md | 3 +- .../com/alamkanak/weekview/MonthLoader.java | 26 ++++++++++++----- .../java/com/alamkanak/weekview/WeekView.java | 29 ++++++++++--------- .../alamkanak/weekview/WeekViewLoader.java | 7 +++-- .../weekview/sample/MainActivity.java | 3 +- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index db2d162e3..ef64d5c64 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,8 @@ Interfaces Use the following interfaces according to your need. -- `mWeekView.setMonthChangeListener()` to provide events to the calendar +- `mWeekView.setWeekViewLoader()` to provide events to the calendar +- `mWeekView.setMonthChangeListener()` to provide events to the calendar by months - `mWeekView.setOnEventClickListener()` to get a callback when an event is clicked - `mWeekView.setEventLongPressListener()` to get a callback when an event is long pressed - `mWeekView.setEmptyViewClickListener()` to get a callback when any empty space is clicked diff --git a/library/src/main/java/com/alamkanak/weekview/MonthLoader.java b/library/src/main/java/com/alamkanak/weekview/MonthLoader.java index c77c76e3a..1768e143b 100644 --- a/library/src/main/java/com/alamkanak/weekview/MonthLoader.java +++ b/library/src/main/java/com/alamkanak/weekview/MonthLoader.java @@ -5,27 +5,39 @@ public class MonthLoader implements WeekViewLoader { - private WeekView.MonthChangeListener mOnMonthChangeListener; - public MonthLoader(WeekView.MonthChangeListener listener){ + private MonthChangeListener mOnMonthChangeListener; + + public MonthLoader(MonthChangeListener listener){ this.mOnMonthChangeListener = listener; } @Override public double toWeekViewPeriodIndex(Calendar instance){ - return instance.get(Calendar.YEAR)*12 + instance.get(Calendar.MONTH) + (instance.get(Calendar.DAY_OF_MONTH)-1)/30.0; + return instance.get(Calendar.YEAR) * 12 + instance.get(Calendar.MONTH) + (instance.get(Calendar.DAY_OF_MONTH) - 1) / 30.0; } @Override public List onLoad(int periodIndex){ - return mOnMonthChangeListener.onMonthChange(periodIndex/12,periodIndex%12+1); + return mOnMonthChangeListener.onMonthChange(periodIndex / 12, periodIndex % 12 + 1); } - - public WeekView.MonthChangeListener getOnMonthChangeListener() { + public MonthChangeListener getOnMonthChangeListener() { return mOnMonthChangeListener; } - public void setOnMonthChangeListener(WeekView.MonthChangeListener onMonthChangeListener) { + public void setOnMonthChangeListener(MonthChangeListener onMonthChangeListener) { this.mOnMonthChangeListener = onMonthChangeListener; } + + public interface MonthChangeListener { + /** + * Very important interface, it's the base to load events in the calendar. + * This method is called three times: once to load the previous month, once to load the next month and once to load the current month.
+ * That's why you can have three times the same event at the same place if you mess up with the configuration + * @param newYear: year of the events required by the view. + * @param newMonth: month of the events required by the view
1 based (not like JAVA API) --> January = 1 and December = 12. + * @return a list of the events happening during the specified month. + */ + List onMonthChange(int newYear, int newMonth); + } } diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java index d4f34f080..e6110a05f 100755 --- a/library/src/main/java/com/alamkanak/weekview/WeekView.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java @@ -9,6 +9,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; +import android.support.annotation.Nullable; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.ViewCompat; import android.text.Layout; @@ -1119,20 +1120,32 @@ public EventClickListener getEventClickListener() { return mEventClickListener; } - public MonthChangeListener getMonthChangeListener() { + public @Nullable MonthLoader.MonthChangeListener getMonthChangeListener() { if (mWeekViewLoader instanceof MonthLoader) return ((MonthLoader) mWeekViewLoader).getOnMonthChangeListener(); return null; } - public void setMonthChangeListener(MonthChangeListener monthChangeListener) { + public void setMonthChangeListener(MonthLoader.MonthChangeListener monthChangeListener) { this.mWeekViewLoader = new MonthLoader(monthChangeListener); } + /** + * Get event loader in the week view. Event loaders define the interval after which the events + * are loaded in week view. For a MonthLoader events are loaded for every month. You can define + * your custom event loader by extending WeekViewLoader. + * @return The event loader. + */ public WeekViewLoader getWeekViewLoader(){ return mWeekViewLoader; } + /** + * Set event loader in the week view. For example, a MonthLoader. Event loaders define the + * interval after which the events are loaded in week view. For a MonthLoader events are loaded + * for every month. You can define your custom event loader by extending WeekViewLoader. + * @param loader The event loader. + */ public void setWeekViewLoader(WeekViewLoader loader){ this.mWeekViewLoader = loader; } @@ -1772,18 +1785,6 @@ public interface EventClickListener { void onEventClick(WeekViewEvent event, RectF eventRect); } - public interface MonthChangeListener { - /** - * Very important interface, it's the base to load events in the calendar. - * This method is called three times: once to load the previous month, once to load the next month and once to load the current month.
- * That's why you can have three times the same event at the same place if you mess up with the configuration - * @param newYear: year of the events required by the view. - * @param newMonth: month of the events required by the view
1 based (not like JAVA API) --> January = 1 and December = 12. - * @return a list of the events happening during the specified month. - */ - List onMonthChange(int newYear, int newMonth); - } - public interface EventLongPressListener { /** * Similar to {@link com.alamkanak.weekview.WeekView.EventClickListener} but with a long press. diff --git a/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java b/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java index c6c4b4b27..d19864318 100644 --- a/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java +++ b/library/src/main/java/com/alamkanak/weekview/WeekViewLoader.java @@ -7,17 +7,18 @@ public interface WeekViewLoader { /** * Convert a date into a double that will be used to reference when you're loading data. * - * All periods that have the same integer part, define one period. Dates that are later in time should have a greater return value. + * All periods that have the same integer part, define one period. Dates that are later in time + * should have a greater return value. * * @param instance the date * @return The period index in which the date falls (floating point number). */ - public double toWeekViewPeriodIndex(Calendar instance); + double toWeekViewPeriodIndex(Calendar instance); /** * Load the events within the period * @param periodIndex the period to load * @return A list with the events of this period */ - public List onLoad(int periodIndex); + List onLoad(int periodIndex); } diff --git a/sample/src/main/java/com/alamkanak/weekview/sample/MainActivity.java b/sample/src/main/java/com/alamkanak/weekview/sample/MainActivity.java index 724ba9c04..8ae323f34 100644 --- a/sample/src/main/java/com/alamkanak/weekview/sample/MainActivity.java +++ b/sample/src/main/java/com/alamkanak/weekview/sample/MainActivity.java @@ -9,6 +9,7 @@ import android.widget.Toast; import com.alamkanak.weekview.DateTimeInterpreter; +import com.alamkanak.weekview.MonthLoader; import com.alamkanak.weekview.WeekView; import com.alamkanak.weekview.WeekViewEvent; @@ -23,7 +24,7 @@ * Created by Raquib-ul-Alam Kanak on 7/21/2014. * Website: http://alamkanak.github.io/ */ -public class MainActivity extends ActionBarActivity implements WeekView.MonthChangeListener, +public class MainActivity extends ActionBarActivity implements MonthLoader.MonthChangeListener, WeekView.EventClickListener, WeekView.EventLongPressListener { private static final int TYPE_DAY_VIEW = 1; From eccb677b656694c8244df6e2f977588d569d5245 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Sat, 12 Dec 2015 18:38:44 +0600 Subject: [PATCH 38/39] Release version 1.2.4 --- README.md | 12 ++++++++++-- gradle.properties | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ef64d5c64..b6a0063f9 100644 --- a/README.md +++ b/README.md @@ -31,14 +31,14 @@ Usage com.github.alamkanak android-week-view - 1.2.3 + 1.2.4 aar ``` * Grab via gradle ```groovy - compile 'com.github.alamkanak:android-week-view:1.2.3' + compile 'com.github.alamkanak:android-week-view:1.2.4' ``` 2. Add WeekView in your xml layout. @@ -155,6 +155,14 @@ To do Changelog --------- +**Version 1.2.4** + +* Add support to have loaders other than MonthViewLoader +* Add pinch to zoom support +* Add support for location +* Add ability to have different colors for past, future, weekend days +* Add support for "now" line + **Version 1.2.3** * Get callbacks when scrolling horizontally diff --git a/gradle.properties b/gradle.properties index eb8507362..4172128ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -VERSION_NAME=1.2.3 +VERSION_NAME=1.2.4 GROUP=com.github.alamkanak POM_DESCRIPTION=An android library to show day view, week view, 3 day view etc. in your app. From a55ae0034a78953b46cd2aaaccb1c7b5e665cb56 Mon Sep 17 00:00:00 2001 From: Alam Kanak Date: Sat, 12 Dec 2015 19:11:24 +0600 Subject: [PATCH 39/39] Update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b6a0063f9..153d08e7f 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ Changelog **Version 1.2.4** +* **NOTE:** If you are using `WeekView.MonthChangeListener`, make sure to change it into `MonthLoader.MonthChangeListener` * Add support to have loaders other than MonthViewLoader * Add pinch to zoom support * Add support for location