Skip to content

Commit 6621e83

Browse files
author
Jens Claes
committed
Vertical zoom on weekview. Fixes #8
Based on code from @sylvaindd. The min and maxHourHeight are configurable via attributes.
1 parent 95581d6 commit 6621e83

File tree

2 files changed

+77
-17
lines changed

2 files changed

+77
-17
lines changed

library/src/main/java/com/alamkanak/weekview/WeekView.java

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import android.view.GestureDetector;
2323
import android.view.HapticFeedbackConstants;
2424
import android.view.MotionEvent;
25+
import android.view.ScaleGestureDetector;
2526
import android.view.SoundEffectConstants;
2627
import android.view.View;
2728
import android.widget.OverScroller;
@@ -80,6 +81,10 @@ public class WeekView extends View {
8081

8182
// Attributes and their default values.
8283
private int mHourHeight = 50;
84+
private int mNewHourHeight = -1;
85+
private int mMinHourHeight = 0; //no minimum specified (will be dynamic, based on screen)
86+
private int mEffectiveMinHourHeight = mMinHourHeight; //compensates for the fact that you can't keep zooming out.
87+
private int mMaxHourHeight = 250;
8388
private int mColumnGap = 10;
8489
private int mFirstDayOfWeek = Calendar.MONDAY;
8590
private int mTextSize = 12;
@@ -115,6 +120,8 @@ public class WeekView extends View {
115120
private Calendar mLastVisibleDay;
116121
private Calendar mScrollToDay = null;
117122
private double mScrollToHour = -1;
123+
private ScaleGestureDetector mScaleDetector;
124+
private boolean mIsZooming;
118125

119126
// Listeners.
120127
private EventClickListener mEventClickListener;
@@ -136,6 +143,8 @@ public boolean onDown(MotionEvent e) {
136143

137144
@Override
138145
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
146+
if(mIsZooming)
147+
return true;
139148
if (mCurrentScrollDirection == Direction.NONE) {
140149
if (Math.abs(distanceX) > Math.abs(distanceY)){
141150
mCurrentScrollDirection = Direction.HORIZONTAL;
@@ -245,6 +254,9 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) {
245254
try {
246255
mFirstDayOfWeek = a.getInteger(R.styleable.WeekView_firstDayOfWeek, mFirstDayOfWeek);
247256
mHourHeight = a.getDimensionPixelSize(R.styleable.WeekView_hourHeight, mHourHeight);
257+
mMinHourHeight = a.getDimensionPixelSize(R.styleable.WeekView_minHourHeight, mMinHourHeight);
258+
mEffectiveMinHourHeight = mMinHourHeight;
259+
mMaxHourHeight = a.getDimensionPixelSize(R.styleable.WeekView_maxHourHeight, mMaxHourHeight);
248260
mTextSize = a.getDimensionPixelSize(R.styleable.WeekView_textSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mTextSize, context.getResources().getDisplayMetrics()));
249261
mHeaderColumnPadding = a.getDimensionPixelSize(R.styleable.WeekView_headerColumnPadding, mHeaderColumnPadding);
250262
mColumnGap = a.getDimensionPixelSize(R.styleable.WeekView_columnGap, mColumnGap);
@@ -359,6 +371,33 @@ private void init() {
359371

360372
// Set default event color.
361373
mDefaultEventColor = Color.parseColor("#9fc6e7");
374+
375+
mScaleDetector = new ScaleGestureDetector(mContext, new ScaleGestureDetector.OnScaleGestureListener() {
376+
@Override
377+
public void onScaleEnd(ScaleGestureDetector detector) {
378+
mIsZooming = false;
379+
}
380+
381+
@Override
382+
public boolean onScaleBegin(ScaleGestureDetector detector) {
383+
mIsZooming = true;
384+
mScroller.forceFinished(true);
385+
mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE;
386+
goToNearestOrigin();
387+
return true;
388+
}
389+
390+
@Override
391+
public boolean onScale(ScaleGestureDetector detector) {
392+
mNewHourHeight = Math.round(mHourHeight * detector.getScaleFactor());
393+
if(mNewHourHeight < mEffectiveMinHourHeight)
394+
mNewHourHeight = mEffectiveMinHourHeight;
395+
else if(mNewHourHeight > mMaxHourHeight)
396+
mNewHourHeight = mMaxHourHeight;
397+
invalidate();
398+
return true;
399+
}
400+
});
362401
}
363402

364403
/**
@@ -387,13 +426,6 @@ protected void onDraw(Canvas canvas) {
387426
}
388427

389428
private void drawTimeColumnAndAxes(Canvas canvas) {
390-
// Do not let the view go above/below the limit due to scrolling. Set the max and min limit of the scroll.
391-
if (mCurrentScrollDirection == Direction.VERTICAL) {
392-
if (mCurrentOrigin.y - mDistanceY > 0) mCurrentOrigin.y = 0;
393-
else if (mCurrentOrigin.y - mDistanceY < -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 - getHeight())) mCurrentOrigin.y = -(mHourHeight * 24 + mHeaderTextHeight + mHeaderRowPadding * 2 - getHeight());
394-
else mCurrentOrigin.y -= mDistanceY;
395-
}
396-
397429
// Draw the background color for the header column.
398430
canvas.drawRect(0, mHeaderTextHeight + mHeaderRowPadding * 2, mHeaderColumnWidth, getHeight(), mHeaderColumnBackgroundPaint);
399431

@@ -418,6 +450,7 @@ private void drawHeaderRowAndEvents(Canvas canvas) {
418450

419451
if (mAreDimensionsInvalid) {
420452
mAreDimensionsInvalid = false;
453+
mEffectiveMinHourHeight= Math.max(mMinHourHeight, (int) ((getHeight() - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) / 24));
421454

422455
if(mScrollToDay != null)
423456
goToDate(mScrollToDay);
@@ -434,6 +467,25 @@ private void drawHeaderRowAndEvents(Canvas canvas) {
434467
}
435468
}
436469

470+
// Do not let the view go above/below the limit due to scrolling. Set the max and min limit of the scroll.
471+
if (mCurrentScrollDirection == Direction.VERTICAL)
472+
mCurrentOrigin.y -= mDistanceY;
473+
474+
475+
//Calculate the new height due to the zooming.
476+
if (mNewHourHeight > 0){
477+
mCurrentOrigin.y = (mCurrentOrigin.y/mHourHeight)*mNewHourHeight;
478+
mHourHeight = mNewHourHeight;
479+
mNewHourHeight = -1;
480+
}
481+
482+
//if the new mCurrentOrigin.y is invalid, make it valid.
483+
if (mCurrentOrigin.y < getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom)
484+
mCurrentOrigin.y = getHeight() - mHourHeight * 24 - mHeaderTextHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom;
485+
//Don't put an else if because it will trigger a glitch when completly zoomed out and scrolling vertically.
486+
if(mCurrentOrigin.y > 0)
487+
mCurrentOrigin.y = 0;
488+
437489
// Consider scroll offset.
438490
if (mCurrentScrollDirection == Direction.HORIZONTAL) mCurrentOrigin.x -= mDistanceX;
439491
int leftDaysWithGaps = (int) -(Math.ceil(mCurrentOrigin.x / (mWidthPerDay + mColumnGap)));
@@ -1389,23 +1441,29 @@ public void setXScrollingSpeed(float xScrollingSpeed) {
13891441

13901442
@Override
13911443
public boolean onTouchEvent(MotionEvent event) {
1392-
if (event.getAction() == MotionEvent.ACTION_UP) {
1393-
1444+
if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming) {
13941445
if (mCurrentScrollDirection == Direction.HORIZONTAL) {
1395-
float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap));
1396-
if(mDistanceX > 0)
1397-
leftDays--;
1398-
else
1399-
leftDays++;
1400-
int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap));
1401-
mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0);
1402-
ViewCompat.postInvalidateOnAnimation(WeekView.this);
1446+
goToNearestOrigin();
14031447
}
14041448
mCurrentScrollDirection = Direction.NONE;
14051449
}
1450+
mScaleDetector.onTouchEvent(event);
14061451
return mGestureDetector.onTouchEvent(event);
14071452
}
14081453

1454+
private void goToNearestOrigin(){
1455+
float leftDays = Math.round(mCurrentOrigin.x / (mWidthPerDay + mColumnGap));
1456+
if(!mIsZooming){
1457+
if(mDistanceX > 0)
1458+
leftDays--;
1459+
else
1460+
leftDays++;
1461+
}
1462+
int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay+mColumnGap));
1463+
mStickyScroller.startScroll((int) mCurrentOrigin.x, 0, - nearestOrigin, 0);
1464+
ViewCompat.postInvalidateOnAnimation(WeekView.this);
1465+
}
1466+
14091467

14101468
@Override
14111469
public void computeScroll() {

library/src/main/res/values/attrs.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
<enum name="saturday" value="7"/>
1212
</attr>
1313
<attr name="hourHeight" format="dimension"/>
14+
<attr name="minHourHeight" format="dimension"/>
15+
<attr name="maxHourHeight" format="dimension"/>
1416
<attr name="textSize" format="dimension"/>
1517
<attr name="eventTextSize" format="dimension"/>
1618
<attr name="headerColumnPadding" format="dimension"/>

0 commit comments

Comments
 (0)