2013-06-11 1 views
2

Я считаю новичком в программировании для Android, это только мое второе приложение, и я изучаю вещи по мере их появления. Поэтому, если есть очевидные оплошности, несите меня.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; 
      } 
     } 

    } 

А вот LogCat за ошибки

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

'IllegalArgumentException: pointerIndex из range' в коде' на com.example.damavand.Graph.spacing (Graph.java:231) '. установите точку останова на этой линии, и вы должны увидеть проблему. –

+0

@DavidM После прочтения, я обнаружил, что проблема связана с неправильным значением pointerindex. Однако я совершенно не знаю, как я смогу решить эту проблему. –

+1

проверить ответ AlexBcn ниже .... –

ответ

3

Хорошо, я решил пойти по этому поводу другой способ и использовать пользовательский встроенный зум и панорамирование функции сделанные Marcin Lepicki, который был достаточно любезен, чтобы разделить свою работу. Его способ подбора функции масштабирования намного проще отслеживать, а также более аккуратно, пока рассматривается кодирование.

Вот ссылка на его код для всех, кто может столкнуться с таким же вопросом или хочет работать с AndroidPlot

AndroidPlot multitouch zoom & scroll

Надежда это было полезно.

+0

Эта ссылка была удалена. Можете ли вы поделиться этим решением. Благодарю. –

+0

@DivyaNagrath Прошло более двух лет с тех пор, как я опубликовал это, я больше не помню и не имел доступа к коду, который использовался здесь, но вот документы для androidPlot, надеюсь, это может помочь вам каким-то образом http://androidplot.com/docs/ –

+0

Я сослался на это. но я получаю такую ​​же ошибку при касании. :( –

2

Вы получаете доступ к неправильному индексу event.getX(1) и getY(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 перед тем

MotionEvent был расширен в Android 2.0 (Eclair) сообщать данные о несколько указателей и новые действия были добавлены для описания событий мультитач. MotionEvent.getPointerCount() возвращает количество активных указателей. getX и getY теперь принимают индекс, чтобы указать, какие данные указателя нужно извлечь.

Взгляните на Making Sense of Multitouch

+0

Спасибо за подсказку. Извините, если я очень медленный, но где именно я помещаю event.getPointerCount в свой код? –

+0

Вы считаете, что индексы всегда будут 0 или 1, и это неверно в ссылке, которую я разместил, вы увидите, что он получает код X и Y, например, «final int pointerIndex = ev.findPointerIndex (mActivePointerId); '' final float x = ev.getX (pointerIndex); '' final float y = ev.getY (pointerIndex); ' – AlexBcn

+0

Да, я вижу, как это имеет смысл. Однако в этом примере нет getPointerCount(), который смущает меня дальше. Как я различаю два указателя и их индексы? –

0

Исключение из spacing() происходит из-за отсутствия в корпусе выключателя break. Таким образом, для второго пальца может быть выполнено только 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); 
Смежные вопросы