如何在执行事件时创builddynamic的androidpath对象?

我正在尝试使用基于Socket.io的Node.js服务器搭载Android构build一个实时协作绘图板应用程序。 我已经使用了Android端的Socket.io Java客户端。 我能够绘制出一条path,并将协调发送到服务器,并从服务器接近实时地获取广播。 整个概念几乎完成,但是我陷入了一个大问题。

我在Android是一个完整的新手,这实际上是我的第一个Android应用程序,我完全是为了学习目的而创build的。 所以,问题是,在每个与服务器的新连接上,我需要一个新的Path对象。 现在我的单path对象发生了什么,当有响应来自服务器,我试图绘制path,它使用相同的path对象,因此,join我画线,与线坐标我从服务器收到的。 此问题导致需要为每个到服务器的新连接创build一个新的Path对象。 请注意,通过一个新的连接,我的意思是,通过打开应用程序连接到服务器的新设备。 这个新人,你可以参与协作绘图的经验,至less,这就是我想要build立的。 我认为会工作的是,在每一个新的连接,我会创build一个新的path对象,并把它放在一个ArrayList,然后根据需要引用相应的path对象。 但是,然后我发现了一个新的问题,即在onDraw()覆盖的方法内实际创build视图时,path被初始化。

所以,我的最后一个问题是:

在Android中,如何在执行事件时创builddynamicpath对象?

这是自定义View

 package com.example.thisisppn.drawtogether; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.socketio.client.Socket; import com.github.nkzawa.socketio.client.IO; import org.json.JSONException; import org.json.JSONObject; import java.net.URISyntaxException; public class MainDrawingView extends View { private Paint paint = new Paint(); private Path path = new Path(); private Socket mSocket; public MainDrawingView(Context context, AttributeSet attrs) { super(context, attrs); paint.setAntiAlias(true); paint.setStrokeWidth(5f); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); try { mSocket = IO.socket("http://192.168.0.4:3000"); } catch (URISyntaxException e) { e.printStackTrace(); } mSocket.on("touch", onTouchEvent); mSocket.on("move", onMoveEvent); mSocket.on("connected", onConnectEvent); mSocket.connect(); } @Override protected void onDraw(Canvas canvas) { canvas.drawPath(path, paint); } @Override public boolean onTouchEvent(MotionEvent event) { // Get the coordinates of the touch event. float eventX = event.getX(); float eventY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // Set a new starting point path.moveTo(eventX, eventY); // mSocket.emit("touch", "{"+eventX+", "+eventY+"}"); mSocket.emit("touch", eventX,eventY); return true; case MotionEvent.ACTION_MOVE: // Connect the points path.lineTo(eventX, eventY); mSocket.emit("move", eventX,eventY); break; default: return false; } // Makes our view repaint and call onDraw invalidate(); return true; } public Emitter.Listener onConnectEvent = new Emitter.Listener() { @Override public void call(Object... args) { ((Activity)getContext()).runOnUiThread(new Runnable() { @Override public void run() { } }); } }; public Emitter.Listener onTouchEvent = new Emitter.Listener() { @Override public void call(final Object... args) { ((Activity)getContext()).runOnUiThread(new Runnable() { @Override public void run() { //Code for the UiThread JSONObject data = (JSONObject) args[0]; String x = null; String y = null; try { x = data.getString("touchX"); y = data.getString("touchY"); } catch (JSONException e) { e.printStackTrace(); } Log.v("Touch", x+", "+y); float touchX = Float.parseFloat(x); float touchY = Float.parseFloat(y); path.moveTo(touchX + 200, touchY + 200); invalidate(); } }); } }; public Emitter.Listener onMoveEvent = new Emitter.Listener() { @Override public void call(final Object... args) { ((Activity)getContext()).runOnUiThread(new Runnable() { @Override public void run() { JSONObject data = (JSONObject) args[0]; String x = null; String y = null; try { x = data.getString("touchX"); y = data.getString("touchY"); } catch (JSONException e) { e.printStackTrace(); } Log.v("Move", x+", "+y); float touchX = Float.parseFloat(x); float touchY = Float.parseFloat(y); path.lineTo(touchX+200, touchY+200); invalidate(); } }); } }; } 

MainActivity.java只有onCreate方法,没有别的。

以下是我用来接收和播放触摸事件的非常基本的Node.js服务器。 它基本上采取触摸坐标并将其广播给所有连接的客户端。

 // Setup basic express server var express = require('express'); var app = express(); var server = require('http').createServer(app); var io = require('socket.io')(server); var port = process.env.PORT || 3000; server.listen(port, function () { console.log('Server listening at port %d', port); }); var numUsers = 0; io.on('connection', function (socket) { console.log("Someone connected"); socket.emit("connected"); socket.on("touch", function (x, y){ console.log("Touch event happened somewhere"); console.log(x+", "+y); socket.broadcast.emit("touch", { touchX: x, touchY: y }); }); socket.on("move", function (x, y){ console.log("Move event happened somewhere"); console.log(x+", "+y); socket.emit("move", { touchX: x, touchY: y }); }); }); 

请让我知道,如果我错过了任何所需的信息。 如果有人能帮我解决这个问题,我真的很感激。 我无法find任何解决scheme,这在我的谷歌search。 在此先感谢您的时间。

您应该尝试唯一识别连接到服务器的任何新设备。可以为连接的每个设备分配一些types的DeviceID ,在服务器端查找。 在Android中为每个连接的新设备创build一个新的Path对象。 并创build一个数据结构来将DeviceID映射到Path对象

HashMap<String, Path> map = new HashMap<String, Path>();

每当连接新设备时,添加相应的DeviceIDnew Path()进行map

 public Emitter.Listener onConnectEvent = new Emitter.Listener() { @Override public void call(Object... args) { JSONObject data = (JSONObject) args[0]; String deviceId = data.getString("DeviceID"); map.put(deviceId, new Path()); } }; 

通过onTouchEventonMoveEventDeviceID的引用更新相应的Path对象

 public Emitter.Listener onTouchEvent = new Emitter.Listener() { @Override public void call(final Object... args) { ((Activity)getContext()).runOnUiThread(new Runnable() { @Override public void run() { //Code for the UiThread JSONObject data = (JSONObject) args[0]; String x = null; String y = null; String deviceId = data.getString("DeviceID"); try { x = data.getString("touchX"); y = data.getString("touchY"); } catch (JSONException e) { e.printStackTrace(); } Log.v("Touch", x+", "+y); float touchX = Float.parseFloat(x); float touchY = Float.parseFloat(y); map.get(deviceId).moveTo(touchX + 200, touchY + 200); invalidate(); } }); } }; 

应用onMoveEvent类似的逻辑。 里面的onDraw()方法

 @Override protected void onDraw(Canvas canvas) { for (String key : map.keySet()) { Path path = map.get(key); canvas.drawPath(path, paint); } }