16224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalapackage com.androidplot.xy; 26224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 36224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalaimport android.content.Context; 46224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalaimport android.graphics.PointF; 56224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalaimport android.util.AttributeSet; 66224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalaimport android.view.MotionEvent; 76224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalaimport android.view.View; 86224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalaimport android.view.View.OnTouchListener; 96224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 106224eda509d436a575f801942337da92a6c18767Eino-Ville Talvalapublic class XYPlotZoomPan extends XYPlot implements OnTouchListener { 116224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private static final float MIN_DIST_2_FING = 5f; 126224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 136224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // Definition of the touch states 146224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private enum State 156224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala { 166224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala NONE, 176224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala ONE_FINGER_DRAG, 186224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala TWO_FINGERS_DRAG 196224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 206224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 216224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private State mode = State.NONE; 226224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float minXLimit = Float.MAX_VALUE; 236224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float maxXLimit = Float.MAX_VALUE; 246224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float minYLimit = Float.MAX_VALUE; 256224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float maxYLimit = Float.MAX_VALUE; 266224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float lastMinX = Float.MAX_VALUE; 276224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float lastMaxX = Float.MAX_VALUE; 286224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float lastMinY = Float.MAX_VALUE; 296224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float lastMaxY = Float.MAX_VALUE; 306224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private PointF firstFingerPos; 316224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float mDistX; 326224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mZoomEnabled; //default is enabled 336224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mZoomVertically; 346224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mZoomHorizontally; 356224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mCalledBySelf; 366224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mZoomEnabledInit; 376224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mZoomVerticallyInit; 386224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private boolean mZoomHorizontallyInit; 396224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 406224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public XYPlotZoomPan(Context context, String title, RenderMode mode) { 416224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super(context, title, mode); 426224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala setZoomEnabled(true); //Default is ZoomEnabled if instantiated programmatically 436224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 446224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 456224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public XYPlotZoomPan(final Context context, final AttributeSet attrs) { 466224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super(context, attrs); 476224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mZoomEnabled || !mZoomEnabledInit) { 486224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala setZoomEnabled(true); 496224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 506224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(!mZoomHorizontallyInit) { 516224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomHorizontally = true; 526224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 536224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(!mZoomVerticallyInit) { 546224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomVertically = true; 556224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 566224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 576224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 586224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public XYPlotZoomPan(final Context context, final AttributeSet attrs, final int defStyle) { 596224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super(context, attrs, defStyle); 606224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mZoomEnabled || !mZoomEnabledInit) { 616224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala setZoomEnabled(true); 626224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 636224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(!mZoomHorizontallyInit) { 646224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomHorizontally = true; 656224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 666224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(!mZoomVerticallyInit) { 676224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomVertically = true; 686224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 696224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 706224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 716224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public XYPlotZoomPan(final Context context, final String title) { 726224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super(context, title); 736224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 746224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 756224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala @Override 766224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public void setOnTouchListener(OnTouchListener l) { 776224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(l != this) { 786224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomEnabled = false; 796224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 806224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setOnTouchListener(l); 816224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 826224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 836224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public boolean getZoomVertically() { 846224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return mZoomVertically; 856224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 866224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 876224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public void setZoomVertically(boolean zoomVertically) { 886224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomVertically = zoomVertically; 896224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomVerticallyInit = true; 906224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 916224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 926224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public boolean getZoomHorizontally() { 936224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return mZoomHorizontally; 946224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 956224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 966224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public void setZoomHorizontally(boolean zoomHorizontally) { 976224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomHorizontally = zoomHorizontally; 986224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomHorizontallyInit = true; 996224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1006224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1016224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public void setZoomEnabled(boolean enabled) { 1026224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(enabled) { 1036224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala setOnTouchListener(this); 1046224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 1056224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala setOnTouchListener(null); 1066224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1076224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomEnabled = enabled; 1086224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mZoomEnabledInit = true; 1096224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1106224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1116224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public boolean getZoomEnabled() { 1126224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return mZoomEnabled; 1136224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1146224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1156224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getMinXLimit() { 1166224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(minXLimit == Float.MAX_VALUE) { 1176224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala minXLimit = getCalculatedMinX().floatValue(); 1186224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinX = minXLimit; 1196224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1206224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return minXLimit; 1216224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1226224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1236224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getMaxXLimit() { 1246224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(maxXLimit == Float.MAX_VALUE) { 1256224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala maxXLimit = getCalculatedMaxX().floatValue(); 1266224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxX = maxXLimit; 1276224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1286224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return maxXLimit; 1296224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1306224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1316224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getMinYLimit() { 1326224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(minYLimit == Float.MAX_VALUE) { 1336224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala minYLimit = getCalculatedMinY().floatValue(); 1346224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinY = minYLimit; 1356224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1366224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return minYLimit; 1376224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1386224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1396224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getMaxYLimit() { 1406224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(maxYLimit == Float.MAX_VALUE) { 1416224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala maxYLimit = getCalculatedMaxY().floatValue(); 1426224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxY = maxYLimit; 1436224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1446224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return maxYLimit; 1456224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1466224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1476224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getLastMinX() { 1486224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(lastMinX == Float.MAX_VALUE) { 1496224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinX = getCalculatedMinX().floatValue(); 1506224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1516224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return lastMinX; 1526224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1536224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1546224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getLastMaxX() { 1556224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(lastMaxX == Float.MAX_VALUE) { 1566224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxX = getCalculatedMaxX().floatValue(); 1576224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1586224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return lastMaxX; 1596224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1606224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1616224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getLastMinY() { 1626224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(lastMinY == Float.MAX_VALUE) { 1636224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinY = getCalculatedMinY().floatValue(); 1646224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1656224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return lastMinY; 1666224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1676224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1686224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getLastMaxY() { 1696224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(lastMaxY == Float.MAX_VALUE) { 1706224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxY = getCalculatedMaxY().floatValue(); 1716224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1726224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return lastMaxY; 1736224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1746224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1756224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala @Override 1766224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public synchronized void setDomainBoundaries(final Number lowerBoundary, final BoundaryMode lowerBoundaryMode, final Number upperBoundary, final BoundaryMode upperBoundaryMode) { 1776224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setDomainBoundaries(lowerBoundary, lowerBoundaryMode, upperBoundary, upperBoundaryMode); 1786224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mCalledBySelf) { 1796224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = false; 1806224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 1816224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala minXLimit = lowerBoundaryMode == BoundaryMode.FIXED ? lowerBoundary.floatValue() : getCalculatedMinX().floatValue(); 1826224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala maxXLimit = upperBoundaryMode == BoundaryMode.FIXED ? upperBoundary.floatValue() : getCalculatedMaxX().floatValue(); 1836224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinX = minXLimit; 1846224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxX = maxXLimit; 1856224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1866224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1876224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 1886224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala @Override 1896224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public synchronized void setRangeBoundaries(final Number lowerBoundary, final BoundaryMode lowerBoundaryMode, final Number upperBoundary, final BoundaryMode upperBoundaryMode) { 1906224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setRangeBoundaries(lowerBoundary, lowerBoundaryMode, upperBoundary, upperBoundaryMode); 1916224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mCalledBySelf) { 1926224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = false; 1936224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 1946224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala minYLimit = lowerBoundaryMode == BoundaryMode.FIXED ? lowerBoundary.floatValue() : getCalculatedMinY().floatValue(); 1956224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala maxYLimit = upperBoundaryMode == BoundaryMode.FIXED ? upperBoundary.floatValue() : getCalculatedMaxY().floatValue(); 1966224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinY = minYLimit; 1976224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxY = maxYLimit; 1986224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 1996224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2006224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 2016224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala @Override 2026224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public synchronized void setDomainBoundaries(final Number lowerBoundary, final Number upperBoundary, final BoundaryMode mode) { 2036224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setDomainBoundaries(lowerBoundary, upperBoundary, mode); 2046224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mCalledBySelf) { 2056224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = false; 2066224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 2076224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala minXLimit = mode == BoundaryMode.FIXED ? lowerBoundary.floatValue() : getCalculatedMinX().floatValue(); 2086224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala maxXLimit = mode == BoundaryMode.FIXED ? upperBoundary.floatValue() : getCalculatedMaxX().floatValue(); 2096224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinX = minXLimit; 2106224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxX = maxXLimit; 2116224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2126224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2136224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 2146224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala @Override 2156224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public synchronized void setRangeBoundaries(final Number lowerBoundary, final Number upperBoundary, final BoundaryMode mode) { 2166224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setRangeBoundaries(lowerBoundary, upperBoundary, mode); 2176224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mCalledBySelf) { 2186224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = false; 2196224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 2206224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala minYLimit = mode == BoundaryMode.FIXED ? lowerBoundary.floatValue() : getCalculatedMinY().floatValue(); 2216224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala maxYLimit = mode == BoundaryMode.FIXED ? upperBoundary.floatValue() : getCalculatedMaxY().floatValue(); 2226224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinY = minYLimit; 2236224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxY = maxYLimit; 2246224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2256224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2266224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 2276224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala @Override 2286224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala public boolean onTouch(final View view, final MotionEvent event) { 2296224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala switch (event.getAction() & MotionEvent.ACTION_MASK) 2306224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala { 2316224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala case MotionEvent.ACTION_DOWN: // start gesture 2326224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala firstFingerPos = new PointF(event.getX(), event.getY()); 2336224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mode = State.ONE_FINGER_DRAG; 2346224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala break; 2356224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala case MotionEvent.ACTION_POINTER_DOWN: // second finger 2366224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala { 2376224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mDistX = getXDistance(event); 2386224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // the distance check is done to avoid false alarms 2396224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mDistX > MIN_DIST_2_FING || mDistX < -MIN_DIST_2_FING) { 2406224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mode = State.TWO_FINGERS_DRAG; 2416224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2426224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala break; 2436224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2446224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala case MotionEvent.ACTION_POINTER_UP: // end zoom 2456224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mode = State.NONE; 2466224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala break; 2476224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala case MotionEvent.ACTION_MOVE: 2486224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mode == State.ONE_FINGER_DRAG) { 2496224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala pan(event); 2506224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else if(mode == State.TWO_FINGERS_DRAG) { 2516224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala zoom(event); 2526224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2536224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala break; 2546224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2556224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return true; 2566224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2576224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 2586224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private float getXDistance(final MotionEvent event) { 2596224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return event.getX(0) - event.getX(1); 2606224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2616224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 2626224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private void pan(final MotionEvent motionEvent) { 2636224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final PointF oldFirstFinger = firstFingerPos; //save old position of finger 2646224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala firstFingerPos = new PointF(motionEvent.getX(), motionEvent.getY()); //update finger position 2656224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala PointF newX = new PointF(); 2666224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mZoomHorizontally) { 2676224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala calculatePan(oldFirstFinger, newX, true); 2686224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = true; 2696224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setDomainBoundaries(newX.x, newX.y, BoundaryMode.FIXED); 2706224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinX = newX.x; 2716224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxX = newX.y; 2726224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2736224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mZoomVertically) { 2746224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala calculatePan(oldFirstFinger, newX, false); 2756224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = true; 2766224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setRangeBoundaries(newX.x, newX.y, BoundaryMode.FIXED); 2776224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinY = newX.x; 2786224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxY = newX.y; 2796224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2806224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala redraw(); 2816224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2826224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 2836224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private void calculatePan(final PointF oldFirstFinger, PointF newX, final boolean horizontal) { 2846224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float offset; 2856224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // multiply the absolute finger movement for a factor. 2866224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // the factor is dependent on the calculated min and max 2876224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(horizontal) { 2886224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = getLastMinX(); 2896224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = getLastMaxX(); 2906224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala offset = (oldFirstFinger.x - firstFingerPos.x) * ((newX.y - newX.x) / getWidth()); 2916224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 2926224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = getLastMinY(); 2936224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = getLastMaxY(); 2946224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala offset = -(oldFirstFinger.y - firstFingerPos.y) * ((newX.y - newX.x) / getHeight()); 2956224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 2966224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // move the calculated offset 2976224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = newX.x + offset; 2986224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = newX.y + offset; 2996224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala //get the distance between max and min 3006224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float diff = newX.y - newX.x; 3016224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala //check if we reached the limit of panning 3026224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(horizontal) { 3036224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.x < getMinXLimit()) { 3046224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = getMinXLimit(); 3056224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = newX.x + diff; 3066224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3076224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.y > getMaxXLimit()) { 3086224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = getMaxXLimit(); 3096224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = newX.y - diff; 3106224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3116224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 3126224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.x < getMinYLimit()) { 3136224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = getMinYLimit(); 3146224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = newX.x + diff; 3156224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3166224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.y > getMaxYLimit()) { 3176224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = getMaxYLimit(); 3186224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = newX.y - diff; 3196224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3206224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3216224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3226224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 3236224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private void zoom(final MotionEvent motionEvent) { 3246224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float oldDist = mDistX; 3256224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float newDist = getXDistance(motionEvent); 3266224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // sign change! Fingers have crossed ;-) 3276224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(oldDist > 0 && newDist < 0 || oldDist < 0 && newDist > 0) { 3286224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return; 3296224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3306224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mDistX = newDist; 3316224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala float scale = (oldDist / mDistX); 3326224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala // sanity check 3336224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(Float.isInfinite(scale) || Float.isNaN(scale) || scale > -0.001 && scale < 0.001) { 3346224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala return; 3356224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3366224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala PointF newX = new PointF(); 3376224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mZoomHorizontally) { 3386224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala calculateZoom(scale, newX, true); 3396224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = true; 3406224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setDomainBoundaries(newX.x, newX.y, BoundaryMode.FIXED); 3416224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinX = newX.x; 3426224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxX = newX.y; 3436224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3446224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(mZoomVertically) { 3456224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala calculateZoom(scale, newX, false); 3466224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala mCalledBySelf = true; 3476224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala super.setRangeBoundaries(newX.x, newX.y, BoundaryMode.FIXED); 3486224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMinY = newX.x; 3496224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala lastMaxY = newX.y; 3506224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3516224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala redraw(); 3526224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3536224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala 3546224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala private void calculateZoom(float scale, PointF newX, final boolean horizontal) { 3556224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float calcMax; 3566224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float span; 3576224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(horizontal) { 3586224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala calcMax = getLastMaxX(); 3596224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala span = calcMax - getLastMinX(); 3606224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 3616224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala calcMax = getLastMaxY(); 3626224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala span = calcMax - getLastMinY(); 3636224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3646224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float midPoint = calcMax - (span / 2.0f); 3656224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala final float offset = span * scale / 2.0f; 3666224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = midPoint - offset; 3676224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = midPoint + offset; 3686224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(horizontal) { 3696224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.x < getMinXLimit()) { 3706224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = getMinXLimit(); 3716224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3726224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.y > getMaxXLimit()) { 3736224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = getMaxXLimit(); 3746224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3756224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } else { 3766224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.x < getMinYLimit()) { 3776224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.x = getMinYLimit(); 3786224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3796224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala if(newX.y > getMaxYLimit()) { 3806224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala newX.y = getMaxYLimit(); 3816224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3826224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3836224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala } 3846224eda509d436a575f801942337da92a6c18767Eino-Ville Talvala} 385