Shinobi chart not accessible when inside a scrollview - charts

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)/

Related

iOS custom-view dynamically resize issue

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?

How to achieve UIPickerView as shown in image, with titles for components?

How to achieve picker view like this? I have implemented all necessary delegate and dataSource methods to populate the data, but the thing I am not able to understand is how to add this titles adults, children and infants?
They are static and does not spin with the component!
Add the 3 labels to your view as subviews when you showing the picker view and then hiding them when the picker is dismissed.
You will have to position the labels on the band.
I got this done just using Interface Builder.
I created a container view and then put picker view inside it.
To be sure that my container size is the same as picker view I set space constraints: leading, trailing, top and bottom.
Then I put 3 labels above picker view (but they're still the subviews of the container) and set their frames to center it.
Also to achieve the same label visual effect as on the screenshot (it seems to be under selection bar) decrease label's alpha to about 0.7.
You could put the labels on a particular frame position and then make the labels background color as clearColor.
You need to add labels as subviews of the picker view. There is no functionality built into UIPickerView to make this easy.
Create your picker, create a label with a shadow, and push it to a picker's subview below the selectionIndicator view.
It would look something like this
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(135, 93, 80, 30)] autorelease];
label.text = #"Label";
label.font = [UIFont boldSystemFontOfSize:20];
label.backgroundColor = [UIColor clearColor];
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake (0,1);
[picker insertSubview:label aboveSubview:[picker.subviews objectAtIndex:5]];
//When you have multiple components (sections)...
//you will need to find which subview you need to actually get under
//so experiment with that 'objectAtIndex:5'
//
//you can do something like the following to find the view to get on top of
// define #class UIPickerTable;
// NSMutableArray *tables = [[NSMutableArray alloc] init];
// for (id i in picker.subviews) if([i isKindOfClass:[UIPickerTable class]]) [tables addObject:i];
// etc...

Convert UIViewController to UIScrollViewController

I am new to iPad developer,
I made one Registration form in my application, when i see my application in Portrait mode,
i am able to see whole form with no scrolling, but when i see same form in Landscape mode, i am not able to see part which is at bottom of page, for that a scrolling should be there to see bottom part.
:
In my .h file when i replace
#interface ReminderPage : UIViewController{
...
...
}
:UIViewController with :UIScrollView
and then when i add label in my .m file like this,
UILabel *Lastpaidlbl = [[[UILabel alloc] initWithFrame:CGRectMake(70 ,400, 130, 50)]autorelease];
Lastpaidlbl.backgroundColor = [UIColor greenColor];
Lastpaidlbl.font=[UIFont systemFontOfSize:20];
Lastpaidlbl.text = #"Lastpaid on :";
[self.view addSubview:Lastpaidlbl];
I am getting error on last line Property view not found on object of type classname.
i am unable to add label in my view.
Any help will be appreciated.
The question appears to be really asking how can all the components on the screen be placed inside a UIScrollView, rather than a UIView. Using Xcode 4.6.3, I found I could achieve this by simply:
In Interface Builder, select all the sub-views inside the main UIView.
Choose Xcode menu item "Editor | Embed In | Scroll View".
The end result was a new scroll view embedded in the existing main UIView, will all the former sub-views of the UIView now as sub-views of the UIScrollView, with the same positioning.
If you want to replace your UIViewController with a UIScrollView, you will have to go a bit of refactoring to your code. The error you get is just an example of that:
the syntax:
[self.view addSubview:Lastpaidlbl];
is correct if self is a UIViewController; since you changed it to be UIScrollView, you should now do:
[self addSubview:Lastpaidlbl];
You will have quite a few changes like this one to make to your code and will face some issues.
Another approach would be this:
instantiate a UIScrollView (not derive from it);
add your UIView (such as you have defined it) to the scroll view;
define the contentSize of the scroll view so to include the whole UIView you have.
The scroll view acts as a container for your existing view (you add your controls to the scroll view, then add the scroll view to self.view); this way, you could integrate it within your existing controller:
1. UIScrollView* scrollView = <alloc/init>
2. [self.view addSubview:scrollView]; (in your controller)
3. [scrollView addSubview:<label>]; (for all of your labels and fields).
4. scrollView.contentSize = xxx;
I think the latter approach will be much easier.
Please put all of your UIComponents to the UIScrollview and then it will start scrolling.
please look in to content size. please change it according to the orientation of device.
You're subclassing UIScrollView, so there is no self.view because already self is the view (of the scrollview). You dont need to subclass the scrollview, you can just embed your components in a ivar scrollview and set its contentSize (in your case, you have to enable the scrolling just when the device is in landscape mode). In interface builder you can embed the selected elements in one click, Editor-> Embed in-> scrollview.
First create scrollview
UIScrollView * scr=[[UIScrollView alloc] initWithFrame:CGRectMake(10, 70, 756, 1000)];
scr.backgroundColor=[UIColor clearColor];
[ self.view addSubview:scr];
second
change [self.view addSubview:Lastpaidlbl];
to
[scr addSubview:Lastpaidlbl];
third
set height depends on content
UIView *view = nil;
NSArray *subviews = [scr subviews];
CGFloat curXLoc = 0;
for (view in subviews)
{
CGRect frame = view.frame;
curXLoc += (frame.size.height);
}
// set the content size so it can be scrollable
[scr setContentSize:CGSizeMake(756, curXLoc)];
Finally
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Override to allow orientations other than the default portrait orientation.
if (interfaceOrientation==UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight) {
self.scr.frame = CGRectMake(0, 0, 703,768);
} else {
self.scr.frame = CGRectMake(0, 0, 768, 1024);
}
return YES;
}

How to create a table in a view ( I dont want the table to cover up my entire screen)

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.

UIAccessibilityContainer in a table view

I'm trying to put a custom view inside a UITableViewCell which of course lives within a UITableView. I want to make this custom view accessible so I need to make it a UIAccessibilityContainer (since it contains several visual elements that aren't implemented as their own UIViews).
When I do this, the location of the elements get all messed up whenever the table scrolls. While paging through the elements using VoiceOver, it will automatically scroll the table to attempt to center the selected element on screen, but then the outline of where VoiceOver thinks the element is no longer lines up with where it is visually.
Note in the screenshot that the inspector says "Row 4, element 2" but the highlighted area is some random place in Row 7 since that happens to be where Row 4 was before it auto-scrolled the table.
My thought is that I might have to use UIAccessibilityPostNotification() to post a layout change when the table view scrolls, but I don't have to do that when I don't use a UIAccessibilityContainer and it feels like I shouldn't have to do it and that the system should be handling this for me - but the fact that UIAccessibilityElement needs to have it's accessibilityFrame set in screen coordinates does seem to throw a wrinkle into things. (Bonus question: Why the heck is the API designed that way? Why not define the frame relative to the element's container or something like that? Arg.)
Here's the custom view's implementation just in case there's something in here which is causing the problem. For the full project (Xcode 4), click here.
#implementation CellView
#synthesize row=_row;
- (void)dealloc
{
[_accessibleElements release];
[super dealloc];
}
- (void)setRow:(NSInteger)newRow
{
_row = newRow;
[_accessibleElements release];
_accessibleElements = [[NSMutableArray arrayWithCapacity:0] retain];
for (NSInteger i=0; i<=_row; i++) {
UIAccessibilityElement *element = [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self];
element.accessibilityValue = [NSString stringWithFormat:#"Row %d, element %d", _row, i];
[_accessibleElements addObject:element];
[element release];
}
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[[UIColor lightGrayColor] setFill];
UIRectFill(self.bounds);
[[UIColor blackColor] setFill];
NSString *info = [NSString stringWithFormat:#"Row: %d", _row];
[info drawAtPoint:CGPointZero withFont:[UIFont systemFontOfSize:12]];
[[[UIColor whiteColor] colorWithAlphaComponent:0.5] setFill];
NSInteger x=0, y=0;
for (NSInteger i=0; i<=_row; i++) {
CGRect rect = CGRectMake(12+x, 22+y, 30, 30);
UIAccessibilityElement *element = [_accessibleElements objectAtIndex:i];
element.accessibilityFrame = [self.window convertRect:[self convertRect:rect toView:self.window] toWindow:nil];
UIRectFill(rect);
x += 44;
if (x >= 300) {
x = 0;
y += 37;
}
}
}
- (BOOL)isAccessibilityElement
{
return NO;
}
- (NSInteger)accessibilityElementCount
{
return [_accessibleElements count];
}
- (id)accessibilityElementAtIndex:(NSInteger)index
{
return [_accessibleElements objectAtIndex:index];
}
- (NSInteger)indexOfAccessibilityElement:(id)element
{
return [_accessibleElements indexOfObject:element];
}
#end
Edit: I should note that I've tried variations that update the element's accessibilityFrame in -indexOfAccessibilityElement: and -accessibilityElementAtIndex: with the idea that VoiceOver will request the element somehow whenever it needs it and that'd be a nice time to update things. However that doesn't seem to work, either. I was kind of hoping maybe VoiceOver would automatically request things to redraw, but that also doesn't seem to work. (The idea of putting the location setting code in -drawRect: comes from something I remember seeing at WWDC about this, but it was unclear to me if that was "best practice" or just happened to be convenient.)
I've solved the problem you described by adding some side effects to the accessibility methods and with collaboration from the table scroll delegates. Inside the drawRect method I calculate the local coordinates of the rectangle, so I don't need to convert the coordinates there, simply calculate them with regards to the cell's top left corner.
Then, I modified the accessor to update the frame with a side effect like this (note the y resetting):
- (id)accessibilityElementAtIndex:(NSInteger)index
{
UIAccessibilityElement *element = [accesible_items_ get:index];
CGRect rect = element.accessibilityFrame;
rect.origin.y = 0;
element.accessibilityFrame = [self.window
convertRect:rect fromView:self];
return element;
}
While this works fine for the initial view, you still get the displaced frames when the user scrolls, so in your table view controller implement the following scrolling delegate:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// This loop has a side effects, see the cell accesor code.
for (id cell in self.tableView.visibleCells)
for (int f = 0; [cell accessibilityElementAtIndex:f]; f++);
UIAccessibilityPostNotification(
UIAccessibilityLayoutChangedNotification, nil);
NSLog(#"Layout changed after scrollViewDidScroll");
}
Depending on the contents of your table not all cells may respond to the accessibility method, so you could first query each cell with respondsToSelector to avoid sending unexpected messages.
I would also post UIAccessibilityLayoutChangedNotification at the end of the cell setter creating the UIAccessibilityElement objects, or you will get log messages saying that your elements disappeared or could not be found.
These changes make the scroll work when iterating the elements one through one with the rotor, but you may get still odd results if the user scrolls with a triple finger gesture. That's because by default tableViews scroll a screen page at a time, which may not happen to have the same element boundaries as your cells, and the rotor selects a cell half visible. Depending on the scrolling direction and other UI elements, the half visible cell could overlap controls the rotor gets confused with. You need to implement paged scrolling to control avoid this behavior.
Is this problem affecting the usability of the app in VoiceOver mode? When I've played with VoiceOver on both Mac OS and iOS, the highlight boxes (especially in Web views) frequently become unmatched with their onscreen objects. If the app is still usable in VoiceOver, I'd call this a known bug and fix it if somebody complains.
After all, most of the blind people I know aren't looking at the highlight boxes.