2013-10-02 12 views
18

Ich mag folgenden Aspekt auf ein UISegmentedControl geben:UISegmentedControl Grenzen

enter image description here

Beachten Sie die graue Hintergrund Ansicht und den weißen Hintergrund des segmentierten Steuer nicht Punkt ausgewählt.

Aber, wenn ich einen weißen Hintergrund zu meinem UISegmentedControl geben, erhalte ich folgendes:

enter image description here

Beachten Sie die weiße Quadrat Ecken rund um die UISegmentedControl. Was soll ich tun, um diese eckigen Ecken zu vermeiden?

Vielen Dank im Voraus,

EDIT: Wenn ich den Eckenradius des Ebenen UISegmentedControl ändern, wie onegray vorgeschlagen, das Ergebnis ist besser, aber nicht perfekt (die weiße Linie auf der rechten Seite beachten):

enter image description here

+0

können Sie einstellen, 'segmented.backgroundColor = [UIColor Clear];' –

+0

@Viruss mca: Vielen Dank für Ihren Kommentar, aber in diesem Fall, den Hintergrund hinter "Tratad wie "ist in grau dargestellt, nicht weiß. – neutrino

+0

Sie können auch zwei UIButtons anstelle von UISegmentedControl als alternative Lösung verwenden. – Engnyl

Antwort

10

Wenn das für alle UISegmentedControls funktionieren sollte, es ist ein bisschen umständlich. Das Problem ist in iOS7 der 1 pt. Grenze zwischen zwei Segmenten zählt nicht zur Größe des Segments. Z.B. Wenn der Rahmen Ihres UISegmentedControl 320 pt. weit müssen Sie 1 pt entfernen. und dann dividiere durch 2. Und (320-1)/2 ist 159.5. iOS legt diesen Wert auf 159 pt. Und du erhältst einen 1 Punkt. Grenze und zwei 159 pt. Segmente. Welches ist 319, und nicht 320. Daher der 1pt. Zeile rechts von Ihrem segmentierten Control.

Es gibt eine Möglichkeit, die Größe "actual" (Größe des Renderings auf dem Bildschirm) des segmentierten Controls zu berechnen. Mit dieser Breite können Sie dann eine UIView mit abgerundeten Ecken unterhalb des UISegmentedControls hinzufügen. Dieser Code sollte für alle Konfigurationen arbeiten, auch wenn Sie manuell große Segmente in Ihrem segmentedControl haben:

- (UIView *)addBackgroundViewBelowSegmentedControl:(UISegmentedControl *)segmentedControl { 
    CGFloat autosizedWidth = CGRectGetWidth(segmentedControl.bounds); 
    autosizedWidth -= (segmentedControl.numberOfSegments - 1); // ignore the 1pt. borders between segments 

    NSInteger numberOfAutosizedSegmentes = 0; 
    NSMutableArray *segmentWidths = [NSMutableArray arrayWithCapacity:segmentedControl.numberOfSegments]; 
    for (NSInteger i = 0; i < segmentedControl.numberOfSegments; i++) { 
     CGFloat width = [segmentedControl widthForSegmentAtIndex:i]; 
     if (width == 0.0f) { 
      // auto sized 
      numberOfAutosizedSegmentes++; 
      [segmentWidths addObject:[NSNull null]]; 
     } 
     else { 
      // manually sized 
      autosizedWidth -= width; 
      [segmentWidths addObject:@(width)]; 
     } 
    } 

    CGFloat autoWidth = floorf(autosizedWidth/(float)numberOfAutosizedSegmentes); 
    CGFloat realWidth = (segmentedControl.numberOfSegments-1);  // add all the 1pt. borders between the segments 
    for (NSInteger i = 0; i < [segmentWidths count]; i++) { 
     id width = segmentWidths[i]; 
     if (width == [NSNull null]) { 
      realWidth += autoWidth; 
     } 
     else { 
      realWidth += [width floatValue]; 
     } 
    } 

    CGRect whiteViewFrame = segmentedControl.frame; 
    whiteViewFrame.size.width = realWidth; 

    UIView *whiteView = [[UIView alloc] initWithFrame:whiteViewFrame]; 
    whiteView.backgroundColor = [UIColor whiteColor]; 
    whiteView.layer.cornerRadius = 5.0f; 
    [self.view insertSubview:whiteView belowSubview:segmentedControl]; 
    return whiteView; 
} 

Bitte beachten Sie die Rahmen selbst ändert.

In diesem Screenshot sehen Sie den Unterschied zwischen den beiden Steuerelementen. Alle Rahmen sind 280 pt. breit.

Aufgrund der Formel UISegmentiertControl verwendet die erste Steuerelemente tatsächliche Größe ist 278 pt. Und die wahre Größe des zweiten ist 279 pt.

enter image description here


Das Problem ist, dass dies irgendwie über die Umsetzung der UISegmentedControl beruht. Apple könnte beispielsweise die Implementierung so ändern, dass segmentWidth, das auf 0,5 Punkte endet, angezeigt wird. Sie könnten dies leicht auf Retina-Displays tun.

Wenn Sie diesen Code verwenden, sollten Sie Ihre Anwendung auf neue iOS-Versionen überprüfen so früh wie möglich. Wir verlassen uns auf Implementierungsdetails, und diese könnten sich jeden Tag ändern. Glücklicherweise passiert nichts Schlechtes, wenn sie die Implementierung ändern. Es wird einfach nicht gut aussehen.

+0

Vielen Dank! Es funktioniert gut. Und du hast eine großartige Erklärung gegeben. – neutrino

16

Einstellen der _segmentedControl.layer.cornerRadius = 5; helfen könnte.

Update: Komplexere Clip rect von 1px richtigen Raum, um loszuwerden:

CAShapeLayer* mask = [[CAShapeLayer alloc] init]; 
    mask.frame = CGRectMake(0, 0, _segmentedControl.bounds.size.width-1, _segmentedControl.bounds.size.height); 
    mask.path = [[UIBezierPath bezierPathWithRoundedRect:mask.frame cornerRadius:4] CGPath]; 
    _segmentedControl.layer.mask = mask; 

Update: Matthias Bauch eine gute Erklärung dafür, warum diese Leerzeichen auf der rechten Seite des UISegmentedControl erscheint. Der einfachste Weg, um es zu entfernen, besteht darin, Segmente mit fester Größe zu erstellen und sie auf die richtige Breite einzustellen.

+0

Vielen Dank für Ihre Antwort. Das Ergebnis ist besser, aber nicht perfekt. Siehe Bild in meinem ursprünglichen Beitrag beigefügt. – neutrino

+0

Nochmals vielen Dank. Schließlich habe ich mit Matthias 'Antwort gesprochen, aber du hast mir sehr geholfen. Ich habe Ihre Lösung getestet und es funktioniert auch für mich. – neutrino

+0

Große Lösung. Vielen Dank!!! –

2

Ich weiß, dass dies eine Art Hack ist, aber Sie könnten einfach eine abgerundete UIView mit weißem Hintergrund direkt unterhalb des segmentierten Steuerelements verwenden - mit Ausnahme der Breite, die der ursprünglichen Steuerbreite minus 1 entsprechen sollte .

Ergebnis: Segmented Control with White Background

+0

Wenn Sie Autolayout verwenden, können Sie die "Hintergrundansicht" an die Breite/Höhe usw. des SegmentControls anheften, sodass Sie nicht mit dem Minus 1 anpassen müssen. Natürlich können Sie auch den cornerRadius der Hintergrundansicht mit Laufzeitattributen festlegen – wuf810

0

Nur zu klären Mattias Bauch ausgezeichnete Antwort. Sie müssen die zurück Ansicht als Subview zu der Ansicht setzen (die wir yourMainView nennen), wo Sie Ihre segmentierte Kontrolle haben:

UIView *segmControlBackground = [self addBackgroundViewBelowSegmentedControl:yourSegmentedControl]; 
[yourMainView addSubview:segmControlBackground]; 



Und Sie müssen, natürlich, erklären die neue Methode in den Header (H) Datei:

- (UIView *)addBackgroundViewBelowSegmentedControl:(UISegmentedControl *)segmentedControl; 
Verwandte Themen