Benutzerdefiniertes Layout, das die Ecken seines Inhalts abrundet

6

Ich möchte eine generische ViewGroup erstellen, die dann in XML-Layouts wiederverwendet werden kann, um die Ecken von allem, was darin eingefügt wird, abzurunden.

Aus irgendeinem Grund scheint canvas.clipPath() keinen Effekt zu haben. Was mache ich falsch?

Hier ist der Java-Code:

%Vor%

Verwendung in XML:

%Vor%     
Peter V 22.11.2012, 17:00
quelle

7 Antworten

32

Der richtige Weg, um ein ViewGroup zu erstellen, das seine untergeordneten Objekte abschneidet, ist die Methode dispatchDraw(Canvas) .

Dies ist ein Beispiel dafür, wie Sie alle untergeordneten Elemente eines ViewGroup mit einem Kreis abschneiden können:

%Vor%

Die dispatchDraw -Methode ist diejenige, die zum Abschneiden von Kindern aufgerufen wird. Keine Notwendigkeit, setWillNotDraw(false) , wenn Ihr Layout nur seine Kinder abschneiden.

Dieses Bild wird mit dem obigen Code erhalten, ich habe Facebook ProfilePictureView (das ist ein FrameLayout einschließlich eines Quadrates ImageView mit dem Facebook-Profilbild) erweitert:

Um einen runden Rand zu erhalten, machen Sie so etwas:

%Vor%

Sie können tatsächlich jeden komplexen Pfad erstellen:)

Denken Sie daran, dass Sie clipPath mehrmals mit der "Op" -Operation aufrufen können, um mehrere Clipping auf die von Ihnen gewünschte Weise zu schneiden.

HINWEIS: Ich habe den Pfad in onSizeChanged erstellt, da dies in onDraw für die Leistung schlecht ist.

HINWEIS2: Das Clippen eines Pfades erfolgt ohne Anti-Aliasing: / Wenn Sie glatte Ränder wünschen, müssen Sie dies auf andere Weise tun. Ich bin mir nicht bewusst, dass Clipping jetzt Anti-Aliasing verwendet.

UPDATE (Gliederung)

Seit Android Lollipop (API 21) können Höhe und Schatten auf Ansichten angewendet werden. Ein neues Konzept namens Gliederung wurde eingeführt. Dies ist ein Pfad, der dem Framework die Form der Ansicht angibt, die verwendet werden soll, um den Schatten zu berechnen und andere Dinge (wie Welleneffekte ).

Der Standard Outline der Ansicht ist ein Rechteck der Größe der Ansicht, kann aber leicht zu einem Oval / Kreis oder einem abgerundeten Rechteck gemacht werden. Um eine benutzerdefinierte Outline zu definieren, müssen Sie die Methode % co_de verwenden % in der Ansicht. Wenn es sich um eine benutzerdefinierte Ansicht handelt, können Sie sie im Konstruktor festlegen, wobei Ihre benutzerdefinierte setOutlineProvider() als innere Klasse Ihrer benutzerdefinierten Ansicht definiert ist. Sie können Ihren eigenen ViewOutlineProvider -Provider mit einem Outline Ihrer Wahl definieren, solange es sich um einen konvexen Pfad handelt (mathematisches Konzept bedeutet einen geschlossenen Pfad ohne Aussparung und keine Löcher, zum Beispiel weder eine Sternform noch eine Zahnradform sind konvex).

Sie können auch die Methode Path verwenden Umreißen auch clip (und ich denke das funktioniert auch mit Anti-Aliasing, kann jemand in Kommentaren bestätigen / widerlegen? ), dies wird aber nur für nicht- setClipToOutline(true) unterstützt Gliederung.

Viel Glück

    
Daniele Segato 24.09.2015, 15:36
quelle
17

Sie können die Methode draw(Canvas canvas) überschreiben:

%Vor%     
Danil Ternovikh 16.08.2013 16:29
quelle
2

ViewGroup (und damit seine Unterklassen) setzt ein Flag, das angibt, dass es standardmäßig keine Zeichnung ausführt. In der Quelle sieht es ungefähr so ​​aus:

%Vor%

So wird dein onDraw(...) im Moment wahrscheinlich überhaupt nicht getroffen. Wenn Sie manuell zeichnen möchten, rufen Sie setWillNotDraw(false) .

auf     
MH. 22.11.2012 18:44
quelle
2

Vergessen Sie nicht nach onDraw zu fragen, um mit setWillNotDraw (false) aufgerufen zu werden; und setze einen Wert auf mRadius, dann mach einfach so etwas:

%Vor%     
gleroyDroid 13.01.2014 19:50
quelle
0

onDraw von FrameLayout wird nicht genannt , wenn Ur Layouthintergrund nicht festgelegt ist;

Sie sollten dispatchDraw außer Kraft setzen;

    
xihua 23.12.2015 09:13
quelle
-2

U muss die drawChild () -Methode überschreiben, um childViews zu trennen.

%Vor%

Wenn Sie auch den Hintergrund der ViewGroup abschneiden möchten, überschreiben Sie stattdessen draw (). Gefällt Ihnen dies

%Vor%     
user1580830 13.11.2013 05:15
quelle
-3

Warum definieren Sie nicht einfach ein ShapeDrawable als Hintergrund Ihres Layouts und ändern einfach den Eckenradius des Zeichenobjekts zur Laufzeit.

    
Neil 22.11.2012 17:10
quelle

Tags und Links