2013-06-11 5 views
2

안드로이드 프로그래밍에서 초보자로 여겨지는데, 이것은 제 두 번째 애플리케이션 일뿐입니다. 따라서 명백한 과오가있는 경우에, 저를 품으십시오.Android : AndroidPlot의 터치 이벤트 중 앱이 다운 됨

큰 응용 프로그램의 일부로 AndroidPlot을 사용하여 그래프 페이지를 구현하려고합니다. 지금은 테스트중인 그래프에 수동으로 입력 값을 사용하고 있습니다. 내 그래프 페이지에서 확대/축소 및 팬을 구현하기 위해 AndroidPlot 웹 사이트에서 자습서를 사용했습니다. 그러나 터치 이벤트가 발생할 때마다 에뮬레이터와 실제 전화에서 발생합니다. 여기

public class Graph extends Activity implements OnTouchListener{ 

Campaign_Db myCamp = new Campaign_Db(this); 
private XYPlot myXY; 
private PointF minXY; 
private PointF maxXY; 
ArrayList<String> array_date; 
ArrayList<Integer> array_cap; 
Array arr_date; 
Integer[] arr_cap; 
float x,y; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.graph); 

    myXY = (XYPlot) findViewById(R.id.myXYplot); 
    myXY.setOnTouchListener(this); 

    getdata(); 

    // Create a couple arrays of y-values to plot: 
    Number[] series1Numbers = {978307200, // 2001 
      1009843200, // 2002 
      1041379200, // 2003 
      1072915200, // 2004 
      1104537600 // 2005 
      }; 
    Number[] series2 = {1,2,3,4,5}; 



    // Turn the above arrays into XYSeries': 
    XYSeries series1 = new SimpleXYSeries(
      Arrays.asList(series1Numbers), 
      Arrays.asList(series2), 
      "cups of water"); 



    // Create a formatter to use for drawing a series using LineAndPointRenderer: 
    @SuppressWarnings("deprecation") 
    LineAndPointFormatter series1Format = new LineAndPointFormatter(
      Color.rgb(0, 200, 0),     // line color 
      Color.rgb(0, 100, 0),     // point color 
      null);         // fill color (none) 

    // add a new series' to the xyplot: 
    myXY.addSeries(series1, series1Format); 


    // reduce the number of range labels 
    myXY.setTicksPerRangeLabel(1); 
    myXY.setTicksPerDomainLabel(2); 

    // get rid of decimal points in our range labels: 
    myXY.setRangeValueFormat(new DecimalFormat("0")); 

    // customize our domain/range labels 
    myXY.setDomainLabel("Date"); 
    myXY.setRangeLabel("# of cups"); 

    myXY.setDomainValueFormat(new Format() { 

     /** 
     * 
     */ 
     private static final long serialVersionUID = 1L; 
     // create a simple date format that draws on the year portion of our timestamp. 
     // see http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html 
     // for a full description of SimpleDateFormat. 
     private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy"); 

     @Override 
     public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { 

      // because our timestamps are in seconds and SimpleDateFormat expects milliseconds 
      // we multiply our timestamp by 1000: 
      long timestamp = ((Number) obj).longValue() * 1000; 
      Date date = new Date(timestamp); 
      return dateFormat.format(date, toAppendTo, pos); 
     } 


     @Override 
     public Object parseObject(String string, ParsePosition position) { 
      // TODO Auto-generated method stub 
      return null; 
     } 


    }); 


    // by default, AndroidPlot displays developer guides to aid in laying out your plot. 
    // To get rid of them call disableAllMarkup(): 
    myXY.disableAllMarkup(); 

    myXY.redraw(); 
    //Set of internal variables for keeping track of the boundaries 
     myXY.calculateMinMaxVals(); 
     minXY=new PointF(myXY.getCalculatedMinX().floatValue(),myXY.getCalculatedMinY().floatValue()); 
     maxXY=new PointF(myXY.getCalculatedMaxX().floatValue(),myXY.getCalculatedMaxY().floatValue()); 

} 
// Definition of the touch states 
    static final int NONE = 0; 
    static final int ONE_FINGER_DRAG = 1; 
    static final int TWO_FINGERS_DRAG = 2; 
    int mode = NONE; 

    PointF firstFinger; 
    float lastScrolling; 
    float distBetweenFingers; 
    float lastZooming; 

    public boolean onTouch(View view, MotionEvent event) { 

     switch (event.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: // Start gesture 
      firstFinger = new PointF(event.getX(), event.getY()); 
      mode = ONE_FINGER_DRAG; 
      break; 
     case MotionEvent.ACTION_UP: 
     case MotionEvent.ACTION_POINTER_UP: 
      //When the gesture ends, a thread is created to give inertia to the scrolling and zoom 
      Timer t = new Timer(); 
       t.schedule(new TimerTask() { 
        @Override 
        public void run() { 
         while(Math.abs(lastScrolling)>1f || Math.abs(lastZooming-1)<1.01){ 
         lastScrolling*=.8; 
         scroll(lastScrolling); 
         lastZooming+=(1-lastZooming)*.2; 
         zoom(lastZooming); 
         myXY.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO); 
          myXY.redraw(); 

        } 
        } 
       }, 0); 


     case MotionEvent.ACTION_POINTER_DOWN: // second finger 
      distBetweenFingers = spacing(event); 
      // the distance check is done to avoid false alarms 
      if (distBetweenFingers > 5f) { 
       mode = TWO_FINGERS_DRAG; 
      } 
      break; 
     case MotionEvent.ACTION_MOVE: 
      if (mode == ONE_FINGER_DRAG) { 
       PointF oldFirstFinger=firstFinger; 
       firstFinger=new PointF(event.getX(), event.getY()); 
       lastScrolling=oldFirstFinger.x-firstFinger.x; 
       scroll(lastScrolling); 
       lastZooming=(firstFinger.y-oldFirstFinger.y)/myXY.getHeight(); 
       if (lastZooming<0) 
        lastZooming=1/(1-lastZooming); 
       else 
        lastZooming+=1; 
       zoom(lastZooming); 
       myXY.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO); 
       myXY.redraw(); 

      } else if (mode == TWO_FINGERS_DRAG) { 
       float oldDist =distBetweenFingers; 
       distBetweenFingers=spacing(event); 
       lastZooming=oldDist/distBetweenFingers; 
       zoom(lastZooming); 
       myXY.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO); 
       myXY.redraw(); 
      } 
      break; 
     } 
     return true; 
    } 




    private void zoom(float scale) { 
     float domainSpan = maxXY.x - minXY.x; 
     float domainMidPoint = maxXY.x - domainSpan/2.0f; 
     float offset = domainSpan * scale/2.0f; 
     minXY.x=domainMidPoint- offset; 
     maxXY.x=domainMidPoint+offset; 
    } 

    private void scroll(float pan) { 
     float domainSpan = maxXY.x - minXY.x; 
     float step = domainSpan/myXY.getWidth(); 
     float offset = pan * step; 
     minXY.x+= offset; 
     maxXY.x+= offset; 
    } 

    private float spacing(MotionEvent event) { 

     x = event.getX(0) - event.getX(1); 
     y = event.getY(0) - event.getY(1); 


     return FloatMath.sqrt(x * x + y * y); 
    } 

    public boolean onInterceptTouchEvent(MotionEvent ev) { 
      try { 
       return super.onTouchEvent(ev); 
      } catch (IllegalArgumentException e) { 
       e.printStackTrace(); 
       return false; 
      } catch (ArrayIndexOutOfBoundsException e) { 
       e.printStackTrace(); 
       return false; 
      } 
     } 

    } 

그리고

가 도움이되었습니다 오류

06-11 14:59:31.764: E/AndroidRuntime(2203): FATAL EXCEPTION: main 
06-11 14:59:31.764: E/AndroidRuntime(2203): java.lang.IllegalArgumentException: pointerIndex out of range 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.MotionEvent.nativeGetAxisValue(Native Method) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.MotionEvent.getX(MotionEvent.java:1974) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.example.damavand.Graph.spacing(Graph.java:231) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.example.damavand.Graph.onTouch(Graph.java:176) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.View.dispatchTouchEvent(View.java:5559) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1931) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1390) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.app.Activity.dispatchTouchEvent(Activity.java:2364) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1879) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.View.dispatchPointerEvent(View.java:5766) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2890) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2466) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:845) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2475) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.os.Handler.dispatchMessage(Handler.java:99) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.os.Looper.loop(Looper.java:137) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at android.app.ActivityThread.main(ActivityThread.java:4441) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at java.lang.reflect.Method.invokeNative(Native Method) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at java.lang.reflect.Method.invoke(Method.java:511) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
06-11 14:59:31.764: E/AndroidRuntime(2203):  at dalvik.system.NativeStart.main(Native Method) 

나는 주위를 읽고 있고 아무것도에 대한 로그 캣입니다 : 여기

그래프 페이지에 대한 코드입니다. 이것은 모션 이벤트와 관련하여 내가 끔찍한 것이기 때문에 가능한 해결책을 찾지 못했기 때문일 수 있습니다. 도움이나 안내에 대해 미리 감사드립니다.

+0

코드'com.example.damavand.Graph.spacing (Graph.java:231)'에서'IllegalArgumentException : pointerIndex가 범위를 벗어났습니다. ' 그 줄에 중단 점을 설정하면 문제가 나타납니다. –

+0

@DavidM 위로 읽은 후, 포인터 인덱스 값이 올바르지 않다는 문제가 발견되었습니다. 그러나 나는이 문제를 어떻게 풀 수 있을지 전혀 모른다. –

+1

아래 AlexBcn의 답변을 확인하십시오. –

답변

3

좋아에서 살펴 보자. 줌 기능을 사용하는 그의 방식은 코딩이 고려되는 한 훨씬 더 쉽게 따라 할 수 있으며 더 조밀합니다. 여기

같은 문제에 직면하거나 AndroidPlot이 도움이 되었기를

AndroidPlot multitouch zoom & scroll

희망 작업을 찾고있을 수도 다른 사람에 대한 자신의 코드에 대한 링크입니다.

+0

이 링크는 삭제되었습니다. 솔루션을 공유 할 수 있습니까? 감사. –

+0

@DivyaNagrath 내가 게시 한 이래로 2 년이 지났습니다. 더 이상 기억하지 않으며 여기에 사용 된 코드에 액세스 할 수 없지만 androidPlot의 문서가 여기에 있습니다. 어쨌든 도움이 될 수 있습니다. http :// /androidplot.com/docs/ –

+0

나는 그것을 언급했다. 터치 이벤트에서 같은 충돌 문제가 발생합니다. :( –

2
당신은 잘못된 인덱스 event.getX(1)에 액세스하는

private float spacing(MotionEvent event) { 

    x = event.getX(0) - event.getX(1); 
    y = event.getY(0) - event.getY(1); 


    return FloatMath.sqrt(x * x + y * y); 
} 

사용 event.getPointerCount이없는 getY(1) 이전

MotionEvent가에 대한 데이터를보고 안드로이드 2.0 (에클 레어)에서 확장 된

멀티 터치 이벤트를 설명하기 위해 여러 포인터와 새로운 동작이 추가되었습니다. MotionEvent.getPointerCount()은 활성 포인터의 수를 반환합니다. getX 및 getY는 이제 검색 할 포인터의 데이터를 지정하는 인덱스를 허용합니다. 나는 이것에 대해 다른 방법을 가서 친절하게도 자신의 작품을 공유 할 수 있었다 마르신 Lepicki 만든 맞춤형 줌 및 팬 기능을 사용하기로 결정

Making Sense of Multitouch

+0

신속한 응답을 가져 주셔서 감사합니다. 미안 해요. 아주 느린데, 정확히 어디에서 event.getPointerCount를 코드에 넣을까요? –

+0

당신은 인덱스가 항상 0 또는 1이 될 것이라고 가정하고 있습니다. 내가 게시 한 링크에서 그 코드가 올바르지 않다는 것을 알았을 때 그는 final int pointerIndex = ev.findPointerIndex (mActivePointerId)와 같은 코드를 사용하여 X와 Y를 얻습니다. ''final float x = ev.getX (pointerIndex);''final float y = ev.getY (pointerIndex);' – AlexBcn

+0

네, 그게 합리적인 방법을 알 수 있습니다. 그러나이 예제에서는 getPointerCount()가 없으므로 혼란 스럽습니다. 두 포인터와 색인을 어떻게 구별합니까? –

0

스위치 케이스 블록에 break이 없기 때문에 spacing()의 예외가 발생합니다. 따라서 두 번째 손가락에 대한 case MotionEvent.ACTION_POINTER_DOWN:은 손가락 하나만 사용하더라도 실행됩니다.

case MotionEvent.ACTION_POINTER_UP: 
     //When the gesture ends, a thread is created to give inertia to the scrolling and zoom 
     Timer t = new Timer(); 
      t.schedule(new TimerTask() { 
       @Override 
       public void run() { 
        while(Math.abs(lastScrolling)>1f || Math.abs(lastZooming-1)<1.01){ 
        lastScrolling*=.8; 
        scroll(lastScrolling); 
        lastZooming+=(1-lastZooming)*.2; 
        zoom(lastZooming); 
        myXY.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO); 
         myXY.redraw(); 

       } 
       } 
      }, 0); 
      break; // <== the MISSING break! 

    case MotionEvent.ACTION_POINTER_DOWN: // second finger 
     distBetweenFingers = spacing(event);