At the beggining, here is the screenshot of my ViewController in Action.
My ViewController is contained of Embedded YouTube video, below it is UIScrollView and under him is UITableView which is for now randomly populated. I want to get all the albums from the specific singer, and for each of them, a seperate UIButton as shown in screenshot ->
svi, lek za spavanje, balkan
The thing is, I will get all the albums from YouTube API, so I do not know how many albums singer has got. I have to add UIButtons programmatically in Swift.
On my language, "svi" means "all", so when I click "svi" I should get all the albums listed below it in UITableView. Similarly, all the albums and "svi"("all") should be in UIScrollView, so when the user clicks, for example, "Balkan", UITableView should be populated with all the tracks from that "Balkan" album.
Can anyone suggest me how to make and position all the UIButtons (as an Array of UIButtons) in UIScrollView according to the screenshot provided at the top? Any help appreciated.
Add Scrollview in storyboard / add programatically
Have a array with list of albums
Create UIButton programatically and add it to scroll view
Set size of the scrollview at the end.
Code snippet as follows,
UIScrollView * scView;
UIButton * btn;
NSMutableArray * array;
float btnWidth = 44;
for(int i=0;i<array.count;i++) {
btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(i*btnWidth, 0, btnWidth, 44);
[btn setTitle:[array objectAtIndex:i]forState:UIControlStateNormal];
[btn addTarget:self action:#selector(btnTapped) forControlEvents:UIControlEventTouchUpInside];
[scView addSubview:btn];
}
[scView setContentSize:CGSizeMake(btnWidth*array.count, 50)];
- (void)btnTapped {
// button click call back method
}
Check the size of the string with following method
- (CGSize)getHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font {
CGSize size = CGSizeZero;
if (text) {
CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName:font } context:nil];
size = CGSizeMake(frame.size.width, frame.size.height);
}
return size;
}
Pass your album name to this method and it returns CGSize, from that get width and set that width value to button width in above for loop.
Related
I have an app that uses a UIPickerView to set various parameters having to do with line style for a graph series (line width, colour, and line style). This picker is used in a table view row. I have defined the frame for the picker so that its width fills the width of the cell's contentView member. Up until iOS 9, this appeared to work. With iOS 9, there appears to be some sort of maximum cap on the width of a UIPickerView. Has anyone encountered anything similar to this?
The picker view is being created like this:
self.picker = [[[UIPickerView alloc] init] autorelease];
[self.contentView addSubview:self.picker];
self.picker.dataSource = self;
self.picker.delegate = self;
self.picker.backgroundColor = [UIColor grouped_table_view_background_colour];
The cell is layed out as follows:
-(void) layoutSubviews
{
// we need to allow the base class to perform its layout.
static CGFloat left_margin = 40;
static CGFloat right_margin = 40;
CGSize my_size;
[super layoutSubviews];
my_size = self.contentView.bounds.size;
my_size.width -= left_margin + right_margin;
// we now need to lay out the views.
CGRect picker_rect = CGRectMake(left_margin, 5, my_size.width, my_size.height);
self.picker.frame = picker_rect;
// we want to look at the bounds of the picker
CGRect picker_bounds = self.picker.bounds;
NSLog(#"picker bounds x=%g, y=%g, w=%g, h=%g", picker_bounds.origin.x, picker_bounds.origin.y, picker_bounds.size.width, picker_bounds.size.height);
}
I am also overloading the widthForComponent method as follows:
-(CGFloat) pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
// we want to look at the bounds of the picker
CGRect picker_bounds = self.picker.bounds;
NSLog(#"picker bounds x=%g, y=%g, w=%g, h=%g", picker_bounds.origin.x, picker_bounds.origin.y, picker_bounds.size.width, picker_bounds.size.height);
return picker_bounds.size.width / 3;
}
I can see that the bounds of the view appear correctly both in the values that are logged as well as the background colour of the view. Despite this, the picker appears to fill less than half the width that is available (688 points on my iPad)
After [[UIPickerView alloc] init] the Picker has a size of {320,216} and this size will be used in pickerView:widthForComponent:. If you just resize the picker afterwards, the function pickerView:widthForComponent: won't be called again, so the components are stuck at their width.
Try to initialise the picker with the correct size like..
picker=[[UIDatePicker new] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), 216.0)];
or call [self.picker setNeedsLayout] after you change the picker frame to force pickerView:widthForComponent: to be called again.
I'm trying to let the user to adjust himself the font size to read the content of the app. therefor i put a slider that if the user swipe right, the fonts will grow and left means that the fonts size will be smaller. it works fine, but the problem is that sometimes the scrollView content size is not getting the new content size.
This is my method:
- (IBAction)enlargeLabelWithSlider:(id)sender{
UISlider *slider = (UISlider *)sender;
int font = 0;
int currentSliderValue = (int)slider.value;
if (currentSliderValue<=lastSilderValue) /* Every time the method call, at the end lastSilderValue = currentSliderValue*/
{
// Need to increase
font =lastSilderValue - currentSliderValue;
[self.gameTitleLabel setFont:[UIFont fontWithName:self.gameTitleLabel.font.fontName size:self.gameTitleLabel.font.pointSize+font]];
[self.gameScoreLabel setFont:[UIFont fontWithName:self.gameScoreLabel.font.fontName size:self.gameScoreLabel.font.pointSize+font]];
self.gameStateLabel.font = [UIFont systemFontOfSize:self.gameStateLabel.font.pointSize+font];
}
else
{
// Need to decrease
font =currentSliderValue - lastSilderValue;
[self.gameTitleLabel setFont:[UIFont fontWithName:self.gameTitleLabel.font.fontName size:self.gameTitleLabel.font.pointSize-font]];
[self.gameScoreLabel setFont:[UIFont fontWithName:self.gameScoreLabel.font.fontName size:self.gameScoreLabel.font.pointSize-font]];
self.gameStateLabel.font = [UIFont systemFontOfSize:self.gameStateLabel.font.pointSize-font];
}
lastSilderValue = currentSliderValue;
CGFloat height = self.gameStateLabel.frame.origin.y+self.gameStateLabel.frame.size.height+20;
CGSize size = CGSizeMake(self.ScrollView.frame.size.width, height);
self.ScrollView.contentSize = CGSizeMake(size.width, size.height); // i used self.gameStateLabel.frame.origin.y because it's the last label on the view.
}
can someone tell me why is this happening? Thanks.
I don't see any change to the UILabel frame.
Maybe you have to adapt this frame to the new font size and then try to modify the scrollview contentSize property.
This will be helpful: Adjust UILabel height depending on the text
I'm trying to build a simple UIScrollView with paging to horizontally scroll between 3 images.
The tricky part is that I would like that each image would be clickable and catch the click event.
My technique is to create 3 UIButtons that each consists UIImage. give each button a tag and set an action.
Problem: I can catch the click event - BUT it's not scrollable!
Here is my code:
- (void) viewDidAppear:(BOOL)animated {
_imageArray = [[NSArray alloc] initWithObjects:#"content_01.png", #"content_02.png", #"content_03.png", nil];
for (int i = 0; i < [_imageArray count]; i++) {
//We'll create an imageView object in every 'page' of our scrollView.
CGRect frame;
frame.origin.x = _contentScrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = _contentScrollView.frame.size;
//
//get the image to use, however you want
UIImage* image = [UIImage imageNamed:[_imageArray objectAtIndex:i]];
UIButton* button = [[UIButton alloc] initWithFrame:frame];
//set the button states you want the image to show up for
[button setImage:image forState:UIControlStateNormal];
[button setImage:image forState:UIControlStateHighlighted];
//create the touch event target, i am calling the 'productImagePressed' method
[button addTarget:self action:#selector(imagePressed:)
forControlEvents:UIControlEventTouchUpInside];
//i set the tag to the image #, i was looking though an array of them
button.tag = i;
[_contentScrollView addSubview:button];
}
//Set the content size of our scrollview according to the total width of our imageView objects.
_contentScrollView.contentSize = CGSizeMake(_contentScrollView.frame.size.width * [_imageArray count], _contentScrollView.frame.size.height);
_contentScrollView.backgroundColor = [ENGAppDelegate backgroundColor];
_contentScrollView.delegate = self;
}
Well, since UIButton is an UIControl subclass, it "eats up" the touches of your scroll view:
[UIScrollView touchesShouldCancelInContentView:] The default returned value is YES if view is not a UIControl object; otherwise, it returns NO.
(from https://developer.apple.com/library/ios/documentation/uikit/reference/UIScrollView_Class/Reference/UIScrollView.html#//apple_ref/occ/instm/UIScrollView/touchesShouldCancelInContentView:)
You could influence this by subclassing UIScrollView and overwriting touchesShouldCancelInContentView: (and/or touchesShouldBegin:withEvent:inContentView:). However, for your use case I'd not use buttons in the first place. Why not just add a tap gesture recognizer to the scrollview and use the touch point to determine which image has been tapped? That's much easier and should work without any issues.
This completely solved this issue for me:
scrollview.panGestureRecognizer.delaysTouchesBegan = YES;
Credit goes to https://stackoverflow.com/users/904365/kjuly for providing the right answer in this topic: ScrollView/TableView with UIControl/UIButton subviews not scrollable under iOS 8
I am creating a modal view in an App, which contains several subviews. Each one of those subviews has a button and an action related to that button. I use a loop to insert each subview in place. The problem is that the first 4 subviews are ok, from the 5th to the last there are no responses.
Here it is the simplified code related to the problem:
Simplified SubviewView.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// More info button
CGRect buttonFrame = CGRectMake(infoMarginLeft + infoWidthWithInfo, infoHeightControl, 25, 25);
UIButton * button = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[button setFrame:buttonFrame];
[button addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
return self;
}
-(void)buttonTapped:(id)sender
{
NSLog(#"Button tapped!";
}
Simplified view.m
- (void)drawRect:(CGRect)rect
{
for (int i = 0; i < 12; i++) {
// Color info container
SubviewView * miniView = [[SubviewView alloc] initWithFrame:CGRectMake(0, 20 * i, 15, 15)];
miniColorView.backgroundColor = [UIColor clearColor];
// Adding subview through array to keep track of objects
[self addSubview:miniColorView];
}
}
Thanks in advance, I have absolutely no ideia of what's going on :p
--
EDIT
Just found out what it was!
The parent view had as height the screen height. The thing is, some of the subviews were beyond the screen height limit. All I had to do was increase the parent view height =)
I would check to make sure you are not adding your view miniView over top of your button.
Also this should be moved outside of drawRect, just put this in your init method.
Edit:
Set your miniView's background color to another besides clear, and see if you still see your button. If not, then you covered up your button, and it won't receive touch events.
gaaah designing in ios gives me headache!!
So please, help me out and maby explain to me how one should think trying to come up with the solution.
I have:
As you can see the UITextField has its frame being set in storyboard to be smaller than its actual content.
Everything above the prototypecell is within a UIView that is set to be tableHeader programatically.
I want to:
Press the read more btn so that the UITextField get its actual size. No problem, I can do that with getting the contentSize programmatically. It works but it ofc overflows the tableHeader
So I thought, good. Then all I have to do is set the tableHeader to be the size of the 'new' calculated height of UITextField + height of the 2 UIImageViews.
But nope. it only resizes to the existing height set in storyboard insted. In other word, it does one or the other.
And using autolayout it totally breaks but not giving me any errors about constraints.
This seems so easy wich makes me feel so stupid haha
this is what I have i code
- (IBAction)toggleReadMore:(id)sender{
_toggleReadMoreBtn.hidden = YES;
CGRect textFrame = _cityDescription.frame;
_cityDescription.frame = textFrame;
CGRect tableHeaderViewFrame = CGRectMake(0, 0, self.tableView.tableHeaderView.frame.size.width, _cityDescription.contentSize.height + 218.0f ); //textFrame.size.height
self.tableView.tableHeaderView.frame = tableHeaderViewFrame;
textFrame.size.height = _cityDescription.contentSize.height;
[self.tableView setTableHeaderView:self.viewForTableHeader];
please, guide me how to think
- (IBAction)readMoreBtnClicked:(UIButton *)sender
{
NSLog(#"Read more Btn Clicked");
NSString *stringToBeDisplayed = #"Any Text Here";
CGSize textSize=[stringToBeDisplayed sizeWithFont:[UIFont systemFontOfSize:30]
constrainedToSize:CGSizeMake(270, 500)
lineBreakMode:NSLineBreakByWordWrapping];
NSLog(#"textSize = %#",NSStringFromCGSize(textSize));
[self.textView setFrame:CGRectMake(self.textView.frame.origin.x,self.textView.frame.origin.y, textSize.width, textSize.height)];
NSLog(#"self.textView.frame = %#",NSStringFromCGRect(self.textView.frame));
[self.textView setText:stringToBeDisplayed];
[self.headerView setFrame:CGRectMake(self.headerView.frame.origin.x,self.headerView.frame.origin.y, 320, dynamicHeightCalculatedAfterTextSize)];
[self.tableView reloadData];
}