Ефект паралакса 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.