I am having trouble while adding Views to my iCarousel "viewForItemAtIndex" method
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
UIView *sub = nil;
//iCarousel *temp;
//create new view if no view is available for recycling
if (view == nil)
{
UIViewController * viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"UIidentifier"];
view = [viewController.view viewWithTag:20];
CGRect Frame = CGRectMake(view.frame.origin.x, view.frame.origin.y + 100, view.frame.size.width, view.frame.size.height);
view.frame = Frame;
}
UILabel *label=(UILabel*)[view viewWithTag:23];
label.text = [[listOfAnimalsNames objectAtIndex:index]nameOfTheCompanie];
return view;
}
I want to display a UIView "mockUp" and fill the labels with some data by using the "index" of the iCarousel, I have created my own UIViewController that contains the "mockup" UIView. The thing is that when I call this UIView (as in the code) nothing happens. (I use the reloadData method after loading data)
Why does each view need its own ViewController? They should all be controlled by whatever is controlling the iCarousel view (or at least its data source). Also, the UILabel should be instantiated only once.
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
UIView *sub = nil;
if (view == nil)
{
view = [UIView alloc] initWithFrame:CGRectMake(...);
UILabel *label=[[UILabel alloc] initWithFrame:(...)];
[view addSubview:label];
}
label.text = [[listOfAnimalsNames objectAtIndex:index]nameOfTheCompanie];
return view;
}
Related
I have 2 labels.
First label, named "label" is placed inside every view within the carousel. The string/text of the label is the view's index.
label.text = [[items1 objectAtIndex:index] stringValue];
I also have a second label (outside the carousel) named "outsideLabel".
I want the outsideLabel's string/text to be the view's index aswell (always the view being in front of the carousel).
outsideLabel.text = [[items1 objectAtIndex:index] stringValue];
Somehow I am doing it wrong and wonder how I shall code this in order to show the proper number in outsideLabel's string/text (always the view being in front). The code somewhat shows the correct numbers but get messed up when scrolling backwards in the carousel. The carouseltype is timeMachine.
My current code:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
//create new view if no view is available for recycling
if (view == nil)
{
view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)];
view.contentMode = UIViewContentModeCenter;
label = [[UILabel alloc] initWithFrame:view.bounds];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
if (carousel == carousel1)
{
CGRect test = CGRectMake(10, 10, 20, 20);
self.label.frame = test;
}
else {
CGRect test = CGRectMake(50, 40, 40, 40);
self.label.frame = test;
}
[view addSubview:label];
}
else
{
label = [[view subviews] lastObject];
}
if (carousel == carousel1)
{
//items in this array are numbers
outsideLabel.text = [[items1 objectAtIndex:index] stringValue];
label.text = [[items1 objectAtIndex:index] stringValue];
((UIImageView *)view).image = [UIImage imageNamed:[view1background objectAtIndex:index]];
}
else
{
//not relevant....
}
return view;
}
From the code you've provided, it looks like you're not initializing the outsideLabel in the right place. To be safe, you should initialize all your subviews inside the block where you are checking if the view is nil. Another safe convention is to assign tags to all your subviews, so that you can later retrieve them from views that are reused, as in the code below. For easy reference, and to avoid errors, I define constants for these tags at the top of my implementation file, like this:
#define INSIDE_LABEL_TAG 1
#define OUTSIDE_LABEL_TAG 2
This is much safer, since it doesn't depend on the structure of the views, as is the case with your code, where you get the last view:
label = [[view subviews] lastObject];
Try initializing outsideLabel inside that block, and use tags. The pattern used in initialization is identical to that used for the subviews of UITableView cells in a UITableViewDataSource delegate:
(UITableViewCell * _Nonnull)tableView:(UITableView * _Nonnull)tableView
cellForRowAtIndexPath:(NSIndexPath * _Nonnull)indexPath
Here is some pseudo code that shows where I would use tags and initialize the outsideLabel:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
//create new view if no view is available for recycling
if (view == nil)
{
//Configure the view
...
/* Initialize views for all carousels */
//Initialize the insideLabel and set its tag
...
insideLabel.tag = INSIDE_LABEL_TAG;
//Initialize the outsideLabel and set its tag
...
outsideLabel.tag = OUTSIDE_LABEL_TAG;
if (carousel == carousel1)
{
//Do any carousel-specific configurations
}
//Add all subviews initialized in this block
[view addSubview:label];
[view addSubview:outsideLabel];
}
else
{
//Get the subviews from an existing view
insideLabel = (UILabel *)[view viewWithTag:INSIDE_LABEL_TAG];
outsideLabel = (UILabel *)[view viewWithTag:OUTSIDE_LABEL_TAG];
}
if (carousel == carousel1)
{
//Set the values for each subview
} else {
//Other carousels...
}
return view;
}
It looks to me like you want the "time machine" style carousel. I don't see your code setting the carousel type anywhere. Don't you need to set the carousel type?
AIM: To achieve the scroll of parent upto a particular point. Freeze its scroll and let the child view scroll till the bottom. Again move up, let child view controller scroll, till it reaches its top then let the parent view scroll till it reaches top and page comes to original state.
I am adding any childviewcontroller like this:
- (void)switchCurrentControllerWith:(UIViewController*)viewController andViewHeight:(float)height{
//1. The current controller is going to be removed
[selectedViewController willMoveToParentViewController:nil];
// ((DRBaseViewController *)viewController).hideNavBar = YES;
//2. The new controller is a new child of the container
[self addChildViewController:viewController];
//3. Setup the new controller's frame depending on the animation you want to obtain
viewController.view.frame = containerRect;
//The transition automatically removes the old view from the superview and attaches the new controller's view as child of the
//container controller's view
[self transitionFromViewController:selectedViewController
toViewController:viewController
duration:0.1
options:UIViewAnimationOptionShowHideTransitionViews|UIViewAnimationOptionTransitionCrossDissolve
animations:^{
} completion:^(BOOL finished) {
//Remove the old view controller
[selectedViewController removeFromParentViewController];
//Set the new view controller as current
selectedViewController = viewController;
[selectedViewController didMoveToParentViewController:self];
[self.view bringSubviewToFront:navigationBar];
[self.scrollView setContentSize:CGSizeMake(320., CGRectGetMaxY(segmentedControl.frame) + height)];
}];
}
Now, there is a UIScrollView scaled to fit view height (504) in the parent view controller. I am doing following tasks in scrollview delegate methods for disabling the parent's scrollview and enabling the scroll of childviewcontroller's scrollview/tableview :
-(void)scrollViewDidScroll:(UIScrollView*)scrollView
{
if (scrollView.contentOffset.y >= self.segmentScrollView.frame.origin.y) {
scrollView.scrollEnabled = NO;
for (UIViewController *selectedViewController in containedControllers) {
for (UIView *view in selectedViewController.view.subviews) {
if ([view isKindOfClass:[UITableView class]]) {
UITableView *tableView = (UITableView*)view;
tableView.scrollEnabled = YES;
}
else if ([view isKindOfClass:[UIScrollView class]]){
UIScrollView *scrollView = (UIScrollView *)view;
scrollView.scrollEnabled = YES;
}
}
}
}
else{
for (UIViewController *selectedViewController in containedControllers) {
for (UIView *view in selectedViewController.view.subviews) {
if ([view isKindOfClass:[UITableView class]]) {
UITableView *tableView = (UITableView*)view;
tableView.scrollEnabled = NO;
}
else if ([view isKindOfClass:[UIScrollView class]]){
UIScrollView *scrollView = (UIScrollView *)view;
scrollView.scrollEnabled = NO;
}
}
}
}
if ([scrollView isAtBottom]) {
for (UIView *view in selectedViewController.view.subviews) {
if ([view isKindOfClass:[UITableView class]]) {
UITableView *tableView = (UITableView*)view;
tableView.scrollEnabled = YES;
}
else if ([view isKindOfClass:[UIScrollView class]]){
UIScrollView *scrollView = (UIScrollView *)view;
scrollView.scrollEnabled = YES;
}
}
}
}
Now my PROBLEM IS THE CHILDVIEW'S SCROLL/TABLEVIEW is not getting scrolled when the parent's scrollview reaches a fixed content offset and then the childview's scrollview have to be scrolled! What seems to be the problem here?
PS. I checked the childview's Scroll/TableView's frame and content Size and that is not an issue.
NOTE: I see the scrolling of my child view's table/scrollview has been disabled in one direction and is enabled in another!
I am trying to achieve a right to left iCarousel object with a fade on both sides.
So i imported the GtiHub Project into My application, Assigned a UIView to iCarousel...Linked that to an IBOutLet on my MainViewController and passed the Delegate as well as the DataSource just like the UITableViewController.
Though it will not show up and i am unsure of what could be causing this issue.
My iCarousel DataSource is is an NSMutableArray *items; designed like so:
for (int i = 0; i < 100; i++)
{
[_items addObject:#(i)];
}
I am initializing the iCarousel in the ViewDidLoad like below
- (void)viewDidLoad
{
[super viewDidLoad];
//Initialize Carousel
_carousel = [[iCarousel alloc] init];
_carousel.delegate = self;
_carousel.dataSource = self;
//Carousel Testing Data
for (int i = 0; i < 100; i++)
{
[_items addObject:#(i)];
}
//configure carousel
_carousel.type = iCarouselTypeRotary;
}
My Delegate Methods for Carousel are below:
#pragma mark -
#pragma mark iCarousel methods
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
//return the total number of items in the carousel
return [_items count];
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
UILabel *label = nil;
//create new view if no view is available for recycling
if (view == nil)
{
view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)];
((UIImageView *)view).image = [UIImage imageNamed:#"page.png"];
view.contentMode = UIViewContentModeCenter;
label = [[UILabel alloc] initWithFrame:view.bounds];
label.backgroundColor = [UIColor clearColor];
label.font = [label.font fontWithSize:50];
label.tag = 1;
[view addSubview:label];
}
else
{
//get a reference to the label in the recycled view
label = (UILabel *)[view viewWithTag:1];
}
label.text = [_items[index] stringValue];
return view;
}
- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
{
switch (option)
{
case iCarouselOptionFadeMin:
return -0.2;
case iCarouselOptionFadeMax:
return 0.2;
case iCarouselOptionFadeRange:
return 2.0;
default:
return value;
}
}
Everything from the storyboard seems to be connected and the data should be presenting itself, what is wrong and how can i fix this issue?
Since you have the DataSource array (_items) setup after the view gets loaded:
Make sure that the carousel view in your storyboard does have the IBOutlet to the controller, but NOT the 'Delegate' and 'DataSource' linked to the File's Owner (Controller or view).
Set the _carousel.delegate and _carousel.dataSource to 'self' only After you initialize and update the dataSource array (_items in this case).
Place breakpoints to check whether the iCarousel Datasource and Delegate methods are being called or not.
If the methods are not called, check whether the controller follows the iCarousel protocols like this:
#interface yourViewController : UIViewController <iCarouselDataSource, iCarouselDelegate>
Obviously you'll have to
#import "iCarousel.h"
UPDATE: In your viewDidLoad, you have
_carousel = [[iCarousel alloc] init];
looks like you forgot to set a frame for _carousel and add it as a subView.
To get the imageView reference, try this:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)];
imageView.image = [UIImage imageNamed:#"page.png"];
view = imageView;
I have a UIView subclass of a table's header view, is it possible to get the table view from my header view subclass using viewWithTag:? I tried below methods but still get nothing:
my method 1:
UIView *tv = (UIView *)[self.superview viewWithTag:11];
my method 2:
UITableView *tv = (UITableView *)[self.superview viewWithTag:11];
Thanks.
The best solution is to walk the view's superview hierarchy until you get to the table view. This approach will work regardless of the underlying table view structure.
UIView *view = self.superview;
UITableView *tv = nil;
while (view) {
if ([view isKindOfClass:[UITableView class]]) {
tv = (UITableView *)view;
break;
}
view = view.superview;
}
if (tv) {
// found the table view. Do something with it
}
Create your UITableView:
TableHeaderView *v = [[TableHeaderView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
_tableView.tableHeaderView = v;
// I think you miss this line
_tableView.tag = 101;
_tableView.backgroundColor = [UIColor redColor];
NSLog(#"%#",_tableView.backgroundColor);
// value: UIDeviceRGBColorSpace 1 0 0 1
In your TableHeaderView:
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
// just example to get super class
[self performSelector:#selector(doSomething) withObject:nil afterDelay:5];
}
return self;
}
- (void) doSomething
{
UITableView *tb = (UITableView*) [self.superview viewWithTag:101];
NSLog(#"%#",tb.backgroundColor);
// value: after:UIDeviceRGBColorSpace 1 0 0 1
}
In my code i was trying to set label in iCarouselView.My icarousel contains labels and textView so i am trying to set label but it is not setting properly.I have array of months and setting that array of months to each icarousel label, like this.
(UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (!view)
{
UIViewController * viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PopUpView"];
view = [viewController.view viewWithTag:999];
UILabel *label=(UILabel*)[viewController.view viewWithTag:109];
label.text = [_monthsArray objectAtIndex:index];
CGRect Frame = CGRectMake(view.frame.origin.x, view.frame.origin.y+100, view.frame.size.width, view.frame.size.height);
view.frame = Frame;
}
return view;}
I am loading external view as popUpView in storyBoard and getting label using tag.
And i am returning carousel count as [monthsArray count].
carousel delegate and datasource is also set and reloadData method is also called on iCarousel.
The output which i am getting is something like this.
| January,February,March,November,December|
Please tell me where i am wrong?and what to do now?
Update you code to below one -
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (!view){
UIViewController * viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PopUpView"];
view = [viewController.view viewWithTag:999];
CGRect Frame = CGRectMake(view.frame.origin.x, view.frame.origin.y+100, view.frame.size.width, view.frame.size.height);
view.frame = Frame;
}
UILabel *label=(UILabel*)[view viewWithTag:109];
label.text = [_monthsArray objectAtIndex:index];
return view;
}
iCaurosel will take UIView, In your case you are creating a view controller, which is not retained and is dangerous. See if you change it to view via a custom Xib.