Können wir zeichnen einen Kreis, verwendet das Path-Objekt? [in den Argumenten, wie drawPath()]
Habe ich getippt, ein Programm, das zieht auf Leinwand.
Es bietet ein popup-Menü, das gibt 3-Zeichnung tools wie Optionen:
-
Linie zeichnen, während kratzen über Bildschirm
-
Linie zeichnen, basierend auf start-und end-Punkte auf dem Bildschirm
-
Zeichnen Sie einen Kreis
Weiter, gibt es Optionen wie:
-
Klar
-
Rückgängig
Während der Durchführung rückgängig machen auf Linien, es gibt kein Thema, da beide basieren auf den Weg. (Verwendet List<Path>
).
Aber hier beginnt das problem. Der Kreis ist gezeichnet mit Point-Objekt. Also die Fragen sind:
- Kann ich nicht machen Android unterscheiden - die Reihenfolge der Zeichnung, die Linien und Kreise. ZB: ich ziehe 5 Zeilen, gefolgt von 5 Kreisen (oder
alternativ dazu). Es gibt keine Intelligenz, die derzeit um Ihre
Reihenfolge der Zeichnung. Daher Verhängnis Leinwand mit Linien und Kreise gezeichnet
zusammen führt zu versauen. - Den aktuellen code (nicht meditiert in der Tiefe noch) braucht 2 Klicks rückgängig machen einen Kreis anstelle von 1.
Ich hoffe, ich bin klar. [Downvoters, wenn angezogen, werden aufgefordert, geben Sie in der Grund, um nach dieser Anleitung für Anfänger, eine übliche Opfer downvotes nicht wissen, den genauen Grund zu verbessern].
Code shared unten (ist Komplex). Ich habe versucht, zu widmen, eine Klasse zu jedem Zeichenwerkzeuge (Linie,Kreis) - es funktionierte - außer - Sie zeichnen nicht auf der Leinwand. So, alles gepackt-in-1-Klasse wieder zurück.
Code:
package com.example.orbit_.undofortouch;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
Button b1, b2, b3;
PopupMenu popup;
int dtool;
boolean touch,circle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linearLayout2);
final DrawPanel dp = new DrawPanel(this);
linearLayout.addView(dp);
b1 = (Button) findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dp.Clear();
}
});
b2 = (Button) findViewById(R.id.button2);
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dp.Undo();
}
});
b3 = (Button) findViewById(R.id.button3);
b3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popup = new PopupMenu(MainActivity.this, v);
popup.getMenuInflater().inflate(R.menu.menu_main, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.touch:
dtool = 1;
break;
case R.id.line:
dtool = 2;
break;
case R.id.circle:
dtool = 3;
break;
}
Log.v("EDITL:", "Drawtool:".concat(String.valueOf(item.getTitle())));
Toast.makeText(MainActivity.this,"Clicked popup menu item " + item.getTitle(),Toast.LENGTH_SHORT).show();
return true;
}
});
popup.show();
}
});
}
class DrawPanel extends View implements View.OnTouchListener {
Bitmap bmp;
Canvas canvas;
List<Path> paths, undone;
List<Point> circlePoints,removeCircles;
Paint paint;
Path path;
Point point;
public DrawPanel(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
}
public DrawPanel(Context context) {
super(context);
paint = new Paint();
path = new Path();
paths = new ArrayList<>();
undone = new ArrayList<>();
circlePoints = new ArrayList<>();
removeCircles = new ArrayList<>();
canvas = new Canvas();
this.setOnTouchListener(this);
paint.setStrokeWidth(3);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setDither(true);
paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.desert);
touch=false;
circle=false;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
for (Path p : paths)
canvas.drawPath(p, paint);
if (touch)
canvas.drawPath(path, paint);
touch = false;
Log.v("Inside onDraw","Circle is".concat(String.valueOf(circle)));
for (Point p : circlePoints)
canvas.drawCircle(p.x, p.y, 5, paint);
}
float mX, mY,mx,my;
final float TOUCH_TOLERANCE = 0;
private void touch_start(float x, float y) {
undone.clear();
Log.v("ONTOUCH:", "Inside DOWN".concat("DOWN-X---:").concat(String.valueOf(x)).concat("**DOWN-Y---:").concat(String.valueOf(y)));
path.reset();
path.moveTo(x, y);
mX = x;
mY = y;
mx = x;
my = y;
}
private void touch_up() {
paths.add(path);
path = new Path();
}
private void touch_move(float x, float y) {
path.moveTo(mX, mY);
Log.v("ONTOUCH:", "Inside MOVE".concat("mX:").concat(String.valueOf(mX)).concat("mY:").concat(String.valueOf(mY)));
Log.v("ONTOUCH:", "Inside MOVE".concat("MOVE-X---:").concat(String.valueOf(x)).concat("**MOVE-Y---:").concat(String.valueOf(y)));
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
path.lineTo(mX, mY);
Log.v("MOVE:", " PATH ADDED & New Created");
}
@Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (dtool) {
case 1:
touch=true;
Touch(v, event, x, y);
break;
case 2:
Line(v,event,x,y);
break;
case 3:
Circle(v,event,x,y);
break;
}
Log.v("ONTOUCH:", "OUTSIDE CASE");
return true;
}
public void Line(View v, MotionEvent event, float x, float y) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
}
}
public void Touch(View v, MotionEvent event, float x, float y) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
canvas.drawPath(path, paint);
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
canvas.drawPath(path, paint);
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
}
}
public void Circle(View v, MotionEvent event, float x, float y)
{ point = new Point();
point.x = (int)x;
point.y = (int)y;
path.moveTo(x,y);
circle=true;
if(event.getAction()==MotionEvent.ACTION_DOWN) {
circlePoints.add(new Point(Math.round(point.x), Math.round(point.y)));
invalidate();
Log.v("Circle", "Inside Circle");
circlePoints.add(point);
paths.add(path);
}
}
public void Clear() {
paths.clear(); //Needs to be experimented
path.reset();
invalidate();
}
public void Undo() {
if (paths.size() > 0) {
undone.add(paths.remove(paths.size() - 1));
invalidate();
}
else if(circlePoints.size()>0)
{
removeCircles.add(circlePoints.remove(circlePoints.size()-1));
invalidate();
}
}
}
}
XML-Layout-Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="0"
android:layout_gravity="top">
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Undo"
android:id="@+id/button2"
android:layout_gravity="right"
android:layout_marginTop="-50dp" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear"
android:layout_gravity="center_vertical|bottom"
android:layout_marginTop="-50dp"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tools"
android:id="@+id/button3"
android:layout_gravity="center_horizontal"
android:layout_weight="0"
android:layout_marginTop="-50dp" />
</LinearLayout>
XML-Hauptmenü-code:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item
android:id="@+id/touch"
android:title="Touch"/>
<item
android:id="@+id/circle"
android:title="Circle"/>
<item
android:id="@+id/line"
android:title="Line"/>
</menu>
"Can we draw a circle using Path object?"
ja:Path#addCircle (float x, float y, float radius, Path.Direction dir)
- Hey, du hast mich da. Ich habe daher aktualisiert die Frage. Wenn Sie Lesen, das Szenario oder die behaupten, Sie 'll verstehen, meine situation zu bieten, eine sehr sympathische Antworten 🙂
- sorry, ich konnte nur verstehen, der Titel, und konnte nicht den rest... also eigentlich, was wollen Sie erreichen?
- Ich tippte, es ist alles da, das ist der beste Weg zu erklären. Aber kurz gesagt, eine Leinwand, die akzeptiert ein line-sowie Kreis-und sollte in der Lage sein, rückgängig machen beides-IN der RICHTIGEN REIHENFOLGE-.
- Eine andere Sache, die obigen code nimmt 2 Klicks rückgängig zu machen, ein Kreis gezogen. Wenn das gelöst ist (ich werde versuchen morgen), dann oben genannte Problem bleibt immer noch. Vielen Dank für die Bemühungen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diesem einfachen code hat die Sache. Da der Punkt den Kreis Hinzugefügt wird, werden in der Pfad-Objekt. Und
paths.addPath(path)
einfach fügt es zu der vorherigen Liste von Pfaden (in der gezeichneten Linien).Damit rückgängig machen wird leicht und natürlich, wie gut. Daher die Lösung.
Dank @pskink für die ursprüngliche Lösung.
P. S: Heute habe ich realisiert, eine Pause von ein unvollendetes Projekt ist nicht eine gute Praxis, aber in einer Weise, es ist manchmal für einige Menschen, für die Sie aus der Vertrautheit und kann jetzt denke, der normale Weg, die konnte man nicht vor.
path
(der name von Ihrem Pfad) nichtPath
am start, oder du wirst "Nicht-statische Methode addCircle(float, float, float, android.Grafik.Pfad.Richtung)' verwiesen werden kann aus einem statischen Kontext"Lollipop+
Nur den Kreis einen Pfad als gut. Sie können eine 360-Grad-Bogen, und werde ein Kreis. Die rip out all die anderen code für den Umgang mit Kreisen als ein anderes Tier.
Path.addCircle(float x,float y,float radius, Path.Direction)
?