Uiview scroll with webview - html

I have a webpage in WkWebview, and in the webpage there is rect region where I want to put a UIView playing live movie. I've made the webview and uiview, but I cannot figure out how to make the uiview's position to the rect region. That's to say, when user scroll the webview, the uiview scroll also scrolls. It seems the uiview is a a part of webpage. How can I fix the uiview to webpage in webview?
Thanks for any help.

For this can you go to storyboard and see if the uiview is inside the view or not and if then drag it outside and try to set its frame in property console because if you drag and drop to set uiview frame it will be gone in subview of your uiwebview
Hope it will help you

Finally I solved this by use javascript to get the regin location of webpage. Then set the UIView to that location.
Here is the code, in the webpage the regin div has tag movie, and the uiview has name player.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.wk.evaluateJavaScript("var rect = document.getElementById('movie').getBoundingClientRect();[rect.left, rect.top];") {
(result, error) -> Void in
print(result)
self.player.view.frame.origin.x = (result as! Array)[0]
self.player.view.frame.origin.y = (result as! Array)[1]
}
}

Related

Animate UINavigationBar when pushing view controller onto stack

The Apple Music app has a nice transition when a view controller with a visible navigation bar ("My Music" view controller) has a view controller with a transparent navigation bar (An artist's view controller) pushed on to the stack.
I'm looking to recreate this transition myself.
I've set the navigationbar to be transparent with the following code:
private func _setNavigationBarVisible(isVisible isVisible: Bool)
{
title = nil
/*
Update the navigation bar's visibility.
Create a helper method to prevent running the same code twice.
*/
func _updateNavigationBarVisibility(isVisible isVisible: Bool, userViewController: UserViewController?)
{
// Create a dummy navigation bar we can rip the default values out of if it should be visible
let navigationBar = UINavigationBar()
let backgroundImage = isVisible ? navigationBar.backgroundImageForBarMetrics(.Default) : UIImage()
let shadowImage = isVisible ? navigationBar.shadowImage : UIImage()
userViewController?.navigationController?.navigationBar.setBackgroundImage(backgroundImage,
forBarMetrics: .Default)
userViewController?.navigationController?.navigationBar.shadowImage = shadowImage
}
// Animate alongside the view controller's presentation transition if there is one
let isTransitionAnimationRun = transitionCoordinator()?.animateAlongsideTransition({ [weak self] context in
_updateNavigationBarVisibility(isVisible: isVisible, userViewController: self)
}, completion: nil)
// Or just update the values if there's no transition
if isTransitionAnimationRun == false
{
_updateNavigationBarVisibility(isVisible: isVisible, userViewController: self)
}
}
This function is run in my viewWillAppear: and viewWillDisappear: methods passing false and true to the isVisible parameter respectively.
This code does achieve a similar effect, but despite the code doing what it should, I want a different effect.
Currently, this code animates the shadow image making them visible on both view controllers rather than like Apple Music where only the one that presented it should have the shadow. As for the background image, there's a visible "swipe" animation as the navigation bar's background animates from transparent to translucent.
There's also an issue with the swipe gesture which I am looking in to, but currently if during the swipe gesture you keep your finger in one position so no swiping occurs and then lift the finger, the navigationbar updates as though the swipe finished, but the view controllers become glitched and the stack is never pushed or popped despite using the fully useable navigation bar.

Open UIViewController modally from tab bar with transparent background and transition style

I've got a custom tab bar that I created using this link: https://github.com/jain-mohit/CustomTabBar. Now, I want to open a view modally after pressing a button. The opened view must be transparent, meaning I can see the view beneath it. The modal view also must a navigation bar so I can put a "Cancel" button to dismiss it. I've tried it like this:
DetailsViewController *detailViewController = [[DetailsViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:detailViewController];
nav.modalPresentationStyle = UIModalPresentationCurrentContext;
nav.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
detailViewController.view.backgroundColor = [UIColor greenColor];
detailViewController.view.alpha = 0.5f;
[self presentViewController:nav animated:YES completion:nil];
This method quite works but when opening, the view doesn't transition from bottom to top. And I also got this error:
Presenting view controllers on detached view controllers is discouraged <UINavigationController: 0x8f52280>
So, I'm looking for another way to do this. Hopefully someone can help. This method should work for iOS6, 7 and 8. Also I'm not using storyboard to do this.
Thank You.
Try to use UIWindow, instead of presenting a new ViewController:
UIWindow *w = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
w.windowLevel = UIWindowLevelAlert;
w.autoresizesSubviews = NO;
w.clipsToBounds = YES;
w.hidden = NO;
[w addSubview:detailViewController];
In this case background of your new ViewController will be transparent, but you can't use UINavigationController here...

Swipe from one ViewController to another with Swift

I'm currently trying to connect different ViewControllers with each other using Swift, but I'm stuck and would appreciate some help in order to proceed.
What I have now is a main view and when you swipe to the right you would enter another view (like Snapchat works). I've done this using the tutorial found here.
Basically I have a ContainerViewController that store two subviews in its view hierarchy. So I can swipe back and forth between Subview 1 and Subview 2 (see illustration for an idea). Subview 2 has a button that 'modally' loads another ViewController. My question is, if it is possible, how could I make it so that when I swipe left in the "modal ViewController" I would swipe back to Subview 1?
Here is my code that controls the transition from Subview 2 (BViewController) and the modal ViewController (InfoVC):
class BViewController: UIViewController, UITabBarDelegate {
#IBOutlet var item: UIBarButtonItem!
var info: InfoVC = InfoVC(nibName: "InfoVC", bundle: nil )
func tabBar( tabBar: UITabBar!, didSelectItem item: UITabBarItem!){
if item.tag == 2{ // we are in new view controller
info.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
self.presentViewController(info, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println("info hash \(info.hashValue)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
And this is my ContainerViewController class where the ScrollView/swipe mechanism is made.
class ContainerViewController: UIViewController {
// Outlet used in storyboard
#IBOutlet var scrollView: UIScrollView?;
override func viewDidLoad() {
super.viewDidLoad();
// 1) Create the three views used in the swipe
var AVc: AViewController = AViewController(nibName: "AViewController", bundle: nil)
var BVc: BViewController = BViewController(nibName: "BViewController", bundle: nil)
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hieracrhy is a stack
self.addChildViewController(BVc);
self.scrollView!.addSubview(BVc.view);
BVc.didMoveToParentViewController(self);
self.addChildViewController(AVc);
self.scrollView!.addSubview(AVc.view);
AVc.didMoveToParentViewController(self);
// 3) Set up the frames of the view controllers to align
// with eachother inside the container view
var adminFrame :CGRect = AVc.view.frame;
adminFrame.origin.x = adminFrame.width;
BVc.view.frame = adminFrame;
var BFrame :CGRect = BVc.view.frame;
BFrame.origin.x = 2*BFrame.width;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = 2 * self.view.frame.width
var scrollHeight: CGFloat = self.view.frame.size.height
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In summary:
What I can do already is to scroll from AViewController to BViewController (back and forth) and go from BViewController to InfoVC by pressing the tab bar item/button. What I then cannot figure out is to swipe backwards in InfoVC and reach AViewController with the same transition as when I swipe between AViewController and BViewController.
You need to add a UISwipeGestureRecognizer to your InfoVC. The easiest way, in Interface Builder, is to drag one from your Object Library onto your InfoVC. You'll see a new icon for it appear in the toolbar at the top of your IB scene. Select it, then in the Attributes Inspector, choose which direction you want the swipe to go--in your case, it's probably left to right.
Next, implement touchesBegan() and touchesEnded() methods in your InfoVC, and use the locations of the events to determine whether the user has swiped whatever distance you specify between the start and end points. If touchesEnded() is at least that distance away, then you can dismiss your InfoVC by removing it from its parent, BViewController.
Load the ViewController from your storyboard
Embed the BViewController in a UINavigation controller.
That will allow you to do all segues in a storyboard kind of fashion
// lets try to load them from the storyboard
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyboard.instantiateViewControllerWithIdentifier("navController") as UINavigationController
var BVc = navigationController
This will be a good first step. In your BVc prepare for Segue enabling and disabling the scrolling as it will interfere with the containerviews swiping. ReEnable it in your BVc's view did appear.
var parentVC = self.navigationController?.parentViewController as ContainerViewController
parentVC.scrollView?.scrollEnabled = false
You might have to do some additional work to re-receive swipe events in your modal, I am not sure.
I suggest using UIPageViewController, it was created for tasks like this and you can hide the dots bar by deleting these methods:
presentationCountForPageViewController
presentationIndexForPageViewController
For the button to work you need to add:
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) {
Here is a good tutorial:
https://www.youtube.com/watch?v=8bltsDG2ENQ

Need right direction for reload application by action

My scenario is a UIView Controller displays different subview programmatically... Like a game board. Now I'm in a incredible situation:
I can't find a way to reload application after the game is finish!? What I would like to do is after terminate scenario clic on IBAction for star new game. My doubt is about ViewDidLoad or call Main.
try moving your code from viewDidLoad into a new function like -(void)startGame or -(void)refreshViews: and call that function whenever you want to reload your view. even in viewDidLoad you can load your view using this function.
-(void)viewDidLoad
{
[super viewDidLoad];
[self startGame];
}
remember if you are creating allocating and add some of your subviews outside this function then they will remain visible untill and unless yu remove them from superView before calling startGame.
I solved it with this code:
(IBAction)newGame:(id)sender{
UIView *parent = self.view.superview;
[self.view removeFromSuperview];
self.view = nil; // unloads the view
[parent addSubview:self.view];
}

Keep a UIButton fixed on screen when pushing and popping UIViewController

Hi i currently have a navigation based app with a navigation controller, within the app numerous views and pushed and popped back displaying different xibs, what I would like to do is display a button fixed on the screen in the bottom right of the screen, which when tapped will take the user to a help xib,
However at the moment the button is being animated and moved into place every time I push a or pop a view, I would like the button not to move and stay on top of the views when they are being pushed and popped.
Wondering if anyone can help me, thanks, Sami.
Create a UIView Class in that create UIButton And create object of that view in all the viewcontrollers,and add it to the self.view.
using this in appdelegate will help u to show button in all the screen.
if u need handle this button, import viewcontrollerAppdelegate.h to the view controller. and use
UIAppDelegate.SettingButton.hidden=True;
or like this any. just try
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
settingButton = [UIButton buttonWithType:UIButtonTypeCustom];
[settingButton addTarget:self action:#selector(settingButtonPressed:)forControlEvents:UIControlEventTouchDown];
UIImage *buttonImage = [UIImage imageNamed:#"icon-lb.png"];
[settingButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
[settingButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
settingButton.frame = CGRectMake(265, 17, 40, 45);
settingButton.hidden=TRUE;
[self.window addSubview:settingButton];
[self.window makeKeyAndVisible];
return YES;
}
- (void)settingButtonPressed:(id) sender {
[[NSNotificationCenter defaultCenter] postNotificationName:#"settingButtonPressed" object:nil];
setting *obj = [[setting alloc] initWithNibName:#"setting" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:obj];
navController.navigationBar.tintColor=[UIColor blackColor];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[self.window addSubview:navController.view];
[navController.view setFrame:CGRectMake(0,480,320,480)];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:navController.view cache:YES];
[navController.view setFrame:CGRectMake(0,0,320,480)];
[UIView commitAnimations];
}