2012-07-13 13 views
17

Próbuję animować przejście CALayer od normalnych narożników do zaokrąglonych narożników. Chcę tylko zaokrąglić górne rogi, więc używam UIBezierPath. Oto kod:CABasicAnimation ze ścieżką CALayer nie animuje

UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight; 

UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)]; 
UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0f, 0.0f)]; 

CAShapeLayer* layer = [CAShapeLayer layer]; 
layer.frame = self.bounds; 
layer.path = oldPath.CGPath; 

self.layer.mask = layer; 

CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"]; 
[a setDuration:0.4f]; 
[a setFromValue:(id)layer.path]; 
[a setToValue:(id)newPath.CGPath]; 

layer.path = newPath.CGPath; 
[layer addAnimation:a forKey:@"path"]; 

Ale gdy uruchamiam to, narożniki są zaokrąglone, ale nie ma animation- zdarza się natychmiast. Widziałem kilka podobnych pytań tutaj na SO, ale nie rozwiązały mojego problemu.

iPhone CALayer animation

Animating CALayer's shadowPath property

jestem pewien, że jestem po prostu robi jeden drobiazg źle który jest przyczyną problemu, ale dla życia mnie nie mogę zrozumieć.

Rozwiązanie:

- (void)roundCornersAnimated:(BOOL)animated { 
    UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight; 

    UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)]; 
    UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0001f, 0.0001f)]; 

    CAShapeLayer* layer = [CAShapeLayer layer]; 
    layer.frame = self.bounds; 

    self.layer.mask = layer; 

    if(animated) { 
     CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"]; 
     [a setDuration:0.4f]; 
     [a setFromValue:(id)oldPath.CGPath]; 
     [a setToValue:(id)newPath.CGPath]; 

     layer.path = newPath.CGPath; 
     [layer addAnimation:a forKey:@"path"]; 
    } else { 
     layer.path = newPath.CGPath; 
    } 
} 

Naprawdę wszystko, co potrzebne do zrobienia została ustawiona właściwa 'od' wartości dla animacji.

+1

rozwiązaniem byłoby miłe, jako odpowiedź zamiast części pytania, ale jest to pomocne tak więc +1 :) – buildsucceeded

Odpowiedz

10

Wygląda na to, że tworzysz warstwę kształtu, która nie ma ścieżki, a następnie próbuje animować dodawanie ścieżki do niej. Warstwy kształtów są przypadkami specjalnymi i nie działają w ten sposób.

Musisz mieć ścieżkę w warstwie kształtu przed i po animacji, a ścieżka musi mieć taką samą liczbę punktów zarówno przed jak i po.

Musisz utworzyć zaokrągloną prostokątną ścieżkę z promieniem naroża równym 0 (ręcznie, używając serii boków i łuków narożnych), a następnie utwórz nową ścieżkę o niezerowych promieniach dla narożników, które chcesz zaokrąglić i zainstaluj tę ścieżkę jako swoją animację.

Nawet to może nie zadziałać, ponieważ ścieżka musi mieć dokładnie taką samą liczbę punktów i podejrzewam, że łuki upraszczają punkty, gdy promień jest równy zero.

Właśnie znalazłem wywołanie UIBezierPath, które utworzy prostokąt, w którym można wybrać rogi dookoła. Połączenie to bezierPathWithRoundedRect: byRoundingCorners: cornerRadii:

To utworzy prostokąt z dowolną liczbą zaokrąglonych narożników, jak chcesz. Jednak nie jestem pewien, czy zadziała w przypadku animacji ścieżki. Konieczne może być zażądanie, aby wszystkie narożniki zostały zaokrąglone za pomocą 2 nie zaokrąglonych narożników o promieniu zerowym. W ten sposób MOŻESZ uzyskać ścieżkę z taką samą liczbą punktów jak zaokrąglony prostokąt, aby animacja ścieżki działała poprawnie. Musisz spróbować.

+0

Dzięki. Miałeś rację. Ustawienie poprawnej wartości "z" dla animacji zrobiło to. –

4

spróbować umieścić:

layer.path = newPath.CGPath; 

po:

[layer addAnimation:a forKey:@"path"]; 
Powiązane problemy