Some background. I'm helping a group of students at my son's school and they want to write a simple tracking app that managers student observations that will be used on iPod Touch.
I've only done very basic iOS development using the standard widgets, but I'm keen to help.
We worked through and designed the functionality and interface of the app and are now starting to program. Where I am out of my depth is that they want to have a strip running along the bottom of the screen with each day as a little block displaying the date and date and an indicator to show if there was an observation for that day.
I was hoping that you guys might be able to point me in the right direction, either an existing widget or explain in detail how to achieve this. I've tried a few approaches with no luck.
I'd appreciate any assistance with this as I know this must be a common requirement, but I'm struggling to get through this.
I thought I'd post my final solution in case others find it useful.
In view root view controller I added a custom UITableViewController which basically rotates the table 90 degrees and then rotates each table cell -90 degrees. It does what I want is was pretty straight forward.
Code for root view controller. This sets the size and position of the table :
scrollingDateViewController=[[ScrollingDateViewController alloc] initWithNibName:#"ScrollingDateView" bundle:[NSBundle mainBundle]];
CGRect rect=CGRectMake(0,330,320,100);
scrollingDateViewController.view.frame=rect;
scrollingDateViewController.view.backgroundColor=[UIColor clearColor];
scrollingDateViewController.delegate = self;
[self.view addSubview:scrollingDateViewController.view];
Key Code for ScrollingDateViewController. This rotates the table 90 degrees and the each cell -90 degress :
- (void)viewDidLoad {
today = [[NSDate alloc] init];
CGRect rect=self.view.frame;
myTableView.frame=rect;
myTableView.layer.transform = CATransform3DRotate(CATransform3DIdentity,1.57079633,0,0,1);
myTableView.backgroundColor=[UIColor clearColor];
myTableView.separatorColor=[UIColor clearColor];
myTableView.frame=rect;
myTableView.rowHeight=44; // cellWidth
myTableView.showsHorizontalScrollIndicator=NO;
myTableView.showsVerticalScrollIndicator=NO;
myTableView.separatorColor=nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"tableCell"];
if(!cell){
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"tableCell"];
cell.contentView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"cell_back.png"]];
cell.contentView.transform = CGAffineTransformMakeRotation(-1.57079633);
cell.selectionStyle=UITableViewCellSelectionStyleGray;
// Add background image view
CGRect rect=CGRectZero;
UIImageView *imgView=[[UIImageView alloc] initWithFrame:rect];
imgView.contentMode=UIViewContentModeScaleToFill;
imgView.layer.transform = CATransform3DRotate(CATransform3DIdentity,-1.57079633,0,0,1);
imgView.tag=101;
[cell addSubview:imgView];
rect.origin.x=0;
rect.origin.y=0;
rect.size.height=80;
rect.size.width=44;
imgView.frame=rect;
[imgView release];
// Add Day Label
UILabel *dayLabel=[[UILabel alloc] initWithFrame:rect];
dayLabel.layer.transform = CATransform3DRotate(CATransform3DIdentity,-1.57079633,0,0,1);
dayLabel.tag=102;
dayLabel.font = [UIFont fontWithName:#"Geogrotesque-Medium" size:14.0];
dayLabel.textAlignment=UITextAlignmentCenter;
dayLabel.backgroundColor=[UIColor clearColor];
dayLabel.textColor=[UIColor darkGrayColor];
[cell addSubview:dayLabel];
rect.origin.x=40;
rect.origin.y=0;
rect.size.height=44;
rect.size.width=20;
dayLabel.frame=rect;
[dayLabel release];
// Add Date Label
UILabel *dateLabel=[[UILabel alloc] initWithFrame:rect];
dateLabel.layer.transform = CATransform3DRotate(CATransform3DIdentity,-1.57079633,0,0,1);
dateLabel.tag=103;
dateLabel.font = [UIFont fontWithName:#"Geogrotesque-Bold" size:18.0 ];
dateLabel.textAlignment=UITextAlignmentCenter;
dateLabel.backgroundColor=[UIColor clearColor];
dateLabel.textColor=[UIColor darkGrayColor];
[cell addSubview:dateLabel];
rect.origin.x=55;
rect.origin.y=0;
rect.size.height=44;
rect.size.width=20;
dateLabel.frame=rect;
[dateLabel release];
}
UILabel *label=(UILabel*)[cell viewWithTag:102];
label.text= [self getDayString:displayDate];
label=(UILabel*)[cell viewWithTag:103];
label.text= [self getDateString:displayDate];
return cell;
}
IMHO, you should create a view which you want to be shown for each date. Create something like
#interface DayView : UIView {
You can implement it with nib or make everything programmatically in drawRect method.
After it go to your Xcode documentation and search for UIScrollView. Xcode will provide your with code samples, use project "Scrolling" to find out how to use scrollView. In this sample they scroll pics, and you replace them with our custom DayViews.
Good luck!
Related
I've been struggling with this for awhile and was hoping anyone could shed some light on why this isn't working.
I'm simply try to implement a Popover on a TableViewCell. Here is the code..
TodoView.m
- (void)tableView:(TUITableView *)tableView didClickRowAtIndexPath:(TUIFastIndexPath *)indexPath withEvent:(NSEvent *)event {
// MyViewController is a TUIViewController with a nib called MyView with just a button in it
MyViewController *t = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
TUIView *theView = [[TUIView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300)];
TUIPopover *myPopover = [[TUIPopover alloc] initWithContentViewController:t];
[myPopover showRelativeToRect:NSMakeRect(0, 0, 300, 300) ofView:theView preferredEdge:NSMaxYEdge];
}
For awhile, nothing would show up. I could tell something was happening though because the window itself would lose focus as if a Popover was there.
Sometimes I see a very small blip– like a small rectangle 2px by 2px. It's hard to see it, looks like dead pixel on the screen, but it appears sometimes when I run this code.
The TUIPopover is from the Twitter UIKit Framework.
Some possibilities...
1) The popover cannot be seen over the CGFillRect?
TodoTableViewCell.m
- (void)drawRect:(CGRect)rect
{
CGRect b = self.bounds;
CGContextRef ctx = TUIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(ctx, 247.0/255, 247.0/255, 247.0/255, 1);
CGContextFillRect(ctx, b);
}
2) The popover doesn't fit inside the TableViewCell and cannot be seen
Anyone have any thoughts?
Really simple answer:
I forgot to set the content size of the popover!
So, for anyone else who is wondering why their popup isn't working, make sure you set the content size!
TUIPopover *p = [[TUIPopover alloc] initWithContentViewController:commentsViewController];
[p setAnimates:TRUE];
[p setContentSize:CGSizeMake(300, 350)];
[p setBehaviour:TUIPopoverViewControllerBehaviourTransient];
[p showRelativeToRect:b.bounds ofView:b preferredEdge:CGRectMinYEdge];
So I created a custom UINavigationItem category to be able to make a custom titleview for my navbar, but everytime I push/pop a view, it simply adds the new title without getting rid of the old one causing the title to just be a jumble of letters. Here's the relevant code:
#implementation UINavigationItem (CustomNavigationItem)
-(UIView *)titleView
{
[self setTitleView:nil];
UILabel *newTitleView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 220, 32)];
newTitleView.center = CGPointMake(160, 22);
newTitleView.backgroundColor = [UIColor clearColor];
newTitleView.textColor = [UIColor whiteColor];
newTitleView.textAlignment = UITextAlignmentCenter;
newTitleView.text = self.title;
newTitleView.textAlignment = UITextAlignmentCenter;
return newTitleView;
}
#end
You have to remove the old uilabel from its superview, by setting to nil it doesn't do that. That's why you are messing the letters on screen. I also do not think you are getting a recursion, because you are caling the setter, but I maybe wrong.
A quick thing you could is to assign a tag to your newest created view.
[[self.view viewWithTag:YourCustomEnumTag] removeFromSuperView];
// create your view....
textView.tag=YourEnumCustomTag;
hi I have a problem I made an application based on apples sample app called photoscroller and i want to add a login screen.but when i add it the showed view move upward 10-15 pixels and the main window is visible underneath.I ask why?
Parts of my code:
at view did load:
InfoViewController *infoView = [[InfoViewController alloc] initWithNibName:nil bundle:nil];
self.view = infoView.view;
[infoView release];
then later after validating the login:
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
pagingScrollView.delegate = self;
self.view = pagingScrollView;
...
I do not know why is pushed upward when i add other view.
thank for every answer
Could you past the method - (CGRect) frameForPagingScrollView, without that method it's bit harder to understand your code.
But i guess the self.view.frame and the CGRect returned from that method differ.
Further guess would be, that the difference are not 10-15 pixels, but 20 pixels (for the height of the UIStatusBar), which might be enabled in your .xib-File but is actually not displayed.
I am making an NSTableView programmatically but for some reason no matter what I do, I cannot make the darn headerView show up. It is imperative that I do this programmatically and not use the IB because I am actually developing this widget in an IDE called clozure cl which is a lisp ide that includes a cocoa bridge. Originally I thought this problem might have been caused by my development environement but I just created an example in Xcode using only objective C and it seems that the problem persists. What I do is pretty straightforward:
I make a window in the IB and in its awkefromnib methods I create and setup a table-view here is the code:
- (void)awakeFromNib {
mydatasource *data = [[mydatasource alloc] init];
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:#"id"];
NSTableView *table = [[NSTableView alloc] initWithFrame: [[self
contentView]frame]];
[table setDataSource:data];
[table addTableColumn:column];
[table addTableColumn:column];
[[self contentView] addSubview:table];
}
Here is the code for my data source object:
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
printf("NUM ROwS");
return 4;
}
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
printf("THE OTHER ONE");
return #"OKAY";
}
With this code I get a window with two colums and four rows and each cell displaying the string "OKAY", this is all fine and good except the table has no header. This might make sense except when I look at the tables header method, it has an initialized header with a frame whose values make sense. I am just wondering why I do not see it. Is there some special kind of magic I need to do so the header will display? I cannot seem to find any clues in the documentation. Once again it is imperative for the lisp ide that this be done programmatically so it would not be helpful no suggest using the IB which I know will have a working headerView. Thanks a lot.
Here is some code to programmatically create a table view with a scroll bar, and multiple columns.
// create a table view and a scroll view
NSScrollView * tableContainer = [[NSScrollView alloc] initWithFrame:NSMakeRect(10, 10, 380, 200)];
NSTableView * tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 364, 200)];
// create columns for our table
NSTableColumn * column1 = [[NSTableColumn alloc] initWithIdentifier:#"Col1"];
NSTableColumn * column2 = [[NSTableColumn alloc] initWithIdentifier:#"Col2"];
[column1 setWidth:252];
[column2 setWidth:198];
// generally you want to add at least one column to the table view.
[tableView addTableColumn:column1];
[tableView addTableColumn:column2];
[tableView setDelegate:self];
[tableView setDataSource:self];
[tableView reloadData];
// embed the table view in the scroll view, and add the scroll view
// to our window.
[tableContainer setDocumentView:tableView];
[tableContainer setHasVerticalScroller:YES];
[[self contentView] addSubview:tableContainer];
[tableContainer release];
[tableView release];
[column1 release];
[column2 release];
Just thought I would post this for anyone still looking for a straight forward answer. :)
I wrote this Swift version of #Alex Nichol's answer:
let tableContainer = NSScrollView(frame:NSMakeRect(10, 10, 380, 200))
let tableView = NSTableView(frame:NSMakeRect(0, 0, 364, 200))
let column1 = NSTableColumn(identifier: "Col1")
let column2 = NSTableColumn(identifier: "Col2")
column1.width = 252
column2.width = 198
tableView.addTableColumn(column1)
tableView.addTableColumn(column2)
tableView.setDelegate(self)
tableView.setDataSource(self)
tableView.reloadData()
tableContainer.documentView = tableView
tableContainer.hasVerticalScroller = true
window.contentView.addSubview(tableContainer)
It worked.
Well I answered my own question and I thought this might be helpful to someone else, it seems that that the headerView will only show up if you add the tableview to a scrollview.
I have a UIViewController class where I create a UIView instance.
And then I initialize (means fill) it with 25 subviews each containing an image (1, 2, ..., 25). Then after clicking 5 times in these image I called a function where I used
for(UIView *subview in [contentView subviews]) {
[subview removeFromSuperview];//ContentView name of my view
}
to remove the previously added subview. And then I use the same approch to
add 25 new subviews (image 1,2,3,....25). But this time no subview is added.
Can someone plz give me full code of adding & removing subview.
I have used the following code when I first add subview
//create main window
contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
contentView.backgroundColor = [UIColor blackColor];
self.view = contentView;
[contentView release];
//adding 25 subview 1st time
int a=0;
int b=0;
for (int i = 0; i < 26; i++)
{
CGRect dragRect = CGRectMake(0.0f, 0.0f, x, y);
dragRect.origin = CGPointMake(a,b);
DragView *dragger = [[DragView alloc] initWithFrame:dragRect];
NSString *Flower = [[NSArray arrayWithObjects:#"1.png", #"2.png", #"3.png",#"4.png", #"5.png", #"6.png",#"7.png",#"8.png", #"9.png",#"10.png", #"11.png", #"12.png",#"13.png",#"14.png",#"15.png",#"16.png",#"17.png",#"18.png",#"19.png",#"20.png",#"21.png",#"22.png",#"23.png",#"24.png",#"25.png",#"26.png", nil] objectAtIndex:i];
[dragger setImage:[UIImage imageNamed:Flower]];
[dragger setUserInteractionEnabled:YES];
[self.view addSubview:dragger];
[dragger release];
a+=10;
b+=10;
}
//then removing 25 subview
//adding 25 subview 2nd times
I used the same approch to add the second time as first time, but the problem is that when I remove 25 subview and then add 25 subview, these subview are not added/shown, the view remain same. I am tired with these problem. plz someone help me.
The problem might be the way you remove the old views. You are modifying an array while iterating over it, which does not work. Try this code to remove the old views:
UIView* subview;
while ((subview = [[contentView subviews] lastObject]) != nil)
[subview removeFromSuperview];
A nice one liner is:
[view.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
Looking at your code, I can suggest the following changes. There's one line in your for loop which is terribly inefficient:
NSString *Flower = [[NSArray arrayWithObjects:#"1.png", #"2.png", #"3.png",#"4.png", #"5.png", #"6.png",#"7.png",#"8.png", #"9.png",#"10.png", #"11.png", #"12.png",#"13.png",#"14.png",#"15.png",#"16.png",#"17.png",#"18.png",#"19.png",#"20.png",#"21.png",#"22.png",#"23.png",#"24.png",#"25.png",#"26.png", nil] objectAtIndex:i];
[dragger setImage:[UIImage imageNamed:Flower]];
Either take the Flower initialisation out of the the for loop (to only create the array once) or do the following:
[dragger setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d.png", i]]];
The code itself looks like it should work though. If you add 26 subviews then remove the 26 subviews then add the 26 subviews in exactly the same way then it should display as you'd expect.