Efek paralaks iOS 7 di pengontrol tampilan saya

112

Saya sedang mengembangkan aplikasi untuk iOS 7 di Objective-C. Saya memiliki layar di aplikasi saya dengan beberapa tombol dan gambar latar belakang yang cantik. (Ini adalah xib sederhana dengan UIButtonsdi atas a UIImageView.)

Saya berpikir akan keren jika tombol-tombol itu memiliki efek paralaks yang dimiliki layar beranda iOS 7, jadi jika Anda memiringkan ponsel, Anda dapat melihat latar belakang.

Bagaimana cara menerapkan efek itu di aplikasi saya sendiri?

Dan Fabulich
sumber
1
Lihat perpustakaan ini: github.com/Przytua/UIView-MWParallax
CRDave
Untuk cepat, coba dengan itu: github.com/ArvindPrakashJoshi/AJParallaxEffect
Arvind

Jawaban:

273

Dengan iOS 7, Apple diperkenalkan UIMotionEffectuntuk menambahkan efek Gerak yang terkait dengan orientasi perangkat pengguna. Misalnya, untuk meniru efek paralaks di layar beranda, Anda dapat menggunakan subkelas UIInterpolationMotionEffect, seperti yang dijelaskan di sini dan di sini , hanya dengan beberapa baris kode.

Objective-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 (Terima kasih kepada @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)

Selain itu, Anda dapat menemukan banyak pustaka untuk melakukan ini dengan lebih mudah atau untuk menambahkan fungsionalitas ini ke versi iOS yang lebih lama:

veducm.dll
sumber
2
NGAParallaxMotion adalah untuk iOS 7+, bukan untuk versi iOS yang lebih lama. Ini menyediakan kategori untuk UIView, memungkinkan Anda untuk menyetel nilai .parallaxIntensity, menyiapkan parameter UIMotionEffect dengan satu baris kode.
Dan Fabulich
2
Terima kasih! Saya telah memperbarui jawaban untuk menyertakan versi dan persyaratan yang didukung.
veducm
1
Sebenarnya, Anda ingin menambahkan efek gerakan ke tampilan latar belakang, bukan tampilan depan. Tapi selain itu, kode ini berfungsi dengan baik! Terima kasih.
gstroup
1
Apakah ada yang tahu cara memeriksa apakah pengguna telah menonaktifkan efeknya? stackoverflow.com/questions/19132000/…
Eric
3
@gstroup Sebenarnya, di layar beranda, latar depan dan latar belakang sedang bergerak. Tetapi jika Anda memilih hanya satu lapisan untuk menerapkan efek paralaks, saya setuju latar belakangnya mungkin yang terbaik.
Rubberduck
16

Diterjemahkan ke cepat jika ada yang malas. Silakan pilih @veducm menjawab jika menurut Anda ini berguna

@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)
}
Lucas
sumber
Terima kasih @Lucas! Saya telah memperbarui jawaban saya untuk menyertakan sampel cepat juga. Itu didasarkan pada yang satu ini. Jangan ragu untuk memeriksanya dan melakukan perubahan apa pun yang diperlukan.
veducm
7

Solusi @ veducm bisa sedikit lebih singkat. UIMotionEffectGroup untuk gerakan x dan y sudah usang jika Anda menambahkan efek motionEffects sumbu x dan y secara terpisah.

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];
XOXO
sumber
2
Hanya sebagai kepala jika ada yang menggunakan versi singkat ini, pertama kebutuhan efek gerakan untuk memiliki typedari UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxisdan tidak UIInterpolatingMotionEffectTypeTiltAlongVerticalAxisseperti di kode ditata
Flexicoder
1
@BooHoo Menambahkan mereka sebagai grup sudah usang? Di mana Anda melihatnya? Pada saat penulisan ini, dokumen Apple tidak memiliki apa-apa tentang itu menjadi usang. Seluruh tujuan pengelompokan mereka adalah untuk meningkatkan kinerja. Semua efek dalam grup dirender sekali. Saat Anda menerapkannya secara terpisah, mereka harus dirender secara terpisah. Jangan ragu untuk mengoreksi saya jika saya salah (dan arahkan saya ke dokumentasi Apple tentang itu.)
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];
     }
}
sialan
sumber
1
@Rob menurut saran Anda memperbarui jawabannya
sialan
5

Berikut adalah kategori yang mudah untuk mengintegrasikan efek pada iOs7 +:

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

Bejil
sumber
1
Meskipun tautan ini mungkin menjawab pertanyaan, lebih baik menyertakan bagian penting dari jawaban di sini dan menyediakan tautan untuk referensi. Jawaban link saja bisa menjadi tidak valid jika halaman tertaut berubah.
Maciej Swic
Akan sulit untuk mengintegrasikan seluruh proyek github di sini
Bejil
1
Anda tidak perlu membawa keseluruhan proyek, hanya bagian esensial seperti yang saya tunjukkan dengan mengedit jawabannya. Ini agar kode tetap ada jika Github tidak aktif, Anda menarik repo atau langit jatuh.
Maciej Swic
3

Ini akan membantu seseorang yang ingin mengimplementasikan paralaks untuk tableView atau collectionView.

  • pertama-tama buat sel untuk tampilan tabel dan letakkan tampilan gambar di dalamnya.

  • atur tinggi gambar sedikit lebih tinggi dari tinggi sel. jika tinggi sel = 160 biarkan tinggi gambar menjadi 200 (untuk membuat efek paralaks dan Anda dapat mengubahnya sesuai)

  • letakkan dua variabel ini di viewController Anda atau kelas apa pun tempat delegasi tableView Anda diperpanjang

let imageHeight:CGFloat = 150.0
let OffsetSpeed: CGFloat = 25.0
  • tambahkan kode berikut di kelas yang sama
 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))
        }
    }
}
  • di mana seriesTabelView adalah UItableview saya

  • dan sekarang mari kita pergi ke sel tableView ini dan menambahkan kode berikut

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

Jika Anda ingin mengimplementasikan ini ke collectionView, ubah saja tableView vairable ke variabel collectionView Anda

dan hanya itu. Saya tidak yakin apakah ini cara terbaik. tapi hal ini bekerja untukku. semoga berhasil juga untuk Anda. dan beri tahu saya jika ada masalah

Muneef M
sumber
2

Sangat mudah untuk melakukannya mengapa merujuk kode kompleks. Cobalah. Kerja

Mengambil tampilan di imageview ukuran persis dari tampilan gambar. secara default alfa untuk kumpulan tampilan 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;
}
Tuan Javed Multani
sumber
-1

Terjemahan cepat:

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