I can't figure out why this UIButton is not working in the header of my UITableView. It's appearing there but the touch is not working.
The NSLog statement isn't triggering either. It's almost like it's beneath another view or something so that you can see it but the press action doesn't work.
thanks for any help with this
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *sectionHeader = [[UILabel alloc] initWithFrame:CGRectNull];
sectionHeader.backgroundColor = [UIColor clearColor];
[sectionHeader addSubview:self.topMapView];
// add map launch button
mapLaunchButton = [UIButton buttonWithType:UIButtonTypeCustom];
[mapLaunchButton addTarget:self
action:#selector(mapButtonTouch:)
forControlEvents:UIControlEventTouchDown];
[mapLaunchButton setTitle:#"ggggggg" forState:UIControlStateNormal];
mapLaunchButton.frame = CGRectMake(0, 0, 300, 90);
mapLaunchButton.backgroundColor = [UIColor redColor];
[sectionHeader addSubview:mapLaunchButton];
// [sectionHeader bringSubviewToFront:mapLaunchButton];
self.tableView.tableHeaderView = sectionHeader;
return sectionHeader;
}
- (void)mapButtonTouch:(id)sender {
NSLog(#"map button was touched");
}
I can see more than one mistake -
If your table has only one section (to verify this check for numberOfSectionsInTableView delegate) then remove this line -
self.tableView.tableHeaderView = sectionHeader;
Set sectionHeader.frame to something appropriate (not CGRectNull). The benefit of setting section header (versus table header view) is that when user will scroll the table rows then the section header will stick on top (float) and will not go away. (Plain style table)
Still the problem is not resolved, then please verify his method -
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 50; // depending upon the height of the sectionHeader
}
As pointed out by other poster, to capture touch event on UIButton UIControlEventTouchUpInside is preferred event.
EDIT - (as table header view implementation)
If you want to scroll it up then make it as table header (not section header). So remove all this from viewForHeaderInSection and put it inside viewDidLoad of your view controller class. Keep this line (don't remove it in this case) -
self.tableView.tableHeaderView = sectionHeader;
However, above points 2 and 4 still holds true.
If you change UIControlEventTouchDown to UIControlEventTouchUpInside?
One thing is the section header, and another is the table header. You are assigning the same view as both. I'm not sure this is the cause of your problem, but it's something to get you started.
Instead of implementing that method, on your viewDidLoad, create that view and assign it as the self.tableView.tableHeaderView
Additionally, the most common user experience is associated with the UIControlEventTouchUpInside (the action will not execute until the finger is lifted and still inside the button). However this likely has nothing to do with your issue. It's just a matter of when the action is called.
If this doesn't fix your issue let me know and I'll try to check if there's something else I've missed
Cheers!
If you add a view
self.tableView.tableHeaderView = ({
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 184.0f)];
you can add new components: UIImageView, UIlabel...
Its works for me!
I tested.
The final code:
self.tableView.tableHeaderView = ({
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 184.0f)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 40, 100, 100)];
imageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
imageView.image = [UIImage imageNamed:#"avatar.jpg"];
imageView.layer.masksToBounds = YES;
imageView.layer.cornerRadius = 50.0;
imageView.layer.borderColor = [UIColor whiteColor].CGColor;
imageView.layer.borderWidth = 3.0f;
imageView.layer.rasterizationScale = [UIScreen mainScreen].scale;
imageView.layer.shouldRasterize = YES;
imageView.clipsToBounds = YES;
UIButton *mapLaunchButton = [UIButton buttonWithType:UIButtonTypeCustom];
[mapLaunchButton addTarget:self action:#selector(mapButtonTouch:) forControlEvents:UIControlEventTouchDown];
[mapLaunchButton setTitle:#"ggggggg" forState:UIControlStateNormal];
mapLaunchButton.frame = CGRectMake(0, 0, 300, 90);
mapLaunchButton.backgroundColor = [UIColor redColor];
[view addSubview:imageView];
[view addSubview:mapLaunchButton];
view;
});
I had the same problem. Changing UIXXXXX from UILabel to UIView in the following line worked for me:
UIView *sectionHeader = [[UIXXXXX alloc] initWithFrame:CGRectNull];
and I didn't use:
self.tableView.tableHeaderView = sectionHeader;
Related
I added the date label and the share button via code. Now I want to add a static button in the right top corner to open a slide out menu(I'm using MMDrawerController). If I'm adding the via code, it's moving with the carousel.
If I'm adding a button on the name label(My App) on the storyboard, it's not getting clicked and the carousel gesture is being registered instead of the button click.
How should I proceed to add a button for a slide out menu on the right ?
-(UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view{
UIView *magView = nil;
CGFloat height = self.myCarousel.bounds.size.height;
CGFloat width = self.myCarousel.bounds.size.width;
//Magazine View
magView = [[UIView alloc] initWithFrame:CGRectMake(0, 40, width/1.35, height/1.75)];
magView.backgroundColor = [UIColor clearColor];
UIImageView *magImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"4 1:2.jpg"]];
magImage.frame = CGRectMake(0, 0, width/1.35, height/1.75);
[magView addSubview:magImage];
//Date Label
UILabel *dateLabel = nil;
dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, height/1.7, width/4, height/25)];
dateLabel.backgroundColor = [UIColor clearColor];
dateLabel.text = #"12-03-2017";
dateLabel.font = [UIFont fontWithName:#"Roboto-Black" size:5];
dateLabel.textColor = [UIColor whiteColor];
//Share Button
UIButton *shareButton = nil;
shareButton = [[UIButton alloc] initWithFrame:CGRectMake(width/1.49, height/1.7, height/25, height/25)];
shareButton.backgroundColor = [UIColor clearColor];
[shareButton setBackgroundImage:[UIImage imageNamed:#"share_icon_1x"] forState:UIControlStateNormal];
[magView addSubview:dateLabel];
[magView addSubview:shareButton];
return magView;
}
Simulator
Storyboard
How do I proceed to add the button ?
Add button to storyboard and after adding carousel programmatically. add code to bring the button to top on view.
[self.view bringSubviewToFront:button];
if you are adding it programmatically then just after [self.view addSubview:carousel];
call [self.view bringSubviewToFront:button](make sure button is added on view before calling it)
I solved the issue. Instead of taking the view of the ViewController I dragged/dropped another view onto the ViewController and displayed the carousel on it. Now I can set the button easily. Thanks for the help though. Cheers
It will help you
[xyzButton.superview setUserInteractionEnabled:YES];
:)
I have set header back ground using the code below but I want to change the color of header back again on run time when I click on the button that is added as a subview on the header.
please provide me code, thanks in advance :)
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
header = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _tableView.bounds.size.width, 50)];
header.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"homeCellHeaderBackGround.png"]];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 10, 100, 30)];
label.text = _array[section][#"name"];
label.textColor = [UIColor whiteColor];
[header addSubview:label];
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(230, 10, 70, 35)];
[button addTarget:self action:#selector(onExpandButton:) forControlEvents:UIControlEventTouchUpInside];
//[button setTitle:#"Expand" forState:UIControlStateNormal];
[button setTag:section];
[header addSubview:button];
return header;
}
You can modify it in run time by:
first:
you can declare a global variable/propery like:
#property (nonatomic) UIView *tableHeader;
and set it under -(void)viewDidLoad
like
self.tableView.tableHeaderView = self.tableHeader;
or using the delagate:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return self.tableHeader;
}
and modify it anywhere you like, but dont forget to reload you table section header, probably [tableView reloadSections:NSIndexSet withRowAnimation:UITableViewRowAnimation]; will do.
But
In your case you can retreive/get the tableHeader made inside the delegate:
-(UIView *)tableView:tableView viewForHeaderInSection:section
by
UIView *tableHeaderView = [self tableView:yourTableView viewForHeaderInSection:yourSection];
then modify tableHeaderView..
or simply reassign tableHeader by:
yourTableView.tableHeaderView = tableHeaderView;
your by using header alone, since as i can see it's a global variable..
change/update it directly like:
header.backgroundColor = [UIColor yourNewColor];
hope i've helped you.. happy coding, cheers..
You can change the background color of the section header by following code:
- (IBAction)onExpandButton:(id)sender {
UIView *header = ((UIButton *)sender).superView;
header.backgroundColor = <Whatever UIColor you like>;
...
}
-(IBAction)onExpandButton:(UIButton *)sender
{
UIView *tmpView = [self.YourTableViewName headerViewForSection:sender.tag];
tmpView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"homeCellHeaderBackGround.png"]];
}
-You got the view from your table view header for section method. After you can set your image view on view.
I'm creating a UITableView with more section "closed". When I tap on a section, with a workaround, I make the section explode showing the rows for that section. The problem that I have is that I have to animate the header to collapse it to an half of its width.
This is the code I'm using
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
Sport *sport = [self.sportList objectAtIndex:section];
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, tableView.frame.size.width, SECTION_HEIGHT)];
headerView.backgroundColor = [UIColor colorWithRed:31.0/255.0 green:59.0/255.0 blue:143.0/255.0 alpha:1.0];
UILabel *sportTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 2.0, tableView.frame.size.width, SECTION_HEIGHT-4)];
sportTitle.textColor = [UIColor whiteColor];
[headerView addSubview:sportTitle];
UIButton *sportButton = [[UIButton alloc] initWithFrame:headerView.frame];
[sportButton addTarget:self action:#selector(didSelectedButton:) forControlEvents:UIControlEventTouchUpInside];
[sportButton setTitle:#"" forState:UIControlStateNormal];
[sportButton setBackgroundColor:[UIColor clearColor]];
sportButton.tag = section;
[headerView addSubview:sportButton];
return headerView;
}
This is the selector:
-(void)didSelectedButton:(UIButton *)_button
{
if (self.delegate && [self.delegate respondsToSelector:#selector(didSelectedSport:)])
{
[self.delegate didSelectedSport:sport];
}
}
The delegate updates only the dataSource and calls the reloadData, making possible the explosion/collapse of the sections. But now I want to animate the changes to the width of the header for that section, is it possible? Thanks
EDIT: I can modify the header using the property superview of the UIButton in the selector, but I have to do it after the controller drew it
Try using the function below. Set your superview of uibutton as the from view in the method.
Create another view with your needed width and set it as to view in the method. Give a animation of choice in options.
[UIView transitionFromView:from
toView:to
duration:.5
options:UIViewAnimationOptionTransitionFlipFromBottom
completion:^(BOOL finished) {
}];
I really need your help with this one (first post on SO -- be gentle):
I have two dynamic UIButtons which I would like to have centered in a UIView, which in turn should be centered in a UINavigationbar and UIToolbar. I can't - despite a lot of Googling - seem to figure out a proper way to do this.
This is what I've done so far:
In viewDidLoad, I add the two buttons as subviews and set the view as the UINavigationbar's titleView
self.myClass.viewForTitleAndButton = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 32)];
[self.myClass.viewForTitleAndButton setBackgroundColor:[UIColor blackColor]];
[self.myClass.viewForTitleAndButton addSubview:self.myClass.myButton];
[self.myClass.viewForTitleAndButton addSubview:self.myClass.myOtherButton];
self.navigationItem.titleView = self.myClass.viewForTitleAndButton;
In a method being triggered when I press certain buttons, I set the title (and bounds) of one of the buttons depending on what's clicked:
CGSize titleSize = [title sizeWithAttributes:#{NSFontAttributeName : [UIFont italicSystemFontOfSize:17.0]}];
CGSize screenSize = [UIScreen mainScreen].bounds.size;
CGFloat newX = (screenSize.width - titleSize.width) / 2;
CGRect buttonFrame = self.myClass.myButton.frame;
//Removing the line below doesn't do any difference at the moment
self.myClass.myButton.bounds = CGRectMake(newX, buttonFrame.origin.y, titleSize.width+8, buttonFrame.size.height);
[self.myClass.myButton setTitle:title forState:UIControlStateNormal];
NSLog(#"Title: %#", title);
//title is a NSString that changes depending on what is clicked. I am 100% sure it changes as I can see it in the log every time the method is triggered.
The problem is that the title of myButton is not changed. It worked before with the very same button when it was placed in a different spot and not as a subview.
Q1: What am I missing to make the title of the button change?
Q2: Is adding the buttons as subViews to a view that is then placed in the navigationbar and toolbar respectively a sound way to accomplish what I want?
This is really bugging me, any pointers in the right direction is much appreciated.
I don't think you can add a button which is already an outlet of a view controller. Thinking in another way, a button(view) can only has one superview.
Create button dynamically for the title view.
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *iv = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 160, 44)];
iv.backgroundColor = [UIColor greenColor];
titleButton = [UIButton buttonWithType:UIButtonTypeCustom];
titleButton.frame = CGRectMake(0, 0, 120, 44);
[titleButton setTitle:#"test" forState:UIControlStateNormal];
[titleButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[iv addSubview:titleButton];
self.navigationItem.titleView = iv;
}
//some event to change the button title
- (void)click:(UIButton *)button
{
[titleButton setTitle:#"I changed" forState:UIControlStateNormal];
}
I'm have been trying to get the header of the table scrolling along with the UITableView. It's finally working, however, now there's a whitespace showing up right under the map view (see screenshot). I had difficulty getting the map in the table header section to scroll with the table and also to get the UIButton to trigger within the table header with a user touch (the UIButton simply expands the map to full screen.).
I asked a question related to this yesterday regarding the scrolling and button touch. Those are working now - I'm sure the coding could be done better, but this is what I have at the moment and have to get this done asap. If I can resolve this whitespace issue I can refactor and optimize the code later.
thanks for any help with this.
notice the whitespace under the map and above the table view in the screenshot - I want to bring the table view so it's close to the map.
in my viewDidLoad: method
// mapview
self.topMapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 140)];
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.height,self.view.frame.size.height)];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.tableView];
then in the viewForHeaderInSection: method (It was suggested that this be done in the viewDidLoad: method and I tried that but it gave me more problems
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0, 320, 140)];
UIButton *showMapButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
showMapButton.frame = CGRectMake(0.0, 0, 320.0, 140.0);
[showMapButton setTitle:#"show map" forState:UIControlStateNormal];
[showMapButton addTarget:self
action:#selector(mapDetailViewDisplay:)
forControlEvents:UIControlEventTouchDown];
[headerView addSubview:self.topMapView];
[headerView showMapButton];
self.tableView.tableHeaderView = headerView;
return headerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 140;
}
Just add this in you ViewDidLoad method
self.automaticallyAdjustsScrollViewInsets = NO;
[UITableView tableHeaderView] is something different than viewForHeaderInSection but you are setting the same object to both of them.
You should rather set self.tableView.tableHeaderView in viewDidLoad: or return a headerView through viewForHeaderInSection delegate method depending on what kind of behaviour you are trying to achieve.
try to move all code in - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section leaving only return headerView
in viewDidLoad
and change
UIView *headerView = [[UIView alloc] init];
instead of
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0, 320, 140)];