Center Image in ScrollView Xcode - ios

I have a problem with images in a scrollview. I want to scroll the images and they should be centered. There is a problem because each picture has other values in the width.
I tried it with subclassing the scrollview and, but i don't know how to get the actual image in the layoutSubviews-Method.
Status-Update:
Now i try it with scrollViewDidScroll:. But it don't stop on the next image, when i scroll fast.
The method
In arrayWithXValues stands the values where the image begins in scrollview.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
float middleOfScreenX = scrollView.contentOffset.x + iOSDeviceScreenSize.width / 2;
for (int i = 1; i < 19; i++) {
if (i < 17) {
if (middleOfScreenX > [[arrayWithXValues objectAtIndex:i] floatValue] && middleOfScreenX < [[arrayWithXValues objectAtIndex:i + 1] floatValue] && actualPage != i) {
...
actualPage = i;
[self killScroll];
}
} else {
if (valMiddleX > [[arrayWithXValues objectAtIndex:i] floatValue]) {
...
actualPage = i;
[self killScroll];
}
}
}
}
- (void)killScroll {
self.horizontalScrollView.scrollEnabled = NO;
self.horizontalScrollView.scrollEnabled = YES;
}
Thanks for all your help

Related

Keep the first visable headerview’s uilabel’s textcolor = yellow when sliding the uicollectionview

I want to make the uicollectionview’s first visable headerview’s uilabel’s color is yellow and the other visable headerview is black when sliding the uicollectionview.
How can I achieve this?
The problem has been solved perfectly, below I uploaded the demo:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == self.CollectionView) {
//Calculate the section with contentOffset
CGFloat contentOffset = scrollView.contentOffset.y;
NSInteger lastSection = self.firstSection;
if (contentOffset <= 0) {
self.firstSection = 0;
} else {
for (NSInteger section = 0; section < self.playListArr.count - 1; section++) {
contentOffset = contentOffset - (HEADER_VIEW_HEIGHT + (LINE_SPACING + CELL_HEIGHT) * ceil([(NSMutableArray *)self.playListArr[section] count] / 3.0) - LINE_SPACING);
if (contentOffset <= 0 || section == self.playListArr.count - 1) {
//return the current first section:
self.firstSection = section;
break;
}
}
}
}

How can I keep the same collection view cells on the screen when zooming a UICollectionView?

I have a UICollectionView that uses a UICollectionViewLayout subclass for its layout. The layout is a simple grid.
When I zoom the collection view in or out, the positions of the cells on the screen change. In some cases, when zooming in, cells move off the screen entirely. I zoom the cells with a pinch gesture recognizer that sends x and y scale values to the layout class and then invalidates the layout.
As the cells get bigger, they move because their origins are calculated relative to the 0,0 position of the collection view.
I want to be able to zoom the collection view in, while having as many of the cells that were originally on the screen stay there. A good solution would be to have the cell in the center of the screen stay in the center as it becomes larger. Cells around the center cell would grow, and that might push them off the screen.
I've tried adjusting the collection view's content offset, but I haven't achieved what I want. I'm not quite sure how to calculate its new value, and I've learned that the changes caused by invalidateLayout do not happen immediately.
I tried a key value observer for the collection view's content size, but that caused stuttering because the changes in the KVO method happened well after the original zooming.
I've also worked a little bit with scrollToItemAtIndexPath, but the code in my full app is not guaranteed to have a cell at the exact center of the screen. That solution is less desirable for me.
Here is the code where the pinch recognizer sends changes to the layout class:
[self.gridLayout updateCellWidthScale:xScale];
[self.gridLayout updateCellHeightScale:yScale];
[self.gridLayout invalidateLayout];
Here is the code in the layout class
(numberOfRows and numberOfColumns are both set to 20):
-(id)initWithNumberOfRows:(NSUInteger)numberOfRows
andNumberOfColumns:(NSUInteger)numberOfColumns
{
self = [super init];
if (self)
{
_numberOfRows = numberOfRows;
_numberOfColumns = numberOfColumns;
_cellWidth = 80.0f;
_cellHeight = 80.0f;
_cellWidthScale = 1.0f;
_cellHeightScale = 1.0f;
}
return self;
}
-(void)updateCellWidthScale:(CGFloat)newWidthScale
{
self.cellWidthScale *= newWidthScale;
}
-(void)updateCellHeightScale:(CGFloat)newHeightScale
{
self.cellHeightScale *= newHeightScale;
}
-(CGSize)collectionViewContentSize
{
CGSize returnValue = CGSizeMake(self.numberOfColumns * self.cellWidth * self.cellWidthScale,
self.numberOfRows * self.cellHeight * self.cellHeightScale);
return returnValue;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path
{
UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];
CGRect rect = [self frameForItemAtIndexPath:path];
attributes.size = CGSizeMake(rect.size.width, rect.size.height);
attributes.center = CGPointMake(rect.origin.x + (0.5f * rect.size.width),
rect.origin.y + (0.5f * rect.size.height));
return attributes;
}
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *returnValue = [[NSMutableArray alloc] init];
for (NSInteger i=0; i < self.numberOfRows; i++)
{
for (NSInteger j=0; j < self.numberOfColumns; j++)
{
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:j inSection:i];
CGRect frame = [self frameForItemAtIndexPath:indexPath];
if (CGRectIntersectsRect(frame, rect))
{
[returnValue addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
}
}
}
return returnValue;
}
- (CGRect)frameForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect returnValue = CGRectMake(indexPath.section * self.cellWidth * self.cellWidthScale,
indexPath.row * self.cellHeight * self.cellHeightScale,
self.cellWidth * self.cellWidthScale,
self.cellHeight * self.cellHeightScale);
return returnValue;
}
You need to set your collectionView contentOffset to the value it was before starting to zoom multiplied the gestures scale.
Your pinch recognizer method should look like this (you need to add some more code to stop changing contentOffset when reaching the MAXIMUM_SCALE or MINIMUM_SCALE).
- (void)didReceivePinchGesture:(UIPinchGestureRecognizer*)gesture
{
static CGFloat scaleStart;
static CGPoint p;
if (gesture.state == UIGestureRecognizerStateBegan)
{
scaleStart = self.scale;
p = self.collectionView.contentOffset;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
CGFloat tempScale = scaleStart * gesture.scale;
if (tempScale < MINMUM_SCALE)
{
self.scale = MINMUM_SCALE;
}
else if (tempScale > MAXIMUM_SCALE)
{
self.scale = MAXIMUM_SCALE;
}
else
{
self.scale = tempScale ;
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView.collectionViewLayout invalidateLayout];
self.collectionView.contentOffset = CGPointMake(0, p.y * gesture.scale);
});
}
}

Star-Half image is not displaying in Custom RatingView IOS

I am using this tutorial http://www.raywenderlich.com/1768/uiview-tutorial-for-ios-how-to-make-a-custom-uiview-in-ios-5-a-5-star-rating-view for custom rating-bar. but I am not able to give half rating. I am trying to display half star when user touch on imageview. Please suggest me
Finally I fixed half-star problem.
if (!self.editable) return;
//The rating starts out as 0 and then builds from there.
CGFloat newRating = 0;
//loop through the image collection backwards so if it exits the loop it will have identified the MAX
for(int i = self.imageViews.count - 1; i >= 0; i--) {
UIImageView *imageView = [self.imageViews objectAtIndex:i];
CGFloat distance = touchLocation.x - imageView.frame.origin.x;
CGFloat frameWidth = imageView.frame.size.width;
if (distance <= 0){
//this means that the click was to the left of the frame
continue;
}
if (distance /frameWidth >.75) {
//If this ratio is >.75 then you are to the right 3/4 of the image or past th image
newRating = i + 1;
break;
} else {
//you didn't drop out or mark the entire star, so mark it half.
newRating = i + 0.5;
break;
}
}
self.rating = newRating;

How to looping a set of cells in UICollectionView?

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;
}
}

How to translate viewWillLayoutSubviews to viewWillTransitionToSize

I'm using viewWillLayoutSubviews to detect orientation changes but as in iOS 8 and Xcode 6 is deprecated I need to use new viewWillTransitionToSize. My problem is that I'm not able to use it.
My viewWillLayoutSubviews is:
- (void)viewWillLayoutSubviews{
NSInteger maxQuantityForWidth = MAX(3, [self.barButtons count]);
CGFloat buttonWidth = (CGRectGetWidth(self.tabBar.bounds) - (kBarButtonSeparation * (maxQuantityForWidth - 1))) / maxQuantityForWidth;
for (NSInteger i = 0; i < [self.barButtons count]; i++) {
[self.barButtons[i] setFrame:CGRectMake(i * ((buttonWidth + kBarButtonSeparation)), 2.0, buttonWidth, CGRectGetHeight(self.tabBar.bounds) - 2.0)];
}
if ([self isShowingTabBar]) {
self.functionalityContainer.frame = CGRectMake(0.0, CGRectGetHeight(self.tabBar.bounds), CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - CGRectGetHeight(self.tabBar.bounds));
} else {
self.functionalityContainer.frame = self.view.bounds;
}
if (IS_IPAD){
[self updateToolbar];
CGRect frame = self.slidingViewController.topViewController.view.frame;
if (LANDSCAPE) {
frame.size.width = 700;
} else {
frame.size.width = 768;
}
[self.slidingViewController.topViewController.view setFrame:frame];
}
}
and it's part of the Navigation section using ECSLidingViewController.
I tried the following:
- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self updateToolbar];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
if (IS_IPAD){
CGRect frame = self.slidingViewController.topViewController.view.frame;
if (LANDSCAPE) {
NSInteger maxQuantityForWidth = MAX(3, [self.barButtons count]);
CGFloat buttonWidth = (758 - (kBarButtonSeparation * (maxQuantityForWidth - 1))) / maxQuantityForWidth;
for (NSInteger i = 0; i < [self.barButtons count]; i++) {
[self.barButtons[i] setFrame:CGRectMake(i * ((buttonWidth + kBarButtonSeparation)), 2.0, buttonWidth, CGRectGetHeight(self.tabBar.bounds) - 2.0)];
}
frame.size.width = 768;
} else {
NSInteger maxQuantityForWidth = MAX(3, [self.barButtons count]);
CGFloat buttonWidth = (758 - (kBarButtonSeparation * (maxQuantityForWidth - 1))) / maxQuantityForWidth;
for (NSInteger i = 0; i < [self.barButtons count]; i++) {
[self.barButtons[i] setFrame:CGRectMake(i * ((buttonWidth + kBarButtonSeparation)), 2.0, buttonWidth, CGRectGetHeight(self.tabBar.bounds) - 2.0)];
}
frame.size.width = 768;
}
[self.slidingViewController.topViewController.view setFrame:frame];
}
if([self isShowingTabBar]){
[self showTabBar];
}else{
[self hideTabBar];
}
if (IS_IPAD && LANDSCAPE) {
self.slidingViewController.resetStrategy = ECNone;
[self.navigationItem setLeftBarButtonItems:#[] animated:YES];
if (!self.slidingViewController.underLeftShowing) {
[self.slidingViewController anchorTopViewTo:ECRight];
}
} else {
self.slidingViewController.resetStrategy = ECTapping | ECPanning;
[self.navigationItem setLeftBarButtonItems:#[self.displayMenuBarButtonItem] animated:YES];
[self.slidingViewController resetTopView];
}
[self.slidingViewController.topViewController.view setNeedsDisplay];
[self.functionalityNavigationController.view setNeedsDisplay];
[self.view setNeedsDisplay];
}];
NSString *orientation = [[NSString alloc]initWithFormat:#"Larghezza: %f Altezza: %f", self.view.frame.size.width, self.view.frame.size.height];
[self.view makeToast:orientation duration:3.0 position:#"bottom"];
[super viewWillTransitionToSize: size withTransitionCoordinator: coordinator];
}
but it doesn't work, it seems doesn't "understand" when it's landscape or portrait. Any idea on how to fix it?
*** EDIT:
here the definitions I use
#define LANDSCAPE UIInterfaceOrientationIsLandscape(self.interfaceOrientation)
#define LANDSCAPE_RIGHT [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft
#define LANDSCAPE_LEFT [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight
#define PORTRAIT UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
#define PORTRAIT_REVERSE [UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown
The question seems a bit "old", anyway, at least with the introduction of iOS9 (especially multitasking), it is not recommended to draw conclusions regarding the current screen format based on device-orientation - instead, one should evaluate the current screen size. The following indicates whether the screen format is portrait or rather landscape-ish:
- (void) viewWillTransitionToSize : (CGSize) screenSize withTransitionCoordinator : (id<UIViewControllerTransitionCoordinator> _Nonnull) coordinator
{
BOOL isLandscapeOrientation = (screenSize.width > screenSize.height);
...
...
}
You should be using the trait collection method and then check the size class.
/*
This method is called when the view controller's trait collection is changed by its parent.
If you override this method, you should either call super to propagate the change to children or manually forward the change to children.
*/
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);

Resources