package com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.touch; import android.graphics.RectF; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.view.ViewParent; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.charts.LineChart; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.manager.MappingManager; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.utils.RectD; public class GodTouchListener implements View.OnTouchListener { GestureDetector _GestureDetector; ScaleGestureDetector _ScaleGestureDetector; LineChart _LineChart; public GodTouchListener(LineChart lineChart) { _LineChart = lineChart; _GestureDetector = new GestureDetector(lineChart.getContext(), new GestureListener()); _ScaleGestureDetector = new ScaleGestureDetector(lineChart.getContext(), new ScaleListener()); } @Override public boolean onTouch(View v, MotionEvent event) { ViewParent parent = v.getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } boolean hit = _GestureDetector.onTouchEvent(event); hit |= _ScaleGestureDetector.onTouchEvent(event); if (hit) { _LineChart.invalidate(); return true; } return false; } class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { float _lastSpanX, _lastSpanY; public ScaleListener() { super(); } @Override public boolean onScale(ScaleGestureDetector detector) { float spanX = detector.getCurrentSpanX(); float kx = spanX / _lastSpanX; float spanY = detector.getCurrentSpanY(); float ky = spanY / _lastSpanY; RectF godRect = _LineChart.get_GodRect(); RectF mainRect = _LineChart.get_MainPlotRect(); godRect.right = godRect.left + godRect.width() * kx; godRect.bottom = godRect.top + godRect.height() * ky; constrainRect(godRect, mainRect); nofityViewPortChanged(godRect); _lastSpanX = spanX; _lastSpanY = spanY; return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { _lastSpanX = detector.getCurrentSpanX(); _lastSpanY = detector.getCurrentSpanY(); return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { super.onScaleEnd(detector); } } RectD _rectD_ob = new RectD(); class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDoubleTap(MotionEvent e) { return super.onDoubleTap(e); } @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return super.onFling(e1, e2, velocityX, velocityY); } @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { RectF godRect = _LineChart.get_GodRect(); RectF mainRect = _LineChart.get_MainPlotRect(); float w = godRect.width(); float h = godRect.height(); godRect.left += -distanceX; godRect.right = godRect.left + w; godRect.top += -distanceY; godRect.bottom = godRect.top + h; constrainRect(godRect, mainRect); nofityViewPortChanged(godRect); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent e) { return super.onSingleTapConfirmed(e); } } private void nofityViewPortChanged(RectF godRect) { // 计算出godRect对应的viewport MappingManager mappingManager = _LineChart.get_MappingManager(); double left = mappingManager.p2v_x(godRect.left); double right = mappingManager.p2v_x(godRect.right); double bottom = mappingManager.p2v_y(godRect.bottom); double top = mappingManager.p2v_y(godRect.top); _rectD_ob.left = left; _rectD_ob.top = top; _rectD_ob.right = right; _rectD_ob.bottom = bottom; _LineChart.notifyOB_ViewportChanged(_rectD_ob); } private void constrainRect(RectF godRect, RectF maxRect) { float w = godRect.width(); float h = godRect.height(); // 1. 保持比例 if (godRect.left < maxRect.left) { godRect.left = maxRect.left; godRect.right = godRect.left + w; } if (godRect.top < maxRect.top) { godRect.top = maxRect.top; godRect.bottom = godRect.top + h; } if (godRect.right > maxRect.right) { godRect.right = maxRect.right; godRect.left = godRect.right - w; } if (godRect.bottom > maxRect.bottom) { godRect.bottom = maxRect.bottom; godRect.top = godRect.bottom - h; } // 2. 限定值的范围 if (godRect.left < maxRect.left) { godRect.left = maxRect.left; } if (godRect.top < maxRect.top) { godRect.top = maxRect.top; } if (godRect.right > maxRect.right) { godRect.right = maxRect.right; } if (godRect.bottom > maxRect.bottom) { godRect.bottom = maxRect.bottom; } } }