2

私は Android プログラミングの初心者と見なされています。したがって、明らかな見落としがある場合は、ご容赦ください。

大規模なアプリケーションの一部として、AndroidPlot を使用してグラフ ページを実装しようとしています。今のところ、テストのみを行っているため、グラフに手動で入力した値を使用しています。グラフ ページにズームとパンを実装するために、AndroidPlot Web サイトのチュートリアルを使用しました。ただし、エミュレーターと実際の電話で、タッチ イベントが発生するたびに。

グラフ ページのコードは次のとおりです。

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)

私は周りを読んでいて、何も役に立ちませんでした。これは、モーション イベントに関して私がひどいので、考えられる解決策を見逃した可能性があるためです。ヘルプやガイダンスをお寄せいただきありがとうございます。

4

3 に答える 3

3

よし、私はこれを別の方法で進め、親切にも作品を共有してくれたMarcin Lepickiによって作成された特注のズームおよびパン機能を使用することにしました。ズーム機能にアプローチする彼の方法は、コーディングが考慮されている限り、従うのがはるかに簡単で、整頓されています.

これは、同じ問題に直面している、またはAndroidPlotで作業しようとしている他の人のための彼のコードへのリンクです。

AndroidPlot マルチタッチ ズーム & スクロール

これがお役に立てば幸いです。

于 2013-06-12T07:14:04.110 に答える
2

event.getX(1)間違ったインデックスにアクセスしており、getY(1)2 つもない場合

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 は、取得するポインターのデータを指定するインデックスを受け入れるようになりました。

マルチタッチを理解するをご覧ください

于 2013-06-11T11:00:24.170 に答える
0

switch case ブロックに欠落spacing()があるため、例外が発生します。breakしたがって、case MotionEvent.ACTION_POINTER_DOWN:1 本の指だけを使用する場合でも、2 番目の指の次の操作が実行されます。

    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);
于 2014-02-20T18:43:54.720 に答える