iOS SDK: UITableView Styling - iphone

I've searched high a low for a solution to this problem. I can't find why the style from my nib isn't loading? If I change anything in the nibs the functioning stops. So I've resorted to overriding the style.
I have:
- (id)initWithCoder:(NSCoder *)inCoder
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
// Custom initialization
}
return self;
}
This is on the second view controller, so following from rootviewcontroller. I would rather fix it another way, but if I have to override it I can.
So, the table is now grouped, but how can I programatically change the view background colour?
Any help appreciated.
Ps. For the initial problem, I have 3 nibs: MainWindow.xib, RootViewController.xib and CollectionsViewController.xib created by following this tutorial: http://www.techotopia.com/index.php/Creating_a_Navigation_based_iOS_4_iPhone_Application_using_TableViews#Setting_up_the_Data_in_the_Root_View_Controller
The first table is styled using the RootViewController.xib, but changing CollectionsViewController.xib does nothing.
Cheers,
Rhys
EDIT:
Got it with:
self.tableView.backgroundColor = [UIColor blackColor];
self.parentViewController.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.5 alpha:0.7];

if you override initWithCoder: method, you must call it's super version, which one is responsible for decoding the nib file data

To change the background color of the Table view you need to redesign the table.
In your header viewcontroller add the following code and on IB connect the IBOutlet:
#interface TableController : UIViewController <UITableViewDelegate> {
UITableView *tableView;
}
#property (nonatomic, retain) IBOutlet UITableView *tableView;
and in your implementation file add on viewDidLoad:
- (void)viewDidLoad {
CGFloat tableBorderLeft = 25;
CGFloat tableBorderRight = 15;
CGFloat tableBorderUP = 10;
CGRect tableRect = self.view.frame;
tableRect.origin.x += tableBorderLeft; // make the table begin a few pixels right from its origin
tableRect.origin.y += tableBorderUP;
tableRect.size.width -= tableBorderLeft + tableBorderRight; // reduce the width of the table
tableView.frame = tableRect;
tableView.backgroundColor = [UIColor clearColor];
tableView.separatorColor = [UIColor whiteColor];
tableView.opaque = NO;
tableView.backgroundView = nil;
[super viewDidLoad];
}
Hope that works for you

Related

How to make the changes with slider in viewcontroller 2 reflecting the changes in viewcontroller 1?

I do not know how to figure out the changes of the slider value with the view controller2 in the view controller 1. I think i am calling it correctly but the values are not getting passed to the view.
I put a slider in the nib file and when i change it's value the value of the rect height and width should change.
here's my //appdelegate.m
CGRect bounds = [self.window bounds];
KaleidoTab *view = [[KaleidoTab alloc] initWithFrame:bounds];
view.backgroundColor = [UIColor whiteColor];
KaleidoTabFirstViewController *vc = [[KaleidoTabFirstViewController alloc] init];
[vc setView: view];
KaleidoTabSecondViewController *vc2 = [[KaleidoTabSecondViewController alloc] init];
//[vc2 setView: view];
vc2.vc = vc;
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[vc, vc2];
self.window.rootViewController = self.tabBarController;
here's my //secondviewcontroller.h
#import <UIKit/UIKit.h>
#import "KaleidoTabFirstViewController.h"
#interface KaleidoTabSecondViewController : UIViewController {
IBOutlet UISlider *changeSize;
IBOutlet UILabel *label1; }
#property KaleidoTabFirstViewController *vc;
#property (nonatomic, retain) IBOutlet UISlider *changeSize;
- (IBAction) changeSizeSlider:(id)sender;
here's //secondviewcontroller.m
- (IBAction)changeSizeSlider:(UISlider *)sender
{
/// Change label to match slider's value
label1.text = [NSString stringWithFormat:#"%g", changeSize.value];
CGFloat changeSizeCont = changeSize.value;
((KaleidoTab *)vc.view).rect_width = changeSizeCont;
((KaleidoTab *)vc.view).rect_height = changeSizeCont;
}
kaleidotab.m has the methods for drawing the rectangles.
I synthesized the properties and everything is fine. I think there is something wrong with my firstviewcontroller object.
appreciate your time.
Thanks
Your code is using Java-like syntax rather than Objective-C syntax. You'll find it easier to diagnose issues like these if you adopt Objective-C's approach to OOP syntax:
// For getting property values
[objectName propertyName];
// For setting property values
[objectName setPropertyName];
A lot of how the iOS Framework works depends on following these conventions. Try changing your code to the following:
- (IBAction)changeSizeSlider:(UISlider *)sender
{
// Change label to match slider's value
[label1 text] = [NSString stringWithFormat:#"%g", [changeSize value]];
// Var for changing size
CGFloat changeSizeCont = [changeSize value];
// Log to the console so that we can confirm changeSizeCont is being set appropriately
NSLog(#"changeSizeCont = %d", changeSizeCont);
/* I'm not used to this current syntax, this may be what's going wrong
It's confusing to read, it should be clearer.
I understand that you are attempting to grab the 1st view controller and
change its view properties, I think you can drop the
((KaleidoTab *)vc.view).rect_width and replace it with
vc.view.rect_width
vc.view.rect_height
*/
((KaleidoTab *)vc.view).rect_width = changeSizeCont;
((KaleidoTab *)vc.view).rect_height = changeSizeCont;
// Log to the console so that we can confirm the rect_width and rect_height properties are receiving the change
NSLog("Current values for VC's view properties:");
NSLog(#"rect_width = %d", ((KaleidoTab *)vc.view).rect_width);
NSLog(#"rect_width = %d", ((KaleidoTab *)vc.view).rect_height);
}
This should help you head in the right direction. You'll be able to check on the console whether or not the property values are updating or not. If they are and the view isn't changing appropriately, you probably need to look at the life-cycle of the application and find out where you need to reload or update your view to reflect the changes of your view to the screen.

Set border in UICollectionView

It is my first time that I want to create a UICollectionView. This is how I want it to look like:
I read some tutorials and I know how it works exactly. The thing is as you see in the image, The UICollection cells have border from up, bottom, left and right. Do you know how can set these kind of border in Collection View?
As you see two of the items are selected by red color. is it possible in UICollectionView to have multiple selected items? if yes, could you please give send me some tutorials.
Small example project here: https://github.com/erikt/ETMultiSelect
First you have to make it possible to select more than one cell in the UICollectionView. This is done by setting the allowsMultipleSelectionproperty to YES on the collection view.
The view controller would look something like this:
#import "ETViewController.h"
#import "ETCellView.h"
#implementation ETViewController
static NSString *cellIdentifier = #"cvCell";
- (void)viewDidLoad {
[super viewDidLoad];
// Register our custom collection view cell
[self.collectionView registerClass:ETCellView.class forCellWithReuseIdentifier:cellIdentifier];
// Make it possible to select multiple cells
self.collectionView.allowsMultipleSelection = YES;
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
#pragma mark - UICollectionViewDelegate
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ETCellView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}
#end
The UICollectionViewCell is made up of several views. It has a content view, a background view and a selected background view.
There are many ways to achieve something similar to your picture, but I set the border on the selected background layer and add a subview to the content view that's inset so the background border is visible:
#import "ETCellView.h"
#import <QuartzCore/QuartzCore.h>
#implementation ETCellView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.restorationIdentifier = #"cvCell";
self.backgroundColor = [UIColor clearColor];
self.autoresizingMask = UIViewAutoresizingNone;
CGFloat borderWidth = 3.0f;
UIView *bgView = [[UIView alloc] initWithFrame:frame];
bgView.layer.borderColor = [UIColor redColor].CGColor;
bgView.layer.borderWidth = borderWidth;
self.selectedBackgroundView = bgView;
CGRect myContentRect = CGRectInset(self.contentView.bounds, borderWidth, borderWidth);
UIView *myContentView = [[UIView alloc] initWithFrame:myContentRect];
myContentView.backgroundColor = [UIColor whiteColor];
myContentView.layer.borderColor = [UIColor colorWithWhite:0.5f alpha:1.0f].CGColor;
myContentView.layer.borderWidth = borderWidth;
[self.contentView addSubview:myContentView];
}
return self;
}
#end
The result is something like this:
Clone and play with the sample project.
In a real project you would want to keep track of what the user has selected in the view controller, by adding the selected data model entities to some structure (like a NSMutableArray) in the – collectionView:didSelectItemAtIndexPath: method on the UICollectionViewDelegate protocol.

What is the correct way to re-use UILabel's style?

I have several UILabels which have same visual treatment. Instead of redefining every single property every time, I am thinking of just making copies of an instance and changing the text. Is this how it should be done?
Another way is to create a factory method, but I'm not that fond of the idea.
If you're willing to learn Three20, you could use the TTLabel class, which is incorporated with Three20's stylesheet system, which is basically designed to solve your problem. However, I personally have had trouble parsing Three20's so-called documentation, so I think learning to use this library just to solve your problem is a lot of overhead.
My work-around for this problem is to put together a mini factory method, like this:
// Example:
- (UILabel *)makeLabel {
UILabel *label = [[[UILabel alloc] init] autorelease];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont systemFontOfSize:kMyFontSize];
label.textColor = [UIColor blueColor];
label.textAlignment = UITextAlignmentCenter;
[self.view addSubview:label];
return label;
}
Then when I use this method, other code gets cleaner:
UILabel *nameLabel = [self makeLabel];
nameLabel.text = userName;
UILabel *titleLabel = [self makeLabel];
titleLable.text = myTitle;
// Both labels have consistent style.
PengOne suggests subclassing UILabel. That's an option, although I think this factory method does the job just as well with less work.
It seems like you want to subclass UILabel so that it defaults to your preferences. It's pretty simple to do. Create a new file in Xcode (and Objective C Class) called CustomLabel (or whatever you like).
CustomLabel.m :
#import <UIKit/UIKit.h>
#interface CustomLabel : UILabel {
}
#end
CustomLabel.h :
#import "CustomLabel.h"
#implementation CustomLabel
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// CUSTOMIZATION HERE
}
return self;
}
- (void)dealloc {
[super dealloc];
}
#end
If this seems like overkill, then you can just create a method in your ViewController to do the customization:
-(void)customizeLabel:(UILabel *)label {
// CUSTOMIZATION HERE
}
then call this on any label you create.

iPhone SDK - UIButton not working in custom view

This is driving me nuts... I've seen a few posts on similar issues but can't seem to make it work, so here it is:
it is a very simple example, I am just creating a custom UIButton in a custom view, then assigning it a custom action to respond to touch events. When I run the app, the button is created, but nothing happens when I try to click it.
Here is the code for my custom class:
#import "MySegmentedControl.h"
#implementation MySegmentedControl
#synthesize button1;
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CGFloat a = frame.origin.x+5;
CGFloat b = frame.origin.y+5;
CGFloat l = frame.size.width-15;
CGFloat h = frame.size.height-15;
CGFloat c = a+l;
CGFloat d = b;
CGRect frame2 = CGRectMake(a, b, l, h);
UIButton *mybutton1 = [UIButton buttonWithType:UIButtonTypeCustom];
mybutton1.frame = frame2;
[mybutton1 setTitle:#"TEST" forState:UIControlStateNormal];
mybutton1.titleLabel.textColor = [UIColor blackColor];
mybutton1.backgroundColor = [UIColor blueColor];
[mybutton1 addTarget:self action:#selector(action)forControlEvents:UIControlEventTouchUpInside];
[self setButton1:mybutton1];
self.userInteractionEnabled = YES;
button1.userInteractionEnabled = YES;
[self addSubview:button1];
[self bringSubviewToFront:button1];
}
return self;
}
-(void)action {
[button1 setTitle:#"done" forState:UIControlStateNormal];
button1.backgroundColor = [UIColor greenColor];
NSLog(#"Working!");
}
And here is the appDelegate:
#import "MySegmentedControlAppDelegate.h"
#import "MySegmentedControl.h"
#implementation MySegmentedControlAppDelegate
#synthesize window;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[window makeKeyAndVisible];
MySegmentedControl *mycontrol = [[MySegmentedControl alloc] initWithFrame:CGRectMake(10,50,135,50)];
[window addSubview:mycontrol];
return YES;
}
as you can see from the custom class, from what I've read in other posts I've tried to add a few things to increase my chances of success:
enabling the custom's view userinteraction
bringing the UIButton to front
making sure the button's frame is completely included in the view's frame
...
... yet it still doesn't work!...
Any help would be greatly appreciated - thanks!
Edit: here is also the header for the custom view:
#import <UIKit/UIKit.h>
#interface MySegmentedControl : UIView {
UIButton *button1;
}
#property (nonatomic, retain) IBOutlet UIButton *button1;
- (void)action;
#end
Can you join the header file of your custom view too?
(Sorry to do that in answer, I don't just have enough reputation for the moment).
Edit (and real answer) :
I've build a projet similar to yours and I think I've find the problem.
Your button frame is not good. Look at this screenshot from simulator, custom UIView frame is in red (just add self.backgroundColor=[UIColor redColor]; in your view constructor) :
By using this code :
CGFloat a = frame.origin.x+5;
CGFloat b = frame.origin.y+5;
CGFloat l = frame.size.width-15;
CGFloat h = frame.size.height-15;
You refer at the frame in windows base coordinates ! So your button is outside of your view and it can't handle touch event.
If you want to place your button dynamically, you should use this :
CGFloat a = self.bounds.origin.x+5;
CGFloat b = self.bounds.origin.y+5;
GFloat l = self.bounds.size.width-15;
CGFloat h = self.bounds.size.height-15;
By using self.bounds you use view base coordinate and it's working (see screenshots below) !
Hope this helps !

Custom colors in UITabBar

Is it possible to use custom colors and background images in a UITabBar? I realize that Apple would like everyone to use the same blue and gray tab bars, but is there any way to customize this?
Second, even I were to create my own TabBar-like view controller, along with custom images, would this violate Apple's Human Interface Guidelines?
I found an answer to this at Silent Mac Design.
I implemented this way:
First make a subclass of UITabBarContoller
// CustomUITabBarController.h
#import <UIKit/UIKit.h>
#interface CustomUITabBarController: UITabBarController {
IBOutlet UITabBar *tabBar1;
}
#property(nonatomic, retain) UITabBar *tabBar1;
#end
 
// CustomUITabBarController.m
#import "CustomUITabBarController.h"
#implementation CustomUITabBarController
#synthesize tabBar1;
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0.0, 0, self.view.bounds.size.width, 48);
UIView *v = [[UIView alloc] initWithFrame:frame];
[v setBackgroundColor:[[UIColor alloc] initWithRed:1.0
green:0.0
blue:0.0
alpha:0.1]];
[tabBar1 insertSubview:v atIndex:0];
[v release];
}
#end
And in your Nib file replace the class of your TabBar Controller with CustomUITabBarController.
FYI, from iOS 5 onwards you can customize various aspects of the UITabBar, including setting its background image using the backgroundImage property.
The new UITabBar "Customizing Appearance" properties in iOS 5 are:
backgroundImage
selectedImageTintColor
selectionIndicatorImage
tintColor
Given that Apple have introduced these methods in iOS 5, then it's possible they may be more sympathetic to attempts to customize the UITabBar for earlier OSes. This website says the Twitter app uses a custom tab bar, so that might be more reason that Apple would let such an app into the App Store, it's no guarantee though!
Use Following images ( Assuming, tabBar is having 5 Tabs as follows )
Create a new project using - "TabBar Application" template & Place following code.
Contents of AppDel.h File.
#import <UIKit/UIKit.h>
#interface cTabBarAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#property (nonatomic, retain) IBOutlet UIImageView *imgV;
#end
Contents of AppDel.m File.
#import "cTabBarAppDelegate.h"
#implementation cTabBarAppDelegate
#synthesize window=_window;
#synthesize tabBarController=_tabBarController;
#synthesize imgV = _imgV;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.tabBarController.delegate=self;
self.imgV.frame=CGRectMake(0, 425, 320, 55);
[self.tabBarController.view addSubview:self.imgV];
self.tabBarController.selectedIndex=0;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
NSUInteger index=[[tabBarController viewControllers] indexOfObject:viewController];
switch (index) {
case 0:
self.imgV.image=[UIImage imageNamed:#"tBar1.png"];
break;
case 1:
self.imgV.image=[UIImage imageNamed:#"tBar2.png"];
break;
case 2:
self.imgV.image=[UIImage imageNamed:#"tBar3.png"];
break;
case 3:
self.imgV.image=[UIImage imageNamed:#"tBar4.png"];
break;
case 4:
self.imgV.image=[UIImage imageNamed:#"tBar5.png"];
break;
default:
break;
}
return YES;
}
At the beginning of ***ViewController.m add the following might help set background image of UITabBar.
#implementation UITabBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"background.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end
If you want to use custom colors for the icons (and not just the background) instead of the default gray and blue, do it like this: http://blog.theanalogguy.be/2010/10/06/custom-colored-uitabbar-icons/
Basically, you need to create complete tabbar images (background and icons and text) for each selected tab and set your UITabBarItems to no icon and no title and insert the image into the tabbar as an UIImageView in viewWillAppear:
And Apple won't mind since we are not using any private APIs.
Since iOS 7.0, you can use -[UIImage imageWithRenderingMode:] with UIImageRenderingModeAlwaysOriginal to preserve colors:
// Preserve the colors of the tabs.
UITabBarController *controller = (UITabBarController *)((UIWindow *)[UIApplication sharedApplication].windows[0]).rootViewController;
NSArray *onIcons = #[ #"tab1-on", #"tab2-on", #"tab3-on" ];
NSArray *offIcons = #[ #"tab1-off", #"tab2-off", #"tab3-off" ];
NSArray *items = controller.tabBar.items;
for (NSUInteger i = 0; i < items.count; ++i) {
UITabBarItem *item = items[i];
item.image = [[UIImage imageNamed:offIcons[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
item.selectedImage = [[UIImage imageNamed:onIcons[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
Works like a charm.
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UITabBar appearance] setSelectedImageTintColor:[UIColor redColor]];
return YES;
}
As far as the UITabBar class is concerned, the icons in the bar are limited to the colours: blue for selected and grey for unselected. This is because the tab bar only uses the alpha value from the icons you supply to create the image on the bar.
The bar itself is limited to being black, as far as I can remember. I've not seen anything like the 'tint' property on UINavigationBar in the docs.
I guess you could go ahead and create your own tab bar style class and do what you want with it, but I have absolutely no idea how that fits in with Apple's HIG, or whether or not they'd challenge it during the review process.
In my experience, Apple reviewers only rejected my app if I didn't use THEIR UI elements according to the HIG. They might have a different view when it's your own UI elements you're playing with.
Here's the document that says we can't change pressed or selected appearance with our icons.
https://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/MobileHIG/IconsImages/IconsImages.html#//apple_ref/doc/uid/TP40006556-CH14-SW1
It's under the heading
Icons for Navigation Bars, Toolbars, and Tab Bars
Its possible without adding any subView.
In the class where you define the tab bar set the property of the
tabBarItem to ->>
UITabBarItem *tabBarItem1 = [[self.tabBar.tabBar items] objectAtIndex:0];
[tabBarItem1 setFinishedSelectedImage:[UIImage imageNamed:#"campaigns_hover.png"] withFinishedUnselectedImage:[UIImage imageNamed:#"campaigns.png"]];
Its a property of tabBarItem and u can change the default blue image to a custom image.
campaigns_hover.png is the selected custom image AND
campaigns.png is the custom image when not selected...
Enjoy the secret.. :)
The below code helps you to add custom colors with RGB values to ur tabBar.
self.tabBarController.tabBar.tintColor = [[UIColor alloc] initWithRed:0.00
green:0.62
blue:0.93
alpha:1.0];
You can do that without -insertSubview:atIndex, because a new UIView is not needed. You can apply a theme using QuartzCore on each view (UITabBar and it's subviews). So the UITabBar's background is added as I've described here.
Now we must apply the image on each UITabBarItem as it's background:
// UITabBar+CustomItem.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface UITabBar (CustomItem)
-(void)setSelectedItemBackground:(UIImage *)backgroundImage;
#end
Now the .m file:
// UITabBar+CustomItem.m
#implementation UITabBar (CustomItem)
#define kItemViewTag 445533 // <-- casual number
#define kItemViewOldTag 445599 // <-- casual number different from the above
-(void)setSelectedItemBackground:(UIImage *)backgroundImage {
UIView *oldView = [self viewWithTag:kImageViewItemTag];
oldView.layer.contents = nil; // <-- remove the previous background
oldView.tag = kItemViewOldTag; // <-- this will avoid problems
NSUInteger index = [self.items indexOfObject:self.selectedItem];
UIView *buttonView = [self.subviews objectAtIndex:index];
buttonView.tag = kItemViewTag;
buttonView.layer.contents = (id)backgroundImage.CGImage; // <-- add
// the new background
}
#end
You can also change the color of the selected images, as someone made here. But what I'm wondering is: can I change the color of the selected label? The answer is yes, as described below (the following works on ios 3.x/4.x, not iOS5+):
#implementation UITabBar (Custom)
#define kSelectedLabel 334499 // <-- casual number
-(void)changeCurrentSelectedLabelColor:(UIColor *)color {
UIView *labelOldView = [self viewWithTag:kSelectedLabel];
[labelOldView removeFromSuperview];
NSString *selectedText = self.selectedItem.title;
for(UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class])
isEqualToString:#"UITabBarButton"]) {
for(UIView *itemSubview in subview.subviews) {
if ([itemSubview isKindOfClass:[UILabel class]]) {
UILabel *itemLabel = (UILabel *)itemSubview;
if([itemLabel.text isEqualToString:selectedText]) {
UILabel *selectedLabel = [[UILabel alloc]
initWithFrame:itemLabel.bounds];
selectedLabel.text = itemLabel.text;
selectedLabel.textColor = color;
selectedLabel.font = itemLabel.font;
selectedLabel.tag = kSelectedLabel;
selectedLabel.backgroundColor = [UIColor clearColor];
[itemSubview addSubview:selectedLabel];
[selectedLabel release];
}
}
}
}
}
}
#end