I'm using MBXPageViewController as a UIPageViewController.
I'm trying to make the app more accessible with the UIAccessibilityScrollDirection method.
This works almost fine, but has a couple of issues:
The scrollDirection makes 2 steps to the right at first. I've logged it and give a currentIndex from 0 -> 2.
The scrollDirection won't go back to the first childViewController, the currentIndex 0. Voice-over tells there is no object left.
Here is how the accessibilityScroll method look like.
The setPageControllerForIndex:(NSInteger)index direction:(UIPageViewControllerNavigationDirection)direction currentMBXViewController:(id)weakSelf destionation:(NSInteger)destination method is described here
-(BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction {
__weak __typeof(&*self)weakSelf = self;
NSInteger tempIndex = _currentPageIndex;
NSLog(#"%ld", (long)tempIndex);
if (direction == UIAccessibilityScrollDirectionRight) {
//Previous Page
if (direction < tempIndex) {
NSLog(#"links");
for (int i = (int)tempIndex-1; i >= direction; i--) {
[self setPageControllerForIndex:i direction:UIPageViewControllerNavigationDirectionReverse currentMBXViewController:weakSelf destionation:direction];
NSLog(#"%d", i);
}
NSLog(#"%ld", direction);
UIAccessibilityPostNotification(UIAccessibilityPageScrolledNotification, #"links");
}
} else if (direction == UIAccessibilityScrollDirectionLeft) {
//Next Page
if (direction > tempIndex) {
NSLog(#"rechts");
for (int i = (int)tempIndex+1; i <= direction; i++) {
[self setPageControllerForIndex:i direction:UIPageViewControllerNavigationDirectionForward currentMBXViewController:weakSelf destionation:direction];
NSLog(#"%d", i);
}
NSLog(#"%ld", direction);
UIAccessibilityPostNotification(UIAccessibilityPageScrolledNotification, #"rechts");
}
}
UIAccessibilityPostNotification(UIAccessibilityPageScrolledNotification, nil);
return YES;
}
Related
I implemented corePlot in my xcode project using the pie chart. I'm having trouble the animation. When a slice gets selected, the radial offset changes with animation. Here is the code:
- (void)pieChart:(CPTPieChart *)plot sliceWasSelectedAtRecordIndex:(NSUInteger)idx
{
if (self.selectedIndex == idx)
{
[self animateSelectedIndex:20 :0];
self.selectedIndex = -1;
}
else
{
self.selectedIndex = idx;
[self animateSelectedIndex:0 :20];
}
}
- (void)animateSelectedIndex:(CGFloat)from :(CGFloat)to
{
[CPTAnimation animate:self
property:#"sliceOffset"
from:from
to:to
duration:0.25
animationCurve:CPTAnimationCurveCubicInOut
delegate:nil];
}
- (CGFloat)radialOffsetForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)idx
{
return idx == self.selectedIndex ? sliceOffset : 0.0;
}
- (void)setSliceOffset:(CGFloat)newOffset
{
if (newOffset != sliceOffset) {
sliceOffset = newOffset;
[self.graph reloadData];
}
}
The problem is, when a slice gets re-selected, the slice's radial offset goes to 0, but it doesn't animate to 0. (When it goes from 0 to 20 it does animate. The only problem is when it goes from 20 to 0)
Clearing the selectedIndex drives the radial offset to zero right away. Don't clear it until after the animation finishes. You can use an animation delegate or clear it in -setSliceOffset: after the offset reaches zero.
I don't know is that topic had asked before, but I do some search before asking this simple question, something like "UICollectionView cycling cells" "UIColloectionView Infinite Loop".
If the post is duplicated, I am sorry for that...
I had a Horizontal Collection View as a slider in my app, 5 image will be shown, how can I set the function when user scroll to the end (the fifth Items) and slide to right and move to the first cells? also, if the user scroll the first item and slide to left, it will show the fifth item? Thanks.
SDK: iOS 7
Thank alot~
I had wrote a stupid program to control this
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = _sliderCV.frame.size.width;
self.pageControl.currentPage = _sliderCV.contentOffset.x / pageWidth;
NSLog(#"%f", _sliderCV.contentOffset.x);
CGFloat firstSlide = 0.f;
CGFloat lastSlide = pageWidth * 4;
NSLog(#"contentOffset = %f, firstSlide = %f, SelFirstCount = %li",_sliderCV.contentOffset.x, firstSlide, (long)selFirstCount);
if (_sliderCV.contentOffset.x == firstSlide) {
if (selFirstCount == 0) {
selFirstCount += 1 ;
NSLog(#"%li", (long)selFirstCount);
} else {
NSLog(#"Move to Last");
[_sliderCV setContentOffset:CGPointMake(lastSlide, 0) animated:YES];
selFirstCount = 0;
self.pageControl.currentPage = 4;
selLastCount = 1;
}
} else if (_sliderCV.contentOffset.x == lastSlide) {
if (selLastCount == 0) {
selLastCount += 1;
} else {
[_sliderCV setContentOffset:CGPointMake(firstSlide,0) animated:YES];
selLastCount = 0;
self.pageControl.currentPage = 0;
selFirstCount = 1;
}
} else {
NSLog(#"Clear");
selFirstCount = 0;
selLastCount = 0;
}
}
This is turing into a bit of a brain buster, but I assume there is a very simple and efficient method to do this.
In my app I have views laid out in a grid. Views can be moved to any location via gesture. The problem is making the view sort to just the right location after the gesture event. Basically I am doing this. Works sort of but not correct yet.
Note: the tag of the views will always update to the current position of the view in the grid.
Below is the code I am using to sort, and here is a link to the actual project in a zip file.
-(void)sortViews:(UIView*)myView {
__block int newIndex;
// myView is the view that was moved.
[viewsArray removeObject:myView];
[viewsArray enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop){
if (myView.center.x > view.center.x) {
if (myView.center.y > view.center.y) {
newIndex = view.tag -1;
*stop = YES;
} else {
newIndex = view.tag +1;
*stop = YES;
}
} else if (myView.center.x < view.center.x) {
if (myView.center.y > view.center.y) {
newIndex = view.tag -1;
*stop = YES;
} else {
newIndex = view.tag +1;
*stop = YES;
}
}
}];
if (newIndex < 0) {
newIndex = 0;
} else if (newIndex > 5) {
newIndex = 5;
}
[viewsArray insertObject:myView atIndex:newIndex];
[UIView animateWithDuration:.4 animations:^{
[self arrangeGrid];
}];
}
You can store the original positions of all the views in an array (lets say positionArray), and then when you are moving a view "A" just go on checking the current position of view "A" with the stored positions in the positionArray, if a view is in range of any stored location just swap the position of view "A" with the view in whose range view "A" has come.
Hope this will help you
Found an easier solution that seems to work just fine. I replace the code within the viewsArray enumeration with this:
if (CGRectContainsPoint(view.frame, myView.center)) {
newIndex = view.tag;
*stop = YES;
}
How change value of segmentedcontrol by swipegesture?
"Invalid parameter not satisfying: selectedSegmentIndex < (NSInteger)self._items.count"
- (void)updateSelectedSegmentText
{
int theSegmentIndex = [_segmentedControl selectedSegmentIndex];
NSDictionary *theInfo = [self.top.segments objectAtIndex:theSegmentIndex];
self.bioTextView.text = [NSString stringWithFormat:#"%#", theInfo [#"sData"]];
[self.bioTextView scrollRangeToVisible:NSMakeRange(0, 0)];
}
- (void)swipe:(UISwipeGestureRecognizer *)swipeRecogniser
{
s = 1;
if ([swipeRecogniser direction] == UISwipeGestureRecognizerDirectionLeft)
{
self.segmentedControl.selectedSegmentIndex -=s;
[self updateSelectedSegmentText];
}
else if ([swipeRecogniser direction] == UISwipeGestureRecognizerDirectionRight)
{
self.segmentedControl.selectedSegmentIndex +=s;
[self updateSelectedSegmentText];
}
}
You need to first check if the new index is valid. You cannot go to the left if you are already on the first tab and you cannot go to the right if you are on the last tab. So you need to first calculate the new index and then check if it is in range before you set the selectedSegmentIndex property:
NSInteger index = self.segmentedControl.selectedSegmentIndex;
if ([swipeRecogniser direction] == UISwipeGestureRecognizerDirectionLeft) {
--index;
} else if ([swipeRecogniser direction] == UISwipeGestureRecognizerDirectionRight) {
++index;
}
if (0 <= index && index < self.segmentedControl.numberOfSegments) {
self.segmentedControl.selectedSegmentIndex = index;
[self updateSelectedSegmentText];
}
I am using iOS 5 to implement an app.
In this app I have 4 button, each button triggers an animation to unhide a UIView. However, if I press a button and then another, the view that appeared first should disappear and the view for the new button would appear.
I have this working so far. But if the user taps two buttons rapidly it will display the two views. How can I insure that only once touch event is processed?
The action for the button is something like:
- (void)buttonPressed:(id)sender
{
MenuButton *aButton = (MenuButton *)sender;
switch (aButton.tag) {
case 0:
if (displayingView && currentlyDisplayingView != picker1)
[self toggleView:currentlyDisplayingView atIndex:currentIndex];
[self toggleView:picker1 atIndex:aButton.tag];
currentlyDisplayingView = picker1;
currentIndex = aButton.tag;
break;
case 1:
if (displayingView && currentlyDisplayingView != picker2)
[self toggleView:currentlyDisplayingView atIndex:currentIndex];
[self toggleView:picker2 atIndex:aButton.tag];
currentlyDisplayingView = picker2;
currentIndex = aButton.tag;
break;
case 2:
if (displayingView && currentlyDisplayingView != picker3)
[self toggleView:currentlyDisplayingView atIndex:currentIndex];
[self toggleView:picker3 atIndex:aButton.tag];
currentlyDisplayingView = picker3;
currentIndex = aButton.tag;
break;
default:
break;
}
NSLog(#"Pressed %#",[buttonNames objectAtIndex:aButton.tag]);
}
And the animation code:
- (void)toggleView:(UIView *)picker
atIndex:(NSInteger)index
{
if (picker) {
picker.hidden = NO;
[UIView animateWithDuration:0.5
animations:^{
picker.alpha = abs(picker.alpha - 1);
CGRect rect = picker.frame;
if (rect.size.height == 0){
rect.size.height = 76;
} else if (rect.size.height == 76) {
rect.size.height = 0;
}
picker.frame = rect;
for (int i = index+1; i < [viewButtons count]; i++) {
UIButton *aButton = [viewButtons objectAtIndex:i];
CGRect frame = aButton.frame;
if (rect.size.height == 0){
frame.origin.y -= 75;
} else if (rect.size.height == 76) {
frame.origin.y += 75;
}
aButton.frame = frame;
}
}
completion:^(BOOL success){
if (picker.alpha == 0){
picker.hidden = YES;
} else if (picker.alpha == 1) {
picker.hidden = NO;
}
displayingView = !displayingView;
}];
}
}
Call beginIgnoringInteractionEvents before calling animateWithDuration, and call endIgnoring... in the completion handler.