Ich habe zwei Punkte auf der Leinwand, jetzt kann ich mit diesen Punkten eine Linie zwischen den Punkten wie diesem unter dem Bild zeichnen
Dieser Code canvas.drawLine(p1.x, p1.y, p2.x, p2.y, Paint);
Ich möchte den Bogen zwischen zwei Punkten wie unter dem Bild zeichnen.
Wie kann ich so zeichnen?.
Endlich bekam ich die Lösung aus diesem Code:
float radius = 20;
final RectF oval = new RectF();
oval.set(point1.x - radius, point1.y - radius, point1.x + radius, point1.y+ radius);
Path myPath = new Path();
myPath.arcTo(oval, startAngle, -(float) sweepAngle, true);
Um startAngle
zu berechnen, verwenden Sie diesen Code:
int startAngle = (int) (180 / Math.PI * Math.atan2(point.y - point1.y, point.x - point1.x));
Hier bedeutet point1
, wo Sie mit dem Zeichnen des Bogens beginnen möchten. sweepAngle
bezeichnet den Winkel zwischen zwei Linien. Wir müssen das berechnen, indem wir zwei Punkte wie die blauen Punkte in meinem Fragenbild verwenden.
Tun Sie so etwas:
@Override
protected void onDraw(Canvas canvas) {
Paint p = new Paint();
RectF rectF = new RectF(50, 20, 100, 80);
p.setColor(Color.BLACK);
canvas.drawArc (rectF, 90, 45, true, p);
}
Ich habe versucht, etwas anders zu machen, und es geht nur darum, die Schwenk- und Startwinkel zu berechnen.
Ich wollte einen Bogen zeigen, der den Fortschritt auf einem Kreis darstellt, der von oben nach unten verläuft.
Ich hatte also einen Fortschrittswert von 0 ... 100 und möchte einen Bogen zeigen, der von oben nach unten beginnt, um den Kreis zu füllen, wenn der Fortschritt 100 beträgt.
Zur Berechnung des sweepAngle verwende ich:
int sweepAngle = (int) (360 * (getProgress() / 100.f));
Als nächstes berechnen Sie den StartAngle
int startAngle = 270 - sweepAngle / 2;
Der Startwinkel wird auf folgende Weise berechnet:
Wenn man bedenkt, dass ich einen Fortschritt von 25% habe
sweepAngle = 90 degrees (90 degrees is quarter of a circle)
start angle = 225 (45 degrees away from 270)
Wenn Sie möchten, dass der Fortschritt von anderen Seiten (von links nach rechts, von rechts nach links usw.) verläuft, müssen Sie nur 270 durch den Start des Winkels ersetzen.
eine Probe für den Zeichenbogen.
public static Bitmap clipRoundedCorner(Bitmap bitmap, float r, boolean tr, boolean tl, boolean bl, boolean br)
{
int W = bitmap.getWidth();
int H = bitmap.getHeight();
if (r < 0)
r = 0;
int smallLeg = W;
if(H < W )
smallLeg = H;
if (r > smallLeg)
r = smallLeg / 2;
float lineStop = r/2;
Path path = new Path();
path.moveTo(0,0);
if(tr)
{
path.moveTo(0, lineStop);
path.arcTo(new RectF(0,0, r,r), 180, 90, false);
}
path.lineTo(W-lineStop, 0);
if(tl)
path.arcTo(new RectF(W-r,0, W,r), 270, 90, false);
else
path.lineTo(W, 0);
path.lineTo(W, H-lineStop);
if(bl)
path.arcTo(new RectF(W-r,H-r, W,H), 0, 90, false);
else
path.lineTo(W, H);
path.lineTo(lineStop, H);
if(br)
path.arcTo(new RectF(0,H-r, r,H), 90, 90, false);
else
path.lineTo(0,H);
if(tr)
path.lineTo(0,lineStop);
else
path.lineTo(0,0);
Bitmap output = Bitmap.createBitmap(W, H, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint.setColor(Color.BLACK);
canvas.drawPath(path, Paint);
Paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, 0, 0, Paint);
return output;
}
Ich kann zu spät antworten, aber ich habe mehr Informationen.
Nach Android Lollipop
Es gibt zwei Möglichkeiten, um dieses Problem zu beheben
public void drawArc (RectF oval, float startAngle, float sweepAngle, Boolean useCenter, Paint paint)
public void drawArc (Float links, Float oben, Float rechts, Float unten, Float StartAngle, Float SweepAngle, Boolean UseCenter, Paint Paint)
Verwendung:
RectF rectF = new RectF(left, top, right, bottom);
// method 1
canvas.drawArc (rectF, 90, 45, true, paints[0]);
// method 2
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
}
Der Schwenkwinkel ist nichts anderes als der Winkel des Sektors, der im Uhrzeigersinn gezeichnet wird, z. für untenstehenden Code
private void drawArcs(Canvas canvas) {
RectF rectF = new RectF(left, top, right, bottom);
// white arc
canvas.drawArc (rectF, 90, 45, true, paints[0]);
// Green arc
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
}
// Red stroked arc
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
canvas.drawArc (left, top, right, bottom, 180, 45, true, paints[2]);
}
}
Das Ergebnis wird so aussehen
Dasselbe kann erreicht werden, indem Pfade definiert und dann in der onDraw-Methode über sie iteriert werden, wie in diesem Snippet dargestellt:
public class ArcDrawable extends Drawable {
private int left, right, top, bottom;
private Paint[] paints = new Paint[3];
private HashMap<Path, Paint> pathMap = new HashMap();
public ArcDrawable() {
// white Paint
Paint whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
whitePaint.setColor(Color.WHITE);
paints[0]= whitePaint;
// green Paint
Paint greenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
greenPaint.setColor(Color.GREEN);
paints[1]= greenPaint;
// red Paint
Paint redPaint =new Paint(Paint.ANTI_ALIAS_FLAG);
redPaint.setColor(Color.RED);
redPaint.setStyle(Paint.Style.STROKE);
paints[2]= redPaint;
}
@Override
public void draw(Canvas canvas) {
//----------USE PATHS----------
// Define and use custom Path
for (Map.Entry<Path, Paint> entry : pathMap.entrySet()) {
// Draw Path on respective Paint style
canvas.drawPath(entry.getKey(), entry.getValue());
}
// -------OR use conventional Style---------
//drawArcs(canvas);
}
//Same result
private void drawArcs(Canvas canvas) {
RectF rectF = new RectF(left, top, right, bottom);
// method 1
canvas.drawArc (rectF, 90, 45, true, paints[0]);
// method 2
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
canvas.drawArc (left, top, right, bottom, 0, 45, true, paints[1]);
}
// method two with stroke
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
canvas.drawArc (left, top, right, bottom, 180, 45, true, paints[2]);
}
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
int width = bounds.width();
int height = bounds.height();
left = bounds.left;
right = bounds.right;
top = bounds.top;
bottom = bounds.bottom;
final int size = Math.min(width, height);
final int centerX = bounds.left + (width / 2);
final int centerY = bounds.top + (height / 2);
pathMap.clear();
//update pathmap using new bounds
recreatePathMap(size, centerX, centerY);
invalidateSelf();
}
private Path recreatePathMap(int size, int centerX, int centerY) {
RectF rectF = new RectF(left, top, right, bottom);
// first arc
Path arcPath = new Path();
arcPath.moveTo(centerX,centerY);
arcPath.arcTo (rectF, 90, 45);
arcPath.close();
// add to draw Map
pathMap.put(arcPath, paints[0]);
//second arc
arcPath = new Path();
arcPath.moveTo(centerX,centerY);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
arcPath.arcTo (rectF, 0, 45);
}
arcPath.close();
// add to draw Map
pathMap.put(arcPath, paints[1]);
// third arc
arcPath = new Path();
arcPath.moveTo(centerX,centerY);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
arcPath.arcTo (rectF, 180, 45);
}
arcPath.close();
// add to draw Map
pathMap.put(arcPath, paints[2]);
return arcPath;
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return 0;
}
}
Vollständiger Quellcode:
Eine einfache Lösung wurde vorgeschlagen hier von Langkiller. Dies zeichnet eine kubische Linie vom Startpunkt über den Kontrollpunkt zum Endpunkt.
Path path = new Path();
float startX = 0;
float startY = 2;
float controlX = 2;
float controlY = 4;
float endX = 4
float endY = 2
conePath.cubicTo(startX, startY, controlX, controlY,endX, endY);
Paint paint = new Paint();
Paint.setARGB(200, 62, 90, 177);
Paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, Paint)