I am trying to mimic the tabbing system of the mobile safari app. When you go into tab mode, it looks like the page is shrinking. In my app, i have tried 3 different ways to achieve this effect.
1) capture image of the UIWebView, hide the web view and scale the image.
2) scale the UIWebView
3) apply a transform to the web view.
The first way is one of the best, except if i rotate the screen, the image is funky looking, because it ether expands the image, or shrinks the image.
The second way doesn't work, The web view does skink but it basically just zooms in on the web view content, so if your on google.com, it would zoom into the google logo or somewhere on the page, instead of keeping how it looks when not zoomed, and shrinking that.
The third way also works! except using transforms i don't see a way of controlling the x, y, width and height of the web view. i can add a translation or scale it, but with rotation, it doesnt work that well.
for portrait size of the web view on an iPhone 5 im trying to make it (64, 91.5, 192, 315), and landscape CGRectMake(113, 65, 341, 161). How can I fix this to make it scale right?
The transform approach is likely to be the best; when you apply a transform to a layer (including indirectly via the view) you instruct the GPU to do something special when compositing it. So you have free rein to do whatever you want without the view's logic on how to fit things into a particular space having any effect. As it's all a composition effect, the original pixel rendering of the view is unchanged.
However, when you rotate the device you want to adjust the view itself because what you actually want is for the web view to relayout content.
If you're just literally emulating Safari then use the view's frame to set the normal full screen layout; when you want to show the zoomed out view also apply a scaling transform and create a suitable paged scrollview to swipe between pages. If the device rotates then that should affect the frame and the scrollview but not the transform.
Related
I have a simple metal setup which draw image in the middle of MTKView. I wish I could add pinch zoom and other functionality as we have in scroll views, so i can zoom image and move it around with some thresholds.
I also don't want to implement it myself since my app will live in both Mac OS and iOS and this is twice more code to support and write.
Is there a way I could use default scroll view controlls to manipulate my projection? I mean set scroll view somehow on top of my view and get some data in delegate manner or whatever.
Any help would be appreciated!
You may want to try Metal2DScrollable sample code. The idea is that:
place MTKView behind (not a subview) UIScrollView,
Place dummy content view as a subview of UIScrollView
Make the dummy content view to be the target of zooming
Set up UIScrollView properly such as contentSize, contentInset etc.
Make both UIScrollView and dummy content view to be transparent
Calculate transform from dummy content view's bounds -> MTKView's coordinate -> device coordinate
Apply that transform when rendering with Metal
So, MTKView is not in the UIScrollView, but this tricks fools user's eyes.
https://github.com/codelynx/Metal2DScrollable
The same technique may work with macOS with some tweaks, but I haven't tried.
I have a UIViewController that overlays controls on a view presenting what the camera sees. I have a couple of scenarios I would like to allow.
For the iPad, I want to keep the controls on the right most edge of the device, by your right thumb, no matter what the device's rotation. The controls should rotate their content so that their top is always upwards (away from the ground). I don't want the camera view to rotate at all, because that would just be silly – its position & size should stay the same and its contents shouldn't rotate either.
For the iPhones, I want to keep the controls at the bottom of the device's screen, by to the home button, wherever the home button actually is. The controls should rotate their content so that up is always pointing upwards. Again, I don't want the camera view's frame or content to take part in any view rotation animation at all.
I'm using auto-layout.
I'm wondering if there is any way to describe some or all of this in a storyboard. In particular, it'd be great to be able to describe that some view positions need to autorotate (ie, the controls, on iPad), but that other views don't (the camera view).
A question from 2011 indicates this wasn't possible at the time, but perhaps things have moved on since then? If it's not directly supported, can you suggest an approach and are there some sensible places to be hooking in to autorotation to achieve this?
Ok, this isn't quite a complete answer, but I tried a few things which look promising.
First, you can create a separate set of constraints for portrait vs. landscape using the size specifiers: landscape is w Regular, h Any; portrait is w Any, h Regular (I think -- double-check these) This is accessible via the pop-up control in the bottom-center of the storyboard view. By installing different constraints for portrait and landscape, it should be possible to scale the width and height of your controls' container view so it appears to be in a constant position w.r.t. device orientation; in other words, the container doesn't actually counter-rotate -- it scales so it effectively looks like it has counter-rotated.
I got this close to working. It looks like it's doing the correct thing in the storyboard view, but when I actually run it, I get debug messages about conflicting constraints. Not sure how to fix this, but maybe play with the constraint priorities? That sometimes helps.
A second thing I (partially) tried was creating a custom container view class which counter-rotates itself to the correct position based on the device orientation (in the UIDevice class). You implement this by overriding layoutSubviews. For each orientation, you define a transform which puts it in the correct position, and set the view's transform property.
Another possible solution is to override updateConstraints in your view controller and add/remove constraints to position/scale your container to the correct place for each orientation.
For all of these, the idea is that you "force" the container to be in the correct place, but leave the subviews (the actual controls) alone. The controls should do the right thing if their constraints are independent of the specific orientation of the container view.
So, those are some ideas anyway... if they lead you to an actual solution, could you post it? I anticipate having a need for this myself.
Let's say I have a complex UIView, which is initially on the screen with quite small frame, let's say 80x80.
One of its subviews is an UIImageView displaying an image whose actual resolution is 1024x1024.
When the user tap the UIView i want the view to zoom in almost full screen so that the user can better see the image.
I know already how to scale a UIView to zoom in, my question is the following.
What's the best way to zoom in this view without pixellating the image?
I thought of these options:
I can actually set the frame of the UIView to the full screen size, and normally scale it down, so I'm sure that when it's zoomed in, it will be perfectly detailed. This solution anyway have a strong performance issue, cause moving around many of these scaled down views, will be quite an hit on the CPU/GPU.
I can do it just as I described, so small frame and scale > 1 to zoom in, but in this case will the image be displayed without pixellating?
I can actually set the frame to redisplay the view at the big/small size. In this case the detail will be good, but I have a performance hit here too, because my UIView have around 15 subviews that need complex calculation to relayout, so it's not so "fast" to set the frame.
Which is the best solution? Or do anybody have any other better solution?
Why dont you just have thumbnail representations that are 80x80, and when the user taps on any thumbnail, you transition from your current view containing all the thumbnails to a new view with the +transitionFromView:toView:duration:options:completion: method and simply display a UIImageView with the full resolution image loaded into that new view :)
I've added a UIPageViewController to my app to act as a manual for the app. When the user pops it up it shows one page in portrait and two in landscape with the spine in the middle. Since I have about 100 pages, there is a sibling view UICollectionView page selector view above it to allow jumping to a page quickly. Both the UIPageViewController and the UICollectionView sit on a backing view that contains them both.
The problem I am having with the UIPageViewController is that when the views are first rotated they seem to constrain themselves to the short dimension of the original layout. So, if it first appears in portrait, then when rotating to landscape the width of the two pages is the same as the old portrait width. Likewise, if it first appears landscape with two pages, rotating to portrait has the correct width, but the height is the height of the initial landscape height. This is consistent on any device.
When I create my content views they are all the size I desire, but for some reason they seem to be transformed by some component of UIPageViewController and I'm not grasping why it is only doing one of the two dimensions and why it is always the "short side" that is the problem.
This is one of those kinds of problem that makes me feel a bit nutty, any ideas on how I might debug it if it isn't some trivial misconfiguration?
I finally found it after a long period of debugging. The critical hint was seeing that the spine is set to the correct mid for the width of the view BEFORE the rotation for portrait to landscape. The solution was to reset the frame of the view to the new size given the orientation in willAnimateRotationToInterfaceOrientation.
I calculate the new size before I call an animation block that uses the duration passed into the method, then inside the block I have:
pageViewController.view.frame = newFrame;
When the page is rotated the view holding the content pages is shifted to the correct size and the spine is place correctly and the content fills the given area. I suppose that I ran into the problem because the complexity of the views required me to take over so many defaults, but this one was left hanging.
I am working on an diagramming application which displays boxes as subviews inside a larger view. The user can move the boxes around. I am persisting the positions of these boxes using core data into a sqlite database by holding the height, width, x and y (of the top-left corner). When I open up a diagram I am reading these values from the database and using them to set the frame of the subview within the main view.
In portrait mode this works fine and the boxes are repositioned at the correct points on the display. However, when I rotate into landscape, or start the application in landscape and open the diagram, the positions of the boxes are wrong.
I have traced through the code and can see that the correct values are coming back from the persistent store and being used to correctly set the frame. However, once the UIView for the subview is on screen it is positioned at a different location (clearly visible and confirmed by checking the values in the frame of the view).
Now the odd thing is that instead of being a fixed pixel offset, the x co-ordinate is always 8.5% larger than the value used to create the frame, and the y value is always 9.1% smaller.
Does anyone have any explanation as to why this might be and how I might solve the problem?
If it provides any clues, the main view is inside a UIScrollView.
Okay, I found the answer. I needed to set Autoresize Subviews to false on the UIScrollView. Having done that (by un-checking the appropriate box in IB) everything seems to be working fine.