Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement drawing of empty event rectangle onEmptyViewClicked #321

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 126 additions & 6 deletions library/src/main/java/com/alamkanak/weekview/WeekView.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import android.text.format.DateFormat;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
Expand All @@ -31,6 +32,7 @@
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.OverScroller;

import java.text.SimpleDateFormat;
Expand Down Expand Up @@ -81,12 +83,14 @@ private enum Direction {
private Paint mNowLinePaint;
private Paint mTodayHeaderTextPaint;
private Paint mEventBackgroundPaint;
private Paint mEmptyEventBackgroundPaint;
private float mHeaderColumnWidth;
private List<EventRect> mEventRects;
private List<? extends WeekViewEvent> mPreviousPeriodEvents;
private List<? extends WeekViewEvent> mCurrentPeriodEvents;
private List<? extends WeekViewEvent> mNextPeriodEvents;
private TextPaint mEventTextPaint;
private TextPaint mEmptyEventTextPaint;
private Paint mHeaderColumnBackgroundPaint;
private int mFetchedPeriod = -1; // the middle period the calendar has fetched.
private boolean mRefreshEvents = false;
Expand All @@ -99,6 +103,8 @@ private enum Direction {
private int mDefaultEventColor;
private int mMinimumFlingVelocity = 0;
private int mScaledTouchSlop = 0;
private float mEmptyEventX;
private int mEmptyEventTextColor = Color.WHITE;
// Attributes and their default values.
private int mHourHeight = 50;
private int mNewHourHeight = -1;
Expand Down Expand Up @@ -135,13 +141,15 @@ private enum Direction {
private int mEventMarginVertical = 0;
private float mXScrollingSpeed = 1f;
private Calendar mScrollToDay = null;
private Calendar mCachedEmptyEventDay = null;
private double mScrollToHour = -1;
private int mEventCornerRadius = 0;
private boolean mShowDistinctWeekendColor = false;
private boolean mShowNowLine = false;
private boolean mShowDistinctPastFutureColor = false;
private boolean mHorizontalFlingEnabled = true;
private boolean mVerticalFlingEnabled = true;
private boolean mShowEmptyEventRect = false;
private int mAllDayEventHeight = 100;
private int mScrollDuration = 250;

Expand Down Expand Up @@ -241,7 +249,6 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve
return true;
}


@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// If the tap was on an event then trigger the callback.
Expand All @@ -257,12 +264,15 @@ public boolean onSingleTapConfirmed(MotionEvent e) {
}
}

// If the tap was on in an empty space, then trigger the callback.
if (mEmptyViewClickListener != null && e.getX() > mHeaderColumnWidth && e.getY() > (mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom)) {
// If the tap was on an empty space, then trigger the callback.
if ((mEmptyViewClickListener != null) && e.getX() > mHeaderColumnWidth && e.getY() > (mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom)) {
Calendar selectedTime = getTimeFromPoint(e.getX(), e.getY());
if (selectedTime != null) {
playSoundEffect(SoundEffectConstants.CLICK);
mEmptyViewClickListener.onEmptyViewClicked(selectedTime);
mEmptyEventX = e.getX();
mEmptyViewClickListener.onEmptyViewClicked(selectedTime, isSameDayAndHour(selectedTime, mCachedEmptyEventDay));
mCachedEmptyEventDay = selectedTime;
invalidate();
}
}

Expand Down Expand Up @@ -419,6 +429,10 @@ private void init() {
mTodayBackgroundPaint = new Paint();
mTodayBackgroundPaint.setColor(mTodayBackgroundColor);

// Prepare header column background color.
mEmptyEventBackgroundPaint = new Paint();
mEmptyEventBackgroundPaint.setColor(Color.argb(128, 60, 147, 217));

// Prepare today header text color paint.
mTodayHeaderTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTodayHeaderTextPaint.setTextAlign(Paint.Align.CENTER);
Expand All @@ -440,6 +454,12 @@ private void init() {
mEventTextPaint.setColor(mEventTextColor);
mEventTextPaint.setTextSize(mEventTextSize);

// Prepare empty event text size and color.
mEmptyEventTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
mEmptyEventTextPaint.setStyle(Paint.Style.FILL);
mEmptyEventTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
mEmptyEventTextPaint.setColor(mEmptyEventTextColor);

// Set default event color.
mDefaultEventColor = Color.parseColor("#9fc6e7");

Expand Down Expand Up @@ -528,7 +548,8 @@ private void calculateHeaderHeight(){

private void drawTimeColumnAndAxes(Canvas canvas) {
// Draw the background color for the header column.
canvas.drawRect(0, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, getHeight(), mHeaderColumnBackgroundPaint);
canvas.drawRect(0, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, getHeight()
, mHeaderColumnBackgroundPaint);

// Clip to paint in left column only.
canvas.clipRect(0, mHeaderHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, getHeight(), Region.Op.REPLACE);
Expand Down Expand Up @@ -712,6 +733,12 @@ else if (day.before(today)) {
startPixel += mWidthPerDay + mColumnGap;
}

//Draw empty event
if (mShowEmptyEventRect && (mCurrentScrollDirection == Direction.NONE || mCurrentScrollDirection == Direction.VERTICAL) && mCachedEmptyEventDay != null)
{
drawEmptyEvent(canvas);
} else mCachedEmptyEventDay = null;

// Hide everything in the first cell (top left corner).
canvas.clipRect(0, 0, mTimeTextWidth + mHeaderColumnPadding * 2, mHeaderHeight + mHeaderRowPadding * 2, Region.Op.REPLACE);
canvas.drawRect(0, 0, mTimeTextWidth + mHeaderColumnPadding * 2, mHeaderHeight + mHeaderRowPadding * 2, mHeaderBackgroundPaint);
Expand Down Expand Up @@ -816,6 +843,94 @@ top < getHeight() &&
}
}

/**
* Draw empty event
*
* @param canvas The canvas to draw upon.
*/
private void drawEmptyEvent(Canvas canvas) {
Calendar day = today();
day.add(Calendar.HOUR, 6);
int leftDaysWithGaps = (int) -(Math.ceil(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)));

for (int dayNumber = leftDaysWithGaps + 1; dayNumber <= leftDaysWithGaps + mNumberOfVisibleDays + 1; dayNumber++) {
// Check if the day is today.
day = (Calendar) today().clone();
day.add(Calendar.DATE, dayNumber - 1);

boolean sameDay = isSameDay(day, mCachedEmptyEventDay);
if (sameDay) {
float bottom = (mCachedEmptyEventDay.get(Calendar.HOUR_OF_DAY) + 1) * 60;
bottom = mHourHeight * 24 * bottom / 1440 + mCurrentOrigin.y + mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight / 2 - mEventMarginVertical;
float top = mCachedEmptyEventDay.get(Calendar.HOUR_OF_DAY) * 60;
top = mHourHeight * 24 * top /1440 + mCurrentOrigin.y + mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight / 2 + mEventMarginVertical;

// Calculate left and right.
float left = 0;
for (int i =0; i < mNumberOfVisibleDays + 1; i++) {
int j = i + 1;
float h_wpd = mHeaderColumnWidth + (mWidthPerDay * j);
if (i != 0) h_wpd += (mColumnGap * j);
if (mEmptyEventX <= h_wpd){
left = mHeaderColumnWidth;
if (i != 0) left += (mWidthPerDay * i) + (mColumnGap * i);
break;
}
}
float right = left + mWidthPerDay;

// Draw the empty event and text on of rectangle
RectF dayRectF = new RectF(left, top, right, bottom);
canvas.drawRect(dayRectF, mEmptyEventBackgroundPaint);
drawEmptyText("+", canvas, dayRectF.centerX(), dayRectF.centerY());
break;
}

}
}

/**
* Draw text on top of the empty event rectangle.
* @param text The text to draw.
* @param canvas The canvas to draw upon.
* @param rectX The horizontal center of the rectangle.
* @param rectY the vertical center of the rectangle.
*/
public void drawEmptyText(String text, Canvas canvas, float rectX, float rectY) {
// Get text dimensions
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metrics);
float textSize = 18f;
switch (metrics.densityDpi) {
case DisplayMetrics.DENSITY_LOW:
textSize = textSize * 0.75f;
break;
case DisplayMetrics.DENSITY_MEDIUM:
textSize = textSize * 1f;
break;
case DisplayMetrics.DENSITY_HIGH:
textSize = textSize * 1.5f;
break;
case DisplayMetrics.DENSITY_XHIGH:
textSize = textSize * 2.0f;
break;
case DisplayMetrics.DENSITY_XXHIGH:
textSize = textSize * 2.5f;
break;
}

mEmptyEventTextPaint.setTextSize(textSize);
mEmptyEventTextPaint.setColor(mEmptyEventTextColor);

// Draw text
canvas.save();
Rect textBounds = new Rect();
mEmptyEventTextPaint.getTextBounds(text, 0, text.length(), textBounds);
canvas.drawText(text, rectX - textBounds.exactCenterX(), rectY - textBounds.exactCenterY(), mEmptyEventTextPaint);
canvas.restore();
}

/**
* Draw all the Allday-events of a particular day.
* @param date The day.
Expand Down Expand Up @@ -1407,6 +1522,10 @@ public void setShowFirstDayOfWeekFirst(boolean show) {
mShowFirstDayOfWeekFirst = show;
}

public void setShowEmptyEventRect(boolean show) {
mShowEmptyEventRect = show;
}

public int getTextSize() {
return mTextSize;
}
Expand Down Expand Up @@ -1912,6 +2031,7 @@ private boolean forceFinishScroll() {
public void goToToday() {
Calendar today = Calendar.getInstance();
goToDate(today);
mCachedEmptyEventDay = null;
}

/**
Expand Down Expand Up @@ -2018,7 +2138,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.
*/
void onEmptyViewClicked(Calendar time);
void onEmptyViewClicked(Calendar time, boolean clickedTwice);
}

public interface EmptyViewLongPressListener {
Expand Down
15 changes: 15 additions & 0 deletions library/src/main/java/com/alamkanak/weekview/WeekViewUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,19 @@ public static Calendar today(){
today.set(Calendar.MILLISECOND, 0);
return today;
}

/**
* Checks if two times are on the same day and hour.
*
* @param dayOne The first day.
* @param dayTwo The second day.
* @return Whether the times are on the same day and hour.
*/
public static boolean isSameDayAndHour(Calendar dayOne, Calendar dayTwo) {

if (dayTwo != null) {
return dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR) && dayOne.get(Calendar.DAY_OF_YEAR) == dayTwo.get(Calendar.DAY_OF_YEAR) && dayOne.get(Calendar.HOUR_OF_DAY) == dayTwo.get(Calendar.HOUR_OF_DAY);
}
return false;
}
}
1 change: 1 addition & 0 deletions library/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<attr name="todayHeaderTextColor" format="color"/>
<attr name="hourSeparatorHeight" format="dimension"/>
<attr name="eventTextColor" format="color"/>
<attr name="emptyEventTextColor" format="color"/>
<attr name="eventPadding" format="dimension"/>
<attr name="headerColumnBackground" format="color"/>
<attr name="dayNameLength" format="enum">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* Created by Raquib-ul-Alam Kanak on 1/3/2014.
* Website: http://alamkanak.github.io
*/
public abstract class BaseActivity extends AppCompatActivity implements WeekView.EventClickListener, MonthLoader.MonthChangeListener, WeekView.EventLongPressListener, WeekView.EmptyViewLongPressListener {
public abstract class BaseActivity extends AppCompatActivity implements WeekView.EventClickListener, MonthLoader.MonthChangeListener, WeekView.EventLongPressListener, WeekView.EmptyViewLongPressListener, WeekView.EmptyViewClickListener {
private static final int TYPE_DAY_VIEW = 1;
private static final int TYPE_THREE_DAY_VIEW = 2;
private static final int TYPE_WEEK_VIEW = 3;
Expand Down Expand Up @@ -52,6 +52,12 @@ protected void onCreate(Bundle savedInstanceState) {
// Set long press listener for empty view
mWeekView.setEmptyViewLongPressListener(this);

// Set listener for empty event view
mWeekView.setEmptyViewClickListener(this);

// Show Empty Event Rectangle
mWeekView.setShowEmptyEventRect(true);

// Set up a date time interpreter to interpret how the date and time will be formatted in
// the week view. This is optional.
setupDateTimeInterpreter(false);
Expand Down Expand Up @@ -160,6 +166,14 @@ public void onEmptyViewLongPress(Calendar time) {
Toast.makeText(this, "Empty view long pressed: " + getEventTitle(time), Toast.LENGTH_SHORT).show();
}

@Override
public void onEmptyViewClicked(Calendar time, boolean clickedTwice)
{
if(clickedTwice) {
Toast.makeText(getApplicationContext(), "Clicked Twice", Toast.LENGTH_SHORT).show();
}
}

public WeekView getWeekView() {
return mWeekView;
}
Expand Down