Basically this is what i have done
I subclassed uiview and created a custom multiple choice view
in the view I resize the frame to fit the content on the fly by doing this
my_frame.size.height = y;
[self setFrame:my_frame];
I want to initiate my custom view in a scrollview and after I init I wanna add more content below.
NSArray *choices = #[#"1", #"2", #"3 ", #"4", #"5", #"6" , #"7"];
MultipleChoice *mc = [[MultipleChoice alloc]initWithNSArray:choices withFrame:CGRectMake(self.view.frame.size.width/2 - 125, originY, 0, 0)];
[_scroll addSubview:mc];
originY += mc.frame.size.height + 10;
The problem that i am having is that when i try to access the height of the frame the resulting value hasn't changed and is 0 so when i use originY to create a new label, for example, the label is on top of the multiple choice view
How do I properly obtain the height of the customview during runtime?
Related
My application shows an horizontally scrollable area which should contain two different chart implemented using the Shinobi libraries. As my paged Scrollview is made using ATPagingView, I included the chart using the following code:
- (NSInteger)numberOfPagesInPagingView:(ATPagingView *)pagingView {
return 2;
}
- (UIView *)viewForPageInPagingView:(ATPagingView *)pagingView atIndex:(NSInteger)index {
// Instantiate a tutorial item controller and initialise with the proper content
self.chartView = [[ShinobiChart alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
chartView.title = #"example charts";
chartView.autoresizingMask = ~UIViewAutoresizingNone;
// Use a number axis for the x axis.
SChartNumberAxis *xAxis = [[SChartNumberAxis alloc] init];
chartView.xAxis = xAxis;
// Use a number axis for the y axis.
SChartNumberAxis *yAxis = [[SChartNumberAxis alloc] init];
chartView.yAxis = yAxis;
chartView.datasource = self;
chartView.userInteractionEnabled = YES;
return chartView;
}
The chart gets displayed correctly but, when I try to scroll it, the scrollable container doesn't move to show the second chart. The strange thing is that if I resize the chart in order to have some space to interact with the underlying container or if I do the same operation with a plain view like:
- (UIView *)viewForPageInPagingView:(ATPagingView *)pagingView atIndex:(NSInteger)index {
// Instantiate a tutorial item controller and initialise with the proper content
self.chartView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
return chartView;
}
well..it works perfectly.
It looks like the ShinobiChart view is somehow intercepting the touch event and not forwarding to the scrollview. As you can notice I tried to activate the user interaction but it doesn't work. Boxing the chart inside another view doesn't work either.
Any idea?
Found a possible solution here. Apparently is a well know issue and the only workaround is to disable pan gestures for the view containing the chart.
chartView.gesturePanType = SChartGesturePanTypeNone;
This is the source:
http://www.shinobicontrols.com/forum/shinobicontrols/2013/5/propagate-gesture-events-to-containing-controller-(shinobicharts)/
I have a UITextView added on my UIView programmatically. The textview added is not editable, it is just to display some data. The data displayed in the textview is getting from array.The no of the textviews are same as texts which I Stored in Array.Textview is displaying from start to end one by one.I need to set the postion of textview one by one means first textview come and set at some postion,second will be set as just before first textview,third will be just before on second and so on.. Note: Something like using Animation. suppose one textview come from top and it stops at Y postion at 250 then next textview will set at just before that..it cant come upto 250 of Y postion. and so on. I have no clue how to do this. Please give me some ideas.
Don't Consider the array and the UITextView data.... its fot temporary..
NSMutableArray *array = [[NSMutableArray alloc]initWithObjects:#"One",#"Two",#"three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine",#"Ten", nil];
for(int i=0;i<[array count];i++) {
UITextView *textView = [[UITextView alloc]init];
[textView setFrame:CGRectMake(20, 20*i+height, 200, height)];
[textView setBackgroundColor:[UIColor redColor]];
[textView setText:[array objectAtIndex:i]];
[self.view addSubview:textView];
}
you want to add textviews programmatically in your view based on the array,if you are adding textviews to your view then there is a problem(if u are having more number of textviews then you must take scroll view ) that's why better to take scroll view and add scroll view to your view after that you will add textviews to your scroll view ,
now take constant x-coordinate value ,width and height only change y-coordinate value and you must give the content size to scrollview .
for(int i=1;i<[array length];i++){
text_desc = [[UITextView alloc] initWithFrame:CGRectMake(63,64*i,370,60)];
text_desc.font = [UIFont fontWithName:#"Helvetica" size:13.0];
text_desc.editable=NO;
text_desc.tag=1;
}
and then set srollview content size,
scroll.contentSize = CGSizeMake(0,total*87);
//loop over the substrings of type Array to add textfields at run time
for (int i = 0; i < [substrings count]; i++)
{
CGRect frame = CGrectMake(0, i * 40, 100, 30);
UITextField * txtDynamic = [[UITextField alloc] initWithFrame: frame];
txtDynamic.text = [substrings objectAtIndex:i];
//add as subview
[view addSubview:txtDynamic];
//if you are not using ARC release the txtDynamic
}
Note
If number of UITextField more i.e it goes out of screen, then Add UITextField to UIScrollView and you can make its Size and content size dynamic.
Hope this will give you some clue.
hey mate then take one scrollview and in it just set all textview with its ContentSize like bellow
here i give an example ,
Note: this is just example here take one UIScrollView and give name scrview and after add your all this UITextField in it.
you add this code after you add data in textfield
txt1.frame = CGRectMake(txt1.frame.origin.x, txt1.frame.origin.y, txt1.frame.size.width, txt1.contentSize.height);
float txtscreen1 = txt1.frame.origin.y + txt1.contentSize.height + 10;
txt2.frame = CGRectMake(txt2.frame.origin.x, txtscreen1, txt2.frame.size.width, txt2.contentSize.height);
float txtscreen2 = txt2.frame.origin.y + txt2.contentSize.height + 10;
txt3.frame = CGRectMake(txt3.frame.origin.x, txtscreen2, txt3.frame.size.width, txt3.contentSize.height);
//.....and so on to 10
float txtscreen10 = txt3.frame.origin.y + txt3.contentSize.height + 10;
txt10.frame = CGRectMake(txt10.frame.origin.x, txtscreen10, txt10.frame.size.width, txt10.contentSize.height);
float scrollviewscreen = txtscreen10.frame.origin.y + txtscreen10.frame.size.height + 20;
scrview.contentSize=CGSizeMake(320, scrollviewscreen);//take scrollview
i hope this help you....
:)
The problem is, that I do have a view containing 3 parts.
The first part is a simple header - same height always!
The second part is a simple description line - same height always!
Now the problem is the third part. It's a viewContainer for dynamically calculated subviews (each of them having a custom controller). The height of the content is dynamic caused by some text information downloaded from a backend. So some times I would need to scroll to be able to read the whole text, sometimes not.
Currently I am doing it this way:
Calculate the size of the UILabel for a specific text.
Then resize the parent view so fit the UILabel (if smaller).
Then resize the scrollView of my 3-Part-ViewController-View to fit its subviews.
The detail viewController with the dynamic content:
self.labelDescription.text = self.customData.descriptionText;
[self.labelDescription sizeToFit];
if(self.view.frame.size.height < (self.labelDescription.frame.size.height + self.labelDescription.frame.origin.y)) {
CGRect newSize = CGRectMake(0,
0,
self.view.frame.size.width,
self.labelDescription.frame.size.height +
self.labelDescription.frame.origin.y);
self.view.frame = newSize;
}
The resizing of the scroll view after adding and resizing my detail view:
[self addChildViewController:controllerCustomData];
[self.scrollView addSubview:controllerCustomData.view];
CGRect newRect = CGRectMake(0,
self.viewElementDetailContentContainer.frame.origin.y,
controllerCustomData.view.frame.size.width,
controllerCustomData.view.frame.size.height);
controllerCustomData.view.frame = newRect;
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, newRect.origin.y + newRect.size.height);
So my question is, are there easier ways to do this?
You could create a method that does everything you need. You'll need to write the method (maybe methodS) once and use it passing the necessary arguments.
Is there any way out .., that I can create a UITableView in a view such that it doesn cover up entire the screen...
For example :
I want the first half of the screen to be a UITextView and the next half portion of my screen to be
a UITableView..
Thanks in advance
CGRect cgRct = CGRectMake(0, 50, 320, 250);
UITableView *tableView1 = [[UITableView alloc] initWithFrame:cgRct style:UITableViewStylePlain];
//tableView.editing = YES;
tableView1.dataSource = self;
tableView1.delegate = self;
tableView1.backgroundColor=[UIColor clearColor];
[self.view addSubview:tableView1];
You are probably creating a UITableViewController for your tableView and then realizing that you can't change the size of the tableView. Am I right? If that is the case then don't create a UITableViewController, just create a normal UIViewController and than add your tableView using Interface Builder or the code which other people posted here.
In Interface Builder (if you are using it), just drag-drop a UITableView to your UIView and adjust its width, height and y position in the Inspector.
If you are programmatically creating the view, change the frame of the UITableView
CGRect tablefrm = [tableViewObject frame];
tablefrm.origin.y = 240.0f //new origin
tablefrm.size.height = 240.0f; //new height
[tableViewObject setFrame:tablefrm]; //assuming already added the tableview to the view.
I'm having a scrollview as the detailedview of tableview cell. There are multiple views on the detailedview like labels, buttons etc. which I'm creating through interface builder. What I'm creating through interface builder is static. I'm putting everything on a view of height 480.
A label on my detailedview is having dynamic text which can extend to any length. The problem is that I need to set the scrollview's content size for which I need its height.
How shall I set scrollview's height provided the content is dynamic?
You could try to use the scrollview'ers ContentSize. It worked for me and I had the same problem with the control using dynamic content.
// Calculate scroll view size
float sizeOfContent = 0;
int i;
for (i = 0; i < [myScrollView.subviews count]; i++) {
UIView *view =[myScrollView.subviews objectAtIndex:i];
sizeOfContent += view.frame.size.height;
}
// Set content size for scroll view
myScrollView.contentSize = CGSizeMake(myScrollView.frame.size.width, sizeOfContent);
I do this in the method called viewWillAppear in the controller for the view that holds the scrollview. It is the last thing i do before calling the viewDidLoad on the super.
Hope it will solve your problem.
//hannes
Correct shorter example:
float hgt=0; for (UIView *view in scrollView1.subviews) hgt+=view.frame.size.height;
[scrollView1 setContentSize:CGSizeMake(scrollView1.frame.size.width,hgt)];
Note that this only sums heights, e.g. if there are two subviews side by side their heights with both be added, making the sum greater than it should be. Also, if there are vertical gaps between the subviews, the sum will be less than it should be. Wrong height confuses scrollRectToVisible, giving random scroll positions :)
This loop is working and tested:
float thisy,maxy=0;for (UIView *view in scrollView1.subviews) {
thisy=view.frame.origin.y+view.frame.size.height; maxy=(thisy>maxy) ? thisy : maxy;
}
A somewhat easier way to do this is to nest your layout within a view then put that view within the scrollview. Assuming you use tags, this works as follows:
UIScrollView *scrollview = (UIScrollView *)[self.view viewWithTag:1];
UIView *longView = (UIView *)[self.view viewWithTag:2];
scrollview.contentSize = CGSizeMake(scrollView.frame.size.width, longView.frame.size.height);
That way the longView knows how tall it is, and the scrollview's content is just set to match.
This depends on the type of content you are going to add dynamically. So let's say you have a big text data to show, then use the UITextView and as it is a subclass of the UIScrollView, you can get the setContentSize of TextView when you assign the text content. Based on that you can set the total size of the UIScrollView.
float yPoint = 0.0f;
UIScrollView *myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f, yPoint, 320.0f, 400.0f)];
UITextView *calculatorTextView = [[UITextView alloc] init]; calculatorTextView.text = #"My looong content text ..... this has a dynamic content"; `
[calculatorTextView sizeToFit];
yPoint = yPoint + calculatorTextView.contentSize.height; // Bingo, we have the new yPoint now to start the next component.
// Now you know the height of your text and where it will end. So you can create a Label or another TextView and display your text there. You can add those components as subview to the scrollview.
UITextView *myDisplayContent = [[UITextView alloc] initWithFrame:CGRectMake(0.0f, yPoint, 300.f, calculatorTextView.contentSize.height)];
myDisplayContent.text = #"My lengthy text ....";
[myScrollView addSubview:myDisplayContent];
// At the end, set the content size of the 'myScrollView' to the total length of the display area.
[myScrollView setContentSize:yPoint + heightOfLastComponent];
This works for me.
I guess there's no auto in case of scrollview, and the contentsize should be calculated for static views on the screen at least and for dynamic once it should be calculated on the go.
scrollView.contentSize = [scrollView sizeThatFits:scrollView.frame.size]
I believe would also work
I had the same situation, but then I wrote a new version in Swift 4 mirroring the better answer in Objective-C by Hannes Larsson:
import UIKit
extension UIScrollView {
func fitSizeOfContent() {
let sumHeight = self.subviews.map({$0.frame.size.height}).reduce(0, {x, y in x + y})
self.contentSize = CGSize(width: self.frame.width, height: sumHeight)
}
}