Görünüm denetleyicimde iOS 7 paralaks efekti


112

Objective-C'de iOS 7 için bir uygulama geliştiriyorum. Uygulamamda birkaç düğme ve güzel bir arka plan resmi olan bir ekranım var. (Bu basit bir xib ve UIButtonsüstünde a UIImageView.)

Bu düğmelerin iOS 7 ana ekranının sahip olduğu paralaks etkisine sahip olmasının harika olacağını düşünüyordum, bu yüzden telefonu eğerek arka planı görebilirsiniz.

Bu etkiyi kendi uygulamamda nasıl uygulayabilirim?


1
Bu kitaplığa bir göz atın: github.com/Przytua/UIView-MWParallax
CRDave

Hızlı bir şekilde şunu deneyin: github.com/ArvindPrakashJoshi/AJParallaxEffect
Arvind

Yanıtlar:


273

Apple, iOS 7 ile birlikte UIMotionEffectkullanıcının cihazının yönüyle ilgili Hareket efektleri eklemeye başladı. Örneğin, ana ekranda paralaks etkisini taklit etmek için UIInterpolationMotionEffect, burada ve burada açıklandığı gibi , sadece birkaç satır kodla alt sınıfı kullanabilirsiniz .

Amaç-C :

// Set vertical effect
UIInterpolatingMotionEffect *verticalMotionEffect = 
  [[UIInterpolatingMotionEffect alloc] 
  initWithKeyPath:@"center.y"
             type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
verticalMotionEffect.minimumRelativeValue = @(-10);
verticalMotionEffect.maximumRelativeValue = @(10);

// Set horizontal effect 
UIInterpolatingMotionEffect *horizontalMotionEffect = 
  [[UIInterpolatingMotionEffect alloc] 
  initWithKeyPath:@"center.x"     
             type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
horizontalMotionEffect.minimumRelativeValue = @(-10);
horizontalMotionEffect.maximumRelativeValue = @(10);

// Create group to combine both
UIMotionEffectGroup *group = [UIMotionEffectGroup new];
group.motionEffects = @[horizontalMotionEffect, verticalMotionEffect];

// Add both effects to your view
[myBackgroundView addMotionEffect:group];

Swift (@Lucas sayesinde):

// Set vertical effect
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y",
type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = -10
verticalMotionEffect.maximumRelativeValue = 10

// Set horizontal effect
let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x",
    type: .TiltAlongHorizontalAxis)
horizontalMotionEffect.minimumRelativeValue = -10
horizontalMotionEffect.maximumRelativeValue = 10

// Create group to combine both
let group = UIMotionEffectGroup()
group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]

// Add both effects to your view
myBackgroundView.addMotionEffect(group)

Ayrıca, bunu daha kolay yapmak veya bu işlevi eski iOS sürümlerine eklemek için bir dizi kitaplık bulabilirsiniz:


2
NGAParallaxMotion, eski iOS sürümleri için değil, iOS 7+ içindir. UIView için bir kategori sağlar ve bir .parallaxIntensity değeri ayarlamanıza ve UIMotionEffect parametrelerini bir satır kodla ayarlamanıza olanak tanır.
Dan Fabulich

2
Teşekkürler! Yanıtı, desteklenen sürümleri ve gereksinimleri içerecek şekilde güncelledim.
veducm

1
Aslında, hareket efektini ön görünüme değil arka plan görünümüne eklemek istersiniz. Ancak bunun dışında bu kod harika çalışıyor! Teşekkürler.
gstroup

1
Kullanıcının etkileri devre dışı bırakıp bırakmadığını kontrol etmeyi bilen var mı? stackoverflow.com/questions/19132000/…
Eric

3
@gstroup Aslında, ana ekranda hem ön plan hem de arka plan hareket ediyor. Ancak paralaks efekti uygulamak için yalnızca bir katman seçerseniz, arka planın muhtemelen en iyi olacağını kabul ediyorum.
Rubberduck

16

Birinin tembel olması durumunda hızlı olarak tercüme edildi. Bunu yararlı bulduysanız lütfen @veducm yanıtına oy verin

@IBOutlet var background : UIImageView!

func parallaxEffectOnBackground() {
    let relativeMotionValue = 50
    var verticalMotionEffect : UIInterpolatingMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y",
        type: .TiltAlongVerticalAxis)
    verticalMotionEffect.minimumRelativeValue = -relativeMotionValue
    verticalMotionEffect.maximumRelativeValue = relativeMotionValue

    var horizontalMotionEffect : UIInterpolatingMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x",
        type: .TiltAlongHorizontalAxis)
    horizontalMotionEffect.minimumRelativeValue = -relativeMotionValue
    horizontalMotionEffect.maximumRelativeValue = relativeMotionValue

    var group : UIMotionEffectGroup = UIMotionEffectGroup()
    group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]

    self.background.addMotionEffect(group)
}

Teşekkürler @ Lucas! Cevabımı hızlı örneği de içerecek şekilde güncelledim. Buna dayanıyor. İncelemekten ve gerekli değişiklikleri yapmaktan çekinmeyin.
veducm

7

@ veducm'un çözümü biraz daha kısa olabilir. X ve y ekseni motionEffects'i ayrı ayrı eklerseniz, x ve y hareketi için UIMotionEffectGroup artık kullanılmıyor.

UIInterpolatingMotionEffect *motionEffect;
motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                               type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[bgView addMotionEffect:motionEffect];

motionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                               type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
motionEffect.minimumRelativeValue = @(-25);
motionEffect.maximumRelativeValue = @(25);
[bgView addMotionEffect:motionEffect];

2
Sadece bu kısaltılmış versiyonunu kullanıyor herkes, ilk hareket etkisinin ihtiyaçları var ise yukarı bir kafaları olarak typebir UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxisdeğil UIInterpolatingMotionEffectTypeTiltAlongVerticalAxiso kodda olduğu gibi dışarı atılmıştır
Flexicoder

1
@BooHoo Bunları bir grup olarak eklemek eski mi? Onu nerede göruyorsun? Bu yazının yazıldığı tarih itibariyle, Apple belgelerinin modası geçmiş olduğuna dair hiçbir şey yok. Bunları gruplamanın tüm amacı performansı artırmaktır. Gruptaki tüm efektler bir kez oluşturulur. Bunları ayrı ayrı uyguladığınızda, ayrı olarak oluşturulmaları gerekir. Yanılıyorsam beni düzeltmekten çekinmeyin (ve beni Apple'ın bu
David Lari

6
const static CGFloat kCustomIOS7MotionEffectExtent = 10.0; 

- (void)applyMotionEffects:(UIView *YOUR_VIEW) {
     if (NSClassFromString(@"UIInterpolatingMotionEffect")) {
         UIInterpolatingMotionEffect *horizontalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
                                                                                                        type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
         horizontalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent);
         horizontalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent);
         UIInterpolatingMotionEffect *verticalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
                                                                                                      type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
         verticalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent);
         verticalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent);
         UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroup alloc] init];
         motionEffectGroup.motionEffects = @[horizontalEffect, verticalEffect]; 
         [YOUR_VIEW addMotionEffect:motionEffectGroup];
     }
}

1
@Rob, önerinize göre cevabı güncelledi
damithH

5

İşte iOs7 + üzerindeki etkiyi entegre etmek için kolay bir kategori:

NSString *const centerX = @"center.x";
NSString *const centerY = @"center.y";

//#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

@implementation UIView (TLMotionEffect)

- (void)addCenterMotionEffectsXYWithOffset:(CGFloat)offset {

//    if(!IS_OS_7_OR_LATER) return;
    if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) return;

    UIInterpolatingMotionEffect *xAxis;
    UIInterpolatingMotionEffect *yAxis;

    xAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:centerX type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
    xAxis.maximumRelativeValue = @(offset);
    xAxis.minimumRelativeValue = @(-offset);

    yAxis = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:centerY type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
    yAxis.minimumRelativeValue = @(-offset);
    yAxis.maximumRelativeValue = @(offset);

    UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init];
    group.motionEffects = @[xAxis, yAxis];

    [self addMotionEffect:group];
}

@end

https://github.com/jvenegas/TLMotionEffect


1
Bu bağlantı soruyu cevaplayabilirken, cevabın temel kısımlarını buraya eklemek ve referans için bağlantıyı sağlamak daha iyidir. Bağlantılı sayfa değişirse, yalnızca bağlantı yanıtları geçersiz hale gelebilir.
Maciej Swic

Tüm github projesini buraya entegre etmek zor olacak
Bejil

1
Tüm projeyi getirmek zorunda değilsiniz, sadece cevabı düzenleyerek gösterdiğim gibi temel kısmı getirmeniz gerekiyor. Bu, Github'un çökmesi, depoyu çekmeniz veya gökyüzü düşmesi durumunda kodun takılıp kalması içindir.
Maciej Swic


3

Bu, tableView veya collectionView için paralaks uygulamak isteyen birine yardımcı olacaktır.

  • her şeyden önce tablo görünümü için hücreyi oluşturun ve resim görünümünü içine yerleştirin.

  • görüntü yüksekliğini hücre yüksekliğinden biraz daha fazla ayarlayın. Hücre yüksekliği = 160 ise, görüntü yüksekliğinin 200 olmasına izin verin (paralaks etkisini yapmak için ve buna göre değiştirebilirsiniz)

  • bu iki değişkeni viewController'ınıza veya tableView temsilcinizin genişletildiği herhangi bir sınıfa koyun

let imageHeight:CGFloat = 150.0
let OffsetSpeed: CGFloat = 25.0
  • aşağıdaki kodu aynı sınıfa ekleyin
 func scrollViewDidScroll(scrollView: UIScrollView) {
    //  print("inside scroll")

    if let visibleCells = seriesTabelView.visibleCells as? [SeriesTableViewCell] {
        for parallaxCell in visibleCells {
            var yOffset = ((seriesTabelView.contentOffset.y - parallaxCell.frame.origin.y) / imageHeight) * OffsetSpeedTwo
            parallaxCell.offset(CGPointMake(0.0, yOffset))
        }
    }
}
  • seriesTabelView kullanıcı arayüzümdür

  • ve şimdi bu tableView hücresine gidip aşağıdaki kodu ekleyelim

func offset(offset: CGPoint) {
        posterImage.frame = CGRectOffset(self.posterImage.bounds, offset.x, offset.y)
    }
  • posterImage benim UIImageView

Bunu collectionView'a uygulamak istiyorsanız, sadece tableView vairable'ını collectionView değişkeninize değiştirin

ve bu kadar. Bunun en iyi yol olduğundan emin değilim. ama benim için çalışıyor. umarım senin için de çalışır. ve herhangi bir sorun varsa bana haber ver


2

Yapması gerçekten çok kolay , bu yüzden neden karmaşık kodu ifade eder. sadece dene. Çalışma

Görüntü görünümünün tam boyutunda bir görüntü görünümü alın. 0 görünüm grubu için varsayılan alfa.

//MARK: Scroll View Delegate methods
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

NSLog(@"X: %f Y: %f",scrollView.contentOffset.x,scrollView.contentOffset.y);

CGFloat scrollY = _mainScrollView.contentOffset.y;
CGFloat height = _alphaView.frame.size.height;

CGFloat alphaMonitor = scrollY/height;

_alphaView.alpha = alphaMonitor;
}

-1

Hızlı çeviri:

// Set vertical effect
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = -value
verticalMotionEffect.maximumRelativeValue = value

// Set vertical effect
let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.x", type: .TiltAlongHorizontalAxis)
verticalMotionEffect.minimumRelativeValue = -value
verticalMotionEffect.maximumRelativeValue = value

let group = UIMotionEffectGroup()
group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]
self.motionEffect = group
self.addMotionEffect(group)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.