2017-04-19 3 views
2

Ich möchte eine benutzerdefinierte Form (unterschiedlicher Radius für jede Ecke des Rechtecks) zu meinem Rahmenlayout festlegen, so dass Ansichten im Rahmenlayout an die Grenzen der Form clip.Erstellen Sie benutzerdefinierte konvexe Pfad Android

ViewOutlineProvider provider = new ViewOutlineProvider() { 
     @Override 
     public void getOutline(View view, Outline outline) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
       configurePath(getWidth(), getHeight()); 
       outline.setConvexPath(borderPath); 
      } 
     } 
    }; 

    setOutlineProvider(provider); 
    setClipToOutline(true); 

Und die configurePath() sieht wie folgt aus:

private void configurePath (int width, int height) { 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 
     return; 
    } 

    borderPath.rewind(); 

    float minSize = Math.min(width, height); 
    float maxRadiusWidth = 2 * Math.max(Math.max(topLeftRadius, topRightRadius), 
      Math.max(bottomLeftRadius, bottomRightRadius)); 

    if (minSize < maxRadiusWidth) { 
     borderPath.addRect(0, 0, width, height, Path.Direction.CCW); 
     return; 
    } 

    // Top left circle 
    oval.set(0, 0, 2 * topLeftRadius, 2 * topLeftRadius); 
    borderPath.moveTo(0, topLeftRadius); 
    borderPath.arcTo(oval, 180, -90); 

    borderPath.rLineTo(width - topLeftRadius - topRightRadius, 0); 

    // Top right circle 
    oval.set(width - 2 * topRightRadius, 0, width, 2 * topRightRadius); 
    borderPath.arcTo(oval, 90, -90); 

    borderPath.rLineTo(0, height - topRightRadius - bottomRightRadius); 

    // Bottom right circle 
    oval.set(width - 2 * bottomRightRadius, height - 2 * bottomRightRadius, width, height); 
    borderPath.arcTo(oval, 0, -90); 

    borderPath.rLineTo(-width + bottomRightRadius + bottomLeftRadius, 0); 

    // Bottom left circle 
    oval.set(0, height - 2 * bottomLeftRadius, 2 * bottomLeftRadius, height); 
    borderPath.arcTo(oval, -90, -90); 

    borderPath.rLineTo(0, -height + bottomLeftRadius + topLeftRadius); 
} 

Wenn ich es laufen, ich habe java.lang.IllegalArgumentException: path must be convex und ich konnte nicht in native_isConvex() und sehen, wie es entscheidet, ob ein Weg konvex ist.

Was ist also ein konvexer Pfad? Warum ist der Pfad in congfigurePath() nicht konvex? Wie kann ich einen benutzerdefinierten konvexen Pfad erstellen? Vielen Dank.

+0

Mit dem gleichen Problem konfrontiert. Im Moment weiß ich, dass 'isConvex', wenn ich nur' lineTo'-Methoden verwende, 'true' zurückgeben kann. Die Verwendung von 'quadTo' oder' arcTo' bewirkt, dass 'isConvex'' 'false' zurückgibt. Vielleicht kann dies ein Tipp sein ... – pxsx

+0

@pxsxYeah, 'arcTo' ist, was ich dachte, dass das Problem verursacht. Aber ich muss es verwenden, weil ich eine benutzerdefinierte Form für die Ansichtsgruppe erstellen wollte. Wie auch immer, ich habe das Problem der benutzerdefinierten Form mit clipPath gelöst. –

Antwort

1

Ich habe es selbst herausgefunden. Der Pfad ist nicht konvex, weil ich den Pfad nicht korrekt gezeichnet habe.

// Top left circle 
    oval.set(0, 0, 2 * topLeftRadius, 2 * topLeftRadius); 
    borderPath.moveTo(0, topLeftRadius); 
    borderPath.arcTo(oval, -180, 90); 

    borderPath.rLineTo(width - topLeftRadius - topRightRadius, 0); 

    // Top right circle 
    oval.set(width - 2 * topRightRadius, 0, width, 2 * topRightRadius); 
    borderPath.arcTo(oval, -90, 90); 

    borderPath.rLineTo(0, height - topRightRadius - bottomRightRadius); 

    // Bottom right circle 
    oval.set(width - 2 * bottomRightRadius, height - 2 * bottomRightRadius, width, height); 
    borderPath.arcTo(oval, 0, 90); 

    borderPath.rLineTo(-width + bottomRightRadius + bottomLeftRadius, 0); 

    // Bottom left circle 
    oval.set(0, height - 2 * bottomLeftRadius, 2 * bottomLeftRadius, height); 
    borderPath.arcTo(oval, 90, 90); 

    borderPath.rLineTo(0, -height + bottomLeftRadius + topLeftRadius); 

aktualisieren

: Der richtige Weg, die mehrere Eckenradius Wirkung erzielen soll ich sein wollte Obwohl der Weg nun richtig ist, ist es immer noch nicht konvex Weg, scheint wie maßgeschneiderter Pfad nicht als konvexer Weg behandelt werden.

0

Schön, dass Sie es funktioniert haben, aber es sind eingebaute Tools dafür.
Einfachste ist in einem ziehbaren xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
    <corners 
     android:bottomLeftRadius="8dp" 
     android:topLeftRadius="8dp" 
     android:topRightRadius="8dp" 
     android:bottomRightRadius="0dp" /> 

    <solid android:color="#fff" /> 

</shape> 

Programatically können Sie die RoundRectShape Klasse. Das ist auch, was von oben xml aufgeblasen wird.
Im Kursor übergeben Sie den äußeren Eckenradius, die Liniendicke und den inneren Eckenradius. Sie können auch die Quelle betrachten, um zu sehen, wie sie einen Pfad erstellen (Tipp: path.addRoundRect()).

+1

Vielen Dank, dass Sie mich über 'addRoundRect (RectF rect, float [] Radien, direction dir) informiert haben. Aber nach dem Quellcode von Outline: 'public boolean canClip() { return mMode! = MODE_CONVEX_PATH; } Umriss unterstützt keine benutzerdefinierte Form –

Verwandte Themen