diff --git a/DraggableFloatingViewController.podspec b/DraggableFloatingViewController.podspec new file mode 100644 index 0000000..768a2a4 --- /dev/null +++ b/DraggableFloatingViewController.podspec @@ -0,0 +1,120 @@ +# +# Be sure to run `pod spec lint DraggableFloatingViewController.podspec' to ensure this is a +# valid spec and to remove all comments including this before submitting the spec. +# +# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html +# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ +# + +Pod::Spec.new do |s| + + # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # These will help people to find your library, and whilst it + # can feel like a chore to fill in it's definitely to your advantage. The + # summary should be tweet-length, and the description more in depth. + # + + s.name = "DraggableFloatingViewController" + # s.version = "v1.0" + s.summary = "A short description of DraggableFloatingViewController." + + s.description = <<-DESC + A longer description of DraggableFloatingViewController in Markdown format. + + * Think: Why did you write this? What is the focus? What does it do? + * CocoaPods will be using this to generate tags, and improve search results. + * Try to keep it short, snappy and to the point. + * Finally, don't worry about the indent, CocoaPods strips it! + DESC + + s.homepage = "http://github.com/entotsu/DraggableFloatingViewController" + # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" + + + # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Licensing your code is important. See http://choosealicense.com for more info. + # CocoaPods will detect a license file if there is a named LICENSE* + # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. + # + + s.license = "MIT (example)" + # s.license = { :type => "MIT", :file => "FILE_LICENSE" } + + + # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Specify the authors of the library, with email addresses. Email addresses + # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also + # accepts just a name if you'd rather not provide an email address. + # + # Specify a social_media_url where others can refer to, for example a twitter + # profile URL. + # + + s.author = { "Sandeep Mukherjee" => "vizllx@gmail.com" } + # Or just: s.author = "Sandeep Mukherjee" + # s.authors = { "Sandeep Mukherjee" => "vizllx@gmail.com" } + # s.social_media_url = "http://github.com/vizllx" + + # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # If this Pod runs only on iOS or OS X, then specify the platform and + # the deployment target. You can optionally include the target after the platform. + # + + # s.platform = :ios + s.platform = :ios, "6.0" + + # When using multiple platforms + # s.ios.deployment_target = "5.0" + # s.osx.deployment_target = "10.7" + + + s.source = { :git => "http://github.com/entotsu/DraggableFloatingViewController.git", :tag => "v1.0" } + s.source_files = "Classes", "YouTubeDraggableVideo/Source/*.{h,m}" + # s.exclude_files = "Classes/Exclude" + + # s.public_header_files = "Classes/**/*.h" + + + # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # A list of resources included with the Pod. These are copied into the + # target bundle with a build phase script. Anything else will be cleaned. + # You can preserve files from being cleaned, please don't preserve + # non-essential files like tests, examples and documentation. + # + + # s.resource = "icon.png" + # s.resources = "Resources/*.png" + + # s.preserve_paths = "FilesToSave", "MoreFilesToSave" + + + # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Link your library with frameworks, or libraries. Libraries do not include + # the lib prefix of their name. + # + + # s.framework = "SomeFramework" + # s.frameworks = "SomeFramework", "AnotherFramework" + + # s.library = "iconv" + # s.libraries = "iconv", "xml2" + + + # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # If your library depends on compiler flags you can set them in the xcconfig hash + # where they will only apply to your library. If you depend on other Podspecs + # you can include multiple dependencies to ensure it works. + + # s.requires_arc = true + + # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } + # s.dependency "JSONKit", "~> 1.4" + +end diff --git a/README.md b/README.md index 2b0240f..a38d89d 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,179 @@ -# DraggableYoutubeFloatingVideo -DraggableYoutubeFloatingVideo allows you to play videos on a floating mini window at the bottom of your screen from sites like YouTube, Vimeo & Facebook or custom video url , yes you have to specify URL for that. -Usage ------ -Initialize from a storyboard id programmatically. Set the video URL , then you're pretty much good to go! Check out the demo app to see how it can be used. + +# DraggableFloatingViewController + +### Like YouTube app + +DraggableFloatingViewController allows you to play videos on a floating mini window at the bottom of your screen from sites like YouTube, Vimeo & Facebook or custom video , yes you have to prepare your video view for that. How it works ------------ -This demo app will animate the view just like Youtube mobile app, while tapping on video a UIView pops up from right corner of the screen and the view can be dragged to right corner through Pan Gesture and more features are there as Youtube iOS app +The view will animate the view just like Youtube mobile app, while tapping on video a UIView pops up from right corner of the screen and the view can be dragged to right corner through Pan Gesture and more features are there as Youtube iOS app + Screenshot ------------ + ![Output sample](https://github.com/entotsu/DraggableFloatingViewController/raw/master/Screenshot2.gif) + + + +# Usage + + +## extend this class + +#### set your video view in "viewDidLoad" of subclass + +```swift +override func viewDidLoad() { + + self.setupViewsWithVideoView(yourMoivePlayer.view, //UIView + videoViewHeight: yourPlayerHeight, //CGFloat + minimizeButton: yourButton //UIButton + ) + + // add your view to bodyView + self.bodyView.addSubview(yourView) +} +``` + +## in parent view controller + +### show + +```swift +func showSecondController() { + removeDraggableFloatingViewController() + self.videoViewController = VideoDetailViewController() + self.videoViewController.delegate = self + self.videoViewController.showVideoViewControllerOnParentVC(self) +} +``` + + +### dismiss + +```swift +func removeDraggableFloatingViewController() { + if self.videoViewController != nil { + self.videoViewController.removeAllViews() + self.videoViewController = nil + } +} +``` + + + + +-------------------------------------------------- + + +# Please edit "info.plist" +To disable swipe down gesture of Notification Center, you need to edit "info.plist" to hide status bar. +http://stackoverflow.com/questions/18059703/cannot-hide-status-bar-in-ios7 +![editInfoPlist](http://i.stack.imgur.com/dM32P.png "editInfoPlist") + + +-------------------------------------------------- + +-------------------------------------------------- + +-------------------------------------------------- +# please override if you want +```swift +override func didExpand() { + showVideoControl() +} +override func didMinimize() { + hideVideoControl() +} +``` + +------------------------------------------------------- + +## Please see demo app +If you want to use this, you have to check this demo app. + + + \ No newline at end of file diff --git a/YouTubeDraggableVideo.xcodeproj/project.pbxproj b/YouTubeDraggableVideo.xcodeproj/project.pbxproj index 87c21f8..1c5c3c7 100644 --- a/YouTubeDraggableVideo.xcodeproj/project.pbxproj +++ b/YouTubeDraggableVideo.xcodeproj/project.pbxproj @@ -8,15 +8,18 @@ /* Begin PBXBuildFile section */ 253F2E2D1A7F5907007FD89E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2E2C1A7F5907007FD89E /* main.m */; }; - 253F2E301A7F5907007FD89E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2E2F1A7F5907007FD89E /* AppDelegate.m */; }; - 253F2E361A7F5907007FD89E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 253F2E341A7F5907007FD89E /* Main.storyboard */; }; 253F2E381A7F5907007FD89E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 253F2E371A7F5907007FD89E /* Images.xcassets */; }; 253F2E3B1A7F5907007FD89E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 253F2E391A7F5907007FD89E /* LaunchScreen.xib */; }; 253F2E471A7F5907007FD89E /* YouTubeDraggableVideoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2E461A7F5907007FD89E /* YouTubeDraggableVideoTests.m */; }; - 253F2E511A7F5984007FD89E /* sample.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 253F2E501A7F5984007FD89E /* sample.mp4 */; }; - 253F2E581A7F5A4A007FD89E /* FirstVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2E541A7F5A4A007FD89E /* FirstVC.m */; }; - 253F2E591A7F5A4A007FD89E /* BSVideoDetailController.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2E571A7F5A4A007FD89E /* BSVideoDetailController.m */; }; 253F2E5C1A7F6027007FD89E /* profilePhoto.png in Resources */ = {isa = PBXBuildFile; fileRef = 253F2E5B1A7F6027007FD89E /* profilePhoto.png */; }; + B01147D81B33B30300D4CEB6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B01147D71B33B30300D4CEB6 /* AppDelegate.swift */; }; + B01147DA1B33D56900D4CEB6 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B01147D91B33D56900D4CEB6 /* SecondViewController.swift */; }; + B01147DC1B33DAC700D4CEB6 /* NSTimerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B01147DB1B33DAC700D4CEB6 /* NSTimerHelper.swift */; }; + B0125D7B1B1BD88B005FF053 /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0125D781B1BD88B005FF053 /* FirstViewController.swift */; }; + B0125D7C1B1BD88B005FF053 /* VideoDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0125D791B1BD88B005FF053 /* VideoDetailViewController.swift */; }; + B0125D801B1BD897005FF053 /* DraggableFloatingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B0125D7F1B1BD897005FF053 /* DraggableFloatingViewController.m */; }; + B04E93C31B168CEB004384E8 /* test.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = B04E93C21B168CEB004384E8 /* test.mp4 */; }; + B0B076F01B33F36A004A027A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B0B076EF1B33F36A004A027A /* AppDelegate.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -33,20 +36,24 @@ 253F2E271A7F5907007FD89E /* YouTubeDraggableVideo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YouTubeDraggableVideo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 253F2E2B1A7F5907007FD89E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 253F2E2C1A7F5907007FD89E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 253F2E2E1A7F5907007FD89E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = YouTubeDraggableVideo/AppDelegate.h; sourceTree = SOURCE_ROOT; }; - 253F2E2F1A7F5907007FD89E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = YouTubeDraggableVideo/AppDelegate.m; sourceTree = SOURCE_ROOT; }; - 253F2E351A7F5907007FD89E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 253F2E371A7F5907007FD89E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 253F2E3A1A7F5907007FD89E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 253F2E401A7F5907007FD89E /* YouTubeDraggableVideoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YouTubeDraggableVideoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 253F2E451A7F5907007FD89E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 253F2E461A7F5907007FD89E /* YouTubeDraggableVideoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YouTubeDraggableVideoTests.m; sourceTree = ""; }; - 253F2E501A7F5984007FD89E /* sample.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = sample.mp4; sourceTree = ""; }; - 253F2E531A7F5A4A007FD89E /* FirstVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FirstVC.h; sourceTree = ""; }; - 253F2E541A7F5A4A007FD89E /* FirstVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirstVC.m; sourceTree = ""; }; - 253F2E561A7F5A4A007FD89E /* BSVideoDetailController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSVideoDetailController.h; sourceTree = ""; }; - 253F2E571A7F5A4A007FD89E /* BSVideoDetailController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSVideoDetailController.m; sourceTree = ""; }; 253F2E5B1A7F6027007FD89E /* profilePhoto.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = profilePhoto.png; sourceTree = ""; }; + B01147D71B33B30300D4CEB6 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + B01147D91B33D56900D4CEB6 /* SecondViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = ""; }; + B01147DB1B33DAC700D4CEB6 /* NSTimerHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSTimerHelper.swift; sourceTree = ""; }; + B0125D781B1BD88B005FF053 /* FirstViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = ""; }; + B0125D791B1BD88B005FF053 /* VideoDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoDetailViewController.swift; sourceTree = ""; }; + B0125D7A1B1BD88B005FF053 /* YouTubeDraggableVideo-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "YouTubeDraggableVideo-Bridging-Header.h"; sourceTree = ""; }; + B0125D7E1B1BD897005FF053 /* DraggableFloatingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DraggableFloatingViewController.h; sourceTree = ""; }; + B0125D7F1B1BD897005FF053 /* DraggableFloatingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DraggableFloatingViewController.m; sourceTree = ""; }; + B04E93C21B168CEB004384E8 /* test.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = test.mp4; sourceTree = ""; }; + B04E93C41B168D16004384E8 /* sample.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = sample.mp4; sourceTree = ""; }; + B0B076EE1B33F36A004A027A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + B0B076EF1B33F36A004A027A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -88,12 +95,11 @@ 253F2E291A7F5907007FD89E /* YouTubeDraggableVideo */ = { isa = PBXGroup; children = ( - 253F2E5A1A7F5A68007FD89E /* AppDelegate */, - 253F2E521A7F5A4A007FD89E /* FirstController */, - 253F2E551A7F5A4A007FD89E /* VideoController */, - 253F2E341A7F5907007FD89E /* Main.storyboard */, + B0125D7D1B1BD897005FF053 /* Source */, + B0125D771B1BD88B005FF053 /* Demo */, 253F2E371A7F5907007FD89E /* Images.xcassets */, 253F2E391A7F5907007FD89E /* LaunchScreen.xib */, + B04E93C11B168CEB004384E8 /* sampleMovies */, 253F2E2A1A7F5907007FD89E /* Supporting Files */, ); path = YouTubeDraggableVideo; @@ -103,7 +109,6 @@ isa = PBXGroup; children = ( 253F2E5B1A7F6027007FD89E /* profilePhoto.png */, - 253F2E501A7F5984007FD89E /* sample.mp4 */, 253F2E2B1A7F5907007FD89E /* Info.plist */, 253F2E2C1A7F5907007FD89E /* main.m */, ); @@ -127,31 +132,37 @@ name = "Supporting Files"; sourceTree = ""; }; - 253F2E521A7F5A4A007FD89E /* FirstController */ = { + B0125D771B1BD88B005FF053 /* Demo */ = { isa = PBXGroup; children = ( - 253F2E531A7F5A4A007FD89E /* FirstVC.h */, - 253F2E541A7F5A4A007FD89E /* FirstVC.m */, + B0125D791B1BD88B005FF053 /* VideoDetailViewController.swift */, + B0125D781B1BD88B005FF053 /* FirstViewController.swift */, + B01147D91B33D56900D4CEB6 /* SecondViewController.swift */, + B01147DB1B33DAC700D4CEB6 /* NSTimerHelper.swift */, + B0B076EE1B33F36A004A027A /* AppDelegate.h */, + B0B076EF1B33F36A004A027A /* AppDelegate.m */, + B01147D71B33B30300D4CEB6 /* AppDelegate.swift */, + B0125D7A1B1BD88B005FF053 /* YouTubeDraggableVideo-Bridging-Header.h */, ); - path = FirstController; + path = Demo; sourceTree = ""; }; - 253F2E551A7F5A4A007FD89E /* VideoController */ = { + B0125D7D1B1BD897005FF053 /* Source */ = { isa = PBXGroup; children = ( - 253F2E561A7F5A4A007FD89E /* BSVideoDetailController.h */, - 253F2E571A7F5A4A007FD89E /* BSVideoDetailController.m */, + B0125D7E1B1BD897005FF053 /* DraggableFloatingViewController.h */, + B0125D7F1B1BD897005FF053 /* DraggableFloatingViewController.m */, ); - path = VideoController; + path = Source; sourceTree = ""; }; - 253F2E5A1A7F5A68007FD89E /* AppDelegate */ = { + B04E93C11B168CEB004384E8 /* sampleMovies */ = { isa = PBXGroup; children = ( - 253F2E2E1A7F5907007FD89E /* AppDelegate.h */, - 253F2E2F1A7F5907007FD89E /* AppDelegate.m */, + B04E93C41B168D16004384E8 /* sample.mp4 */, + B04E93C21B168CEB004384E8 /* test.mp4 */, ); - path = AppDelegate; + path = sampleMovies; sourceTree = ""; }; /* End PBXGroup section */ @@ -198,11 +209,13 @@ 253F2E1F1A7F5907007FD89E /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 1220; ORGANIZATIONNAME = "Sandeep Mukherjee"; TargetAttributes = { 253F2E261A7F5907007FD89E = { CreatedOnToolsVersion = 6.1; + DevelopmentTeam = 8ET8BLFZ87; + ProvisioningStyle = Automatic; }; 253F2E3F1A7F5907007FD89E = { CreatedOnToolsVersion = 6.1; @@ -212,7 +225,7 @@ }; buildConfigurationList = 253F2E221A7F5907007FD89E /* Build configuration list for PBXProject "YouTubeDraggableVideo" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -235,10 +248,9 @@ buildActionMask = 2147483647; files = ( 253F2E5C1A7F6027007FD89E /* profilePhoto.png in Resources */, - 253F2E361A7F5907007FD89E /* Main.storyboard in Resources */, + B04E93C31B168CEB004384E8 /* test.mp4 in Resources */, 253F2E3B1A7F5907007FD89E /* LaunchScreen.xib in Resources */, 253F2E381A7F5907007FD89E /* Images.xcassets in Resources */, - 253F2E511A7F5984007FD89E /* sample.mp4 in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -256,10 +268,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 253F2E581A7F5A4A007FD89E /* FirstVC.m in Sources */, - 253F2E301A7F5907007FD89E /* AppDelegate.m in Sources */, + B01147DA1B33D56900D4CEB6 /* SecondViewController.swift in Sources */, + B01147D81B33B30300D4CEB6 /* AppDelegate.swift in Sources */, 253F2E2D1A7F5907007FD89E /* main.m in Sources */, - 253F2E591A7F5A4A007FD89E /* BSVideoDetailController.m in Sources */, + B0125D7C1B1BD88B005FF053 /* VideoDetailViewController.swift in Sources */, + B0B076F01B33F36A004A027A /* AppDelegate.m in Sources */, + B0125D801B1BD897005FF053 /* DraggableFloatingViewController.m in Sources */, + B0125D7B1B1BD88B005FF053 /* FirstViewController.swift in Sources */, + B01147DC1B33DAC700D4CEB6 /* NSTimerHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -282,14 +298,6 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 253F2E341A7F5907007FD89E /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 253F2E351A7F5907007FD89E /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; 253F2E391A7F5907007FD89E /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( @@ -305,24 +313,38 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -335,7 +357,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -346,17 +368,29 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -364,15 +398,17 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; name = Release; @@ -381,9 +417,20 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 8ET8BLFZ87; INFOPLIST_FILE = YouTubeDraggableVideo/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.vizllx.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "YouTubeDraggableVideo/Demo/YouTubeDraggableVideo-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -391,9 +438,19 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 8ET8BLFZ87; INFOPLIST_FILE = YouTubeDraggableVideo/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.vizllx.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "YouTubeDraggableVideo/Demo/YouTubeDraggableVideo-Bridging-Header.h"; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -411,6 +468,7 @@ ); INFOPLIST_FILE = YouTubeDraggableVideoTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.vizllx.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YouTubeDraggableVideo.app/YouTubeDraggableVideo"; }; @@ -426,6 +484,7 @@ ); INFOPLIST_FILE = YouTubeDraggableVideoTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.vizllx.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/YouTubeDraggableVideo.app/YouTubeDraggableVideo"; }; @@ -450,6 +509,7 @@ 253F2E4C1A7F5907007FD89E /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 253F2E4D1A7F5907007FD89E /* Build configuration list for PBXNativeTarget "YouTubeDraggableVideoTests" */ = { isa = XCConfigurationList; @@ -458,6 +518,7 @@ 253F2E4F1A7F5907007FD89E /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/YouTubeDraggableVideo.xcodeproj/project.xcworkspace/xcshareddata/YouTubeDraggableVideo.xccheckout b/YouTubeDraggableVideo.xcodeproj/project.xcworkspace/xcshareddata/YouTubeDraggableVideo.xccheckout index 29ca625..45683bc 100644 --- a/YouTubeDraggableVideo.xcodeproj/project.xcworkspace/xcshareddata/YouTubeDraggableVideo.xccheckout +++ b/YouTubeDraggableVideo.xcodeproj/project.xcworkspace/xcshareddata/YouTubeDraggableVideo.xccheckout @@ -11,7 +11,7 @@ IDESourceControlProjectOriginsDictionary C0796BA5C0F25FE444F34B630D9B7AA6F9BEA0B4 - https://github.com/vizllx/DraggableYoutubeFloatingVideo.git + https://github.com/entotsu/DraggableYoutubeFloatingVideo.git IDESourceControlProjectPath YouTubeDraggableVideo.xcodeproj @@ -21,7 +21,7 @@ ../.. IDESourceControlProjectURL - https://github.com/vizllx/DraggableYoutubeFloatingVideo.git + https://github.com/entotsu/DraggableYoutubeFloatingVideo.git IDESourceControlProjectVersion 111 IDESourceControlProjectWCCIdentifier @@ -34,7 +34,7 @@ IDESourceControlWCCIdentifierKey C0796BA5C0F25FE444F34B630D9B7AA6F9BEA0B4 IDESourceControlWCCName - YouTubeDraggableVideo + DraggableYoutubeFloatingVideo diff --git a/YouTubeDraggableVideo.xcodeproj/xcuserdata/Takuya.xcuserdatad/xcschemes/YouTubeDraggableVideo.xcscheme b/YouTubeDraggableVideo.xcodeproj/xcuserdata/Takuya.xcuserdatad/xcschemes/YouTubeDraggableVideo.xcscheme new file mode 100644 index 0000000..60a31aa --- /dev/null +++ b/YouTubeDraggableVideo.xcodeproj/xcuserdata/Takuya.xcuserdatad/xcschemes/YouTubeDraggableVideo.xcscheme @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/YouTubeDraggableVideo/AppDelegate.h b/YouTubeDraggableVideo/AppDelegate.h index 6c33961..ee019fb 100644 --- a/YouTubeDraggableVideo/AppDelegate.h +++ b/YouTubeDraggableVideo/AppDelegate.h @@ -1,9 +1,9 @@ // // AppDelegate.h -// YouTubeDraggableVideo +// test // -// Created by Sandeep Mukherjee on 02/02/15. -// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// Created by Takuya Okamoto on 2015/06/19. +// Copyright (c) 2015年 Uniface. All rights reserved. // #import diff --git a/YouTubeDraggableVideo/AppDelegate.m b/YouTubeDraggableVideo/AppDelegate.m index 13cd265..0d269e9 100644 --- a/YouTubeDraggableVideo/AppDelegate.m +++ b/YouTubeDraggableVideo/AppDelegate.m @@ -1,9 +1,9 @@ // // AppDelegate.m -// YouTubeDraggableVideo +// test // -// Created by Sandeep Mukherjee on 02/02/15. -// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// Created by Takuya Okamoto on 2015/06/19. +// Copyright (c) 2015年 Uniface. All rights reserved. // #import "AppDelegate.h" diff --git a/YouTubeDraggableVideo/Base.lproj/LaunchScreen.xib b/YouTubeDraggableVideo/Base.lproj/LaunchScreen.xib index 4c20972..c3f8bee 100644 --- a/YouTubeDraggableVideo/Base.lproj/LaunchScreen.xib +++ b/YouTubeDraggableVideo/Base.lproj/LaunchScreen.xib @@ -1,8 +1,10 @@ - - + + + - - + + + @@ -12,19 +14,19 @@ - + @@ -38,4 +40,9 @@ + + + + + diff --git a/YouTubeDraggableVideo/Base.lproj/Main.storyboard b/YouTubeDraggableVideo/Base.lproj/Main.storyboard deleted file mode 100644 index f226fb7..0000000 --- a/YouTubeDraggableVideo/Base.lproj/Main.storyboard +++ /dev/null @@ -1,563 +0,0 @@ - - - - - - - - - RobotoCondensed-Light - RobotoCondensed-Light - RobotoCondensed-Light - RobotoCondensed-Light - RobotoCondensed-Light - RobotoCondensed-Light - - - RobotoCondensed-Regular - RobotoCondensed-Regular - RobotoCondensed-Regular - RobotoCondensed-Regular - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/YouTubeDraggableVideo/Demo/AppDelegate.h b/YouTubeDraggableVideo/Demo/AppDelegate.h new file mode 100644 index 0000000..227f986 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/AppDelegate.h @@ -0,0 +1,20 @@ +// +// AppDelegate.h +// test +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +#import + + +@class VideoDetailViewController; + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) VideoDetailViewController *videoViewController; + +@end + diff --git a/YouTubeDraggableVideo/Demo/AppDelegate.m b/YouTubeDraggableVideo/Demo/AppDelegate.m new file mode 100644 index 0000000..d9ea329 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/AppDelegate.m @@ -0,0 +1,65 @@ +// +// AppDelegate.m +// test +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +#import "AppDelegate.h" +#import "YouTubeDraggableVideo-Swift.h" + + +@interface AppDelegate () +@end + +@implementation AppDelegate + +//+ (VideoDetailViewController) video + +// static func appDelegate() -> AppDelegate? { +// return UIApplication.sharedApplication().delegate as? AppDelegate +// } + ++ (AppDelegate *) appDelegate { + return [[UIApplication sharedApplication] delegate]; +} + +//+ (VideoDetailViewController *) videoController { +// return [[[UIApplication sharedApplication] delegate] videoViewController]; +//} + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + + self.videoViewController = [[VideoDetailViewController alloc] init]; + + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.rootViewController = [[FirstViewController alloc] init]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/YouTubeDraggableVideo/Demo/AppDelegate.swift b/YouTubeDraggableVideo/Demo/AppDelegate.swift new file mode 100644 index 0000000..b51a642 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/AppDelegate.swift @@ -0,0 +1,63 @@ +//// +//// AppDelegate.swift +//// APlayerViewController +//// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// +// +//import UIKit +// +//@UIApplicationMain +//class AppDelegate: UIResponder, UIApplicationDelegate { +// +// var window: UIWindow? +// var videoViewController = VideoDetailViewController() +// +// +// static func appDelegate() -> AppDelegate? { +// return UIApplication.sharedApplication().delegate as? AppDelegate +// } +// +// static func videoController() -> VideoDetailViewController { +// return appDelegate()!.videoViewController +// } +// +// static func getWindow() -> UIWindow { +// return appDelegate()!.window! +// } +// +// +// func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { +// // Override point for customization after application launch. +// self.window = UIWindow(frame: UIScreen.mainScreen().bounds) +// self.window!.rootViewController = FirstViewController() +// self.window!.makeKeyAndVisible() +// return true +// } +// +// func applicationWillResignActive(application: UIApplication) { +// // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. +// // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +// } +// +// func applicationDidEnterBackground(application: UIApplication) { +// // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. +// // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +// } +// +// func applicationWillEnterForeground(application: UIApplication) { +// // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +// } +// +// func applicationDidBecomeActive(application: UIApplication) { +// // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +// } +// +// func applicationWillTerminate(application: UIApplication) { +// // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +// } +// +// +//} +// diff --git a/YouTubeDraggableVideo/Demo/FirstViewController.swift b/YouTubeDraggableVideo/Demo/FirstViewController.swift new file mode 100644 index 0000000..5f6cfa2 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/FirstViewController.swift @@ -0,0 +1,38 @@ +// +// FirstViewController.swift +// YouTubeDraggableVideo +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +import UIKit + +class FirstViewController: UIViewController { + + + override func viewDidLoad() { + self.view.backgroundColor = .white + + let btn = UIButton() + btn.frame = CGRect(x: self.view.center.x-100, y: self.view.center.y, width: 200, height: 100) + btn.backgroundColor = .blue + btn.setTitle("Show Video Screen", for: .normal) + btn.addTarget(self, action: #selector(onTapShowButton), for: .touchUpInside) + self.view.addSubview(btn) + + + + } + + @objc func onTapShowButton() { + (UIApplication.shared.delegate as! AppDelegate).videoViewController.show() //👈 + } + + override var prefersStatusBarHidden: Bool { + return false + } + + + +} diff --git a/YouTubeDraggableVideo/Demo/NSTimerHelper.swift b/YouTubeDraggableVideo/Demo/NSTimerHelper.swift new file mode 100644 index 0000000..ba60069 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/NSTimerHelper.swift @@ -0,0 +1,40 @@ +// +// NSTimerHelper.swift +// YouTubeDraggableVideo +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +import Foundation + +extension Timer { + static func schedule(delay: TimeInterval, handler: @escaping(Timer?) -> Void) -> Timer? { + let fireDate = delay + CFAbsoluteTimeGetCurrent() + let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler) + CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes) + return timer + } + + static func schedule(repeatInterval interval: TimeInterval, handler: @escaping(Timer?) -> Void) -> Timer? { + let fireDate = interval + CFAbsoluteTimeGetCurrent() + let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler) + CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes) + return timer + } +} + + +// Usage: + +//var count = 0 +//NSTimer.schedule(repeatInterval: 1) { timer in +// println(++count) +// if count >= 10 { +// timer.invalidate() +// } +//} +// +//NSTimer.schedule(delay: 5) { timer in +// println("5 seconds") +//} diff --git a/YouTubeDraggableVideo/Demo/SecondViewController.swift b/YouTubeDraggableVideo/Demo/SecondViewController.swift new file mode 100644 index 0000000..3d5879c --- /dev/null +++ b/YouTubeDraggableVideo/Demo/SecondViewController.swift @@ -0,0 +1,43 @@ +// +// SecondViewController.swift +// YouTubeDraggableVideo +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +import Foundation + +class SecondViewController: UIViewController { + + + @objc func onTapButton() { + (UIApplication.shared.delegate as! AppDelegate).videoViewController.show()//👈 + } + + @objc func onTapDismissButton() { + _ = self.presentingViewController + self.dismiss(animated: true, completion: nil) +// NSTimer.schedule(delay: 0.2) { timer in +// AppDelegate.videoController().changeParentVC(parentVC)//👈 +// } + } + + override func viewDidLoad() { + self.view.backgroundColor = .white + + let btn = UIButton() + btn.frame = CGRect(x: 10, y: 10, width: 100, height: 100) + btn.backgroundColor = .blue + btn.addTarget(self, action: #selector(onTapButton), for: .touchUpInside) + self.view.addSubview(btn) + + let dismissBtn = UIButton() + dismissBtn.frame = CGRect(x: 150, y: 150, width: 100, height: 100) + dismissBtn.backgroundColor = .orange + dismissBtn.addTarget(self, action: #selector(onTapDismissButton), for: .touchUpInside) + self.view.addSubview(dismissBtn) + + } + +} diff --git a/YouTubeDraggableVideo/Demo/VideoDetailViewController.swift b/YouTubeDraggableVideo/Demo/VideoDetailViewController.swift new file mode 100644 index 0000000..8aa1271 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/VideoDetailViewController.swift @@ -0,0 +1,250 @@ +// +// VideoViewController.swift +// YouTubeDraggableVideo +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +import Foundation +import UIKit + +@objc class VideoDetailViewController: DraggableFloatingViewController { + + var moviePlayer: MPMoviePlayerController! + private let loadingSpinner = UIActivityIndicatorView() + + override func viewDidLoad() { + super.viewDidLoad() + + moviePlayer = MPMoviePlayerController() + + self.setupViews(withVideoView: moviePlayer.view, videoViewHeight: 160)//, minimizeButton: minimizeButton) + + setupMoviePlayer() + + NotificationCenter.default.addObserver(self, selector: #selector(onOrientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil) + + // design controller view + let minimizeButton = UIButton() + minimizeButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44) + minimizeButton.setImage(UIImage(named: "DownArrow"), for: .normal) + minimizeButton.addTarget(self, action: #selector(onTapMinimizeButton), for: .touchUpInside) + self.controllerView.addSubview(minimizeButton) + let testControl = UILabel() + testControl.frame = CGRect(x: 100, y: 5, width: 150, height: 40) + testControl.text = "controller view" + testControl.textColor = .white + self.controllerView.addSubview(testControl) + + // design body view + self.bodyView.backgroundColor = .gray + self.bodyView.layer.borderColor = UIColor.blue.cgColor + self.bodyView.layer.borderWidth = 2.0 + let testView = UILabel() + testView.frame = CGRect(x: 20, y: 10, width: 100, height: 40) + testView.text = "body view" + testView.textColor = .blue + self.bodyView.addSubview(testView) + + // design message view + self.messageView.backgroundColor = UIColor.black.withAlphaComponent(0.8) + loadingSpinner.frame = CGRect(x: 0, y: 0, width: 50, height: 50) + loadingSpinner.center = self.messageView.center + loadingSpinner.hidesWhenStopped = false + loadingSpinner.style = .white + self.messageView.addSubview(loadingSpinner) + } + + override func didDisappear() { + moviePlayer.pause() + } + + override func didReAppear() { + setupMoviePlayer() + } + + override var prefersStatusBarHidden: Bool { + return true + } + + + + func onTapButton() { + print("onTapButton") + } + + override func showMessageView() { + loadingSpinner.startAnimating() + super.showMessageView() + } + override func hideMessageView() { + super.hideMessageView() + loadingSpinner.stopAnimating() + } + + override func didFullExpandByGesture() { + showVideoControl() + } + override func didExpand() { + print("didExpand") + + showVideoControl() + } + override func didMinimize() { + print("didMinimized") + hideVideoControl() + } + + override func didStartMinimizeGesture() { + print("didStartMinimizeGesture") + } + + + @objc func onTapMinimizeButton() { + self.minimizeView() + } + + + + // -------------------------------------------------------------------------------------------------- + + func setupMoviePlayer() { + // setupMovie + let url = NSURL.fileURL(withPath: Bundle.main.path(forResource: "test", ofType: "mp4")!) + moviePlayer.contentURL = url + moviePlayer.isFullscreen = false + moviePlayer.controlStyle = .none + moviePlayer.repeatMode = .none + moviePlayer.prepareToPlay() + + // play + let seconds = 1.0 + let delay = seconds * Double(NSEC_PER_SEC)// nanoseconds per seconds + DispatchQueue.main.asyncAfter(deadline: .now() + delay) { + self.moviePlayer.play() + } + + // for movie loop + + NotificationCenter.default.addObserver(self, selector: #selector(moviePlayBackDidFinish), + name: NSNotification.Name.MPMoviePlayerPlaybackDidFinish, + object: moviePlayer) + } + + // movie loop + @objc func moviePlayBackDidFinish(notification: NSNotification) { + print("moviePlayBackDidFinish:") + moviePlayer.play() + removeObserver(aName: NSNotification.Name.MPMoviePlayerPlaybackDidFinish.rawValue) + } + + + + + // ----------------------------- events ----------------------------------------------- + + // MARK: Orientation + @objc func onOrientationChanged() { + let orientation: UIInterfaceOrientation = getOrientation() + + switch orientation { + + case .portrait, .portraitUpsideDown: + print("portrait") + exitFullScreen() + + case .landscapeLeft, .landscapeRight: + print("landscape") + goFullScreen() + + default: + print("no action for this orientation:" + orientation.rawValue.description) + } + + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } + + + + + + // --------------------------------- util ------------------------------------------ + + // MARK: FullScreen Method + func isFullScreen() -> Bool { +// println("isFullScreen: " + String(stringInterpolationSegment: moviePlayer.fullscreen)) + return moviePlayer.isFullscreen + } + func goFullScreen() { + if !isFullScreen() { +// println("goFullScreen") + moviePlayer.controlStyle = MPMovieControlStyle.fullscreen + moviePlayer.isFullscreen = true + addObserver(selector: #selector(willExitFullScreen), name: NSNotification.Name.MPMoviePlayerWillExitFullscreen.rawValue) + } + } + func exitFullScreen() { + if isFullScreen() { +// println("exit fullscreen"); + moviePlayer.isFullscreen = false + } + } + @objc func willExitFullScreen() { +// println("willExitFullScreen") + if isLandscape() + { + setOrientation(orientation: .portrait) + } + + + removeObserver(aName: NSNotification.Name.MPMoviePlayerWillExitFullscreen.rawValue) + } + + + // FIXIT: Don't work + func showVideoControl() { +// println("showVideoControl"); + moviePlayer.controlStyle = .none + } + + // FIXIT: Don't work + func hideVideoControl() { +// println("hideVideoControl") + moviePlayer.controlStyle = .none + } + + + + + //----------------------------------------------------------------------------------- + + func getOrientation() -> UIInterfaceOrientation { + return UIApplication.shared.statusBarOrientation + } + + func setOrientation(orientation: UIInterfaceOrientation) { + let orientationNum: NSNumber = NSNumber(value: orientation.rawValue) + UIDevice.current.setValue(orientationNum, forKey: "orientation") + } + + func addObserver(selector aSelector: Selector, name aName: String) { + NotificationCenter.default.addObserver(self, selector: aSelector, name:NSNotification.Name(aName), object: nil) + } + + func removeObserver(aName: String) { + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(aName), object: nil) + } + + func isLandscape() -> Bool { + if (UIApplication.shared.statusBarOrientation.isLandscape) { + return true + } + else { + return false + } + } +} diff --git a/YouTubeDraggableVideo/Demo/YouTubeDraggableVideo-Bridging-Header.h b/YouTubeDraggableVideo/Demo/YouTubeDraggableVideo-Bridging-Header.h new file mode 100644 index 0000000..bca0501 --- /dev/null +++ b/YouTubeDraggableVideo/Demo/YouTubeDraggableVideo-Bridging-Header.h @@ -0,0 +1,6 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "DraggableFloatingViewController.h" +#import "AppDelegate.h" \ No newline at end of file diff --git a/YouTubeDraggableVideo/FirstController/FirstVC.h b/YouTubeDraggableVideo/FirstController/FirstVC.h deleted file mode 100644 index ce56a0e..0000000 --- a/YouTubeDraggableVideo/FirstController/FirstVC.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// FirstVC.h -// YouTubeDraggableVideo -// -// Created by Sandeep Mukherjee on 02/02/15. -// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. -// -// - -#import -#import "BSVideoDetailController.h" - -//Define the protocol for the delegate - -@interface FirstVC : UIViewController - - -@property(strong,nonatomic)BSVideoDetailController *secondViewController; - -@property (weak, nonatomic) IBOutlet UITableView *commentsTable; - -@property (strong, nonatomic)NSMutableArray *discussionArray; -@property (nonatomic, readwrite)NSInteger totalCount; -@property (nonatomic, readwrite)NSInteger pageno; -@property (nonatomic, readwrite)NSString *topicID; -@property (nonatomic,assign) BOOL isCanceledOperation; - -@end diff --git a/YouTubeDraggableVideo/FirstController/FirstVC.m b/YouTubeDraggableVideo/FirstController/FirstVC.m deleted file mode 100644 index 644f3a8..0000000 --- a/YouTubeDraggableVideo/FirstController/FirstVC.m +++ /dev/null @@ -1,257 +0,0 @@ -// -// FirstVC.m -// YouTubeDraggableVideo -// -// Created by Sandeep Mukherjee on 02/02/15. -// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. -// - -#import "FirstVC.h" -#define PAGESIZE 1 - - -@interface FirstVC () - - - -@end -@implementation FirstVC - - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. - self.pageno=1; - _discussionArray=[[NSMutableArray alloc]initWithObjects:@"demoContent",@"demoContent", @"demoContent", @"demoContent", @"demoContent", nil]; - -} --(void)viewWillDisappear:(BOOL)animated -{ - if(self.secondViewController!=nil && !self.secondViewController.player.isFullscreen) - { - [self.secondViewController removeView]; - [self.secondViewController.view removeFromSuperview]; - self.secondViewController=nil; - - - - } -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} -- (BOOL)prefersStatusBarHidden { - return YES; -} - --(void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; - - - } -- (void)orientationChanged:(NSNotification *)notification{ - [self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; - -} - -- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation { - - switch (orientation) - { - case UIInterfaceOrientationPortrait: - case UIInterfaceOrientationPortraitUpsideDown: - { - //load the portrait view - if(self.secondViewController!=nil) - { - - - if(!self.secondViewController.player .fullscreen) - { - if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) - [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; - } - } - } - - break; - case UIInterfaceOrientationLandscapeLeft: - case UIInterfaceOrientationLandscapeRight: - { - if(self.secondViewController!=nil) - { - NSLog(@"landscape called;"); - - - // if(!self.secondViewController.player.fullscreen && self.secondViewController.viewTable.alpha>=1) - //{ - - self.secondViewController.player.controlStyle = MPMovieControlStyleDefault; - self.secondViewController.player .fullscreen = YES; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil]; - //} - /* else if( self.secondViewController.viewTable.alpha<=0) - { - if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) - [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; - } */ - - - } - - - } - break; - case UIInterfaceOrientationUnknown:break; - } -} - -- (void)willExitFullscreen:(NSNotification*)notification { - - if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) - [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerWillExitFullscreenNotification object:nil]; -} - --(void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - - -} --(void)viewDidDisappear:(BOOL)animated -{ - [super viewDidDisappear:animated]; - - -} -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ - - - - - - -#pragma mark - -#pragma mark - UITableViewDataSource & delegate - - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - - return self.discussionArray.count; -} -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - - return 110; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - - return [self tableView:tableView discussionCellForAtIndexPath:indexPath]; - - -} - -// create discussion cell --(UITableViewCell *)tableView:(UITableView *)tableView discussionCellForAtIndexPath:(NSIndexPath *)indexPath -{ - static NSString *CellIdentifier = @"commentsCell"; - UITableViewCell *cell; - cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; - } - cell.selectionStyle=UITableViewCellSelectionStyleNone; - - UIImageView *bgImage=(UIImageView *)[cell.contentView viewWithTag:1]; - UIImageView *profileImage=(UIImageView *)[cell.contentView viewWithTag:2]; - - // create border of the background image - bgImage.layer.borderColor=[UIColor lightGrayColor].CGColor; - bgImage.layer.borderWidth=0.5; - // create rounded player image - profileImage.layer.cornerRadius=profileImage.frame.size.width/2; - profileImage.layer.masksToBounds=YES; - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - - if(self.secondViewController==nil) - { - [self showSecondController]; - } - else - { - [self.secondViewController removeView]; - [self.secondViewController.view removeFromSuperview]; - self.secondViewController=nil; - - [self showSecondController]; - - } - - - - -} - -#pragma mark - -#pragma mark -Important Methods - --(void)showSecondController -{ - if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) - [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; - - self.secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"BSVideoDetailController"]; - //initial frame - self.secondViewController.view.frame=CGRectMake(self.view.frame.size.width-50, self.view.frame.size.height-50, self.view.frame.size.width, self.view.frame.size.height); - self.secondViewController.initialFirstViewFrame=self.view.frame; - - - self.secondViewController.view.alpha=0; - self.secondViewController.view.transform=CGAffineTransformMakeScale(0.2, 0.2); - - - [self.view addSubview:self.secondViewController.view]; - self.secondViewController.onView=self.view; - - [UIView animateWithDuration:0.9f animations:^{ - self.secondViewController.view.transform=CGAffineTransformMakeScale(1.0, 1.0); - self.secondViewController.view.alpha=1; - - self.secondViewController.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height); - }]; - -} -- (void)removeController -{ - - self.secondViewController=nil; - -} - - - - -@end diff --git a/YouTubeDraggableVideo/Images.xcassets/AppIcon.appiconset/Contents.json b/YouTubeDraggableVideo/Images.xcassets/AppIcon.appiconset/Contents.json index 118c98f..8121323 100644 --- a/YouTubeDraggableVideo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/YouTubeDraggableVideo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -2,37 +2,52 @@ "images" : [ { "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "scale" : "3x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "scale" : "3x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/YouTubeDraggableVideo/Images.xcassets/test.imageset/Contents.json b/YouTubeDraggableVideo/Images.xcassets/test.imageset/Contents.json new file mode 100644 index 0000000..08b4221 --- /dev/null +++ b/YouTubeDraggableVideo/Images.xcassets/test.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "test.jpg" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/YouTubeDraggableVideo/Info.plist b/YouTubeDraggableVideo/Info.plist index 33edb9b..f5d2023 100644 --- a/YouTubeDraggableVideo/Info.plist +++ b/YouTubeDraggableVideo/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.vizllx.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -24,8 +24,6 @@ UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 @@ -36,5 +34,7 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIViewControllerBasedStatusBarAppearance + diff --git a/YouTubeDraggableVideo/Source/DraggableFloatingViewController.h b/YouTubeDraggableVideo/Source/DraggableFloatingViewController.h new file mode 100644 index 0000000..4887e10 --- /dev/null +++ b/YouTubeDraggableVideo/Source/DraggableFloatingViewController.h @@ -0,0 +1,64 @@ +// +// BSVideoDetailController.h +// YouTubeDraggableVideo +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + +#import +#import + + + +@protocol DraggableFloatingViewControllerDelegate +@required +- (void)removeDraggableFloatingViewController; +@end + + +// please extend +@interface DraggableFloatingViewController : UIViewController + + + +// ---------- use from SubClass ------------------------ + +// please add subview on this +@property(nonatomic, strong) UIView *bodyView; +//please add controller on this +@property(nonatomic, strong) UIView *controllerView; +//please add loading spiner on this +@property(nonatomic, strong) UIView *messageView; + +// please call from "viewDidLoad" from sub class +- (void) setupViewsWithVideoView: (UIView *)vView + videoViewHeight: (CGFloat) videoHeight; + +// please override if you want +- (void) didExpand; +- (void) didMinimize; +- (void) didStartMinimizeGesture; +- (void) didFullExpandByGesture;//stil dev +- (void) didDisappear; +- (void) didReAppear; + + +// please call if you want +- (void) minimizeView; +- (void) expandView; +- (void) hideControllerView; +- (void) showControllerView; +- (void) showMessageView; +- (void) hideMessageView; + + + +// ---------- use from other class ------------------------ +// please call from parent view controller +- (void) show; +- (void) bringToFront; + + + +@end diff --git a/YouTubeDraggableVideo/Source/DraggableFloatingViewController.m b/YouTubeDraggableVideo/Source/DraggableFloatingViewController.m new file mode 100644 index 0000000..8bcda79 --- /dev/null +++ b/YouTubeDraggableVideo/Source/DraggableFloatingViewController.m @@ -0,0 +1,1103 @@ +// +// BSVideoDetailController.m +// YouTubeDraggableVideo +// +// Created by Sandeep Mukherjee on 02/02/15. +// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. +// + + +#import "DraggableFloatingViewController.h" +#import "QuartzCore/CALayer.h" + +typedef NS_ENUM(NSUInteger, UIPanGestureRecognizerDirection) { + UIPanGestureRecognizerDirectionUndefined, + UIPanGestureRecognizerDirectionUp, + UIPanGestureRecognizerDirectionDown, + UIPanGestureRecognizerDirectionLeft, + UIPanGestureRecognizerDirectionRight +}; + +@interface DraggableFloatingViewController () +@end + + +@implementation DraggableFloatingViewController +{ + + //local Frame storee + CGRect videoWrapperFrame; + CGRect minimizedVideoFrame; + CGRect pageWrapperFrame; + + // animation Frame + CGRect wFrame; + CGRect vFrame; + + //local touch location + CGFloat _touchPositionInHeaderY; + CGFloat _touchPositionInHeaderX; + + //detecting Pan gesture Direction + UIPanGestureRecognizerDirection direction; + + UITapGestureRecognizer *tapRecognizer; + + //Creating a transparent Black layer view + UIView *transparentBlackSheet; + + //Just to Check wether view is expanded or not + BOOL isExpandedMode; + + + UIView *pageWrapper; + UIView *videoWrapper; +// UIButton *foldButton; + + UIView *videoView; + // border of mini vieo view + UIView *borderView; + + CGFloat maxH; + CGFloat maxW; + CGFloat videoHeightRatio; + CGFloat finalViewOffsetY; + CGFloat minimamVideoHeight; + + UIView *parentView; + + BOOL isDisplayController; + NSTimer *hideControllerTimer; + + BOOL isMinimizingByGesture; + + BOOL isAppear; + BOOL isSetuped; + + CGRect windowFrame; +} + +const CGFloat finalMargin = 3.0; +const CGFloat minimamVideoWidth = 140; +const CGFloat flickVelocity = 1000; + +// please override if you want +- (void) didExpand {} +- (void) didMinimize {} +- (void) didStartMinimizeGesture { + [[UIApplication sharedApplication] setStatusBarHidden:NO]; +} +- (void) didFullExpandByGesture {}// TODO: meke this stable +- (void) didDisappear{} +- (void) didReAppear{} + +- (id)init +{ + self = [super init]; + if (self) { + self.bodyView = [[UIView alloc] init]; + self.controllerView = [[UIView alloc] init]; + self.messageView = [[UIView alloc] init]; + } + return self; +} +- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + self.bodyView = [[UIView alloc] init]; + self.controllerView = [[UIView alloc] init]; + self.messageView = [[UIView alloc] init]; + } + return self; +} + + + +# pragma mark - init + +- (void) show { + if (!isSetuped) { + [self setup]; + } + else { + if (!isAppear) { + [self reAppearWithAnimation]; + } + } +} + + +- (void) setup { + + isSetuped = true; + + NSLog(@"showVideoViewControllerOnParentVC"); + +// if( ![parentVC conformsToProtocol:@protocol(DraggableFloatingViewControllerDelegate)] ) { +// NSAssert(NO, @"❌❌Parent view controller must confirm to protocol .❌❌"); +// } +// self.delegate = parentVC; + + // set portrait + if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) { + [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; + } + + [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; + +// parentView = parentVC.view; +// [parentView addSubview:self.view];// then, "viewDidLoad" called + [[self getWindow] addSubview:self.view]; + + // wait to run "viewDidLoad" before "showThisView" + [self performSelector:@selector(showThisView) withObject:nil afterDelay:0.0]; + + isAppear = true; +} +// ↓ +// VIEW DID LOAD +- (void) setupViewsWithVideoView: (UIView *)vView + videoViewHeight: (CGFloat) videoHeight +// minimizeButton: (UIButton *)foldBtn +{ + NSLog(@"setupViewsWithVideoView"); + + videoView = vView; +// foldButton = foldBtn;//control show and hide + + windowFrame = [[UIScreen mainScreen] bounds]; + maxH = windowFrame.size.height; + maxW = windowFrame.size.width; + CGFloat videoWidth = maxW; + videoHeightRatio = videoHeight / videoWidth; + minimamVideoHeight = minimamVideoWidth * videoHeightRatio; + finalViewOffsetY = maxH - minimamVideoHeight - finalMargin; + + videoWrapper = [[UIView alloc] init]; + videoWrapper.frame = CGRectMake(0, 0, videoWidth, videoHeight); + + videoView.frame = videoWrapper.frame; + self.controllerView.frame = videoWrapper.frame; + self.messageView.frame = videoWrapper.frame; + + pageWrapper = [[UIView alloc] init]; + pageWrapper.frame = CGRectMake(0, 0, maxW, maxH); + + videoWrapperFrame = videoWrapper.frame; + pageWrapperFrame = pageWrapper.frame; + + + borderView = [[UIView alloc] init]; + borderView.clipsToBounds = YES; + borderView.layer.masksToBounds = NO; + borderView.layer.borderColor = [[UIColor whiteColor] CGColor]; + borderView.layer.borderWidth = 0.5f; +// borderView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f); +// borderView.layer.shadowColor = [UIColor blackColor].CGColor; +// borderView.layer.shadowRadius = 1.0; +// borderView.layer.shadowOpacity = 1.0; + borderView.alpha = 0; + borderView.frame = CGRectMake(videoView.frame.origin.y - 1, + videoView.frame.origin.x - 1, + videoView.frame.size.width + 1, + videoView.frame.size.height + 1); + + self.bodyView.frame = CGRectMake(0, videoHeight, maxW, maxH - videoHeight); +} +// ↓ +- (void) showThisView { + // only first time, SubViews add to "self.view". + // After animation, they move to "parentView" + videoView.backgroundColor = [UIColor blackColor]; + videoWrapper.backgroundColor = [UIColor blackColor]; + [pageWrapper addSubview:self.bodyView]; + [videoWrapper addSubview:videoView]; + // move subviews from "self.view" to "parentView" after animation + [self.view addSubview:pageWrapper]; + [self.view addSubview:videoWrapper]; + + transparentBlackSheet = [[UIView alloc] initWithFrame:windowFrame]; + transparentBlackSheet.backgroundColor = [UIColor blackColor]; + transparentBlackSheet.alpha = 1; + + [self appearAnimation]; +} +// ↓ +- (void) appearAnimation { + + self.view.frame = CGRectMake(windowFrame.size.width - 50, + windowFrame.size.height - 50, + windowFrame.size.width, + windowFrame.size.height); + self.view.transform = CGAffineTransformMakeScale(0.2, 0.2); + self.view.alpha = 0; + [UIView animateWithDuration:0.2 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + self.view.transform = CGAffineTransformMakeScale(1.0, 1.0); + self.view.alpha = 1; + self.view.frame = CGRectMake(windowFrame.origin.x, + windowFrame.origin.y, + windowFrame.size.width, + windowFrame.size.height); + } + completion:^(BOOL finished) { + [self afterAppearAnimation]; + }]; +} +// ↓ +-(void) afterAppearAnimation { + videoView.backgroundColor = videoWrapper.backgroundColor = [UIColor clearColor]; + + +// [parentView addSubview:transparentBlackSheet]; + // move from self.view +// [parentView addSubview:pageWrapper]; +// [parentView addSubview:videoWrapper]; + + [[self getWindow] addSubview:transparentBlackSheet]; + [[self getWindow] addSubview:pageWrapper]; + [[self getWindow] addSubview:videoWrapper]; + + + self.view.hidden = TRUE; + + [videoView addSubview:borderView]; + + [videoWrapper addSubview:self.controllerView]; + + self.messageView.hidden = TRUE; + [videoWrapper addSubview:self.messageView]; + + [self showControllerView]; + + UITapGestureRecognizer* expandedTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapExpandedVideoView)]; + expandedTap.numberOfTapsRequired = 1; + expandedTap.delegate = self; + [videoWrapper addGestureRecognizer:expandedTap]; + + vFrame = videoWrapperFrame; + wFrame = pageWrapperFrame; + + // adding Pan Gesture + UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)]; + pan.delegate = self; + [videoWrapper addGestureRecognizer:pan]; + + isExpandedMode = TRUE; +} + + + + + + +- (void) disappear { + isAppear = false; +// [self.delegate removeDraggableFloatingViewController]; +} + + +- (void) reAppearWithAnimation { + borderView.alpha = 0; + transparentBlackSheet.alpha = 0; + + videoWrapper.alpha = 0; + pageWrapper.alpha = 0; + + pageWrapper.frame = pageWrapperFrame; + videoWrapper.frame = videoWrapperFrame; + videoView.frame = videoWrapperFrame; + self.controllerView.frame = videoView.frame; + self.bodyView.frame = CGRectMake(0, + videoView.frame.size.height,// keep stay on bottom of videoView + self.bodyView.frame.size.width, + self.bodyView.frame.size.height); + borderView.frame = CGRectMake(videoView.frame.origin.y - 1, + videoView.frame.origin.x - 1, + videoView.frame.size.width + 1, + videoView.frame.size.height + 1); + + // parentViewにのってるViewは pageWrapper と videoWrapper と transparentView + // pageWrapper と videoWrapper をself.viewと同様のアニメーションをさせた後に、parentViewに戻す + // transparentView は あとで1にすればいい + pageWrapper.frame = CGRectMake(windowFrame.size.width - 50, + windowFrame.size.height - 150, + pageWrapper.frame.size.width, + pageWrapper.frame.size.height); +// pageWrapper.transform = CGAffineTransformMakeScale(0.2, 0.2); + + videoWrapper.frame = CGRectMake(windowFrame.size.width - 50, + windowFrame.size.height - 150, + videoWrapper.frame.size.width, + videoWrapper.frame.size.height); +// videoWrapper.transform = CGAffineTransformMakeScale(0.2, 0.2); + + [UIView animateWithDuration:0.5 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { +// pageWrapper.transform = CGAffineTransformMakeScale(1.0, 1.0); + pageWrapper.alpha = 1; + pageWrapper.frame = CGRectMake(windowFrame.origin.x, + windowFrame.origin.y, + pageWrapper.frame.size.width, + pageWrapper.frame.size.height); + +// videoWrapper.transform = CGAffineTransformMakeScale(1.0, 1.0); + videoWrapper.alpha = 1; + videoWrapper.frame = CGRectMake(windowFrame.origin.x, + windowFrame.origin.y, + videoWrapper.frame.size.width, + videoWrapper.frame.size.height); + + } + completion:^(BOOL finished) { + + transparentBlackSheet.alpha = 1.0; + + for (UIGestureRecognizer *recognizer in videoWrapper.gestureRecognizers) { + if([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { + [videoWrapper removeGestureRecognizer:recognizer]; + } + } + UITapGestureRecognizer* expandedTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapExpandedVideoView)]; + expandedTap.numberOfTapsRequired = 1; + expandedTap.delegate = self; + [videoWrapper addGestureRecognizer:expandedTap]; + + isExpandedMode = TRUE; + [self didExpand]; + [self didReAppear]; + }]; +} + + + +- (void) bringToFront { +// [parentView addSubview:self.view];// then, "viewDidLoad" called +// [parentView addSubview:transparentBlackSheet]; +// [parentView addSubview:pageWrapper]; +// [parentView addSubview:videoWrapper]; + if (isSetuped) { + [[self getWindow] bringSubviewToFront:self.view]; + [[self getWindow] bringSubviewToFront:transparentBlackSheet]; + [[self getWindow] bringSubviewToFront:pageWrapper]; + [[self getWindow] bringSubviewToFront:videoWrapper]; + } +} +// +//- (void) changeParentVC: (UIViewController*) parentVC { +//// if (isSetuped) { +//// parentView = parentVC.view; +//// [parentView addSubview:self.view];// then, "viewDidLoad" called +//// [parentView addSubview:transparentBlackSheet]; +//// [parentView addSubview:pageWrapper]; +//// [parentView addSubview:videoWrapper]; +//// } +//} +// + +- (UIWindow *) getWindow { + return [[[UIApplication sharedApplication] delegate] window]; +} + + +-(void)removeAllViews +{ + [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; + [videoWrapper removeFromSuperview]; + [pageWrapper removeFromSuperview]; + [transparentBlackSheet removeFromSuperview]; + [self.view removeFromSuperview]; +} + +- (void)dealloc +{ + // NSLog(@"dealloc DraggableFloatingViewController"); +} + + + + + + + + + +-(void) showMessageView { + self.messageView.hidden = FALSE; +} +-(void) hideMessageView { + self.messageView.hidden = TRUE; +} + + + +-(void) setHideControllerTimer { + if ([hideControllerTimer isValid]) { + [hideControllerTimer invalidate]; + } + hideControllerTimer = [NSTimer scheduledTimerWithTimeInterval:3.0f + target:self + selector:@selector(hideControllerView) + userInfo:nil + repeats:NO]; +} +-(void) showControllerView { + NSLog(@"showControllerView"); + isDisplayController = true; + [self setHideControllerTimer]; + [UIView animateWithDuration:0.5 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + self.controllerView.alpha = 1.0; + } + completion:^(BOOL finished) { + }]; +} +-(void) hideControllerView { + NSLog(@"hideControllerView"); + isDisplayController = false; + if ([hideControllerTimer isValid]) { + [hideControllerTimer invalidate]; + } + [UIView animateWithDuration:0.5 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + self.controllerView.alpha = 0.0; + } + completion:^(BOOL finished) { + }]; +} + + + + + + + + + + + + +- (void) showControllerAfterExpanded { + [NSTimer scheduledTimerWithTimeInterval:0.5f + target:self + selector:@selector(showControllerView) + userInfo:nil + repeats:NO]; +} + + + + +# pragma mark - tap action +//- (void) onTapDownButton { +// [self minimizeView]; +//} + + +- (void) onTapExpandedVideoView { + NSLog(@"onTapExpandedVideoView"); + if (self.controllerView.alpha == 0.0) { + [self showControllerView]; + } + else if (self.controllerView.alpha == 1.0){ + [self hideControllerView]; + } +} + +- (void)expandViewOnTap:(UITapGestureRecognizer*)sender { + [self expandView]; + [self showControllerAfterExpanded]; + +} + + + +#pragma mark- Pan Gesture Selector Action + +-(void)panAction:(UIPanGestureRecognizer *)recognizer +{ + CGFloat touchPosInViewY = [recognizer locationInView:self.view].y; + + + if(recognizer.state == UIGestureRecognizerStateBegan) { + + direction = UIPanGestureRecognizerDirectionUndefined; + //storing direction + CGPoint velocity = [recognizer velocityInView:recognizer.view]; + [self detectPanDirection:velocity]; + + isMinimizingByGesture = false; + //Snag the Y position of the touch when panning begins + _touchPositionInHeaderY = [recognizer locationInView:videoWrapper].y; + _touchPositionInHeaderX = [recognizer locationInView:videoWrapper].x; + if(direction == UIPanGestureRecognizerDirectionDown) { + if(videoView.frame.size.height > minimamVideoHeight) { + // player.controlStyle = MPMovieControlStyleNone; + NSLog(@"minimize gesture start"); + isMinimizingByGesture = true; + [self didStartMinimizeGesture]; + } + } + } + + + else if(recognizer.state == UIGestureRecognizerStateChanged) { + if(direction == UIPanGestureRecognizerDirectionDown || direction == UIPanGestureRecognizerDirectionUp) { + +// CGFloat appendY = 20; +// if (direction == UIPanGestureRecognizerDirectionUp) appendY = -appendY; + + CGFloat newOffsetY = touchPosInViewY - _touchPositionInHeaderY;// + appendY; + + // CGFloat newOffsetX = newOffsetY * 0.35; + [self adjustViewOnVerticalPan:newOffsetY recognizer:recognizer]; + } + else if (direction==UIPanGestureRecognizerDirectionRight || direction==UIPanGestureRecognizerDirectionLeft) { + [self adjustViewOnHorizontalPan:recognizer]; + } + } + + + + else if(recognizer.state == UIGestureRecognizerStateEnded) { + + CGPoint velocity = [recognizer velocityInView:recognizer.view]; + + if(direction == UIPanGestureRecognizerDirectionDown || direction == UIPanGestureRecognizerDirectionUp) + { + if(velocity.y < -flickVelocity) + { +// NSLog(@"flick up"); + [self expandView]; + if (isMinimizingByGesture == false) { + [self showControllerAfterExpanded]; + } + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + return; + } + else if(velocity.y > flickVelocity) + { +// NSLog(@"flick down"); + [self minimizeView]; + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + return; + } + else if(recognizer.view.frame.origin.y>(windowFrame.size.width/2)) + { + [self minimizeView]; + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + return; + } + else if(recognizer.view.frame.origin.y < (windowFrame.size.width/2) || recognizer.view.frame.origin.y < 0) + { + [self expandView]; + if (isMinimizingByGesture == false) { + [self showControllerAfterExpanded]; + } + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + return; + } + } + + else if (direction==UIPanGestureRecognizerDirectionLeft) + { + if(pageWrapper.alpha <= 0) + { + if(velocity.x < -flickVelocity || pageWrapper.alpha < 0.3) + { + [self fadeOutViewToLeft:recognizer completion: ^{ + [self disappear]; + }]; + return; + } + else if(recognizer.view.frame.origin.x < 0) + { + [self disappear]; + } + else + { + [self animateMiniViewToNormalPosition:recognizer completion:nil]; + + } + } + } + + else if (direction==UIPanGestureRecognizerDirectionRight) + { + if(pageWrapper.alpha <= 0) + { + if(velocity.x > flickVelocity) + { + [self fadeOutViewToRight:recognizer completion: ^{ + [self disappear]; + }]; + return; + } + if(recognizer.view.frame.origin.x > windowFrame.size.width - 50) + { + [self disappear]; + } + else + { + [self animateMiniViewToNormalPosition:recognizer completion:nil]; + } + } + } + + isMinimizingByGesture = false; + } +} + + +-(void)detectPanDirection:(CGPoint )velocity +{ +// foldButton.hidden=TRUE; + BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x); + + if (isVerticalGesture) + { + if (velocity.y > 0) { + direction = UIPanGestureRecognizerDirectionDown; + + } else { + direction = UIPanGestureRecognizerDirectionUp; + } + } + else + { + if(velocity.x > 0) + { + direction = UIPanGestureRecognizerDirectionRight; + } + else + { + direction = UIPanGestureRecognizerDirectionLeft; + } + } +} + + + +-(void)adjustViewOnVerticalPan:(CGFloat)newOffsetY recognizer:(UIPanGestureRecognizer *)recognizer +{ + CGFloat touchPosInViewY = [recognizer locationInView:self.view].y; + + CGFloat progressRate = newOffsetY / finalViewOffsetY; + + if(progressRate >= 0.99) { + progressRate = 1; + newOffsetY = finalViewOffsetY; + } + + [self calcNewFrameWithParsentage:progressRate newOffsetY:newOffsetY]; + + if (progressRate <= 1 && pageWrapper.frame.origin.y >= 0) { + pageWrapper.frame = wFrame; + videoWrapper.frame = vFrame; + videoView.frame = CGRectMake( + videoView.frame.origin.x, videoView.frame.origin.x, + vFrame.size.width, vFrame.size.height + ); + self.bodyView.frame = CGRectMake( + 0, + videoView.frame.size.height,// keep stay on bottom of videoView + self.bodyView.frame.size.width, + self.bodyView.frame.size.height + ); + + borderView.frame = CGRectMake(videoView.frame.origin.y - 1, + videoView.frame.origin.x - 1, + videoView.frame.size.width + 1, + videoView.frame.size.height + 1); + + self.controllerView.frame = videoView.frame; + + CGFloat percentage = touchPosInViewY / windowFrame.size.height; + + pageWrapper.alpha = transparentBlackSheet.alpha = 1.0 - (percentage * 1.5); + if (percentage > 0.2) borderView.alpha = percentage; + else borderView.alpha = 0; + + if (isDisplayController) { + self.controllerView.alpha = 1.0 - (percentage * 2); +// if (percentage > 0.2) borderView.alpha = percentage; +// else borderView.alpha = 0; + } + + if(direction==UIPanGestureRecognizerDirectionDown) + { +// [parentView bringSubviewToFront:self.view]; + [self bringToFront]; + } + + + if(direction==UIPanGestureRecognizerDirectionUp && videoView.frame.origin.y <= 10) + { + [self didFullExpandByGesture]; + } + } + // what is this case...? + else if (wFrame.origin.y < finalViewOffsetY && wFrame.origin.y > 0) + { + pageWrapper.frame = wFrame; + videoWrapper.frame = vFrame; + videoView.frame=CGRectMake( videoView.frame.origin.x, videoView.frame.origin.x, vFrame.size.width, vFrame.size.height); + + self.bodyView.frame = CGRectMake( + 0, + videoView.frame.size.height,// keep stay on bottom of videoView + self.bodyView.frame.size.width, + self.bodyView.frame.size.height + ); + borderView.frame = CGRectMake(videoView.frame.origin.y - 1, + videoView.frame.origin.x - 1, + videoView.frame.size.width + 1, + videoView.frame.size.height + 1); + + borderView.alpha = progressRate; + + self.controllerView.frame = videoView.frame; + } + + + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + +} + + + + +-(void)adjustViewOnHorizontalPan:(UIPanGestureRecognizer *)recognizer { + // [self.txtViewGrowing resignFirstResponder]; + if(pageWrapper.alpha<=0) { + + CGFloat x = [recognizer locationInView:self.view].x; + + if (direction==UIPanGestureRecognizerDirectionLeft) + { +// NSLog(@"recognizer x=%f",recognizer.view.frame.origin.x); + CGPoint velocity = [recognizer velocityInView:recognizer.view]; + + BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x); + + + CGPoint translation = [recognizer translationInView:recognizer.view]; + + recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, + recognizer.view.center.y ); + + + if (!isVerticalGesture) { + + CGFloat percentage = (x/windowFrame.size.width); + + recognizer.view.alpha = percentage; + + } + + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + } + else if (direction==UIPanGestureRecognizerDirectionRight) + { +// NSLog(@"recognizer x=%f",recognizer.view.frame.origin.x); + CGPoint velocity = [recognizer velocityInView:recognizer.view]; + + BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x); + + CGPoint translation = [recognizer translationInView:recognizer.view]; + + recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, + recognizer.view.center.y ); + + if (!isVerticalGesture) { + + if(velocity.x > 0) + { + + CGFloat percentage = (x/windowFrame.size.width); + recognizer.view.alpha =1.0- percentage; } + else + { + CGFloat percentage = (x/windowFrame.size.width); + recognizer.view.alpha =percentage; + + + } + + } + + [recognizer setTranslation:CGPointZero inView:recognizer.view]; + } + } +} + + +- (void) calcNewFrameWithParsentage:(CGFloat) persentage newOffsetY:(CGFloat) newOffsetY{ + CGFloat newWidth = minimamVideoWidth + ((maxW - minimamVideoWidth) * (1 - persentage)); + CGFloat newHeight = newWidth * videoHeightRatio; + + CGFloat newOffsetX = maxW - newWidth - (finalMargin * persentage); + + vFrame.size.width = newWidth;//self.view.bounds.size.width - xOffset; + vFrame.size.height = newHeight;//(200 - xOffset * 0.5); + + vFrame.origin.y = newOffsetY;//trueOffset - finalMargin * 2; + wFrame.origin.y = newOffsetY; + + vFrame.origin.x = newOffsetX;//maxW - vFrame.size.width - finalMargin; + wFrame.origin.x = newOffsetX; + // vFrame.origin.y = realNewOffsetY;//trueOffset - finalMargin * 2; + // wFrame.origin.y = realNewOffsetY; + +} + +-(void) setFinalFrame { + vFrame.size.width = minimamVideoWidth;//self.view.bounds.size.width - xOffset; + // ↓ + vFrame.size.height = vFrame.size.width * videoHeightRatio;//(200 - xOffset * 0.5); + vFrame.origin.y = maxH - vFrame.size.height - finalMargin;//trueOffset - finalMargin * 2; + vFrame.origin.x = maxW - vFrame.size.width - finalMargin; + wFrame.origin.y = vFrame.origin.y; + wFrame.origin.x = vFrame.origin.x; +} + + + + + + + + + +# pragma mark - animations + +-(void)expandView +{ + // [self.txtViewGrowing resignFirstResponder]; + [UIView animateWithDuration:0.5 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + pageWrapper.frame = pageWrapperFrame; + videoWrapper.frame = videoWrapperFrame; + videoWrapper.alpha = 1; + videoView.frame = videoWrapperFrame; + pageWrapper.alpha = 1.0; + transparentBlackSheet.alpha = 1.0; + borderView.alpha = 0.0; + + self.bodyView.frame = CGRectMake(0, + videoView.frame.size.height,// keep stay on bottom of videoView + self.bodyView.frame.size.width, + self.bodyView.frame.size.height); + + borderView.frame = CGRectMake(videoView.frame.origin.y - 1, + videoView.frame.origin.x - 1, + videoView.frame.size.width + 1, + videoView.frame.size.height + 1); + + self.controllerView.frame = videoView.frame; + } + completion:^(BOOL finished) { + + for (UIGestureRecognizer *recognizer in videoWrapper.gestureRecognizers) { + if([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { + [videoWrapper removeGestureRecognizer:recognizer]; + } + } + + UITapGestureRecognizer* expandedTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapExpandedVideoView)]; + expandedTap.numberOfTapsRequired = 1; + expandedTap.delegate = self; + [videoWrapper addGestureRecognizer:expandedTap]; + + + // player.controlStyle = MPMovieControlStyleDefault; + // [self showVideoControl]; + isExpandedMode = TRUE; +// self.controllerView.hidden = FALSE; + [self didExpand]; + }]; +} + + + +-(void)minimizeView +{ +// self.controllerView.hidden = TRUE; + + [self setFinalFrame]; + [self hideControllerView]; + + [UIView animateWithDuration:0.5 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + pageWrapper.frame = wFrame; + videoWrapper.frame = vFrame; + videoView.frame=CGRectMake( videoView.frame.origin.x, videoView.frame.origin.x, vFrame.size.width, vFrame.size.height); + pageWrapper.alpha=0; + transparentBlackSheet.alpha=0.0; + borderView.alpha = 1.0; + + borderView.frame = CGRectMake(videoView.frame.origin.y - 1, + videoView.frame.origin.x - 1, + videoView.frame.size.width + 1, + videoView.frame.size.height + 1); + + self.controllerView.frame = videoView.frame; + } + completion:^(BOOL finished) { +// [self hideVideoControl]; + [self didMinimize]; + //add tap gesture + tapRecognizer = nil; + if(tapRecognizer == nil) + { + + for (UIGestureRecognizer *recognizer in videoWrapper.gestureRecognizers) { + if([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { + [videoWrapper removeGestureRecognizer:recognizer]; + } + } + + tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(expandViewOnTap:)]; + tapRecognizer.numberOfTapsRequired = 1; + tapRecognizer.delegate = self; + [videoWrapper addGestureRecognizer:tapRecognizer]; + } + + isExpandedMode=FALSE; + minimizedVideoFrame = videoWrapper.frame; + + if(direction==UIPanGestureRecognizerDirectionDown) + { +// [parentView bringSubviewToFront:self.view]; + [self bringToFront]; + } + }]; +} + +-(void)animateMiniViewToNormalPosition:(UIPanGestureRecognizer *)recognizer completion:(void (^)())completion { + + [self setFinalFrame]; + + [UIView animateWithDuration:0.25 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + pageWrapper.frame = wFrame; + videoWrapper.frame = vFrame; + videoView.frame=CGRectMake( + videoView.frame.origin.x, + videoView.frame.origin.x, + vFrame.size.width, + vFrame.size.height + ); + pageWrapper.alpha = 0; + videoWrapper.alpha = 1; + borderView.alpha = 1; + + self.controllerView.frame = videoView.frame; + } + completion:^(BOOL finished) { + if (completion) completion(); + }]; + [recognizer setTranslation:CGPointZero inView:recognizer.view]; +} + +-(void)fadeOutViewToRight:(UIPanGestureRecognizer *)recognizer completion:(void (^)())completion { +// [self.txtViewGrowing resignFirstResponder]; + + vFrame.origin.x = maxW + minimamVideoWidth; + wFrame.origin.x = maxW + minimamVideoWidth; + + [UIView animateWithDuration:0.1 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + pageWrapper.frame = wFrame; + videoWrapper.frame = vFrame; + videoView.frame=CGRectMake( videoView.frame.origin.x, videoView.frame.origin.x, vFrame.size.width, vFrame.size.height); + pageWrapper.alpha = 0; + videoWrapper.alpha = 0; + borderView.alpha = 0; + + self.controllerView.frame = videoView.frame; + } + completion:^(BOOL finished) { + if (completion) completion(); + [self didDisappear]; + }]; + [recognizer setTranslation:CGPointZero inView:recognizer.view]; +} + +-(void)fadeOutViewToLeft:(UIPanGestureRecognizer *)recognizer completion:(void (^)())completion { +// [self.txtViewGrowing resignFirstResponder]; + + vFrame.origin.x = -maxW; + wFrame.origin.x = -maxW; + + [UIView animateWithDuration:0.1 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + pageWrapper.frame = wFrame; + videoWrapper.frame = vFrame; + videoView.frame=CGRectMake( videoView.frame.origin.x, videoView.frame.origin.x, vFrame.size.width, vFrame.size.height); + pageWrapper.alpha = 0; + videoWrapper.alpha = 0; + borderView.alpha = 0; + + self.controllerView.frame = videoView.frame; + } + completion:^(BOOL finished) { + if (completion) completion(); + [self didDisappear]; + }]; + + [recognizer setTranslation:CGPointZero inView:recognizer.view]; +} + + +#pragma mark- Pan Gesture Delagate + +- (BOOL)gestureRecognizerShould:(UIGestureRecognizer *)gestureRecognizer { + if(gestureRecognizer.view.frame.origin.y < 0) + { + return NO; + } + else { + return YES; + } +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + return YES; +} + + + +#pragma mark- Status Bar Hidden function + +- (BOOL)prefersStatusBarHidden { + return YES; +} +- (UIInterfaceOrientationMask) supportedInterfaceOrientations { + return UIInterfaceOrientationMaskPortrait; +} +- (BOOL)shouldAutorotate +{ + return NO; +} + +@end diff --git a/YouTubeDraggableVideo/VideoController/BSVideoDetailController.h b/YouTubeDraggableVideo/VideoController/BSVideoDetailController.h deleted file mode 100644 index 7522c86..0000000 --- a/YouTubeDraggableVideo/VideoController/BSVideoDetailController.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// BSVideoDetailController.h -// YouTubeDraggableVideo -// -// Created by Sandeep Mukherjee on 02/02/15. -// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. -// - -#import -#import - - -@protocol RemoveViewDelegate -- (void)removeController; -@end - -typedef NS_ENUM(NSUInteger, UIPanGestureRecognizerDirection) { - UIPanGestureRecognizerDirectionUndefined, - UIPanGestureRecognizerDirectionUp, - UIPanGestureRecognizerDirectionDown, - UIPanGestureRecognizerDirectionLeft, - UIPanGestureRecognizerDirectionRight -}; - -@interface BSVideoDetailController : UIViewController -@property (nonatomic, assign) id delegate; -@property (weak, nonatomic) IBOutlet UIView *viewYouTube; -@property (weak, nonatomic) IBOutlet UIView *viewTable; - -@property (strong, nonatomic) MPMoviePlayerController *player; -@property (weak, nonatomic) IBOutlet UIView *viewShare; -@property (weak, nonatomic) IBOutlet UIView *viewGrowingTextView; -@property (weak, nonatomic) IBOutlet UITableView *tblView; -@property (weak, nonatomic) IBOutlet UIButton *btnDown; -- (IBAction)btnDownTapAction:(id)sender; -@property (weak, nonatomic) IBOutlet UITextView *txtViewGrowing; -- (IBAction)btnSendAction:(id)sender; - - -@property(nonatomic)CGRect initialFirstViewFrame; -@property(nonatomic,strong) UIPanGestureRecognizer *panRecognizer; -@property(nonatomic,strong) UITapGestureRecognizer *tapRecognizer; -@property (weak, nonatomic) IBOutlet NSLayoutConstraint *btnDownBottomLayout; --(void)removeView; -@property(nonatomic,strong) UIView *onView; -@end diff --git a/YouTubeDraggableVideo/VideoController/BSVideoDetailController.m b/YouTubeDraggableVideo/VideoController/BSVideoDetailController.m deleted file mode 100644 index 63070c9..0000000 --- a/YouTubeDraggableVideo/VideoController/BSVideoDetailController.m +++ /dev/null @@ -1,844 +0,0 @@ -// -// BSVideoDetailController.m -// YouTubeDraggableVideo -// -// Created by Sandeep Mukherjee on 02/02/15. -// Copyright (c) 2015 Sandeep Mukherjee. All rights reserved. -// - - -#import "BSVideoDetailController.h" -#import "QuartzCore/CALayer.h" - - - - - - -@interface BSVideoDetailController () - -@end - -@implementation BSVideoDetailController -{ - - - - //local Frame store - CGRect youtubeFrame; - CGRect tblFrame; - CGRect menuFrame; - CGRect viewFrame; - CGRect minimizedYouTubeFrame; - CGRect growingTextViewFrame;; - - //local touch location - CGFloat _touchPositionInHeaderY; - CGFloat _touchPositionInHeaderX; - - //local restriction Offset--- for checking out of bound - float restrictOffset,restrictTrueOffset,restictYaxis; - - //detecting Pan gesture Direction - UIPanGestureRecognizerDirection direction; - - - //Creating a transparent Black layer view - UIView *transaparentVw; - - //Just to Check wether view is expanded or not - BOOL isExpandedMode; - - - - -} -@synthesize player; - - - -- (void)viewDidLoad { - [super viewDidLoad]; - - - // [[BSUtils sharedInstance] showLoadingMode:self]; - - //adding demo Video -- giving a little delay to store correct frame size - [self performSelector:@selector(addVideo) withObject:nil afterDelay:0.8]; - - //adding Pan Gesture - UIPanGestureRecognizer *pan=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)]; - pan.delegate=self; - [self.viewYouTube addGestureRecognizer:pan]; - //setting view to Expanded state - isExpandedMode=TRUE; - - self.btnDown.hidden=TRUE; - - - - - - -} - -#pragma mark- Status Bar Hidden function - -- (BOOL)prefersStatusBarHidden { - return YES; -} -- (NSUInteger) supportedInterfaceOrientations { - - return UIInterfaceOrientationMaskPortrait; - -} -- (BOOL)shouldAutorotate -{ - return NO; -} - -#pragma mark- Add Video on View --(void)addVideo -{ - - NSURL *urlString = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sample" ofType:@"mp4"]]; - player = [[MPMoviePlayerController alloc] initWithContentURL:urlString]; - - [player.view setFrame:self.viewYouTube.frame]; - player.controlStyle = MPMovieControlStyleNone; - player.shouldAutoplay=YES; - player.repeatMode = NO; - player.scalingMode = MPMovieScalingModeAspectFit; - - [self.viewYouTube addSubview:player.view]; - [player prepareToPlay]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(MPMoviePlayerLoadStateDidChange:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil]; - [self calculateFrames]; - - -} -#pragma mark- Calculate Frames and Store Frame Size --(void)calculateFrames -{ - youtubeFrame=self.viewYouTube.frame; - tblFrame=self.viewTable.frame; - [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; - - self.viewYouTube.translatesAutoresizingMaskIntoConstraints = YES; - self.viewTable.translatesAutoresizingMaskIntoConstraints = YES; - CGRect frame=self.viewGrowingTextView.frame; - growingTextViewFrame=self.viewGrowingTextView.frame; - self.viewGrowingTextView.translatesAutoresizingMaskIntoConstraints = YES; - self.viewGrowingTextView.frame=frame; - frame=self.txtViewGrowing.frame; - self.txtViewGrowing.translatesAutoresizingMaskIntoConstraints = YES; - self.txtViewGrowing.frame=frame; - - - - - - self.viewYouTube.frame=youtubeFrame; - self.viewTable.frame=tblFrame; - menuFrame=self.viewTable.frame; - viewFrame=self.viewYouTube.frame; - self.player.view.backgroundColor=self.viewYouTube.backgroundColor=[UIColor clearColor]; - //self.player.view.layer.shouldRasterize=YES; - // self.viewYouTube.layer.shouldRasterize=YES; - //self.viewTable.layer.shouldRasterize=YES; - - restrictOffset=self.initialFirstViewFrame.size.width-200; - restrictTrueOffset = self.initialFirstViewFrame.size.height - 180; - restictYaxis=self.initialFirstViewFrame.size.height-self.viewYouTube.frame.size.height; - - //[[BSUtils sharedInstance] hideLoadingMode:self]; - self.view.hidden=TRUE; - transaparentVw=[[UIView alloc]initWithFrame:self.initialFirstViewFrame]; - transaparentVw.backgroundColor=[UIColor blackColor]; - transaparentVw.alpha=0.9; - [self.onView addSubview:transaparentVw]; - - [self.onView addSubview:self.viewTable]; - [self.onView addSubview:self.viewYouTube]; - [self stGrowingTextViewProperty]; - [self.player.view addSubview:self.btnDown]; - - - - //animate Button Down - - - self.btnDown.translatesAutoresizingMaskIntoConstraints = YES; - self.btnDown.frame=CGRectMake( self.btnDown.frame.origin.x, self.btnDown.frame.origin.y-22, self.btnDown.frame.size.width, self.btnDown.frame.size.width); - CGRect frameBtnDown=self.btnDown.frame; - - [UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat|UIViewAnimationOptionAllowUserInteraction animations:^{ - [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{ - self.btnDown.transform=CGAffineTransformMakeScale(1.5, 1.5); - - [self addShadow]; - self.btnDown.frame=CGRectMake(frameBtnDown.origin.x, frameBtnDown.origin.y+17, frameBtnDown.size.width, frameBtnDown.size.width); - - - }]; - [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{ - self.btnDown.frame=CGRectMake(frameBtnDown.origin.x, frameBtnDown.origin.y, frameBtnDown.size.width, frameBtnDown.size.width); - self.btnDown.transform=CGAffineTransformIdentity; - [self addShadow]; - }]; - } completion:nil]; - -} --(void)addShadow -{ - self.btnDown.imageView.layer.shadowColor = [UIColor whiteColor].CGColor; - self.btnDown.imageView.layer.shadowOffset = CGSizeMake(0, 1); - self.btnDown.imageView.layer.shadowOpacity = 1; - self.btnDown.imageView.layer.shadowRadius = 4.0; - self.btnDown.imageView.clipsToBounds = NO; -} -#pragma mark- MPMoviePlayerLoadStateDidChange Notification -- (void)MPMoviePlayerLoadStateDidChange:(NSNotification *)notification { - - if ((player.loadState & MPMovieLoadStatePlaythroughOK) == MPMovieLoadStatePlaythroughOK) { - //add your code - NSLog(@"Playing OK"); - self.btnDown.hidden=FALSE; - - //[self.btnDown bringSubviewToFront:self.player.view]; - - - } - NSLog(@"loadState=%lu",player.loadState); - //[self.btnDown bringSubviewToFront:self.player.view]; - -} - - - - - -#pragma mark- Pan Gesture Delagate - -- (BOOL)gestureRecognizerShould:(UIGestureRecognizer *)gestureRecognizer { - - if(gestureRecognizer.view.frame.origin.y<0) - { - return NO; - } - return YES; - -} - -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer -{ - return YES; -} - - -#pragma mark- Pan Gesture Selector Action - --(void)panAction:(UIPanGestureRecognizer *)recognizer -{ - - CGFloat y = [recognizer locationInView:self.view].y; - - if(recognizer.state == UIGestureRecognizerStateBegan){ - - direction = UIPanGestureRecognizerDirectionUndefined; - //storing direction - CGPoint velocity = [recognizer velocityInView:recognizer.view]; - [self detectPanDirection:velocity]; - - //Snag the Y position of the touch when panning begins - _touchPositionInHeaderY = [recognizer locationInView:self.viewYouTube].y; - _touchPositionInHeaderX = [recognizer locationInView:self.viewYouTube].x; - if(direction==UIPanGestureRecognizerDirectionDown) - { - player.controlStyle=MPMovieControlStyleNone; - - } - - } - else if(recognizer.state == UIGestureRecognizerStateChanged){ - - - if(direction==UIPanGestureRecognizerDirectionDown || direction==UIPanGestureRecognizerDirectionUp) - { - - CGFloat trueOffset = y - _touchPositionInHeaderY; - CGFloat xOffset = (y - _touchPositionInHeaderY)*0.35; - [self adjustViewOnVerticalPan:trueOffset :xOffset recognizer:recognizer]; - - } - else if (direction==UIPanGestureRecognizerDirectionRight || direction==UIPanGestureRecognizerDirectionLeft) - { - [self adjustViewOnHorizontalPan:recognizer]; - } - - } - else if(recognizer.state == UIGestureRecognizerStateEnded){ - - if(direction==UIPanGestureRecognizerDirectionDown || direction==UIPanGestureRecognizerDirectionUp) - { - - if(recognizer.view.frame.origin.y<0) - { - [self expandViewOnPan]; - - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - - return; - - } - else if(recognizer.view.frame.origin.y>(self.initialFirstViewFrame.size.width/2)) - { - - [self minimizeViewOnPan]; - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - return; - - - } - else if(recognizer.view.frame.origin.y<(self.initialFirstViewFrame.size.width/2)) - { - [self expandViewOnPan]; - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - return; - - } - } - - else if (direction==UIPanGestureRecognizerDirectionLeft) - { - if(self.viewTable.alpha<=0) - { - - if(recognizer.view.frame.origin.x<0) - { - [self.view removeFromSuperview]; - [self removeView]; - [self.delegate removeController]; - - } - else - { - [self animateViewToRight:recognizer]; - - } - } - } - - else if (direction==UIPanGestureRecognizerDirectionRight) - { - if(self.viewTable.alpha<=0) - { - - - if(recognizer.view.frame.origin.x>self.initialFirstViewFrame.size.width-50) - { - [self.view removeFromSuperview]; - [self removeView]; - [self.delegate removeController]; - - } - else - { - [self animateViewToLeft:recognizer]; - - } - } - } - - - } - -} - -#pragma mark - Keyboard events - -//Handling the keyboard appear and disappering events - -- (void)keyboardWasShown:(NSNotification*)aNotification -{ - //__weak typeof(self) weakSelf = self; - NSDictionary* info = [aNotification userInfo]; - CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; - [UIView animateWithDuration:0.3f - delay:0.0f - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - float yPosition=self.view.frame.size.height- kbSize.height- self.viewGrowingTextView.frame.size.height; - self.viewGrowingTextView.frame=CGRectMake(0, yPosition, self.viewGrowingTextView.frame.size.width, self.viewGrowingTextView.frame.size.height); - - // [weakSelf.registerScrView setContentOffset:CGPointMake(0, (weakSelf.userNameTxtfld.frame.origin.y+weakSelf.userNameTxtfld.frame.size.height)-kbSize.height) animated:YES]; - - } - completion:^(BOOL finished) { - }]; - - -} - -- (void)keyboardWillBeHidden:(NSNotification*)aNotification -{ - // __weak typeof(self) weakSelf = self; - //NSDictionary* info = [aNotification userInfo]; - [UIView animateWithDuration:0.3f - delay:0.0f - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - float yPosition=self.view.frame.size.height-self.viewGrowingTextView.frame.size.height; - self.viewGrowingTextView.frame=CGRectMake(0, yPosition, self.viewGrowingTextView.frame.size.width, self.viewGrowingTextView.frame.size.height); - } - completion:^(BOOL finished) { - }]; -} -#pragma mark - -#pragma mark - Text View delegate - - -#pragma mark- View Function Methods --(void)stGrowingTextViewProperty -{ - [[NSNotificationCenter defaultCenter] removeObserver:self - name:UIContentSizeCategoryDidChangeNotification - object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; - - - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; - -} - --(void)animateViewToRight:(UIPanGestureRecognizer *)recognizer{ - [self.txtViewGrowing resignFirstResponder]; - [UIView animateWithDuration:0.25 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = menuFrame; - self.viewYouTube.frame=viewFrame; - player.view.frame=CGRectMake( player.view.frame.origin.x, player.view.frame.origin.x, viewFrame.size.width, viewFrame.size.height); - self.viewTable.alpha=0; - self.viewYouTube.alpha=1; - - - - } - completion:^(BOOL finished) { - - }]; - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - -} - --(void)animateViewToLeft:(UIPanGestureRecognizer *)recognizer{ - [self.txtViewGrowing resignFirstResponder]; - - [UIView animateWithDuration:0.25 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = menuFrame; - self.viewYouTube.frame=viewFrame; - player.view.frame=CGRectMake( player.view.frame.origin.x, player.view.frame.origin.x, viewFrame.size.width, viewFrame.size.height); - self.viewTable.alpha=0; - self.viewYouTube.alpha=1; - - - - } - completion:^(BOOL finished) { - - }]; - - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - -} - - --(void)adjustViewOnHorizontalPan:(UIPanGestureRecognizer *)recognizer { - [self.txtViewGrowing resignFirstResponder]; - CGFloat x = [recognizer locationInView:self.view].x; - - if (direction==UIPanGestureRecognizerDirectionLeft) - { - if(self.viewTable.alpha<=0) - { - - NSLog(@"recognizer x=%f",recognizer.view.frame.origin.x); - CGPoint velocity = [recognizer velocityInView:recognizer.view]; - - BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x); - - - - CGPoint translation = [recognizer translationInView:recognizer.view]; - - recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, - recognizer.view.center.y ); - - - if (!isVerticalGesture) { - - CGFloat percentage = (x/self.initialFirstViewFrame.size.width); - - recognizer.view.alpha = percentage; - - } - - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - } - } - else if (direction==UIPanGestureRecognizerDirectionRight) - { - if(self.viewTable.alpha<=0) - { - - NSLog(@"recognizer x=%f",recognizer.view.frame.origin.x); - CGPoint velocity = [recognizer velocityInView:recognizer.view]; - - BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x); - - - - CGPoint translation = [recognizer translationInView:recognizer.view]; - - recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, - recognizer.view.center.y ); - - - if (!isVerticalGesture) { - - if(velocity.x > 0) - { - - CGFloat percentage = (x/self.initialFirstViewFrame.size.width); - recognizer.view.alpha =1.0- percentage; } - else - { - CGFloat percentage = (x/self.initialFirstViewFrame.size.width); - recognizer.view.alpha =percentage; - - - } - - } - - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - } - } - - - - - -} - --(void)adjustViewOnVerticalPan:(CGFloat)trueOffset :(CGFloat)xOffset recognizer:(UIPanGestureRecognizer *)recognizer -{ - [self.txtViewGrowing resignFirstResponder]; - CGFloat y = [recognizer locationInView:self.view].y; - - if(trueOffset>=restrictTrueOffset+60||xOffset>=restrictOffset+60) - { - CGFloat trueOffset = self.initialFirstViewFrame.size.height - 100; - CGFloat xOffset = self.initialFirstViewFrame.size.width-160; - //Use this offset to adjust the position of your view accordingly - menuFrame.origin.y = trueOffset; - menuFrame.origin.x = xOffset; - menuFrame.size.width=self.initialFirstViewFrame.size.width-xOffset; - - viewFrame.size.width=self.view.bounds.size.width-xOffset; - viewFrame.size.height=200-xOffset*0.5; - viewFrame.origin.y=trueOffset; - viewFrame.origin.x=xOffset; - - - - - [UIView animateWithDuration:0.05 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = menuFrame; - self.viewYouTube.frame=viewFrame; - player.view.frame=CGRectMake( player.view.frame.origin.x, player.view.frame.origin.x, viewFrame.size.width, viewFrame.size.height); - self.viewTable.alpha=0; - - - - } - completion:^(BOOL finished) { - minimizedYouTubeFrame=self.viewYouTube.frame; - - isExpandedMode=FALSE; - }]; - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - - } - else - { - - //Use this offset to adjust the position of your view accordingly - menuFrame.origin.y = trueOffset; - menuFrame.origin.x = xOffset; - menuFrame.size.width=self.initialFirstViewFrame.size.width-xOffset; - viewFrame.size.width=self.view.bounds.size.width-xOffset; - viewFrame.size.height=200-xOffset*0.5; - viewFrame.origin.y=trueOffset; - viewFrame.origin.x=xOffset; - float restrictY=self.initialFirstViewFrame.size.height-self.viewYouTube.frame.size.height-10; - - - if (self.viewTable.frame.origin.y0) { - [UIView animateWithDuration:0.09 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = menuFrame; - self.viewYouTube.frame=viewFrame; - player.view.frame=CGRectMake( player.view.frame.origin.x, player.view.frame.origin.x, viewFrame.size.width, viewFrame.size.height); - - CGFloat percentage = y/self.initialFirstViewFrame.size.height; - self.viewTable.alpha= transaparentVw.alpha = 1.0 - percentage; - - - - - } - completion:^(BOOL finished) { - if(direction==UIPanGestureRecognizerDirectionDown) - { - [self.onView bringSubviewToFront:self.view]; - } - }]; - } - else if (menuFrame.origin.y0) - { - [UIView animateWithDuration:0.09 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = menuFrame; - self.viewYouTube.frame=viewFrame; - player.view.frame=CGRectMake( player.view.frame.origin.x, player.view.frame.origin.x, viewFrame.size.width, viewFrame.size.height); - }completion:nil]; - - - } - - [recognizer setTranslation:CGPointZero inView:recognizer.view]; - } - -} --(void)detectPanDirection:(CGPoint )velocity -{ - self.btnDown.hidden=TRUE; - BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x); - - if (isVerticalGesture) { - if (velocity.y > 0) { - direction = UIPanGestureRecognizerDirectionDown; - - } else { - direction = UIPanGestureRecognizerDirectionUp; - } - } - else - - { - if(velocity.x > 0) - { - direction = UIPanGestureRecognizerDirectionRight; - } - else - { - direction = UIPanGestureRecognizerDirectionLeft; - } - - } - -} - -- (void)expandViewOnTap:(UITapGestureRecognizer*)sender { - - [self expandViewOnPan]; - for (UIGestureRecognizer *recognizer in self.viewYouTube.gestureRecognizers) { - - if([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { - [self.viewYouTube removeGestureRecognizer:recognizer]; - } - } - -} - --(void)minimizeViewOnPan -{ - self.btnDown.hidden=TRUE; - [self.txtViewGrowing resignFirstResponder]; - CGFloat trueOffset = self.initialFirstViewFrame.size.height - 100; - CGFloat xOffset = self.initialFirstViewFrame.size.width-160; - - //Use this offset to adjust the position of your view accordingly - menuFrame.origin.y = trueOffset; - menuFrame.origin.x = xOffset; - menuFrame.size.width=self.initialFirstViewFrame.size.width-xOffset; - //menuFrame.size.height=200-xOffset*0.5; - - // viewFrame.origin.y = trueOffset; - //viewFrame.origin.x = xOffset; - viewFrame.size.width=self.view.bounds.size.width-xOffset; - viewFrame.size.height=200-xOffset*0.5; - viewFrame.origin.y=trueOffset; - viewFrame.origin.x=xOffset; - - - - - [UIView animateWithDuration:0.5 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = menuFrame; - self.viewYouTube.frame=viewFrame; - player.view.frame=CGRectMake( player.view.frame.origin.x, player.view.frame.origin.x, viewFrame.size.width, viewFrame.size.height); - self.viewTable.alpha=0; - transaparentVw.alpha=0.0; - - - } - completion:^(BOOL finished) { - //add tap gesture - self.tapRecognizer=nil; - if(self.tapRecognizer==nil) - { - self.tapRecognizer= [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(expandViewOnTap:)]; - self.tapRecognizer.numberOfTapsRequired=1; - self.tapRecognizer.delegate=self; - [self.viewYouTube addGestureRecognizer:self.tapRecognizer]; - } - - isExpandedMode=FALSE; - minimizedYouTubeFrame=self.viewYouTube.frame; - - if(direction==UIPanGestureRecognizerDirectionDown) - { - [self.onView bringSubviewToFront:self.view]; - } - }]; - -} --(void)expandViewOnPan -{ - [self.txtViewGrowing resignFirstResponder]; - [UIView animateWithDuration:0.5 - delay:0.0 - options:UIViewAnimationOptionCurveEaseInOut - animations:^ { - self.viewTable.frame = tblFrame; - self.viewYouTube.frame=youtubeFrame; - self.viewYouTube.alpha=1; - player.view.frame=youtubeFrame; - self.viewTable.alpha=1.0; - transaparentVw.alpha=1.0; - - - } - completion:^(BOOL finished) { - player.controlStyle = MPMovieControlStyleDefault; - isExpandedMode=TRUE; - self.btnDown.hidden=FALSE; - }]; - - - -} - --(void)removeView -{ - [self.player stop]; - [self.viewYouTube removeFromSuperview]; - [self.viewTable removeFromSuperview]; - [transaparentVw removeFromSuperview]; - - -} - -#pragma mark - UITableViewDataSource -// number of section(s), now I assume there is only 1 section -- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView -{ - return 1; -} - -// number of row in the section, I assume there is only 1 row -- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section -{ - return 10; -} - -// the cell will be returned to the tableView -- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - static NSString *cellIdentifier = @"videoCommentCell"; - - - UITableViewCell *cell; - cell = (UITableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier]; - if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; - } - - cell.backgroundColor = [UIColor clearColor]; - cell.contentView.backgroundColor = [UIColor clearColor]; - - - cell.selectionStyle=UITableViewCellSelectionStyleNone; - - - return cell; -} -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - - return 88.0; - - -} - -#pragma mark - UITableViewDelegate -// when user tap the row, what action you want to perform -- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSLog(@"selected %ld row", (long)indexPath.row); -} -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -#pragma mark - Button Action -- (IBAction)btnDownTapAction:(id)sender { - - [self minimizeViewOnPan]; - -} -- (IBAction)btnSendAction:(id)sender { - [self.txtViewGrowing resignFirstResponder]; - self.txtViewGrowing.text=@""; - [UIView animateWithDuration:0.2f - delay:0.0f - options:UIViewAnimationOptionCurveEaseIn - animations:^{ - - self.viewGrowingTextView.frame=growingTextViewFrame; - }completion:^(BOOL finished) { - - }]; - -} -@end diff --git a/YouTubeDraggableVideo/sample.mp4 b/YouTubeDraggableVideo/sampleMovies/sample.mp4 similarity index 100% rename from YouTubeDraggableVideo/sample.mp4 rename to YouTubeDraggableVideo/sampleMovies/sample.mp4 diff --git a/YouTubeDraggableVideo/sampleMovies/test.mp4 b/YouTubeDraggableVideo/sampleMovies/test.mp4 new file mode 100644 index 0000000..0d7782b Binary files /dev/null and b/YouTubeDraggableVideo/sampleMovies/test.mp4 differ diff --git a/YouTubeDraggableVideoTests/Info.plist b/YouTubeDraggableVideoTests/Info.plist index 6d6d759..ba72822 100644 --- a/YouTubeDraggableVideoTests/Info.plist +++ b/YouTubeDraggableVideoTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.vizllx.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName