iOS 7 Parallaxeeffekt in meinem View Controller


112

Ich entwickle eine App für iOS 7 in Objective-C. Ich habe einen Bildschirm in meiner App mit ein paar Schaltflächen und einem hübschen Hintergrundbild. (Es ist eine einfache xib mit UIButtonsoben auf a UIImageView.)

Ich dachte, es wäre cool, wenn diese Tasten den Parallaxeeffekt hätten, den der iOS 7-Startbildschirm hat. Wenn Sie also das Telefon neigen, können Sie den Hintergrund sehen.

Wie kann ich diesen Effekt in meiner eigenen App implementieren?


1
Schauen Sie sich diese Bibliothek an: github.com/Przytua/UIView-MWParallax
CRDave

Antworten:


273

Mit iOS 7 hat Apple UIMotionEffectMotion-Effekte hinzugefügt, die sich auf die Ausrichtung des Geräts des Benutzers beziehen. Um beispielsweise den Parallaxeeffekt auf dem Startbildschirm zu emulieren, können Sie die hier und hierUIInterpolationMotionEffect erläuterte Unterklasse nur mit wenigen Codezeilen verwenden.

Ziel-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 (Danke an @Lucas):

// 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)

Sie können auch eine Reihe von Bibliotheken finden, um dies zu vereinfachen oder diese Funktionalität älteren iOS-Versionen hinzuzufügen:


2
NGAParallaxMotion ist für iOS 7+, nicht für ältere iOS-Versionen. Es bietet eine Kategorie für UIView, mit der Sie einen .parallaxIntensity-Wert festlegen und die UIMotionEffect-Parameter mit einer Codezeile einrichten können.
Dan Fabulich

2
Vielen Dank! Ich habe die Antwort aktualisiert, um unterstützte Versionen und Anforderungen aufzunehmen.
Veducm

1
Eigentlich möchten Sie den Bewegungseffekt zur Hintergrundansicht hinzufügen, nicht zur Vorderansicht. Aber ansonsten funktioniert dieser Code großartig! Vielen Dank.
Gruppe

1
Weiß jemand, wie man überprüft, ob der Benutzer die Effekte deaktiviert hat? stackoverflow.com/questions/19132000/…
Eric

3
@gstroup Auf dem Startbildschirm bewegen sich sowohl der Vordergrund als auch der Hintergrund. Wenn Sie jedoch nur eine Ebene auswählen, auf die der Parallaxeeffekt angewendet werden soll, ist der Hintergrund wahrscheinlich am besten.
Rubberduck

16

Übersetzt in schnell, falls jemand faul ist. Bitte stimmen @veducm beantworten , wenn Sie das nützlich gefunden

@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)
}

Danke @Lucas! Ich habe meine Antwort aktualisiert, um auch die schnelle Stichprobe aufzunehmen. Es basiert auf diesem. Fühlen Sie sich frei, es zu überprüfen und alle erforderlichen Änderungen vorzunehmen.
Veducm

7

Die Lösung von @ veducm kann etwas kürzer sein. Die UIMotionEffectGroup für ihre x- und y-Bewegung ist veraltet, wenn Sie die Bewegungseffekte der x- und y-Achse separat hinzufügen.

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
Genau wie ein Heads-up, wenn jemand diese verkürzte Version verwendet, muss der erste Bewegungseffekt ein typevon haben UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxisund nicht so, UIInterpolatingMotionEffectTypeTiltAlongVerticalAxiswie es im Code festgelegt ist
Flexicoder

1
@BooHoo Das Hinzufügen als Gruppe ist veraltet? Wo siehst du das? Zum Zeitpunkt dieses Schreibens haben die Apple-Dokumente nichts davon, dass sie veraltet sind. Der gesamte Zweck der Gruppierung besteht darin, die Leistung zu verbessern. Alle Effekte in der Gruppe werden einmal gerendert. Wenn Sie sie separat anwenden, müssen sie separat gerendert werden. Fühlen Sie sich frei, mich zu korrigieren, wenn ich falsch liege (und verweisen Sie mich auf Apples Dokumentation dazu)
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 gemäß Ihrem Vorschlag aktualisiert die Antwort
damithH

5

Hier ist eine einfache Kategorie, um den Effekt auf iOs7 + zu integrieren:

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
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert.
Maciej Swic

Es wird schwierig sein, das gesamte Github-Projekt hier zu integrieren
Bejil

1
Sie müssen nicht das gesamte Projekt mitbringen, sondern nur den wesentlichen Teil, den ich durch Bearbeiten der Antwort demonstriert habe. Dies ist so, dass der Code für den Fall bleibt, dass Github nicht funktioniert, Sie das Repo ziehen oder der Himmel herunterfällt.
Maciej Swic


3

Dies hilft jemandem, der eine Parallaxe für tableView oder collectionView implementieren möchte.

  • Erstellen Sie zunächst die Zelle für die Tabellenansicht und fügen Sie die Bildansicht ein.

  • Stellen Sie die Bildhöhe etwas höher als die Zellenhöhe ein. Wenn die Zellenhöhe = 160 ist, muss die Bildhöhe 200 betragen (um den Parallaxeeffekt zu erzielen, können Sie ihn entsprechend ändern).

  • Fügen Sie diese beiden Variablen in Ihren viewController oder in eine beliebige Klasse ein, in der Ihr tableView-Delegat erweitert ist

let imageHeight:CGFloat = 150.0
let OffsetSpeed: CGFloat = 25.0
  • Fügen Sie den folgenden Code in derselben Klasse hinzu
 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))
        }
    }
}
  • Dabei ist seriesTabelView meine UItableview

  • und jetzt gehen wir zur Zelle dieser Tabellenansicht und fügen den folgenden Code hinzu

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

Wenn Sie dies in collectionView implementieren möchten, ändern Sie einfach die tableView vairable in Ihre collectionView-Variable

und das ist es. Ich bin mir nicht sicher, ob dies der beste Weg ist. aber es funktioniert bei mir. hoffe es funktioniert auch bei dir. und lassen Sie mich wissen, wenn es ein Problem gibt


2

Wirklich verdammt einfach , warum bezieht sich komplexer Code. Probier es einfach. Arbeiten

Betrachten Sie die Bildansicht genau so groß wie die Bildansicht. Standardmäßig Alpha für Ansichtssatz 0.

//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

Schnelle Übersetzung:

// 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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.