лучший способ перехода между двумя изображениями в uiimageview

<p>я реализовал довольно простой просмотрщик картинок, который позволит пользователю просматривать коллекцию изображений. они загружаются из интернета и отображаются на устройстве через объект <code>uiimageview</code>. что-то вроде этого:</p><pre><code>uiimage *image = [[uiimage alloc] initwithdata:imagedata]; [img setimage:image]; </code></pre><p><code>imagedata</code> - это экземпляр <code>nsdata</code>, который я использую для загрузки содержимого изображения из url, а <code>img</code> - это экземпляр <code>uiimageview</code>.</p><p>все работает хорошо, но новое изображение заменяет то, которое отображалось раньше, без каких-либо переходов, и мне было интересно, есть ли простой способ сделать хороший анимационный переход для улучшения пользовательского опыта.</p><p>есть идеи как это сделать? примеры кода будут очень цениться.</p>

<p>я просто просматривал ваш пост и имел точно такое же требование. проблема со всеми вышеупомянутыми решениями заключается в том, что вам придется включить логику перехода в свой контроллер. в этом смысле подход не является модульным. вместо этого я написал этот подкласс uiimageview:</p><p><strong> transitionimageview.h файл: </strong></p><pre><code>#import <uikit/uikit.h> @interface transitionimageview : uiimageview { uiimageview *moriginalimageviewcontainerview; uiimageview *mintermediatetransitionview; } @property (nonatomic, retain) uiimageview *originalimageviewcontainerview; @property (nonatomic, retain) uiimageview *intermediatetransitionview; #pragma mark - #pragma mark animation methods -(void)setimage:(uiimage *)innewimage withtransitionanimation:(bool)inanimation; @end </code></pre><p><strong> файл transitionimageview.m: </strong></p><pre><code>#import "transitionimageview.h" #define transition\_duration 1.0 @implementation transitionimageview @synthesize intermediatetransitionview = mintermediatetransitionview; @synthesize originalimageviewcontainerview = moriginalimageviewcontainerview; - (id)initwithframe:(cgrect)frame { if ((self = [super initwithframe:frame])) { // initialization code } return self; } /* // only override drawrect: if you perform custom drawing. // an empty implementation adversely affects performance during animation. - (void)drawrect:(cgrect)rect { // drawing code } */ - (void)dealloc { [self setoriginalimageviewcontainerview:nil]; [self setintermediatetransitionview:nil]; [super dealloc]; } #pragma mark - #pragma mark animation methods -(void)setimage:(uiimage *)innewimage withtransitionanimation:(bool)inanimation { if (!inanimation) { [self setimage:innewimage]; } else { // create a transparent imageview which will display the transition image. cgrect rectfornewview = [self frame]; rectfornewview.origin = cgpointzero; uiimageview *intermediateview = [[uiimageview alloc] initwithframe:rectfornewview]; [intermediateview setbackgroundcolor:[uicolor clearcolor]]; [intermediateview setcontentmode:[self contentmode]]; [intermediateview setclipstobounds:[self clipstobounds]]; [intermediateview setimage:innewimage]; // create the image view which will contain original imageview's contents: uiimageview *originalview = [[uiimageview alloc] initwithframe:rectfornewview]; [originalview setbackgroundcolor:[uicolor clearcolor]]; [originalview setcontentmode:[self contentmode]]; [originalview setclipstobounds:[self clipstobounds]]; [originalview setimage:[self image]]; // remove image from the main imageview and add the originalview as subview to mainview: [self setimage:nil]; [self addsubview:originalview]; // add the transparent imageview as subview whose dimensions are same as the view which holds it. [self addsubview:intermediateview]; // set alpha value to 0 initially: [intermediateview setalpha:0.0]; [originalview setalpha:1.0]; [self setintermediatetransitionview:intermediateview]; [self setoriginalimageviewcontainerview:originalview]; [intermediateview release]; [originalview release]; // begin animations: [uiview beginanimations:@"imageviewtransitions" context:nil]; [uiview setanimationduration:(double)transition\_duration]; [uiview setanimationdelegate:self]; [uiview setanimationcurve:uiviewanimationcurveeaseout]; [uiview setanimationdidstopselector:@selector(animationdidstop:finished:context:)]; [[self intermediatetransitionview] setalpha:1.0]; [[self originalimageviewcontainerview] setalpha:0.0]; [uiview commitanimations]; } } -(void)animationdidstop:(nsstring *)animationid finished:(nsnumber *)finished context:(void *)context { // reset the alpha of the main imageview [self setalpha:1.0]; // set the image to the main imageview: [self setimage:[[self intermediatetransitionview] image]]; [[self intermediatetransitionview] removefromsuperview]; [self setintermediatetransitionview:nil]; [[self originalimageviewcontainerview] removefromsuperview]; [self setoriginalimageviewcontainerview:nil]; } @end </code></pre><p>вы даже можете переопределить метод <code>-setimage</code> в uiimageview и вызвать мой метод <code>-setimage:withtransitionanimation:</code>. если это сделано так, убедитесь, что вы вызываете <code>[super setimage:]</code> вместо <code>[self setimage:]</code> в методе <code>-setimage:withtransitionanimation:</code>, чтобы он не заканчивался бесконечным рекурсивным вызовом!</p><p>-raj</p>

<pre><code>[uiview animatewithduration:0.2 delay:0 options:uiviewanimationcurveeaseout animations:^{ self.view0.alpha = 0; self.view1.alpha = 1; } completion:^(bool finished){ view0.hidden = yes; } ]; </code></pre>

<p>пожалуйста, проверьте ответ. я думаю, что вы ищете это:</p><pre><code>imgvw.image=[uiimage imagewithdata:[nsdata datawithcontentsofurl:[nsurl urlwithstring:@"your image name as string"]]]; catransition *transition = [catransition animation]; transition.duration = 1.0f; transition.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctioneaseineaseout]; transition.type = kcatransitionfade; [imgvw.layer addanimation:transition forkey:nil]; </code></pre>

<p>хитрость в том, что вы создаете два экземпляра uiimageview. вы меняете их между вызовами uiview + beginanimations и + commitanimations.</p>

<p>ничего не отличается от того, что было объяснено, но в коде это доступные переходы:</p><pre><code>typedef enum { uiviewanimationtransitionnone, uiviewanimationtransitionflipfromleft, uiviewanimationtransitionflipfromright, uiviewanimationtransitioncurlup, uiviewanimationtransitioncurldown, } uiviewanimationtransition; </code></pre><p><strong> код </strong><em>(поместите это в обратный вызов, как touchesended)</em>:</p><pre><code>cgcontextref context = uigraphicsgetcurrentcontext(); [uiview beginanimations:nil context:context]; [uiview setanimationtransition: uiviewanimationtransitionflipfromleft forview:[self superview] cache:yes]; // -- these don't work on the simulator and the curl up will turn into a fade -- // //[uiview setanimationtransition: uiviewanimationtransitioncurlup forview:[self superview] cache:yes]; //[uiview setanimationtransition: uiviewanimationtransitioncurldown forview:[self superview] cache:yes]; [uiview setanimationcurve:uiviewanimationcurveeaseinout]; [uiview setanimationduration:1.0]; // below assumes you have two subviews that you're trying to transition between [[self superview] exchangesubviewatindex:0 withsubviewatindex:1]; [uiview commitanimations]; </code></pre>

<p>есть несколько способов сделать это, и я согласен с тем, что ben view transitions - отличный пример. если вы ищете простые полноэкранные переходы, я бы просто подумал о запуске нового служебного приложения и взглянул на метод toggleview в rootviewcontroller.m. попробуйте переключить uiviewanimationtransitionflipfromleft и uiviewanimationtransitionflipfromright на uiviewanimationtransitioncurlup и uiviewanimationtransitioncurldown для действительно хорошего эффекта перехода (это работает только на устройстве). </p>

<p>вот что я сделал: замирание . я помещаю другой uiimageview с тем же uiimage и размером, который называется tmp . я заменяю uiimage базового uiimageview . затем я помещаю правильное изображение в основание. (по-прежнему покрыты тмп).</p><p>следующим шагом является -, чтобы установить альфа tmp на ноль, -, чтобы растянуть базовый uiimageview к правильному отношению нового uiimage на основе высоты основания.</p><p>вот код:</p><pre><code> uiimage *img = [params objectatindex:0]; // the right image uiimageview *view = [params objectatindex:1]; // the base uiimageview *tmp = [[uiimageview alloc] initwithimage:view.image]; // the one which will use to fade tmp.frame = cgrectmake(0, 0, view.frame.size.width, view.frame.size.height); [view addsubview:tmp]; view.image = img; float r = img.size.width / img.size.height; float h = view.frame.size.height; float w = h * r; float x = view.center.x - w/2; float y = view.frame.origin.y; [uiview beginanimations:nil context:nil]; [uiview setanimationduration:1.0]; tmp.alpha = 0; view.frame = cgrectmake(x, y, w, h); [uiview commitanimations]; [tmp performselector:@selector(removefromsuperview) withobject:nil afterdelay:1.5]; [tmp performselector:@selector(release) withobject:nil afterdelay:2]; </code></pre>