Forráskód Böngészése

improve playback info view animations and look

Tobias Conradi 9 éve
szülő
commit
cd0ff9ccc8

+ 1 - 1
VLC for Apple TV/VLCFullscreenMovieTVViewController.m

@@ -11,7 +11,7 @@
 
 #import "VLCFullscreenMovieTVViewController.h"
 #import "VLCPlaybackInfoTVViewController.h"
-
+#import "VLCPlaybackInfoTVAnimators.h"
 
 @interface VLCFullscreenMovieTVViewController (UIViewControllerTransitioningDelegate) <UIViewControllerTransitioningDelegate, UIGestureRecognizerDelegate>
 @end

+ 2 - 2
VLC for Apple TV/VLCPlaybackInfoAudioTVViewController.h

@@ -9,8 +9,8 @@
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
 
-#import <UIKit/UIKit.h>
+#import "VLCPlaybackInfoPanelTVViewController.h"
 
-@interface VLCPlaybackInfoAudioTVViewController : UIViewController
+@interface VLCPlaybackInfoAudioTVViewController : VLCPlaybackInfoPanelTVViewController
 
 @end

+ 2 - 8
VLC for Apple TV/VLCPlaybackInfoAudioTVViewController.m

@@ -22,17 +22,11 @@
     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
     if (self) {
         self.title = NSLocalizedString(@"AUDIO_INFO_VC_TITLE", nil);
-        self.edgesForExtendedLayout = UIRectEdgeNone;
     }
     return self;
 }
-
-- (CGSize)preferredContentSize {
-    return CGSizeMake(CGRectGetWidth(self.view.bounds), 300);
-}
-- (BOOL)_tvTabBarShouldAutohide
+- (CGSize)preferredContentSize
 {
-    return NO;
+    return CGSizeMake(CGRectGetWidth(self.view.bounds), 300);
 }
-
 @end

+ 17 - 23
VLC for Apple TV/VLCPlaybackInfoAudioTVViewController.xib

@@ -6,33 +6,27 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCPlaybackInfoAudioTVViewController">
             <connections>
-                <outlet property="view" destination="lzE-Lg-I4v" id="muP-eq-TfJ"/>
+                <outlet property="view" destination="SfU-3e-bi3" id="dbi-nU-kf2"/>
             </connections>
         </placeholder>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <visualEffectView opaque="NO" contentMode="scaleToFill" id="lzE-Lg-I4v">
-            <rect key="frame" x="0.0" y="0.0" width="240" height="128"/>
+        <view contentMode="scaleToFill" id="SfU-3e-bi3">
+            <rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
-            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="oh5-AA-mJb">
-                <rect key="frame" x="0.0" y="0.0" width="240" height="128"/>
-                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                <subviews>
-                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Put audio stuff here" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RD5-yN-Bxj">
-                        <rect key="frame" x="45" y="54" width="151" height="21"/>
-                        <animations/>
-                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
-                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
-                        <nil key="highlightedColor"/>
-                    </label>
-                </subviews>
-                <animations/>
-                <constraints>
-                    <constraint firstItem="RD5-yN-Bxj" firstAttribute="centerX" secondItem="oh5-AA-mJb" secondAttribute="centerX" id="LbQ-gh-TnV"/>
-                    <constraint firstItem="RD5-yN-Bxj" firstAttribute="centerY" secondItem="oh5-AA-mJb" secondAttribute="centerY" id="Y2G-FT-lep"/>
-                </constraints>
-            </view>
+            <subviews>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Put audio stuff here" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RD5-yN-Bxj">
+                    <rect key="frame" x="884" y="530" width="151" height="21"/>
+                    <animations/>
+                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
             <animations/>
-            <blurEffect style="light"/>
-        </visualEffectView>
+            <constraints>
+                <constraint firstItem="RD5-yN-Bxj" firstAttribute="centerY" secondItem="SfU-3e-bi3" secondAttribute="centerY" id="U6D-ND-4bN"/>
+                <constraint firstItem="RD5-yN-Bxj" firstAttribute="centerX" secondItem="SfU-3e-bi3" secondAttribute="centerX" id="eNA-sk-bI6"/>
+            </constraints>
+        </view>
     </objects>
 </document>

+ 21 - 0
VLC for Apple TV/VLCPlaybackInfoPanelTVViewController.h

@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import <UIKit/UIKit.h>
+
+@interface VLCPlaybackInfoPanelTVViewController : UIViewController
+
+
+// subclasses should override preferred content size to enable
+// correct sizing of the info VC
+- (CGSize)preferredContentSize;
+
+@end

+ 51 - 0
VLC for Apple TV/VLCPlaybackInfoPanelTVViewController.m

@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCPlaybackInfoPanelTVViewController.h"
+
+@interface VLCPlaybackInfoPanelTVViewController ()
+
+@end
+
+@implementation VLCPlaybackInfoPanelTVViewController
+
+static inline void sharedSetup(VLCPlaybackInfoPanelTVViewController *self)
+{
+    self.edgesForExtendedLayout = UIRectEdgeNone;
+}
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        sharedSetup(self);
+    }
+    return self;
+}
+
+- (void)awakeFromNib
+{
+    [super awakeFromNib];
+    sharedSetup(self);
+}
+
+- (CGSize)preferredContentSize
+{
+    return CGSizeMake(CGRectGetWidth(self.view.bounds), 100);
+}
+
+// private API to prevent tab bar from hiding
+- (BOOL)_tvTabBarShouldAutohide
+{
+    return NO;
+}
+
+@end

+ 2 - 3
VLC for Apple TV/VLCPlaybackInfoSpeedTVViewController.h

@@ -9,9 +9,8 @@
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
 
+#import "VLCPlaybackInfoPanelTVViewController.h"
 
-#import <UIKit/UIKit.h>
-
-@interface VLCPlaybackInfoSpeedTVViewController : UIViewController
+@interface VLCPlaybackInfoSpeedTVViewController : VLCPlaybackInfoPanelTVViewController
 @property (nonatomic) IBOutlet UISegmentedControl *speedSegementedControl;
 @end

+ 2 - 7
VLC for Apple TV/VLCPlaybackInfoSpeedTVViewController.m

@@ -9,7 +9,6 @@
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
 
-
 #import "VLCPlaybackInfoSpeedTVViewController.h"
 
 @interface VLCPlaybackInfoSpeedTVViewController ()
@@ -22,16 +21,12 @@
     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
     if (self) {
         self.title = NSLocalizedString(@"PLAYBACK_SPEED_INFO_VC_TITLE", nil);
-        self.edgesForExtendedLayout = UIRectEdgeNone;
     }
     return self;
 }
 
-- (CGSize)preferredContentSize {
-    return CGSizeMake(CGRectGetWidth(self.view.bounds), 100);
-}
-- (BOOL)_tvTabBarShouldAutohide
+- (CGSize)preferredContentSize
 {
-    return NO;
+    return CGSizeMake(CGRectGetWidth(self.view.bounds), 100);
 }
 @end

+ 25 - 33
VLC for Apple TV/VLCPlaybackInfoSpeedTVViewController.xib

@@ -6,42 +6,34 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCPlaybackInfoSpeedTVViewController">
             <connections>
-                <outlet property="preferredFocusedView" destination="2rV-t5-gXc" id="mn0-9U-gGS"/>
-                <outlet property="speedSegementedControl" destination="2rV-t5-gXc" id="3qY-xe-QuX"/>
-                <outlet property="view" destination="ANq-wj-TcM" id="bgr-uX-P6k"/>
+                <outlet property="view" destination="vgW-9U-IlZ" id="527-h1-jOO"/>
             </connections>
         </placeholder>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <visualEffectView opaque="NO" contentMode="scaleToFill" id="ANq-wj-TcM">
-            <rect key="frame" x="0.0" y="0.0" width="1920" height="109"/>
-            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
-            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="fVw-qf-RcQ">
-                <rect key="frame" x="0.0" y="0.0" width="1920" height="109"/>
-                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                <subviews>
-                    <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="2rV-t5-gXc">
-                        <rect key="frame" x="783" y="20" width="354" height="70"/>
-                        <animations/>
-                        <color key="backgroundColor" white="0.0" alpha="0.10000000000000001" colorSpace="calibratedWhite"/>
-                        <constraints>
-                            <constraint firstAttribute="height" constant="69" id="2e1-aS-ccu"/>
-                        </constraints>
-                        <segments>
-                            <segment title="First"/>
-                            <segment title="Second"/>
-                        </segments>
-                    </segmentedControl>
-                </subviews>
-                <animations/>
-                <constraints>
-                    <constraint firstAttribute="bottom" secondItem="2rV-t5-gXc" secondAttribute="bottom" constant="20" symbolic="YES" id="WS8-am-ULZ"/>
-                    <constraint firstItem="2rV-t5-gXc" firstAttribute="top" secondItem="fVw-qf-RcQ" secondAttribute="top" constant="20" symbolic="YES" id="fCC-KH-NLw"/>
-                    <constraint firstItem="2rV-t5-gXc" firstAttribute="centerX" secondItem="fVw-qf-RcQ" secondAttribute="centerX" id="mq3-vV-MJ9"/>
-                </constraints>
-            </view>
+        <view opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" placeholderIntrinsicWidth="1920" placeholderIntrinsicHeight="100" id="vgW-9U-IlZ">
+            <rect key="frame" x="0.0" y="0.0" width="1920" height="100"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="a34-9y-ZcI">
+                    <rect key="frame" x="783" y="16" width="354" height="70"/>
+                    <animations/>
+                    <color key="backgroundColor" white="0.0" alpha="0.10000000000000001" colorSpace="calibratedWhite"/>
+                    <segments>
+                        <segment title="First"/>
+                        <segment title="Second"/>
+                    </segments>
+                </segmentedControl>
+            </subviews>
             <animations/>
-            <blurEffect style="light"/>
-            <point key="canvasLocation" x="449" y="509"/>
-        </visualEffectView>
+            <constraints>
+                <constraint firstItem="a34-9y-ZcI" firstAttribute="top" relation="greaterThanOrEqual" secondItem="vgW-9U-IlZ" secondAttribute="top" id="9aM-8g-ySI"/>
+                <constraint firstItem="a34-9y-ZcI" firstAttribute="centerX" secondItem="vgW-9U-IlZ" secondAttribute="centerX" id="FTw-3L-I11"/>
+                <constraint firstItem="a34-9y-ZcI" firstAttribute="centerX" secondItem="vgW-9U-IlZ" secondAttribute="centerX" id="cNR-R4-nbS"/>
+                <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="a34-9y-ZcI" secondAttribute="bottom" id="jlh-7n-G5J"/>
+                <constraint firstItem="a34-9y-ZcI" firstAttribute="centerY" secondItem="vgW-9U-IlZ" secondAttribute="centerY" id="qK1-gY-HdN"/>
+            </constraints>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="94" y="-1761.5"/>
+        </view>
     </objects>
 </document>

+ 22 - 0
VLC for Apple TV/VLCPlaybackInfoTVAnimators.h

@@ -0,0 +1,22 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import <UIKit/UIKit.h>
+
+@class VLCPlaybackInfoTVViewController;
+@interface VLCPlaybackInfoTabBarTVTransitioningAnimator : NSObject <UIViewControllerAnimatedTransitioning>
+@property (nonatomic) VLCPlaybackInfoTVViewController *infoContainerViewController;
+@end
+
+@interface VLCPlaybackInfoTVTransitioningAnimator : NSObject <UIViewControllerAnimatedTransitioning>
+
+@end
+

+ 130 - 0
VLC for Apple TV/VLCPlaybackInfoTVAnimators.m

@@ -0,0 +1,130 @@
+/*****************************************************************************
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2015 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Tobias Conradi <videolan # tobias-conradi.de>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+#import "VLCPlaybackInfoTVAnimators.h"
+#import "VLCPlaybackInfoTVViewController.h"
+
+@implementation VLCPlaybackInfoTabBarTVTransitioningAnimator
+
+- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
+{
+    return 0.3;
+}
+
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
+{
+    UIViewController *source = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
+    UIViewController *target = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
+
+    UIView *sourceView = source.view;
+    UIView *targetView = target.view;
+
+    UIView *container = [transitionContext containerView];
+
+    CGRect oldContainerBounds = container.bounds;
+    CGPoint oldCenter = CGPointMake(CGRectGetMidX(oldContainerBounds), CGRectGetMidY(oldContainerBounds));
+
+    CGSize targetSize = target.preferredContentSize;
+    CGPoint newCenter = CGPointMake(targetSize.width/2.0, targetSize.height/2.0);
+
+    targetView.alpha = 0.0;
+    targetView.frame = CGRectMake(0, 0, targetSize.width, targetSize.height);
+    targetView.center = oldCenter;
+    [targetView layoutIfNeeded];
+    [container addSubview:targetView];
+
+    [UIView animateWithDuration:[self transitionDuration:transitionContext]
+                     animations:^{
+
+                         sourceView.center = newCenter;
+                         sourceView.alpha = 0.0;
+
+                         targetView.center = newCenter;
+                         targetView.alpha = 1.0;
+
+                         [self.infoContainerViewController updateViewConstraints];
+                         [self.infoContainerViewController.view layoutIfNeeded];
+
+                     } completion:^(BOOL finished) {
+                         [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
+                     }];
+}
+
+@end
+
+
+@implementation VLCPlaybackInfoTVTransitioningAnimator
+
+- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
+{
+    return 0.5;
+}
+
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
+{
+    UIViewController *source = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
+    UIViewController *target = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
+
+    UIView *container = [transitionContext containerView];
+    CGRect initialSourceFrame = [transitionContext initialFrameForViewController:source];
+    // TODO: calculate
+    CGFloat infoHeight = CGRectGetHeight(initialSourceFrame);
+
+    CGRect largeFrame = ({
+        CGRect frame = initialSourceFrame;
+        frame.origin.y -=infoHeight;
+        frame.size.height += infoHeight;
+        frame;
+    });
+    CGRect smallFrame = initialSourceFrame;
+
+    CGFloat targetAlpha = 1.0;
+    CGRect fromFrame = initialSourceFrame;
+    CGRect toFrame = initialSourceFrame;
+
+    VLCPlaybackInfoTVViewController *infoVC = nil;
+    if ([target isKindOfClass:[VLCPlaybackInfoTVViewController class]]) {
+        infoVC = (VLCPlaybackInfoTVViewController*) target;
+        infoVC.dimmingView.alpha = 0.0;
+        targetAlpha = 1.0;
+        toFrame = smallFrame;
+        fromFrame = largeFrame;
+        [container addSubview:target.view];
+    } else if ([source isKindOfClass:[VLCPlaybackInfoTVViewController class]]) {
+        infoVC = (VLCPlaybackInfoTVViewController*) source;
+        infoVC.dimmingView.alpha = 1.0;
+        targetAlpha = 0.0;
+        toFrame = largeFrame;
+        fromFrame = smallFrame;
+    }
+
+    infoVC.view.frame = fromFrame;
+    [infoVC updateViewConstraints];
+    [infoVC.view layoutIfNeeded];
+
+    // fallback
+    if (!infoVC) {
+        target.view.frame = smallFrame;
+    }
+
+    [UIView animateWithDuration:[self transitionDuration:transitionContext]
+                     animations:^{
+                         infoVC.view.frame = toFrame;
+                         [infoVC.view layoutIfNeeded];
+                         infoVC.dimmingView.alpha = targetAlpha;
+                     }
+                     completion:^(BOOL finished) {
+                         [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
+                     }];
+    
+}
+
+@end

+ 8 - 5
VLC for Apple TV/VLCPlaybackInfoTVViewController.h

@@ -8,13 +8,16 @@
  *
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
-#import <UIKit/UIKit.h>
-
-@interface VLCPlaybackInfoTVTransitioningAnimator : NSObject <UIViewControllerAnimatedTransitioning>
 
-@end
+#import <UIKit/UIKit.h>
 
+@interface VLCPlaybackInfoTVViewController : UIViewController <UITabBarControllerDelegate, UIGestureRecognizerDelegate>
 
-@interface VLCPlaybackInfoTVViewController : UIViewController
+@property (nonatomic) IBOutlet UIView *containerView;
+@property (nonatomic) IBOutlet UIView *dimmingView;
+@property (nonatomic) IBOutlet NSLayoutConstraint *tabBarRegiomHeightConstraint;
+@property (nonatomic) IBOutlet NSLayoutConstraint *containerHeightConstraint;
+@property (nonatomic) IBOutlet UITabBarController *tabBarController;
 
 @end
+

+ 40 - 90
VLC for Apple TV/VLCPlaybackInfoTVViewController.m

@@ -12,31 +12,31 @@
 #import "VLCPlaybackInfoTVViewController.h"
 #import "VLCPlaybackInfoSpeedTVViewController.h"
 #import "VLCPlaybackInfoAudioTVViewController.h"
+#import "VLCPlaybackInfoTVAnimators.h"
 
-@interface VLCPlaybackInfoTVViewController () <UITabBarControllerDelegate, UIGestureRecognizerDelegate>
-@property (nonatomic) IBOutlet UIView *containerView;
-@property (nonatomic) IBOutlet UIView *dimmingView;
-@property (nonatomic) IBOutlet NSLayoutConstraint *containerHeightConstraint;
-@property (nonatomic) IBOutlet UITabBarController *tabBarController;
-
+// just for appearance reasons
+@interface VLCPlaybackInfoTVTabBarController : UITabBarController
+@end
+@implementation VLCPlaybackInfoTVTabBarController
 @end
 
 @implementation VLCPlaybackInfoTVViewController
 
-- (NSArray<UIViewController*>*) tabViewControllers {
+- (NSArray<UIViewController*>*)tabViewControllers
+{
     return @[
              [[VLCPlaybackInfoSpeedTVViewController alloc] initWithNibName:nil bundle:nil],
              [[VLCPlaybackInfoAudioTVViewController alloc] initWithNibName:nil bundle:nil],
              ];
 }
 
-
-
 - (void)viewDidLoad
 {
     [super viewDidLoad];
 
-    UITabBarController *controller = [[UITabBarController alloc] init];
+    [self setupTabBarItemAppearance];
+
+    UITabBarController *controller = [[VLCPlaybackInfoTVTabBarController alloc] init];
     controller.delegate = self;
     controller.viewControllers = [self tabViewControllers];
     self.tabBarController = controller;
@@ -53,35 +53,39 @@
     [self.view addGestureRecognizer:swipeUpRecognizer];
 }
 
-
-- (BOOL)shouldAutomaticallyForwardAppearanceMethods {
+- (BOOL)shouldAutomaticallyForwardAppearanceMethods
+{
     return YES;
 }
 
-- (void)swipeUpRecognized:(UISwipeGestureRecognizer *)recognizer {
-
-    [self dismissViewControllerAnimated:YES completion:nil];
-}
-
-- (void)updateViewConstraints {
+- (void)updateViewConstraints
+{
     [super updateViewConstraints];
-
     UIViewController *viewController = self.tabBarController.selectedViewController;
-    CGFloat tabbarHeight = CGRectGetHeight(self.tabBarController.tabBar.bounds);
+    CGFloat tabBarHeight = CGRectGetHeight(self.tabBarController.tabBar.bounds);
+    self.tabBarRegiomHeightConstraint.constant = tabBarHeight;
     CGFloat controllerHeight = viewController.preferredContentSize.height;
-    self.containerHeightConstraint.constant = controllerHeight + tabbarHeight;
+    self.containerHeightConstraint.constant = controllerHeight;
+}
+
+
+- (void)setupTabBarItemAppearance
+{
+    UITabBarItem *tabBarItemApprearance = [UITabBarItem appearanceWhenContainedInInstancesOfClasses:@[[VLCPlaybackInfoTVTabBarController class]]];
+    NSDictionary *attributesSelected = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:0.75 alpha:1.0]};
+    [tabBarItemApprearance setTitleTextAttributes:attributesSelected forState:UIControlStateSelected];
+    NSDictionary *attributesFocused = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:1.0 alpha:1.0]};
+    [tabBarItemApprearance setTitleTextAttributes:attributesFocused forState:UIControlStateFocused];
 }
 
-- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
+- (void)swipeUpRecognized:(UISwipeGestureRecognizer *)recognizer
 {
-    [UIView animateWithDuration:0.3
-                     animations:^{
-                         [self updateViewConstraints];
-                         [self.view layoutIfNeeded];
-                     }];
+    [self dismissViewControllerAnimated:YES completion:nil];
 }
 
 
+#pragma mark - GestureRecognizerDelegate
+
 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
 {
     // FIXME: is there any other way to figure out if the tab bar item is currenlty focused?
@@ -95,70 +99,16 @@
     return NO;
 }
 
-@end
-
-
-@implementation VLCPlaybackInfoTVTransitioningAnimator
-
-- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
-    return 0.5;
+#pragma mark - TabBarControllerDelegate
+- (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
+                     animationControllerForTransitionFromViewController:(UIViewController *)fromVC
+                                                       toViewController:(UIViewController *)toVC
+{
+    VLCPlaybackInfoTabBarTVTransitioningAnimator* animator = [[VLCPlaybackInfoTabBarTVTransitioningAnimator alloc] init];
+    animator.infoContainerViewController = self;
+    return animator;
 }
 
-- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
-    UIViewController *source = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
-    UIViewController *target = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
-
-    UIView *container = [transitionContext containerView];
-    CGRect initialSourceFrame = [transitionContext initialFrameForViewController:source];
-    // TODO: calculate
-    CGFloat infoHeight = CGRectGetHeight(initialSourceFrame);
-
-    CGRect largeFrame = ({
-        CGRect frame = initialSourceFrame;
-        frame.origin.y -=infoHeight;
-        frame.size.height += infoHeight;
-        frame;
-    });
-    CGRect smallFrame = initialSourceFrame;
-
-    CGFloat targetAlpha = 1.0;
-    CGRect fromFrame = initialSourceFrame;
-    CGRect toFrame = initialSourceFrame;
-
-    VLCPlaybackInfoTVViewController *infoVC = nil;
-    if ([target isKindOfClass:[VLCPlaybackInfoTVViewController class]]) {
-        infoVC = (VLCPlaybackInfoTVViewController*) target;
-        infoVC.dimmingView.alpha = 0.0;
-        targetAlpha = 1.0;
-        toFrame = smallFrame;
-        fromFrame = largeFrame;
-        [container addSubview:target.view];
-    } else if ([source isKindOfClass:[VLCPlaybackInfoTVViewController class]]) {
-        infoVC = (VLCPlaybackInfoTVViewController*) source;
-        infoVC.dimmingView.alpha = 1.0;
-        targetAlpha = 0.0;
-        toFrame = largeFrame;
-        fromFrame = smallFrame;
-    }
-
-    infoVC.view.frame = fromFrame;
-    [infoVC.view layoutIfNeeded];
-
-    // fallback
-    if (!infoVC) {
-        target.view.frame = smallFrame;
-    }
-
-    [UIView animateWithDuration:[self transitionDuration:transitionContext]
-                     animations:^{
-                         infoVC.view.frame = toFrame;
-                         [infoVC.view layoutIfNeeded];
-                         infoVC.dimmingView.alpha = targetAlpha;
-                     }
-                     completion:^(BOOL finished) {
-                         [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
-                     }];
 
-}
+@end
 
-@end

+ 34 - 15
VLC for Apple TV/VLCPlaybackInfoTVViewController.xib

@@ -1,14 +1,15 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <document type="com.apple.InterfaceBuilder.AppleTV.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES">
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9059"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
     </dependencies>
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VLCPlaybackInfoTVViewController">
             <connections>
-                <outlet property="containerHeightConstraint" destination="PQd-PR-z5I" id="zui-1d-1Yo"/>
-                <outlet property="containerView" destination="U6y-cE-eGu" id="pdM-21-C2a"/>
+                <outlet property="containerHeightConstraint" destination="QR2-Gh-Hdy" id="u84-XK-o7J"/>
+                <outlet property="containerView" destination="b8s-Xi-SUg" id="qEg-s0-4Si"/>
                 <outlet property="dimmingView" destination="fkF-mr-3nG" id="NO9-Ww-dkm"/>
+                <outlet property="tabBarRegiomHeightConstraint" destination="qQN-Xf-pTW" id="rPf-Al-chE"/>
                 <outlet property="view" destination="iN0-l3-epB" id="aoh-6Y-hrX"/>
             </connections>
         </placeholder>
@@ -17,28 +18,46 @@
             <rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
             <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fkF-mr-3nG" userLabel="DimmingView">
-                    <rect key="frame" x="0.0" y="400" width="1920" height="680"/>
-                    <animations/>
-                    <color key="backgroundColor" white="0.0" alpha="0.29999999999999999" colorSpace="calibratedWhite"/>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="U6y-cE-eGu" userLabel="Container">
-                    <rect key="frame" x="0.0" y="0.0" width="1920" height="400"/>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="b8s-Xi-SUg">
+                    <rect key="frame" x="0.0" y="0.0" width="1920" height="340"/>
+                    <subviews>
+                        <visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ley-eR-13d">
+                            <rect key="frame" x="0.0" y="140" width="1920" height="200"/>
+                            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="aZZ-Hu-gGZ">
+                                <rect key="frame" x="0.0" y="0.0" width="1920" height="200"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <animations/>
+                            </view>
+                            <animations/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="200" id="QR2-Gh-Hdy"/>
+                            </constraints>
+                            <blurEffect style="light"/>
+                        </visualEffectView>
+                    </subviews>
                     <animations/>
                     <constraints>
-                        <constraint firstAttribute="height" constant="400" identifier="container height constraint" id="PQd-PR-z5I"/>
+                        <constraint firstAttribute="trailing" secondItem="ley-eR-13d" secondAttribute="trailing" id="Ao7-YI-lz8"/>
+                        <constraint firstAttribute="bottom" secondItem="ley-eR-13d" secondAttribute="bottom" id="dVS-rh-HHf"/>
+                        <constraint firstItem="ley-eR-13d" firstAttribute="top" secondItem="b8s-Xi-SUg" secondAttribute="top" constant="140" id="qQN-Xf-pTW"/>
+                        <constraint firstItem="ley-eR-13d" firstAttribute="leading" secondItem="b8s-Xi-SUg" secondAttribute="leading" id="zPq-ti-J51"/>
                     </constraints>
                 </view>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fkF-mr-3nG" userLabel="DimmingView">
+                    <rect key="frame" x="0.0" y="340" width="1920" height="740"/>
+                    <animations/>
+                    <color key="backgroundColor" white="0.0" alpha="0.29999999999999999" colorSpace="calibratedWhite"/>
+                </view>
             </subviews>
             <animations/>
             <constraints>
-                <constraint firstItem="fkF-mr-3nG" firstAttribute="top" secondItem="U6y-cE-eGu" secondAttribute="bottom" id="56R-lg-86y"/>
+                <constraint firstItem="b8s-Xi-SUg" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="14B-v2-BBA"/>
                 <constraint firstItem="fkF-mr-3nG" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="9tl-tu-ZJg"/>
-                <constraint firstItem="U6y-cE-eGu" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="C8C-JW-U5v"/>
+                <constraint firstAttribute="trailing" secondItem="b8s-Xi-SUg" secondAttribute="trailing" id="W2m-A6-QU7"/>
                 <constraint firstAttribute="bottom" secondItem="fkF-mr-3nG" secondAttribute="bottom" id="X7X-Ek-8zE"/>
                 <constraint firstAttribute="trailing" secondItem="fkF-mr-3nG" secondAttribute="trailing" id="a5y-gG-ndP"/>
-                <constraint firstAttribute="trailing" secondItem="U6y-cE-eGu" secondAttribute="trailing" id="amL-DA-aLx"/>
-                <constraint firstItem="U6y-cE-eGu" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="wZW-k5-Ugc"/>
+                <constraint firstItem="b8s-Xi-SUg" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="rWa-6e-vRp"/>
+                <constraint firstItem="fkF-mr-3nG" firstAttribute="top" secondItem="b8s-Xi-SUg" secondAttribute="bottom" id="tow-1m-6YL"/>
             </constraints>
         </view>
     </objects>

+ 12 - 0
VLC for iOS.xcodeproj/project.pbxproj

@@ -329,6 +329,8 @@
 		DD8095EC1BE4F04E0065D8E1 /* VLCPlaybackInfoSpeedTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD8095EA1BE4F04E0065D8E1 /* VLCPlaybackInfoSpeedTVViewController.xib */; };
 		DD8095F21BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8095F01BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.m */; };
 		DD8095F31BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD8095F11BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.xib */; };
+		DD8095F61BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8095F51BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.m */; };
+		DD8095F91BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8095F81BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.m */; };
 		DD8F84311B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8F84301B00EB3B0009138A /* VLCPlaybackController+MediaLibrary.m */; };
 		DDAD5C2B1BB999CA006AFD3B /* VLCMovieViewControlPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = DDAD5C2A1BB999CA006AFD3B /* VLCMovieViewControlPanel.xib */; };
 		DDB7C6A41BAEB28200E6570E /* WKInterfaceController+VLCConnectionAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9FBE761BAD6BB600FFE77A /* WKInterfaceController+VLCConnectionAlert.m */; };
@@ -997,6 +999,10 @@
 		DD8095EF1BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackInfoAudioTVViewController.h; sourceTree = "<group>"; };
 		DD8095F01BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackInfoAudioTVViewController.m; sourceTree = "<group>"; };
 		DD8095F11BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VLCPlaybackInfoAudioTVViewController.xib; sourceTree = "<group>"; };
+		DD8095F41BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackInfoTVAnimators.h; sourceTree = "<group>"; };
+		DD8095F51BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackInfoTVAnimators.m; sourceTree = "<group>"; };
+		DD8095F71BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCPlaybackInfoPanelTVViewController.h; sourceTree = "<group>"; };
+		DD8095F81BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCPlaybackInfoPanelTVViewController.m; sourceTree = "<group>"; };
 		DD8C8F9F1B676C0900B3C4EE /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		DD8C8FA01B676C0F00B3C4EE /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
 		DD8C8FA11B676C1700B3C4EE /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -1895,6 +1901,10 @@
 				7DEC8BDC1BD67899006E1093 /* VLCFullscreenMovieTVViewController.m */,
 				DD8095DD1BE3EFC20065D8E1 /* VLCPlaybackInfoTVViewController.h */,
 				DD8095DE1BE3EFC20065D8E1 /* VLCPlaybackInfoTVViewController.m */,
+				DD8095F41BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.h */,
+				DD8095F51BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.m */,
+				DD8095F71BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.h */,
+				DD8095F81BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.m */,
 				DD8095E81BE4F04E0065D8E1 /* VLCPlaybackInfoSpeedTVViewController.h */,
 				DD8095E91BE4F04E0065D8E1 /* VLCPlaybackInfoSpeedTVViewController.m */,
 				DD8095EF1BE510770065D8E1 /* VLCPlaybackInfoAudioTVViewController.h */,
@@ -2696,6 +2706,7 @@
 				DD3EFF561BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserDSM.m in Sources */,
 				DD3EABF91BE14BD6003668DA /* BasicUPnPDevice+VLC.m in Sources */,
 				7D0C34E71BD951080058CD19 /* NSString+SupportedMedia.m in Sources */,
+				DD8095F61BE624C00065D8E1 /* VLCPlaybackInfoTVAnimators.m in Sources */,
 				DDEAECBF1BDEBF6700756C83 /* VLCNetworkServerLoginInformation.m in Sources */,
 				DD3EFF381BDEBCE500B68579 /* VLCLocalNetworkServiceNetService.m in Sources */,
 				DD8095D61BE3C3BA0065D8E1 /* VLCTransportBar.m in Sources */,
@@ -2709,6 +2720,7 @@
 				DD3EFF3A1BDEBCE500B68579 /* VLCLocalNetworkServiceVLCMedia.m in Sources */,
 				7D7EF3DA1BD56B5900CD4CEE /* VLCOpenNetworkStreamTVViewController.m in Sources */,
 				DD3EFF521BDEBCE500B68579 /* VLCPlexWebAPI.m in Sources */,
+				DD8095F91BE6268A0065D8E1 /* VLCPlaybackInfoPanelTVViewController.m in Sources */,
 				7D60696C1BD93BE200AB765C /* VLCCloudStorageTableViewCell.m in Sources */,
 				DD3EABE91BE13D5B003668DA /* VLCServerBrowsingTVCell.m in Sources */,
 				DD3EABFD1BE14C4B003668DA /* UIViewController+VLCAlert.m in Sources */,