Grid like arrangements in UIScrollView(PhotoScroller) - memory-management

I was using apple's scrollview sample code PhotoScroller for my app using numerous images (and by recycling logic)
in UIScrollView. I implemented that in my app and it works fine.
Now Im working in an app similar to the above, but with the
difference, loading images in grid like view. When I happen to use the
same sample code, every thing works fine except the recycling logic.
I think there is some problem with my frame set which don't tell the
xcode, the visible region.
Please some one temme how to set the visible set for the grid View
structure for scrollview? The code I use is,
CGRect visibleBounds = _scrollView.bounds;
// CGRect gridElementvisibleBounds = CGRectMake(0, 0, 212, 200);
int firstNeededPageIndex = floorf(CGRectGetMinX(visibleBounds) -
CGRectGetWidth(visibleBounds));
int lastNeededPageIndex = floorf((CGRectGetMaxX(visibleBounds)-1) -
CGRectGetWidth(visibleBounds));
firstNeededPageIndex = MAX(firstNeededPageIndex, 0);
lastNeededPageIndex = MIN(lastNeededPageIndex, [self imageCount] - 1);
where _scrollView is the UIScrollView instance that I use and the
gridElement that I use is of frame size (0, 0, 212, 200). The number
of grid elements that occupy the scrollView bounds is
3 x 3 (9).
I don't want to use grid like tableViews(AQGridView, etc,.) since Im gonna load more than 500 images.
Please some one help me finding out the thing that I should correct in
the above code.

I nearly fixed the issue by making use of contentOffset to get the visible area.
Here is the piece of code illustrating what I did to make it working.
int firstNeededPageIndex = ((int)_scrollView.contentOffset.y / 960) * 9;
int lastNeededPageIndex = ((int)_scrollView.contentOffset.y / 960) * 9 + 17;
where I found the visible area by getting the contentOffset.y/960 and got the firstNeededPageIndex as given above.
When the scrollview scrolls, the components of the page that is getting to hide contains 9 elements and the successive page(got by lastNeededPageIndex) that is getting to be visible contains no components.
Hence I made it visible by making 18 objects to the visible area while scrolling.
Hence the objects to be visible while scrolling became 0th object to 17th object.
And the result is whenever the scrollview scrolls, 18 components(0 to 17) in the visible area(got through contentOffSet ) are recycled.

Related

Wrong map center in iOS using nativescript-google-maps-sdk

In iOS when I put marker and mapView location, the map does not display centered, but if I move the phone to landscape and rotate again to portrait the map center displays fine.
In Android works fine.
You can get more information in this GitHub issue:
https://github.com/dapriett/nativescript-google-maps-sdk/issues/322
I have personally faced this and discovered that it's basically a layout problem on iOS. The height and width attribute values supplied to the MapView's XML element are somewhat differently treated by iOS. The solution to our problem, as described in the question itself is resizing the map on runtime (as rotating the screen makes it go through a resizing routine). Applying this absurd logic at the beginning of the map render, solves the problem.
This is how I did it:
Provide the width value of the MapView in XML:
<maps:mapView width="100%" mapReady="onMapReady" />
and set the height of the map inside onMapReady method, with a 100 millisecond delay.
/* if you want to set height in DIP */
setTimeout(() => this.mapView.height = 500, 100);
or if you want to set height in percentage
/* [0.85 means 85% here] */
setTimeout(() => this.mapView.height = {
unit: '%',
value: 0.85
}, 100);
100 millisecond delay makes it go through the resize effect. Tested on iOS 12.1

iOS 11: Scroll to top when "adjustedContentInset" changes with larger title bars?

I noticed that this code doesn't quite work as expected on iOS 11, because the "adjustedContentInset" property value changes as the "navigationBar" shrinks during a scroll:
CGFloat contentInsetTop=[scrollView contentInset].top;
if (#available(iOS 11.0, *))
{
contentInsetTop=[scrollView adjustedContentInset].top;
}
////
[scrollView setContentOffset:CGPointMake(0, -contentInsetTop) animated:YES];
... For example, this might start out as 140, then reduce to 88 beyond a minimal scroll offset. This means if you call this, it doesn't actually scroll all the way to the top.
Aside from preserving the original offset in memory from when the UIScrollView loads, is there a way to recover this value later to ensure that it does indeed scroll to top consistently, no matter the "adjustedContentInset"?
Currently, there is indeed no way to do this with iOS 11, I have heard. The only way to do so is to capture the initial value and store it for the life of the navigation/view controller.
I will update my answer accordingly if I hear otherwise, but it will be broken in the base iOS 11 release forever unfortunately.
I had this same problem with a Large Title in iOS 11, and the following code worked for me.
The following code first scrolls the offset a reasonable size above where you want to be. The value -204.666666666667 was the tallest value from setting the Accessibility > Larger Text > Larger Accessibility Sizes to the highest. I'm sure this doesn't cover other possibilities, but it is working for me so far. -CGFloat.greatestFiniteMagnitude is otherwise too problematic.
tableView.setContentOffset(CGPoint(x: 0.0, y: -204.666666666667), animated: false)
This will now give you back the right adjusted content size. To avoid being scrolled too far higher, i.e. leaving white space, just use the value as follows.
var contentOffset = CGPoint.zero // Just setting a variable we can change as needed below, as per iOS version.
if #available(iOS 11, *) {
contentOffset = CGPoint(x: 0.0, y: -tableView.adjustedContentInset.top)
} else {
contentOffset = CGPoint(x: 0.0, y: -tableView.contentInset.top)
}
tableView.setContentOffset(contentOffset, animated: false)
In summary, set the offset higher first (-204.666666666667 in my case, or just -300 or whatever), then that readjusts the adjustedContentInset.top to include the Large Title, scroll bar, etc., then you can now set the content offset as needed.

Xcode - viewDidLayoutSubviews

i have a view inside a viewController, i wanted to start the smaller view outside the viewController in the left, and animate it to the centre when i press a button. so i made it like this:
override func viewDidLayoutSubviews() {
smallView.center = CGPointMake(smallView.center.x - 400, smallView.center.y)
}
And it works perfectly!, the problem is i have a text view inside that smaller view, and every time i start editing it it jumps outside of the main viewController right where it was, and i have to press the button again to bring it inside.
How to fix this?
PS: i tried positioning it to the centre when i start editing the text view like this:
func textViewDidBeginEditing(textView: UITextView) {
smallView.center = CGPointMake(smallView.center.x + 400, smallView.center.y)
}
But it doesn't work. and the method is connected to the textView properly(delegate)
PS2: i also have imagePickerController inside my viewController.
OK, as you're using Auto Layout.
The first rule of Auto Layout (you will see this in any Auto Layout book) is that you absolutely cannot touch the frame or center of a view directly.
// don't do these
myView.frame = CGRectMake(0, 0, 100, 100);
// ever
myView.center = CGPointMake(50, 50);
You can get the frame and center but you can never set the frame or center.
In order to move stuff around using Auto Layout you need to update the constraints.
For instance if I set up a view called myView and want it to grow and shrink in height I would do something like...
Set the top constraint to the superview at 0.
Set the left constraint to the superview at 0.
Set the right constraint to the superview at 0.
Set the height constraint to 50 (for example) and save it in a property called heightConstraint.
Now to animate the change in height I do this...
self.heightConstraint.constant = 100;
[UIView animateWithDuration:1.0
animations:^ {
[self.view layoutIfNeeded];
}];
This will then animate the height from 50 (where it was when I set it) to 100.
This is the same for ANY animation of views using Auto Layout. If (for instance) I had saved the left constraint I could change that and it would increase and decrease the gap from the left edge of the superview to myView.
There are several really good tutorials about AutoLayout on the Ray Wenderlich site. I'd suggest you take a look at them.
Whatever you do, I'd strongly suggest not just disabling Auto Layout. If you don't know how to use Auto Layout then you will very quickly fall behind with iOS 8 and the new device sizes.

SCNView Re-sizing Issue

I am trying to render 3D bar chart in SCNView using ScreenKit framework.
My rendering code is,
int height=10,y=0,x=0;
for (int i=0; i<10; i++) {
SCNBox *box1 = [SCNBox boxWithWidth:4 height:height length:2 chamferRadius:0];
boxNode1 = [SCNNode nodeWithGeometry:box1];
boxNode1.position = SCNVector3Make(x, y, 0);
SCNMaterial *material = [SCNMaterial material];
material.diffuse.contents = (NSColor *)[self.colorArray objectAtIndex:i%6];
material.specular.contents = [NSColor whiteColor];
material.shininess = 1.0;
box1.materials = #[material];
//boxNode1.transform = rot;
[scene.rootNode addChildNode:boxNode1];
x+=6;
height+=10;
y += 5 ;
}
I can render but while re-sizing the view the chart bars goes to the center of the view.
I need to render the chart, which cover the margins of the view and when Re-size it have to change accordingly. The image(s) below shows my problem.
Original Image:
Image where less stretching of both windows:
Can anyone please help me to fix the issue.
The the windows in the image that you had linked to in your original question was very stretched and that made it very hard to see what was going on. When I took that image and made the windows less stretched it was easier to have some idea of what is going on.
I think that you are seeing a general resizing issue. Either you are using springs and struts and have configured flexible margins on the left and right or you are using auto layout with a centered view with fixed width.
I assume that the red boxes that I have drawn in the image below is the bounds of your scene view in both these cases. You can easily see if this is the case by giving the scene view a different background color and resize it again.
My solution to your problem would be to change how your view resizes as the window resizes, to better meet your expectations.

Time Machine style Navigation

I've been doing some programming for iPhone lately and now I'm venturing into the iPad domain. The concept I want to realise relies on a navigation that is similar to time machine in osx. In short I have a number of views that can be panned and zoomed, as any normal view. However, the views are stacked upon each other using a third dimension (in this case depth). the user will the navigate to any view by, in this case, picking a letter, whereupon the app will fly through the views until it reaches the view of the selected letter.
My question is: can somebody give the complete final code for how to do this? Just kidding. :) What I need is a push in the right direction, since I'm unsure how to even start doing this, and whether it is at all possible using the frameworks available. Any tips are appreciated
Thanks!
Core Animation—or more specifically, the UIView animation model that's built on Core Animation—is your friend. You can make a Time Machine-like interface with your views by positioning them in a vertical line within their parent view (using their center properties), having the ones farther up that line be scaled slightly smaller than the ones below (“in front of”) them (using their transform properties, with the CGAffineTransformMakeScale function), and setting their layers’ z-index (get the layer using the view’s layer property, then set its zPosition) so that the ones farther up the line appear behind the others. Here's some sample code.
// animate an array of views into a stack at an offset position (0 has the first view in the stack at the front; higher values move "into" the stack)
// took the shortcut here of not setting the views' layers' z-indices; this will work if the backmost views are added first, but otherwise you'll need to set the zPosition values before doing this
int offset = 0;
[UIView animateWithDuration:0.3 animations:^{
CGFloat maxScale = 0.8; // frontmost visible view will be at 80% scale
CGFloat minScale = 0.2; // farthest-back view will be at 40% scale
CGFloat centerX = 160; // horizontal center
CGFloat frontCenterY = 280; // vertical center of frontmost visible view
CGFloat backCenterY = 80; // vertical center of farthest-back view
for(int i = 0; i < [viewStack count]; i++)
{
float distance = (float)(i - offset) / [viewStack count];
UIView *v = [viewStack objectAtIndex:i];
v.transform = CGAffineTransformMakeScale(maxScale + (minScale - maxScale) * distance, maxScale + (minScale - maxScale) * distance);
v.alpha = (i - offset > 0) ? (1 - distance) : 0; // views that have disappeared behind the screen get no opacity; views still visible fade as their distance increases
v.center = CGPointMake(centerX, frontCenterY + (backCenterY - frontCenterY) * distance);
}
}];
And here's what it looks like, with a couple of randomly-colored views:
do you mean something like this on the right?
If yes, it should be possible. You would have to arrange the Views like on the image and animate them going forwards and backwards. As far as I know aren't there any frameworks for this.
It's called Cover Flow and is also used in iTunes to view the artwork/albums. Apple appear to have bought the technology from a third party and also to have patented it. However if you google for ios cover flow you will get plenty of hits and code to point you in the right direction.
I have not looked but would think that it was maybe in the iOS library but i do not know for sure.

Resources