ビューコントローラーのiOS 7視差効果


112

Objective-CでiOS 7用のアプリを開発しています。アプリに、いくつかのボタンときれいな背景画像を備えた画面があります。(これは、とシンプルなのXIBだUIButtonsの上にUIImageView。)

これらのボタンにiOS 7のホーム画面にある視差効果があるとすごくいいと思っていたので、電話を傾けると背景が見えるようになりました。

自分のアプリにその効果を実装するにはどうすればよいですか?


1
このライブラリをご覧ください
CRDave

迅速に、それを試してください:github.com/ArvindPrakashJoshi/AJParallaxEffect
Arvind

回答:


273

iOS 7ではUIMotionEffect、ユーザーのデバイスの向きに関連するモーション効果を追加するためにAppleが導入されました。たとえば、ホーム画面で視差効果をエミュレートするには、ここここUIInterpolationMotionEffect説明さいるように、数行のコードだけでサブクラスを使用できます。

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(@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値を設定し、1行のコードでUIMotionEffectパラメータを設定できます。
Dan Fabulich 2013

2
ありがとう!サポートされているバージョンと要件を含めるように回答を更新しました。
veducm 2013年

1
実際には、モーションエフェクトを正面図ではなく背景図に追加したいと考えています。しかし、それ以外は、このコードはうまく機能します!ありがとう。
gstroup 2013年

1
ユーザーが効果を無効にしたかどうかを確認する方法を誰かが知っていますか?stackoverflow.com/questions/19132000/...
エリック・

3
@gstroup実際、ホーム画面では前景と背景の両方が動いています。ただし、視差効果を適用するレイヤーを1つだけ選択した場合、背景がおそらく最良であろうと私は同意します。
Rubberduck 2014年

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のソリューションは少し短くなる場合があります。x軸とy軸のmotionEffectsを個別に追加すると、そのxとyのモーションのUIMotionEffectGroupは廃止されます。

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
誰もがこの短縮バージョンを使用している場合は、ヘッドアップは、第1の動きの効果は持っている必要があります同じようにtypeUIInterpolatingMotionEffectTypeTiltAlongHorizontalAxisはなくUIInterpolatingMotionEffectTypeTiltAlongVerticalAxis、それはコードのレイアウトであるとして
Flexicoder

1
@BooHooそれらをグループとして追加することは廃止されましたか?どこで見ますか?この記事の執筆時点では、Appleのドキュメントには、廃止されたという記述はありません。それらをグループ化する目的は、パフォーマンスを向上させることです。グループ内のすべての効果が一度レンダリングされます。個別に適用する場合は、個別にレンダリングする必要があります。私が間違っている場合は、遠慮なく訂正してください(そして、Appleのドキュメントを参照してください)
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はあなたの提案に従って回答を更新しました
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 14

ここでgithubプロジェクト全体を統合するのは難しいでしょう
Bejil

1
プロジェクト全体を持ち込む必要はありません。答えを編集して示したように、重要な部分だけを持ちます。これは、Githubがダウンした場合、レポを引っ張った場合、または空が落ちた場合にコードが固定されるようにするためです。
Maciej Swic 14


3

これは、tableViewまたはcollectionViewに視差を実装しようとしているユーザーを支援します。

  • まず、テーブルビューのセルを作成し、その中にイメージビューを配置します。

  • 画像の高さをセルの高さよりわずかに高く設定します。セルの高さ= 160の場合、画像の高さを200にします(視差効果を作成し、それに応じて変更できます)。

  • この2つの変数を、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は私のUItableviewです

  • そして今、このtableViewのセルに移動して、次のコードを追加します

func offset(offset: CGPoint) {
        posterImage.frame = CGRectOffset(self.posterImage.bounds, offset.x, offset.y)
    }
  • あったposterImageは私のUIImageViewです

これをcollectionViewに実装したい場合は、tableView vairableをcollectionView変数に変更してください

以上です。これが最善の方法かどうかはわかりません。しかし、それは私にとってはうまくいきます。それもあなたのために働くことを願っています。問題があったら教えてください


2

本当に簡単にできるので、なぜ複雑なコードを参照するのでしょうか。やってみなよ。ワーキング

imageviewの画像を正確にsize of image viewで表示します。デフォルトでは、ビューセット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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.