I have a iCarousel gallery in which I am getting images from web service. The gallery showing perfectly. I used iCarasouel delegate method "didSelectItemAtIndex" for selecting the First to last image. My icarousel type is "carousel.type = iCarouselTypeCoverFlow;".
I selected the image and i got proper index of image, didSelectItemAtIndex works properly only when I scroll gallery and image is moved from center, but when the view is load "Frist or any images" are showing in center are not selected by didSelectItemAtIndex. when I scroll the gallery again and center image is moved from the center then its works fine, then I am able to select the image and go to the next Class or view.
I want to select image which are showing in the center of Icaraosel. Don't know how to do it?
Any hints from experts would be very welcome.
You can get the current index of the image in the given below delegate method
- (void)carouselCurrentItemIndexUpdated:(iCarousel *)carousel1
Once your images load s completely then call
[self carouselCurrentItemIndexUpdated:carousel];
Here is the code :
In your viewDidLoad call the method as shown below,here carsousel is in an instance of iCarsouel.
- (void)viewDidLoad
{
[super viewDidLoad];
[self carouselCurrentItemIndexUpdated:carousel];
}
- (void)carouselCurrentItemIndexUpdated:(iCarousel *)carousel1
{
self.currentItem=carousel1.currentItemIndex;
NSLog(#"currentItem update== %i",self.currentItem);
}
Hope this helps....
I dont know if I understood you right: you want to get a didSelectItemAtIndex: message right after the initial reload of the view and without scrolling?
just ask for currentItemIndex and if you want the selected to be center always call centerItemWhenSelected
so just call [self didSelectItemAtIndex:carousel.currentItemIndex];` manually
-(void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index
{
if (index == carousel.currentItemIndex)
{
///Selected centered item only
}
}
Related
I have a popover with TabBarController in it. In one tab there is a TableViewController with a list of names. And there is a plus button, that has a modal segue to AddCharacterVC for adding new names.
In iOS 7 I do it like this:
AddCharacterViewController *acvc = (AddCharacterViewController *)segue.destinationViewController;
acvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
acvc.modalPresentationStyle = UIModalPresentationCurrentContext;// so it does not take full screen in popover
And in AddCharacterVC I set content size like this:
- (void)viewWillAppear:(BOOL)animated {
CGSize size = CGSizeMake(320, 480); // size of view in popover
if (IDIOM == IPAD && [self respondsToSelector:#selector(preferredContentSize)]){
self.preferredContentSize = size;
}
And it works perfectly.
However, in iOS 8 modal view does not cover the whole popover, leaving TabBar visible. The user can tap on it or not, anyway modal view won't unwind properly.
I've tried:
setting acvc.modalPresentationStyle to UIModalPresentationOverCurrentContext
tried to set TabBar hidden
checked in storyboard that edges of TableVC extend under Bottom Bar and Bottom Bar in Modal View (AddCharacterVC) is set to none
All with no results.
Now the only thing I can think of is to try making modalPresentationStyleCustom and use UIPresentationController (I'm trying to do it now, but I haven't done it before). Am I missing something? Could there be other way to do it? Sorry, I cannot post images here yet. Many thanks in advance!
Ok, so I've set the modalPresentationStile to UIModalPresentationCustom, and used UIPresentationController - I've just copied code from WWDC-14's LookInside project and modified it a bit.
I'm not sure if it was the best solution, but it worked in my case.
I have a custom map of a limited area, and have it set up to correctly show the users' location. The map is a 1600px square image within a UIScrollView.
I have a crosshair image to show the current location of the user, which at zoomScale 1.0 is the desired size. When I pinch and zoom the scrollView, the crosshair scales with it. I would like to have the subview remain the same size on screen.
I haven't been able to find any information on this, what would be the best way to go about this?
If there is anything I can provide you with to help the answer, please let me know.
Many thanks!
EDIT -
Having looked in to this further, there is a UIScrollViewDelegate method - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale which I tried using to take the marker's current center and size, then adjust, but this only scales at the end of the zoom. I would prefer to have the marker remain the same size while the user is zooming.
EDIT 2-
Cake has provided a great answer below, but I haven't been able to implement this in the way I imagined it would be.
I have the UIImageView as a placeholder, with alpha set to 0. This placeholder moves around relative to the map to show the user location. This operates as I expect it to. Unfortunately, this resizes with the map, as it is a subview of the map (so it stays in place).
Taking Cake's below answer, I have created the non-scaling crosshair image, and added it as a sibling subview to the scrollview. The maths, once Cake had pointed them out, were quite simple to get the new frame for the crosshair:
CGPoint ULPC = userLocationPlaceholder.center;
float zs = scrollView.zoomScale;
CGRect newFrame = CGRectMake(((ULPC.x * zs) - scrollView.contentOffset.x) - 20, ((ULPC.y * zs) - scrollView.contentOffset.y) - 20, 40, 40);
Where the image is 40points wide. This matches the centers perfectly.
The problem I now have is that I cannot get the crosshair image to stay locked to the placeholder.
I have tried using a self calling animation as such:
-(void)animeUserLocationAttachment
{
[UIView animateWithDuration:0.05
delay:0
options:(UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear )
animations:^{
userLocationDotContainer.frame = newFrame;
} completion:^(BOOL finished){
// Call self
[self animateUserLocationAttachment];
}];
}
As soon as I start scrolling/zooming, this locks the animation so that the crosshair just sits in place until I release the scrolling/zooming, then it correctly updates it's location.
Is there any way I can get around this, or an alternative method I can apply?
Many thanks
EDIT 3 -
I've re-accepted Cake's answer as it covers 90% of the issue. Further to his answer I have implemented the ScrollViewDelegate methods scrollViewWillBeginDragging: andscrollViewWillBeginDecelerating: to scale the placeholder to match the current size of the crosshair relative to the map, show the placeholder (that is a subview of the map image) and hide the crosshair image. The delegate method scrollviewWillBeginZooming:withView: does not show the placeholder because it scales with the map. As Cake recommends, I'll make a new question for this issue.
The counterpart methods (scrollViewDidEndZooming:withView:atScale:, scrollViewDidEndDragging:willDecelerate: and -scrollViewDidEndDecelerating:`) all hide the placeholder, and re-show the crosshair.
The question is old but for the future similar questions I've recently resolved a similar problem applying the hint of Andrew Madsen of another post.
I'had a UIScrollView, with an UIImageView in it. Attached to the UIImageView I had many MKAnnotationView (those are my subviews that I didn't want scaling with the superview).
I did subclass UIImageView and implement setTransform: method like here:
#import "SLImageView.h"
#implementation SLImageView
- (void)setTransform:(CGAffineTransform)transform
{
[super setTransform:transform];
CGAffineTransform invertedTransform = CGAffineTransformInvert(transform);
for (id obj in self.subviews)
{
if ([obj isKindOfClass:[MKAnnotationView class]])
{
[((UIView *)obj) setTransform:invertedTransform];
}
}
}
#end
This works perfectly!
Mick.
Create another crosshair image that's associated with the view or view controller that contains the scrollview. Then have this one always snap to the center of the crosshair image you already have. Then, hide your original crosshair image. Then you can avoid having the scrollview scale the disassociated crosshair, and it should stay the same size.
Relative coordinate systems
Each view in cocoa touch has a frame property that has an origin. In order to position an object owned by one view properly relative to another view, all you have to do is figure out the differences in their origins. If one view is a subview of another, then this isn't too difficult.
Get the origin of the container view
Get the location of the subview inside of the container view
Get the origin of the subview
Calculate the difference in the positions of the origins
Get the location of the object you want to overlap (relative to the subview)
Calculate the location of the object you want to overlap relative to the container view
Move your crosshair to this position
Swift equivalent for Mick's answer:
class MapContainerView:UIView {
#IBOutlet var nonScalingViews: [UIView]!
override var transform: CGAffineTransform {
didSet {
guard let nonScalingViews = nonScalingViews else {
return
}
let invertedTransform = CGAffineTransformInvert(transform)
for view in nonScalingViews {
view.transform = invertedTransform
}
}
}
}
I'd like to recreate a view that you can zoom like the iPhone/iPad Mail app or Sparrow when viewing an email, where at the top there is block of information and then a UIWebView. I can obviously do this easily in interface builder or code, BUT I would like it behave like the Mail app.
By 'like the Mail App' I mean, when you pinch zoom (anywhere in the view), the UIWebView is the only view that actually zooms, and the top content stays the same size. When you zoom out too far and see the background the whole view zooms out (not just the UIWebview) and the whole view scrolls too.
I've done some experimenting and tried some of the suggestions already, like inserting the top view at the top of the UIWebView, extending the height of the UIWebView based on content size but this always ends up with either the top view zooming too, OR just the UIWebView.
I hope the makes some sense. It might be really simple but I've been trying to sort this for a while on and off that I can't see the wood for the trees any more.
This is for a MonoTouch app, but if anyone has Objective-C examples or anything I can convert and post back.
I have done just that for our application; it is not as simple as it sounds, but on iOS 5 it should be somewhat less complex than iOS 4.
Have a view of the top part you wish to have constant. When your web view finishes loading the HTML and renders it, get the scrollView of the web view, and add your view as a subview to that. Add the top view's frame height to the contentSize.height of the scroll view, and add the height to origin.y of the rest of subviews of the scroll view (those that are not your top view). Set your view controller as the delegate of the web view's scroll view. Whenever the user scrolls:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect frame = contentView.frame;
if(scrollView.contentOffset.x < 0)
{
frame.origin.x = 0;
}
else if((scrollView.contentOffset.x + contentView.frame.size.width) > scrollView.contentSize.width)
{
frame.origin.x = scrollView.contentSize.width - contentView.frame.size.width;
}
else
{
frame.origin.x = scrollView.contentOffset.x;
}
[contentView setFrame:frame];
}
This should make it behave exactly like the mail.app view.
I admit I'm a newby to Objective-C but came pretty far, I guess. Now I'm having an issue and would need some help.
In my app I display images in portrait modes amongst other information and want to display them full screen in landscape mode. I learned that you'd do this defining a Landscape m, h and nib file and load this view when the device is moved to landscape orientation (working with an observer), right?
In portrait mode the images in the end depend on user interaction so the Landscape class needs to be told, which image to display. I created a putImage method in the Landscape class
-(void) putImage:(NSString *)theImage {
pict.image = [UIImage imageNamed: theImage];
NSLog(#"PICT %#",pict.image);
NSLog(#"IMAGE %#",theImage);
}
and call it from the portrait one and here comes the issue:
NSString *actualImage = [NSString stringWithFormat:#"Picture%i.jpg",selected];
pict.image = [UIImage imageNamed: actualImage];
[landscapeViewController putImage:actualImage];
that works perfectly every time except the very first one. So whatever I do I need to first make the App load a new image plus change to landscape orientation (being displayed no image) in any manner. Then after it always works displaying the correct images.
I added debug information and see that the correct image is assigned to pict in landscape class - however it seems it needs to be displayed before it really sets the image.
Any help you guys could give?
Not sure if this it it since your example code is pretty sparse. But when you load your first picture do you do that in init? If so, try to do it in viewWillAppear or viewDidAppear.
thank you for all the hints and tries to help. Now I found the solution myself ... here's what I did:
1) in the LandscapeViewController.h I defined an NSString:
#interface LandscapeViewController : UIViewController
{
IBOutlet UIImageView *pict;
NSString *actualImage;
}
2) I changed the putImage method to only assign the image name to my local NSSTRING variable:
-(void) putImage:(NSString *)theImage {
actualImage = theImage;
[actualImage retain];
}
3) loading the image I only do in viewWillAppear:
- (void)viewWillAppear:(BOOL)animated {
pict.image = [UIImage imageNamed: actualImage];
[super viewWillAppear:animated];
}
So the answer to my question is almost answered - I guess that this issue arose because I did set the image before I loaded the view first time so that it was not instanciated. I was able to call the method but had no Image Object to set ... does that sound logical to you guys?
Thank you all again!
In my iPhone app there is a scrollview pagingEnabled=NO which can contain up to 200 subviews (150 x 150) and the challenge is to do lazy loading and simulate endless scrolling (without bouncing) in horizontal directions.
Is there a solution or an alternative for this request?
Lazy loading of a scroll view is demonstrated in one of Apple's sample code projects: PageControl.
To fake endless scrolling what I'd suggest is to make your scroll view very wide to begin with, wider than an average person would scroll in one set of scrolling behaviors. Then in your delegate methods -scrollViewDidEndScrollingAnimation:, -scrollViewDidEndDragging:willDecelerate: and -scrollViewDidEndDecelerating:, one or more of which will be called after the user is done scrolling, reposition your content to exist in the center of the scroll view and update your contentOffset point without animating.
For that to work visually you would need to also disable the horizontal scroller. You'll also need to consider how to determine what view to draw at a particular contentOffset with this method since you won't be able to just divide the contentOffset.x by the scroll view's bounds anymore to find out where you are.
Hello I found the way to do it.
I have a master array with all the subviews (in my case they are images, so I store the names).
The scrollview only has 3 subviews: left, current, right.
Paging is enabled, so the user cant really spin more that one view left/right at any time.
What I do is:
1) track his current position on the master array. If he moves left, subtract one; right add one. Like this:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[some code to determine current page, based on contentOffset]
if (page == 0){
NSLog(#"Going left");
if (currentPage > 0){
currentPage--;
} else {
//cycle to last
currentPage = [images count] -1;
}
} else if (page == 2){
NSLog(#"Going right");
if (currentPage < ([images count] -1)){
currentPage++;
} else {
//cycle to first
currentPage = 0;
}
} else{
NSLog(#"Not moving");
}
2) after the user moves, I reload 3 new images, like this:
//updates the 3 views of the scrollview with a new center page.
-(void) updateScrollViewForIndex:(NSInteger)newCenterPage{
//fist clean scroll view
for (UIView *sView in [scroll subviews]){
[sView removeFromSuperview];
}
NSInteger imgCount = [images count];
//set center view
[self loadImageIndex:newCenterPage atPosition:1];
//set left view
if (newCenterPage > 0){
[self loadImageIndex:newCenterPage-1 atPosition:0];
} else {
//its the first image, so the left one is the last one
[self loadImageIndex:imgCount-1 atPosition:0];
}
//set right view
if (newCenterPage < imgCount-1){
[self loadImageIndex:newCenterPage+1 atPosition:2];
} else {
//its the last image, so ther right one is the first one
[self loadImageIndex:0 atPosition:2];
}
}
3) Finally re-center the scroll view to the center view again:
[scroll setContentOffset:CGPointMake(1 * viewWidth, 0)];
Hope this helps, although "the man with the plan" is Mr. Clark, who pointed the way.
Gonso
Matt Gallagher has a blog post which describes a solution to this exact problem. I've used it and it works great.
The UIScrollView and UIPageControl in Cocoa Touch allow for user interfaces with multiple panning pages. The sample project that Apple provides (PageControl) keeps all child views for every page in a lazily loaded array. I'll show you how you can implement this using just two child views, no matter how many virtual pages you wish to represent.
It works by shuffling around the child views and reseting their content when necessary. I used this for displaying flash cards, where there could be anywhere from 3 to 3,000 items. Although it's set up right now for paging, I'm sure you could get it to work with regular scrolling.