我被认为是Android编程的新手,这只是我的第二个应用程序,我正在学习他们来的东西。所以如果有明显的疏忽,请耐心等待。
作为更大应用程序的一部分,我正在尝试使用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 :(得分:3)
好吧我决定采用另一种方式,使用由 Marcin Lepicki 制作的定制缩放和平移功能,他们非常友好地分享他的作品。只要编码正在考虑,他的缩放功能的方式就更容易理解和更整洁。
以下是其他任何可能遇到相同问题或希望使用 AndroidPlot
的代码的链接AndroidPlot multitouch zoom & scroll
希望这有用。
答案 1 :(得分: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.getPointerCountMotionEvent在Android 2.0(Eclair)中进行了扩展,以报告有关多个指针的数据,并添加了新的操作来描述多点触控事件。 MotionEvent.getPointerCount()返回活动指针的数量。 getX和getY现在接受一个索引来指定要检索的指针数据。
答案 2 :(得分: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);