diff --git a/README.md b/README.md
index 84af91d82..03669b973 100644
--- a/README.md
+++ b/README.md
@@ -105,6 +105,8 @@ You can customize the look of the `WeekView` in xml. Use the following attribute
- `eventTextColor`
- `eventTextSize`
- `firstDayOfWeek`
+- `zoomFocusPoint` The focused point (percentage of the view height) where the week view is zoomed around. This point will not move while zooming. You can declare it as a fraction `app:focusPoint="30%"` and if is not declared the top of the view is used.
+- `zoomFocusPointEnabled` If you set this to ``false`` the zoomFocusPoint won't take effect any more while zooming. The zoom will always be focused at the center of your gesture.
- `headerColumnBackground`
- `headerColumnPadding`
- `headerColumnTextColor`
diff --git a/library/src/main/java/com/alamkanak/weekview/WeekView.java b/library/src/main/java/com/alamkanak/weekview/WeekView.java
index da3fa71a0..fd3437508 100755
--- a/library/src/main/java/com/alamkanak/weekview/WeekView.java
+++ b/library/src/main/java/com/alamkanak/weekview/WeekView.java
@@ -142,7 +142,9 @@ private enum Direction {
private boolean mShowDistinctPastFutureColor = false;
private boolean mHorizontalFlingEnabled = true;
private boolean mVerticalFlingEnabled = true;
- private int mAllDayEventHeight = 100;
+ private int mAllDayEventHeight= 100;
+ private float mZoomFocusPoint = 0;
+ private boolean mZoomFocusPointEnabled = true;
private int mScrollDuration = 250;
// Listeners.
@@ -352,6 +354,8 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) {
mHorizontalFlingEnabled = a.getBoolean(R.styleable.WeekView_horizontalFlingEnabled, mHorizontalFlingEnabled);
mVerticalFlingEnabled = a.getBoolean(R.styleable.WeekView_verticalFlingEnabled, mVerticalFlingEnabled);
mAllDayEventHeight = a.getDimensionPixelSize(R.styleable.WeekView_allDayEventHeight, mAllDayEventHeight);
+ mZoomFocusPoint = a.getFraction(R.styleable.WeekView_zoomFocusPoint, 1, 1, mZoomFocusPoint);
+ mZoomFocusPointEnabled = a.getBoolean(R.styleable.WeekView_zoomFocusPointEnabled, mZoomFocusPointEnabled);
mScrollDuration = a.getInt(R.styleable.WeekView_scrollDuration, mScrollDuration);
} finally {
a.recycle();
@@ -443,26 +447,7 @@ 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;
- goToNearestOrigin();
- return true;
- }
-
- @Override
- public boolean onScale(ScaleGestureDetector detector) {
- mNewHourHeight = Math.round(mHourHeight * detector.getScaleFactor());
- invalidate();
- return true;
- }
- });
+ mScaleDetector = new ScaleGestureDetector(mContext, new WeekViewGestureListener());
}
// fix rotation changes
@@ -586,7 +571,6 @@ private void drawHeaderRowAndEvents(Canvas canvas) {
else if (mNewHourHeight > mMaxHourHeight)
mNewHourHeight = mMaxHourHeight;
- mCurrentOrigin.y = (mCurrentOrigin.y/mHourHeight)*mNewHourHeight;
mHourHeight = mNewHourHeight;
mNewHourHeight = -1;
}
@@ -1798,6 +1782,45 @@ public void setAllDayEventHeight(int height) {
mAllDayEventHeight = height;
}
+ /**
+ * Enable zoom focus point
+ * If you set this to false the `zoomFocusPoint` won't take effect any more while zooming.
+ * The zoom will always be focused at the center of your gesture.
+ */
+ public void setZoomFocusPointEnabled(boolean zoomFocusPointEnabled) {
+ mZoomFocusPointEnabled = zoomFocusPointEnabled;
+ }
+
+ /*
+ * Is focus point enabled
+ * @return fixed focus point enabled?
+ */
+ public boolean isZoomFocusPointEnabled() {
+ return mZoomFocusPointEnabled;
+ }
+
+ /*
+ * Get focus point
+ * 0 = top of view, 1 = bottom of view
+ * The focused point (multiplier of the view height) where the week view is zoomed around.
+ * This point will not move while zooming.
+ * @return focus point
+ */
+ public float getZoomFocusPoint() {
+ return mZoomFocusPoint;
+ }
+
+ /**
+ * Set focus point
+ * 0 = top of view, 1 = bottom of view
+ * The focused point (multiplier of the view height) where the week view is zoomed around.
+ * This point will not move while zooming.
+ */
+ public void setZoomFocusPoint(int zoomFocusPoint) {
+ mZoomFocusPoint = zoomFocusPoint;
+ }
+
+
/**
* Get scroll duration
* @return scroll duration
@@ -2039,4 +2062,52 @@ public interface ScrollListener {
*/
void onFirstVisibleDayChanged(Calendar newFirstVisibleDay, Calendar oldFirstVisibleDay);
}
+
+ /**
+ * A simple GestureListener that holds the focused hour while scaling.
+ */
+ private class WeekViewGestureListener implements ScaleGestureDetector.OnScaleGestureListener {
+
+ float mFocusedPointY;
+
+ @Override
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ mIsZooming = false;
+ }
+
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ mIsZooming = true;
+ goToNearestOrigin();
+
+ // Calculate focused point for scale action
+ if (mZoomFocusPointEnabled) {
+ // Use fractional focus, percentage of height
+ mFocusedPointY = (getHeight() - mHeaderHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) * mZoomFocusPoint;
+ } else {
+ // Grab focus
+ mFocusedPointY = detector.getFocusY();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ final float scale = detector.getScaleFactor();
+
+ mNewHourHeight = Math.round(mHourHeight * scale);
+
+ // Calculating difference
+ float diffY = mFocusedPointY - mCurrentOrigin.y;
+ // Scaling difference
+ diffY = diffY * scale - diffY;
+ // Updating week view origin
+ mCurrentOrigin.y -= diffY;
+
+ invalidate();
+ return true;
+ }
+
+ }
}
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index a37a3717b..affc40c92 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -50,6 +50,8 @@
+
+