Ефект паралакса iOS 7 в моєму контролері перегляду


112

Я розробляю додаток для iOS 7 в Objective-C. У мене в моєму додатку екран з кількома кнопками та гарним фоновим зображенням. (Це простий xib з UIButtonsвершиною a UIImageView.)

Я думав, що було б здорово, якби ці кнопки мали ефект паралакса, який має головний екран iOS 7, тому, якщо нахилити телефон, ви побачите фон.

Як я можу реалізувати цей ефект у власному додатку?


1
Подивіться цю бібліотеку: github.com/Przytua/UIView-MWParallax
— CRDave

Для стрижа, спробуйте з цим: github.com/ArvindPrakashJoshi/AJParallaxEffect
— Ервінд

Відповіді:


273

Завдяки iOS 7 компанія Apple представила UIMotionEffectдля додавання ефектів Motion, які пов'язані з орієнтацією пристрою користувача. Наприклад, для імітації ефекту паралакса на головному екрані ви можете використовувати підклас UIInterpolationMotionEffect, як пояснено тут і тут , лише за допомогою декількох рядків коду.

Завдання-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];

Свіфт (спасибі @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)

Також ви можете знайти купу бібліотек, щоб зробити це простіше або додати цю функціональність до старих версій iOS:


2
NGAParallaxMotion призначений для iOS 7+, а не для старих версій iOS. Він надає категорію для UIView, що дозволяє встановлювати значення .parallaxIntensity, встановлюючи параметри UIMotionEffect за допомогою одного рядка коду.
— Дан Фабуліч

2
Дякую! Я оновив відповідь, щоб включити підтримувані версії та вимоги.
— veducm

1
Насправді ви хочете додати ефект руху до подання фону, а не виду спереду. Але крім цього, цей код чудово працює! Дякую.
— gstroup

1
Хтось знає, як перевірити, чи користувач відключив ефекти? stackoverflow.com/questions/19132000/…
— Ерік

3
@gstroup Насправді на головному екрані рухаються і передній план, і фон. Але якби ви вибрали лише один шар, щоб застосувати ефект паралакса, я погоджуюся, що фон, мабуть, буде найкращим.
— Rubberduck

16

Перекладається на стрімкий випадок, якщо хтось лінивий. Будь ласка, проголосуйте за відповідь @veducm , якщо ви вважаєте це корисним

@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! Я оновив свою відповідь, щоб також включити швидкий зразок. В основі цього лежить. Сміливо перегляньте його та зробіть будь-які необхідні зміни.
— veducm

7

@ рішення veducm може бути трохи коротшим. Група UIMotionEffectGroup для її руху x і y застаріла, якщо ви додасте окремо xE і y-осі motionEffects.

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
Так само , як керівники, якщо хто -то використовує цей скорочений варіант, перші потреби ефект руху , щоб мати typeвід UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxisі не UIInterpolatingMotionEffectTypeTiltAlongVerticalAxisтак як це в коді викладених
— Flexicoder

1
@BooHoo Додавання їх до групи застаріло? Де ви це бачите? На момент написання цього документа в Apple документи нічого не було про це. Вся мета їх групування - покращення продуктивності. Усі ефекти в групі надаються один раз. Якщо ви застосовуєте їх окремо, вони повинні бути відображені окремо. Не соромтеся виправити мене, якщо я помиляюся (і вкажіть мені документацію Apple про це.)
— Девід Ларі

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 за вашою пропозицією оновив відповідь
— damithH

5

Ось проста категорія інтегрувати вплив на 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


1
Хоча це посилання може відповісти на питання, краще включити сюди суттєві частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться.
— Maciej Swic

Тут буде важко інтегрувати весь проект github
— Bejil

1
Вам не доведеться доносити весь проект, лише необхідну частину, як я продемонстрував, редагуючи відповідь. Це так, що код тримається навколо, якщо Github вниз, ви потягнете репо або небо падає вниз.
— Maciej Swic


3

Це допоможе тому, хто хоче реалізувати паралакс для tableView або collectionView.

  • насамперед створіть комірку для перегляду таблиці і помістіть у неї подання зображення.

  • встановити висоту зображення трохи більше, ніж висоту комірки. якщо висота комірки = 160, нехай висота зображення буде 200 (щоб зробити ефект паралакса, і ви можете змінити його відповідно)

  • помістіть цю дві змінну у ваш viewController або будь-який клас, де розширюється ваш делегат tableView

let imageHeight:CGFloat = 150.0
let OffsetSpeed: CGFloat = 25.0
  • додати наступний код у цьому ж класі
 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 - це мій перегляд інтерфейсу користувача

  • а тепер дозволяє перейти до комірки цієї таблиціПереглянути та додати наступний код

func offset(offset: CGPoint) {
        posterImage.frame = CGRectOffset(self.posterImage.bounds, offset.x, offset.y)
    }
  • були posterImage - це мій UIImageView

Якщо ви хочете реалізувати це у collectionView, просто змініть таблицюView, придатну для змінної collectionView

і це все. я не впевнений, чи це найкращий спосіб. але це працює для мене. сподіваюся, що він працює і для вас. і дайте мені знати, чи є якісь проблеми


2

Дійсно гребля легко зробити так , чому відноситься складний код. просто спробуйте. Робочий

Погляньте на перегляд зображень, точно розмір зображення. за замовчуванням альфа для набору перегляду 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

Швидкий переклад:

// 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.