如何在一个画布上绘制一条线,同时在另一个画布上的完全相同的点上复制该线。我的朋友告诉我要为两者使用相同的听众事件,但我无法弄清楚如何做到这一点。我会给你画布和线条的代码。
package com.mypackage.morphing;
import android.content.Context;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.*;
import java.util.ArrayList;
public class FingerLine extends View {
private ArrayList<Line> lines = new ArrayList<Line>();
private final Paint mPaint;
private float startX;
private float startY;
private float endX;
private float endY;
private Line tempL;
private int idx = 0;
private boolean firstCanContext = false;
public FingerLine(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.endX, l.endY, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lines.add(new Line(event.getX(), event.getY()));
invalidate();
break;
case MotionEvent.ACTION_MOVE:
lines.get(idx).endX = event.getX();
lines.get(idx).endY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP: // when the user lifts up
lines.get(idx).endX = event.getX();
lines.get(idx).endY = event.getY();
idx++;
invalidate();
break;
}
return true;
}
public void clearList(){
lines.clear();
idx = 0;
invalidate();
}
public void removeLineNumber(int indexR){
lines.remove(indexR);
idx--;
invalidate();
}
}
package com.mypackage.morphing;
public class Line {
float startX, startY, endX, endY;
public Line(float startX, float startY, float endX, float endY) {
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
}
public Line(float startX, float startY) { // for convenience
this(startX, startY, startX, startY);
}
}
答案 0 :(得分:0)
如果您要在一个画布上绘图,并且您希望看到绘制的线条出现在第二个画布上,只需在您的班级中创建一个方法,然后添加一行&#34;。每当您使用该方法添加一行(并随后绘制它)时,请通知侦听器(在此实例中为第二个画布)已添加一行。然后,第二个画布也可以决定绘制该行(或者从第一个画布中获取行并重新绘制所有行)。
答案 1 :(得分:0)
所以你有2个类,都扩展了View。 当用户触摸屏幕时,FirstView获取事件。 你希望SecondView绘制与FirstView相同的东西。
你的朋友说你要为这两个课程添加一个听众。 但你也可以从FirstView发送Line到SecondView。 所以你在firstView中创建了一个SecondView实例:
public class FirstView extends View {
SecondView secondView;
现在有两个选择,
1)两个类都有ArrayList,当创建或修改一行时,你在两个类中都这样做。别忘了刷新SecondView!
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Line line = new Line(event.getX(), event.getY());
lines.add(line);
secondView.lines.add(line);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
lines.get(idx).endX = event.getX();
lines.get(idx).endY = event.getY();
secondView.lines.get(idx).endX = event.getX();
secondView.lines.get(idx).endY = event.getY();
2)只有FirstView具有ArrayList,并且你在onDraw方法中的两个classe中绘制所有行。这是一个坏主意,因为经常调用onDraw,所以你必须在内部做最少的工作。
答案 2 :(得分:0)
我找到了答案(但它可能看起来很可怕)
我有3个班级正在研究这个课程(不包括主要课程,我将会这样做)。 这些类是LineController.java,Line.java和EditingView.java。 LineController包含对象的arraylist,line是行对象(我只是为了方便起见)而EditingView是我在上面绘制的视图类型。
LineController类
public class LineController {
public ArrayList<Line> firstCanvas;
public ArrayList<Line> secondCanvas;
private int idx;
LineController(){
firstCanvas = new ArrayList<>();
secondCanvas = new ArrayList<>();
idx = 0;
}
public void addLine(Line l){
firstCanvas.add(l);
secondCanvas.add(l);
idx++;
}
public void addLine(float x, float y){
firstCanvas.add(new Line(x, y));
secondCanvas.add(new Line(x, y));
idx++;
}
public void addX(int index, float x){
if(index <= idx){
firstCanvas.get(index).endX = x;
secondCanvas.get(index).endX = x;
}
}
public void addX(float x){
firstCanvas.get(firstCanvas.size() - 1).endX = x;
secondCanvas.get(secondCanvas.size() - 1).endX = x;
}
public void addY(int index, float y){
if(index <= idx){
firstCanvas.get(index).endY = y;
secondCanvas.get(index).endY = y;
}
}
public void addY(float y){
firstCanvas.get(firstCanvas.size() - 1).endY = y;
secondCanvas.get(secondCanvas.size() - 1).endY = y;
}
public void clearLists(){
firstCanvas.clear();
secondCanvas.clear();
idx = 0;
}
public boolean removeLast(){
if(firstCanvas.isEmpty()){
return false;
}
if(firstCanvas.size() == 1){
idx = 0;
firstCanvas.clear();
secondCanvas.clear();
}else{
idx--;
firstCanvas.remove(idx);
secondCanvas.remove(idx);
}
return true;
}
}
EditingView类
public class EditingView extends View {
private LineController lc;
private final Paint mPaint;
private boolean drawingMode = true;
private int closestIndex = -1;
private Paint editDot;
private Paint editLine;
private boolean endOfLine;
private boolean noLine = true;
private Point lastTouch;
private final static int MAX_DISTANCE = 100;
private Line editingLine = null;
private int viewIndex;
public EditingView(Context context){
super(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
editDot = new Paint(Paint.ANTI_ALIAS_FLAG);
editLine = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
editDot.setColor(Color.BLUE);
editLine.setColor(Color.CYAN);
}
public EditingView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
}
public void init(LineController controller){
lc = controller;
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(viewIndex == 0){ // first View
for (Line l : lc.firstCanvas) {
canvas.drawLine(l.startX, l.startY, l.endX, l.endY, mPaint);
}
if(!drawingMode){
// if in edit, draw a line around the index we found
if(closestIndex != -1) {
canvas.drawCircle(lc.firstCanvas.get(closestIndex).startX,
lc.firstCanvas.get(closestIndex).startY, 20, editDot);
canvas.drawCircle(lc.firstCanvas.get(closestIndex).endX,
lc.firstCanvas.get(closestIndex).endY, 20, editDot);
}
}
}else if(viewIndex == 1){
for (Line l : lc.secondCanvas) {
canvas.drawLine(l.startX, l.startY, l.endX, l.endY, mPaint);
}
if(!drawingMode){
// if in edit, draw a line around the index we found
if(closestIndex != -1) {
canvas.drawCircle(lc.secondCanvas.get(closestIndex).startX,
lc.secondCanvas.get(closestIndex).startY, 20, editDot);
canvas.drawCircle(lc.secondCanvas.get(closestIndex).endX,
lc.secondCanvas.get(closestIndex).endY, 20, editDot);
}
}
}
}
public void drawLine(MotionEvent event){
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lc.addLine(event.getX(), event.getY());
invalidate();
break;
case MotionEvent.ACTION_MOVE:
lc.addX(event.getX());
lc.addY(event.getY());
invalidate();
break;
case MotionEvent.ACTION_UP:
lc.addX(event.getX());
lc.addY(event.getY());
invalidate();
break;
}
}
public void editLine(MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// run function to find the closest point based on that object
lastTouch = new Point((int)event.getX(), (int)event.getY());
editingLine = findClosestLine(); // this should be for any point on the screen
if(editingLine == null){
noLine = true;
}else{
noLine = false;
endOfLine = checkPointStartEnd(editingLine);
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// edit the point to have the new points from the touch event
if(!noLine){
// we found one
if(!endOfLine){
editingLine.startX = event.getX();
editingLine.startY = event.getY();
}else{
editingLine.endX = event.getX();
editingLine.endY = event.getY();
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if(!noLine){
// we found one
if(!endOfLine){
editingLine.startX = event.getX();
editingLine.startY = event.getY();
}else{
editingLine.endX = event.getX();
editingLine.endY = event.getY();
}
editingLine = null;
invalidate();
}
lastTouch = null;
break;
}
}
public void editMode(int index){
drawingMode = false;
closestIndex = index;
}
public void clear() { closestIndex = -1; }
public void drawingMode(){
drawingMode = true;
}
public void viewIndex(int index){
viewIndex = index;
}
// finds the closest line in either array (checks the screen right?)
private Line findClosestLine(){
int temp1, temp2;
Line tempLine = null;
int closestDistance = MAX_DISTANCE;
// needs to loop through the array list, for both startX,Y and endX,Y of each line in the array
// then needs to get the index to that point and draw a circle around that point
// also change the colour of the line and the corresponding line based on that index
if(viewIndex == 0){
for(int i = 0; i < lc.firstCanvas.size(); i++){
temp1 = checkPoint(lc.firstCanvas.get(i));
if(temp1 < closestDistance && temp1 != -1) {
tempLine = lc.firstCanvas.get(i);
closestIndex = i;
}
}
}else{
for(int i = 0; i < lc.firstCanvas.size(); i++){
temp2 = checkPoint(lc.secondCanvas.get(i));
if(temp2 < closestDistance && temp2 != -1){
tempLine = lc.secondCanvas.get(i);
closestIndex = i;
}
}
}
return tempLine;
}
// Checks the point of a line to see if it is close
private int checkPoint(Line l){
int firstDistance = pyth((lastTouch.x - l.startX), (lastTouch.y - l.startY));
int secondDistance = pyth((lastTouch.x - l.endX), (lastTouch.y - l.endY));
if(MAX_DISTANCE > firstDistance) {
return (int)firstDistance;
}else if(MAX_DISTANCE > secondDistance){
return (int)secondDistance;
}
return -1;
}
// Checks the line we have found for the close point being start or end
private boolean checkPointStartEnd(Line l){
boolean start = false;
int firstDistance = pyth((lastTouch.x - l.startX), (lastTouch.y - l.startY));
int secondDistance = pyth((lastTouch.x - l.endX), (lastTouch.y - l.endY));
if(MAX_DISTANCE < firstDistance) {
start = true;
}else if(MAX_DISTANCE < secondDistance){
start = false;
}
return start;
}
// returns pythagorian theorum
private int pyth(double x, double y){
int z;
z = (int)Math.sqrt(((x * x) + (y * y)));
return z;
}
}
线类
public class Line {
float startX, startY, endX, endY;
public Line(float startX, float startY, float endX, float endY) {
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
}
public Line(float startX, float startY) { // for convenience
this(startX, startY, startX, startY);
}
}
MainActivity(唯一重要的)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lc = new LineController();
firstCanvas = new EditingView(this);
secondCanvas = new EditingView(this);
firstCanvas.viewIndex(0);
secondCanvas.viewIndex(1);
firstCanvas.init(lc);
secondCanvas.init(lc);
firstCanvas.setOnTouchListener(new TouchListener());
secondCanvas.setOnTouchListener(new TouchListener());
firstFrame = (FrameLayout)findViewById(R.id.firstFrame);
secondFrame = (FrameLayout)findViewById(R.id.secondFrame);
firstFrame.addView(firstCanvas);
secondFrame.addView(secondCanvas);
}
private class TouchListener implements View.OnTouchListener{
@Override
public boolean onTouch(View v, MotionEvent event) {
EditingView temp = (EditingView)v;
if(drawingMode) {
// drawing mode
temp.drawLine(event);
updateCanvas();
}else{
// edit mode
temp.editLine(event);
updateCanvas();
}
return true;
}
}
这就是我所用的一切。发生的事情是我在main中创建了一个控制器对象,并传递给EditViews来保存数组。然后,我只根据正在使用的视图访问数组。然后我设置了一个在MainActivity(可能被拆分)类中创建的触摸侦听器,该类将用于处理用户所处的模式(绘制或编辑)。使用这一切将允许我使用MainActivity内部整个屏幕的监听器(以编程方式)创建新视图。
我知道这不是做这一切的最佳方式,但它可以解决,我找不到任何其他东西。希望这有助于其他想要做同样事情的人。或者至少为自己的解决方案而努力。