我正在开发一个协作艺术应用程序,其中用户可以使用FireBase实时数据库在画布上一起绘制一段距离。我已经理解到一个用户屏幕上绘制的细分出现在另一用户的屏幕上,反之亦然。
但是,一旦将片段从Firebase中拉出,它将在背景中绘制该片段,而不是在用户的“绘画”上绘制该片段。
有没有办法告诉程序始终将不同的段相互画在上面?
The orange line drawn on the right phone appears in the background of the left phone
我把我使用的代码片段放在这里:
这是我从FireBase中提取分段的地方:
mListener=mRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
String name=dataSnapshot.getKey();
if (!mOutstandingSegments.contains(name)) {
Segment segment = dataSnapshot.getValue(Segment.class);
drawSegmentPath(segment.getPoints(), segment.getColor(), segment.getBlurEnabled(), segment.getStrokeWidth());
//invalidate();
}
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
该段通过以下方法转换为路径:
public void drawSegmentPath(List<Point> segmentPoints, int color, boolean blurEnabled, float strokeWidth){
Point currentSegmentPoint = segmentPoints.get(0);
Path newSegmentPath = new Path();
FingerPath fireBasePath = new FingerPath(color, blurEnabled, strokeWidth, newSegmentPath);
firePath.add(fireBasePath);
newSegmentPath.reset();
newSegmentPath.moveTo(currentSegmentPoint.x, currentSegmentPoint.y);
Point nextSegmentPoint = null;
invalidate();
for (int i = 1; i < segmentPoints.size(); i++) {
nextSegmentPoint = segmentPoints.get(i);
newSegmentPath.quadTo(currentSegmentPoint.x, currentSegmentPoint.y, (int)((nextSegmentPoint.x + currentSegmentPoint.x) / 2), (int)((nextSegmentPoint.y + currentSegmentPoint.y) / 2));
currentSegmentPoint = nextSegmentPoint;
System.out.println("Current Segment Points: " + currentSegmentPoint);
invalidate();
}
if (nextSegmentPoint != null) {
newSegmentPath.lineTo(nextSegmentPoint.x, nextSegmentPoint.y);
invalidate();
}
}
然后在onDraw()中,将路径绘制在与用户在其自己的手机上绘制的线条相同的画布(mCanvas)上:
@Override
protected void onDraw(Canvas canvas){
canvas.save();
mCanvas.drawColor(Color.WHITE);
for(FingerPath fireBasePath : firePath){
mPaint.setColor(fireBasePath.myColor);
mPaint.setStrokeWidth(fireBasePath.strokeWidth);
mPaint.setMaskFilter(null);
if (fireBasePath.blurEnabled){testPaint.setMaskFilter(mBlur);}
mCanvas.drawPath(fireBasePath.path, mPaint);
}
for(FingerPath fp : paths){
mPaint.setColor(fp.myColor);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.blurEnabled){mPaint.setMaskFilter(mBlur);}
mCanvas.drawPath(fp.path, mPaint);
}
canvas.drawBitmap(mBitmap, drawMatrix, mBitmapPaint);
canvas.concat(drawMatrix);
canvas.restore();
invalidate();
}
当用户通过不断在Segment类中添加点来将手指移到屏幕上方时,就形成了一个细分:
pivate void touchStart(float positionX, float positionY){
mPath = new Path();
FingerPath fp = new FingerPath(currentBrushColor, blurEnabled, strokeWidth, mPath);
mCurrentSegment = new Segment(currentBrushColor, strokeWidth, blurEnabled);
paths.add(fp);
mPath.reset();
mPath.moveTo(positionX, positionY);
mX = positionX;
mY = positionY;
mCurrentSegment.addPoint((int)mX, (int)mY);
}
private void touchMove(float positionX, float positionY){
float dx = Math.abs(positionX - mX);
float dy = Math.abs(positionY - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE){
mPath.quadTo(mX, mY, (positionX + mX)/2, (positionY + mY)/2);
mX = positionX;
mY = positionY;
mCurrentSegment.addPoint((int)mX, (int)mY);
}
}
然后,当用户完成绘制时,将线段推入FireBase:
private void touchUp(){
mPath.lineTo(mX,mY);
DatabaseReference segmentRef=mRef.push();
final String segmentName=segmentRef.getKey();
currentSegmentKey=segmentName;
mOutstandingSegments.add(segmentName);
Segment mySegment = new Segment(mCurrentSegment.getColor(), mCurrentSegment.getStrokeWidth(), blurEnabled);
for (Point point: mCurrentSegment.getPoints()) {
mySegment.addPoint(point.x , point.y );
}
System.out.println("Segment is: " + mySegment);
// Save our segment into Firebase.
segmentRef.setValue(mySegment, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError error, DatabaseReference firebaseRef) {
if (error != null) {
throw error.toException();
}
mOutstandingSegments.remove(segmentName);
}
});
}
下面的onTouchEvent lstener中调用了不同的onTouch方法:
@Override
public boolean onTouchEvent(MotionEvent event){
float positionX = event.getX()
float positionY = event.getY()
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(positionX, positionY);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(positionX, positionY);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp();
invalidate();
break;
}
}
return true;
}