Jak mám resetovat po UIScrollView zoom?

hlasů
15

Mám Graph vtahování Uvnitř UIScrollView. Je to jeden velký UIViewpomocí vlastní podtřídy CATiledLayerjako jeho vrstvy.

Když jsem se přibližovat a oddalovat z UIScrollViewchci graf změnit velikost dynamicky, jako to dělá, když se vrátím graf z viewForZoomingInScrollView. Nicméně, graf překreslí sám na nové úrovni přiblížení, a chci obnovit transformace měřítko 1x1, takže příště se uživatel přiblíží, transformace začíná od aktuálního pohledu. Mám-li resetovat transformace identity v scrollViewDidEndZooming, funguje to v simulátoru, ale generuje EXC_BAD_ACCSESv přístroji.

To však ani vyřešit problém úplně na simulátoru a to buď proto, že příště se uživatel přiblíží, transformace resetuje na cokoliv zoom level to bylo u, a tak to vypadá, když jsem byl zvětšen 2x, například, to je najednou na 4x. Když jsem dokončit přiblížení, že končí na správném měřítku, ale skutečný akt zoom vypadá špatně.

Takže první: jak mohu dovolit grafu překreslení sama na standardní stupnice 1x1 po přiblížení, a jak mohu mít hladký zoom skrz?

Edit: Nové poznatky chyba se zdá být „ [CALayer retainCount]: message sent to deallocated instance

Už nikdy zrušení přidělení nějaké vrstvy sám. Předtím jsem nebyl ani vymazání veškeré názory nebo nic. Tato chyba byla vymrštění na zoomem a také otočit. Mám-li odstranit objekt před rotace a znovu ji přidat později, není vyvoláním výjimky. To není volba pro zoomování.

Položena 15/01/2009 v 21:16
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
41

Nemohu vám pomoci s shazovat, jiný než ti, zkontrolovat a ujistěte se, že není neúmyslně autoreleasing pohled nebo vrstvit někde v kódu. Viděl jsem simulátor zvládnout načasování autoreleases jinak než na přístroji (nejčastěji, když se jedná o vlákna).

Měřítko pohledu je problém s UIScrollViewjsem narazit, ačkoli. Během akce pinch-zoom, UIScrollViewbude toho názoru, zadaný v viewForZoomingInScrollView:metodě delegáta a aplikovat transformaci na něj. Tato transformace zajišťuje hladký měřítko zobrazení, aniž by bylo, aby znovu to každý snímek. Na konci operace zoomu, váš způsob delegát scrollViewDidEndZooming:withView:atScale:bude jmenovat a dá vám šanci udělat si více vysoce kvalitní vykreslení vašeho pohledu na nový faktor měřítka. Obecně platí, že to je navrhl, že budete obnovit transformace na svém názoru, že je CGAffineTransformIdentity, a pak váš názor ručně překreslit sám na nové velikosti měřítku.

Nicméně, toto způsobuje problém, protože UIScrollViewse nezdá sledovat pohled obsah transformace, takže na další operaci zoomu nastavuje transformaci zobrazení obsahu na cokoliv celkový Měřítko je. Vzhledem k tomu, že jste ručně překreslit svůj názor na poslední měřítku, to zhoršuje měřítka, což je to, co vidíte.

Jako řešení, já používám UIView podtřídy pro svůj obsah zobrazení s následující metody definované:

- (void)setTransformWithoutScaling:(CGAffineTransform)newTransform;
{
    [super setTransform:newTransform];
}

- (void)setTransform:(CGAffineTransform)newValue;
{
    [super setTransform:CGAffineTransformScale(newValue, 1.0f / previousScale, 1.0f / previousScale)];
}

kde previousScale je plovák instance proměnná pohledu. Pak jsem implementovat zoom metodu delegáta takto:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
    [contentView setTransformWithoutScaling:CGAffineTransformIdentity];
// Code to manually redraw view at new scale here
    contentView.previousScale = scale;
    scrollView.contentSize = contentView.frame.size;
}

Tím se převádí zaslané zobrazení obsahu jsou upraveny na základě stupnice, ve kterém pohled naposledy překreslí. Když je pinch-zoom dokončení transformace se nastaví na stupnici od 1,0 obcházet nastavení v normálním setTransform:způsobem. Zdá se, že poskytovat správné chování měřítka a současně vám umožňuje kreslit ostrý pohled na dokončení zoom.

UPDATE (7/23/2010): iPhone OS 3.2 a vyšší změnily chování zobrazení rolovacích, co se týká zoomování. Nyní, UIScrollViewbude respektovat identitu transformace použít k zobrazení obsahu a poskytují pouze faktor relativní měřítko v -scrollViewDidEndZooming:withView:atScale:. Z tohoto důvodu, výše uvedený kód pro UIViewpodtřídy je nutné pouze pro zařízení s operačním systémem verze iPhone OS starší než 3.2.

Odpovězeno 16/01/2009 v 20:29
zdroj uživatelem

hlasů
12

Díky všem předchozí odpovědi, a tady je moje řešení.
Implementovat UIScrollViewDelegate metody:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return tmv;
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    CGPoint contentOffset = [tmvScrollView contentOffset];   
    CGSize  contentSize   = [tmvScrollView contentSize];
     CGSize  containerSize = [tmv frame].size;

    tmvScrollView.maximumZoomScale = tmvScrollView.maximumZoomScale / scale;
    tmvScrollView.minimumZoomScale = tmvScrollView.minimumZoomScale / scale;

    previousScale *= scale;

    [tmvScrollView setZoomScale:1.0f];

    [tmvScrollView setContentOffset:contentOffset];
    [tmvScrollView setContentSize:contentSize];
    [tmv setFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];  

    [tmv reloadData];
}
  • TMV je můj podtřídy UIView
  • tmvScrollView - výstup na UIScrollView
  • nastavit maximumZoomScale a minimumZoomScale před
  • vytvořit previousScale proměnnou instance a nastavit jeho hodnotu na 1.0f

Pracuje pro mě dokonale.

BR, Eugene.

Odpovězeno 02/08/2011 v 17:33
zdroj uživatelem

hlasů
5

Mám podrobnou diskusi o tom, jak (a proč) UIScrollView zoom pracuje na github.com/andreyvit/ScrollingMadness/ .

(Odkaz obsahuje také popis, jak programově přiblížit UIScrollView, jak emulovat Photo Library ve stylu paging + zoom + rolování, příklad projektu a třídu ZoomScrollView který zapouzdří část zoomu magie).

Citát:

UIScrollView nemá ponětí o „aktuální úroveň zoomu“, protože každá subview obsahuje může mít svůj vlastní aktuální úroveň zoomu. Všimněte si, že není pole UIScrollView udržet současnou úroveň zoomu. Nicméně víme, že někdo ukládá tuto úroveň zoomu, protože pokud špetka-zoom s subview, pak obnovit jeho transformace CGAffineTransformIdentity a znovu štípnout, všimnete si, že předchozí úroveň zvětšení na subview byla obnovena.

Ve skutečnosti, když se podíváte na demontáži je UIView, která ukládá svou vlastní úroveň přiblížení (uvnitř UIGestureInfo objekt, na který ukazuje pole _gestureInfo). Má také řadu pěkných nehlášených metod, jako je zoomScalea setZoomScale:animated:. (Nezapomínejme, že má také spoustu způsobů otáčení souvisejících, možná dostáváme rotační pohyb podpoří nějaký den brzy.)

Nicméně, pokud bychom vytvořit novou UIView jen pro zoomování a přidejte své pravé zoomovatelný pohled jako jeho dítě, budeme vždy začít s úrovní zoomu 1.0. Můj realizace programového zoomování je založen na tento trik.

Odpovězeno 08/05/2009 v 00:04
zdroj uživatelem

hlasů
4

Jen jsem se snaží obnovit na zatížení na výchozí rozsah transfokace, protože když jsem ji přiblížit, scrollview má stejný rozsah zoomu pro příště, až se dostane uvolnit.

-(void) viewWillAppear:(BOOL)animated {
      [self.scrollView setZoomScale:1.0f];
}

Změnila pravidla hry.

Odpovězeno 03/06/2015 v 06:53
zdroj uživatelem

hlasů
3

Poměrně spolehlivý přístup, vhodné IOS 3.2 a 4.0 a později, je následující. Musíte být připraveni poskytnout svůj názor, škálovatelné (hlavní subview toho názoru, rolovací) v libovolném požadovaném rozsahu. Pak scrollViewDidEndZooming:budete odstranit měřítko transformovaných verzi rozmazané tohoto pohledu a nahradit jej novým cílem upozornit na novém měřítku.

Budete potřebovat:

  • Ivar pro zachování předchozího měřítka; nazvěme ji oldScale

  • Způsob identifikace škálovatelné názor, a to jak pro viewForZoomingInScrollView:a scrollViewDidEndZooming:; tady, budu žádat o značku (999)

  • Metoda, která vytváří škálovatelné názor, označí ji a vloží ji do rolovací pohledu (tady budu říkat addNewScalableViewAtScale:). Pamatujte si, že to musí udělat vše podle stupnice - je velikost zobrazení a jeho subviews nebo kreslení a velikosti contentSize pětisměrné pohled tak, aby odpovídal.

  • Konstanty pro minimumZoomScale a maximumZoomScale. Ty jsou potřebné, protože když jsme se nahradit měřítku pohled podrobným větší verze, systém bude myslet, že současná váha je 1, takže musíme blázen do umožňuje uživateli nastavit měřítko zobrazení dolů.

Dobře tedy. Při vytváření zobrazení navigační vložíte škálovatelné pohled na stupnici od 1.0. To by mohlo být ve vašem viewDidLoadnapříklad ( svje scroll view):

[self addNewScalableViewAtScale: 1.0];
sv.minimumZoomScale = MIN;
sv.maximumZoomScale = MAX;
self->oldScale = 1.0;
sv.delegate = self;

Pak ve vaší scrollViewDidEndZooming:děláte to samé, ale kompenzuje změny v měřítku:

UIView* v = [sv viewWithTag:999];
[v removeFromSuperview];
CGFloat newscale = scale * self->oldScale;
self->oldScale = newscale;
[self addNewScalableViewAtScale:newscale];
sv.minimumZoomScale = MIN / newscale;
sv.maximumZoomScale = MAX / newscale;
Odpovězeno 12/11/2010 v 06:33
zdroj uživatelem

hlasů
2

Všimněte si, že řešení za předpokladu, Brad má jeden problém ačkoliv: pokud budete mít programově přiblížení (řekněme o zamezení dvojího události z kohoutku) a nechat uživatel ručně (pinch-out) oddálit, po určité době je rozdíl mezi skutečnou rozsahu a stupnice UIScrollView sleduje poroste příliš velká, takže previousScalev určitém okamžiku pádu z přesnosti float, která bude nakonec mít za následek nepředvídatelné chování

Odpovězeno 28/07/2009 v 04:43
zdroj uživatelem

hlasů
0

Swift 4. * a Xcode 9.3

Nastavení scrollView rozsah zoomu na 0 resetovat scrollView na to počáteční stav.

self.scrollView.setZoomScale(0.0, animated: true)
Odpovězeno 29/06/2018 v 05:21
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more