Skip to content
Browse files

Several visual bug fix:

move books and drop down, orientation change
add a license
  • Loading branch information...
1 parent 2a1c5ba commit a6947f37e5b33c48d2246f9369cb2f5838ec92e0 @ultragtx committed Nov 26, 2012
View
4 BookShelf.xcodeproj/project.pbxproj
@@ -25,6 +25,7 @@
C16047F5150E0908000929CC /* 4@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C16047ED150E0908000929CC /* 4@2x.png */; };
C16047F8150E0911000929CC /* BookShelfCell.png in Resources */ = {isa = PBXBuildFile; fileRef = C16047F6150E0911000929CC /* BookShelfCell.png */; };
C16047F9150E0911000929CC /* BookShelfCell@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C16047F7150E0911000929CC /* BookShelfCell@2x.png */; };
+ C182834616633FB600A69C46 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = C182834516633FB600A69C46 /* LICENSE */; };
C1B5E17915E9DADE0040781D /* Side Shading-iPhone.png in Resources */ = {isa = PBXBuildFile; fileRef = C1B5E16B15E9DADE0040781D /* Side Shading-iPhone.png */; };
C1B5E17A15E9DADE0040781D /* Side Shading-iPhone@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C1B5E16C15E9DADE0040781D /* Side Shading-iPhone@2x.png */; };
C1B5E17B15E9DADE0040781D /* topshelf side shading-iPhone.png in Resources */ = {isa = PBXBuildFile; fileRef = C1B5E16D15E9DADE0040781D /* topshelf side shading-iPhone.png */; };
@@ -83,6 +84,7 @@
C16047ED150E0908000929CC /* 4@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "4@2x.png"; sourceTree = "<group>"; };
C16047F6150E0911000929CC /* BookShelfCell.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BookShelfCell.png; sourceTree = "<group>"; };
C16047F7150E0911000929CC /* BookShelfCell@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "BookShelfCell@2x.png"; sourceTree = "<group>"; };
+ C182834516633FB600A69C46 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
C1B5E16B15E9DADE0040781D /* Side Shading-iPhone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Side Shading-iPhone.png"; sourceTree = "<group>"; };
C1B5E16C15E9DADE0040781D /* Side Shading-iPhone@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Side Shading-iPhone@2x.png"; sourceTree = "<group>"; };
C1B5E16D15E9DADE0040781D /* topshelf side shading-iPhone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "topshelf side shading-iPhone.png"; sourceTree = "<group>"; };
@@ -238,6 +240,7 @@
C1D6738B14F4D247006D3483 = {
isa = PBXGroup;
children = (
+ C182834516633FB600A69C46 /* LICENSE */,
C1539F4C1510C76A00C6A479 /* README.md */,
C1D673A014F4D247006D3483 /* BookShelf */,
C1D6739914F4D247006D3483 /* Frameworks */,
@@ -394,6 +397,7 @@
C1F0ED3015EA6C470034F0FC /* Shelf-Landscape~iphone.png in Resources */,
C1F0ED3115EA6C470034F0FC /* Shelf~iphone.png in Resources */,
C1F0ED3215EA6C470034F0FC /* Shelf@2x~iphone.png in Resources */,
+ C182834616633FB600A69C46 /* LICENSE in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
4 BookShelf/AboveTopView.m
@@ -46,7 +46,9 @@ - (id)initWithFrame:(CGRect)frame
UIImageView *woodImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 139 * 2)];
CGFloat scale = isRetina ? 2.0f : 1.0f;
- [woodImageView setImage:[UIImage imageWithCGImage:CGImageCreateWithImageInRect([[UIImage imageNamed:@"WoodTile-iPhone.png"] CGImage], CGRectMake(0, 0, 320 * scale, 139 * 2 * scale))]];
+ CGImageRef woodImgRef = CGImageCreateWithImageInRect([[UIImage imageNamed:@"WoodTile-iPhone.png"] CGImage], CGRectMake(0, 0, 320 * scale, 139 * 2 * scale));
+ [woodImageView setImage:[UIImage imageWithCGImage:woodImgRef]];
+ CGImageRelease(woodImgRef);
[self addSubview:woodImageView];
UIImageView *sideImageView_left1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 160, 164)];
View
18 BookShelf/GSBookShelfView.m
@@ -126,6 +126,17 @@ - (CGRect)visibleRect {
return visibleRect;
}
+- (CGRect)availableRectFromVisibleRect:(CGRect)visibleRect {
+ // Discussion:
+ // visibleRect: the visible rect
+ // availableRect: highter than the visible rect, make
+ CGRect availableRect = visibleRect;
+
+ availableRect.size.height += fminf(self.contentSize.height - (availableRect.origin.y + availableRect.size.height), [_dataSource cellHeightOfBookShelfView:self] * 2);
+
+ return availableRect;
+}
+
- (void)resetContentSize {
NSLog(@"resetContentSize");
//NSLog(@"resetContentSize");
@@ -207,8 +218,11 @@ - (void)layoutSubviews {
[self resetContentSize];
}
- [_bookViewContainerView layoutSubviewsWithVisibleRect:[self visibleRect]];
- [_cellContainerView layoutSubviewsWithVisibleRect:[self visibleRect]];
+ //[_bookViewContainerView layoutSubviewsWithVisibleRect:[self visibleRect]];
+ CGRect visibleRect = [self visibleRect];
+ CGRect availableRect = [self availableRectFromVisibleRect:visibleRect];
+ [_bookViewContainerView layoutSubviewsWithAvailableRect:availableRect visibleRect:visibleRect];
+ [_cellContainerView layoutSubviewsWithAvailableRect:availableRect];
}
#pragma mark - Public
View
3 BookShelf/GSBookViewContainerView.h
@@ -53,6 +53,7 @@ typedef struct BookViewPostion {
@private
CGRect _visibleRect;
+ CGRect _availableRect;
NSInteger _firstVisibleRow;
NSInteger _lastVisibleRow;
@@ -95,7 +96,7 @@ typedef struct BookViewPostion {
- (NSArray *)visibleBookViews;
- (UIView *)bookViewAtIndex:(NSInteger)index;
-- (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect;
+- (void)layoutSubviewsWithAvailableRect:(CGRect)availableRect visibleRect:(CGRect)visibleRect;
- (UIView *)dequeueReusableBookViewWithIdentifier:(NSString *)identifier;
View
60 BookShelf/GSBookViewContainerView.m
@@ -127,6 +127,8 @@ - (void)calculateLayout {
_bookViewHeight = [_parentBookShelfView.dataSource bookViewHeightOfBookShelfView:_parentBookShelfView];
_bookViewSpacingWidth = numOfBooksInCell == 1 ? 0 : (cellWidth - 2 * cellMargin - numOfBooksInCell * _bookViewWidth) / (numOfBooksInCell - 1);
+
+ NSAssert(_bookViewSpacingWidth >= 0, @"invalid book size");
}
- (void)reloadData {
@@ -240,7 +242,7 @@ - (void)removeBookViewWithType:(RemoveType)rmType {
rmIndex = [_visibleBookViews count] - 1;
}
UIView *bookView = [_visibleBookViews objectAtIndex:rmIndex];
- // Discusstion:When Drag And Scroll happends,somtimes _dragView's pickupPosition may have not changed. Then it may be told to be removed from superView, and this will cause the _dragView dissappear. So here we prevent the removeFromSuperview from happening, but still remove it from the _visibleBookViews. _visibleBookViews tells which view is visible except the _dragView, which means _dragView is "invisible" for _visibleBookViews when it's original position scroll out of the _visibleRect.
+ // Discusstion:When Drag And Scroll happends,somtimes _dragView's pickupPosition may have not changed. Then it may be told to be removed from superView, and this will cause the _dragView dissappear. So here we prevent the removeFromSuperview from happening, but still remove it from the _visibleBookViews. _visibleBookViews tells which view is visible except the _dragView, which means _dragView is "invisible" for _visibleBookViews when it's original position scroll out of the _availableRect.
if (_isDragViewPickedUp && bookView == _dragView) {
_isDragViewRemovedFromVisibleBookViews = YES;
}
@@ -252,7 +254,7 @@ - (void)removeBookViewWithType:(RemoveType)rmType {
}
-- (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
+- (void)layoutSubviewsWithAvailableRect:(CGRect)availableRect visibleRect:(CGRect)visibleRect{
// To reduce memory usage, we only add visible bookViews to the subviews. So every time it scrolls, we shoud add and remove some bookViews.You can check the sample project (ScrollView Suit >> Tiling) for information.
// Discussion: the layout sequence is easy to understand. There are 6 situation we should consider. You can draw these condition on a papper to get it more clear.
@@ -274,7 +276,8 @@ - (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
//NSLog(@"bookViewContainer layout");
- //NSLog(@"visibleRect %@", NSStringFromCGRect(visibleRect));
+ //NSLog(@"availableRect %@", NSStringFromCGRect(availableRect));
+ _availableRect = availableRect;
_visibleRect = visibleRect;
NSInteger numberOfBooksInCell = [_parentBookShelfView.dataSource numberOFBooksInCellOfBookShelfView:_parentBookShelfView];
@@ -285,8 +288,8 @@ - (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
NSInteger cellHeight = [_parentBookShelfView.dataSource cellHeightOfBookShelfView:_parentBookShelfView];
- NSInteger firstNeededRow = MAX(0, floorf(CGRectGetMinY(visibleRect) / cellHeight));
- NSInteger lastNeededRow = MIN(numberOfCells - 1, floorf(CGRectGetMaxY(visibleRect) / cellHeight));
+ NSInteger firstNeededRow = MAX(0, floorf(CGRectGetMinY(availableRect) / cellHeight));
+ NSInteger lastNeededRow = MIN(numberOfCells - 1, floorf(CGRectGetMaxY(availableRect) / cellHeight));
//NSLog(@"\n------------\nfirstNeededRow:%d firstVisibleRow:%d\nlastNeededRow: %d lastVisibleRow: %d\n************", firstNeededRow, _firstVisibleRow, lastNeededRow, _lastVisibleRow);
@@ -377,7 +380,7 @@ - (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
- (void)layoutSubviews {
// Do nothing here
- // use layoutSubviewsWithVisibleRect: instead
+ // use layoutSubviewsWithavailableRect: instead
}
#pragma mark - BookViewPosition
@@ -424,7 +427,7 @@ - (BOOL)isBookViewPositionVisible:(BookViewPostion)position {
}
- (CGRect)bookViewRectAtBookViewPosition:(BookViewPostion)position {
- // Dose not need position.index here
+ // Do not need position.index here
CGFloat cellHeight = _parentBookShelfView.cellHeight;
CGFloat bookViewBottomOffset = _parentBookShelfView.bookViewBottomOffset;
CGFloat cellMarginWidth = _parentBookShelfView.cellMargin;
@@ -435,6 +438,22 @@ - (CGRect)bookViewRectAtBookViewPosition:(BookViewPostion)position {
return CGRectMake(originX, originY, _bookViewWidth, _bookViewHeight);
}
+- (CGRect)bookViewEffectiveRectAtBookViewPosition:(BookViewPostion)position {
+ CGFloat cellHeight = _parentBookShelfView.cellHeight;
+ CGFloat bookViewBottomOffset = _parentBookShelfView.bookViewBottomOffset;
+ CGFloat cellMarginWidth = _parentBookShelfView.cellMargin;
+
+ NSInteger numberOfBooksInCell = _parentBookShelfView.numberOfBooksInCell;
+
+ CGFloat originX = position.col * (_bookViewWidth + _bookViewSpacingWidth) + (position.col > 0 ? (cellMarginWidth - _bookViewSpacingWidth / 2) : 0);
+
+ CGFloat effectiveWidth = _bookViewWidth + _bookViewSpacingWidth + ((position.col == 0 || position.col == numberOfBooksInCell - 1) ? (cellMarginWidth - _bookViewSpacingWidth / 2) : 0);
+
+ CGFloat originY = position.row * cellHeight + bookViewBottomOffset - _bookViewHeight;
+
+ return CGRectMake(originX, originY, effectiveWidth, _bookViewHeight);
+}
+
- (BookViewPostion)bookViewPositionAtPoint:(CGPoint)point {
// Always return a valid BookViewPosition
CGFloat cellHeight = _parentBookShelfView.cellHeight;
@@ -443,12 +462,24 @@ - (BookViewPostion)bookViewPositionAtPoint:(CGPoint)point {
CGFloat cellMarginWidth = _parentBookShelfView.cellMargin;
- NSInteger currentCol = floorf((point.x - cellMarginWidth) / (_bookViewWidth + _bookViewSpacingWidth));
+ CGFloat firstColWidth = cellMarginWidth + _bookViewWidth + _bookViewSpacingWidth / 2;
+ CGFloat middleColWidth = _bookViewWidth + _bookViewSpacingWidth;
NSInteger numberOfBooksInCell = _parentBookShelfView.numberOfBooksInCell;
+ NSInteger currentCol;
+
+ if (point.x < firstColWidth) {
+ currentCol = 0;
+ }
+ else {
+ currentCol = MIN(floorf((point.x - firstColWidth) / middleColWidth) + 1, numberOfBooksInCell - 1);
+ }
+
BookViewPostion position = {currentRow, currentCol, currentRow * numberOfBooksInCell + currentCol};
+ //NSLog(@"position [%d] [%d]", currentRow, currentCol);
+
return position;
}
@@ -570,14 +601,14 @@ - (void)scrollIfNecessary {
[self stopScrollTimer];
CGFloat distanceFromTop = _dragView.center.y - _visibleRect.origin.y;
if (distanceFromTop < kScroll_trigger_dis) {
- double rate = (kScroll_trigger_dis - distanceFromTop) / 6.0;
+ double rate = (kScroll_trigger_dis - distanceFromTop) / 4.0;
NSTimeInterval interval = fmax(kScroll_interval_min, kScroll_interval_max / rate);
_scrollTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(dragScroll:) userInfo:[NSNumber numberWithBool:YES] repeats:YES];
}
else if (distanceFromTop > _visibleRect.size.height - kScroll_trigger_dis) {
- double rate = (kScroll_trigger_dis - (_visibleRect.size.height - distanceFromTop)) / 6.0;
+ double rate = (kScroll_trigger_dis - (_visibleRect.size.height - distanceFromTop)) / 4.0;
NSTimeInterval interval = fmax(kScroll_interval_min, kScroll_interval_max / rate);
_scrollTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(dragScroll:) userInfo:[NSNumber numberWithBool:NO] repeats:YES];
@@ -620,10 +651,17 @@ - (void)moveBooksIfNecessary {
[self bringSubviewToFront:_dragView];
BookViewPostion position = [self bookViewPositionAtPoint:_dragView.center];
CGRect bookViewRect = [self bookViewRectAtBookViewPosition:position];
+ CGRect bookviewEffectiveRect = [self bookViewEffectiveRectAtBookViewPosition:position];
+
+ //NSLog(@"[0] %@", NSStringFromCGPoint(_dragView.center));
+ //NSLog(@"[1] %@", NSStringFromCGRect(bookViewRect));
+ //NSLog(@"[2] %@", NSStringFromCGRect(bookviewEffectiveRect));
- if (CGRectContainsPoint(bookViewRect, _dragView.center) && [self isBookViewPositionVisible:position]) {
+ if (CGRectContainsPoint(bookviewEffectiveRect, _dragView.center) && [self isBookViewPositionVisible:position]) {
+ //NSLog(@"contain");
if (!CGRectEqualToRect(bookViewRect, _pickUpRect)) {
// Rerange _visibleBookViews
+ //NSLog(@"Rerange");
[self animateBookViewToBookViewPostion:position rect:bookViewRect];
}
}
View
2 BookShelf/GSCellContainerView.h
@@ -57,6 +57,6 @@
- (UIView *)cellAtRow:(NSInteger)row;
- (void)reloadData;
- (UIView *)dequeueReuseableCellWithIdentifier:(NSString *)identifier;
-- (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect;
+- (void)layoutSubviewsWithAvailableRect:(CGRect)availableRect;
@end
View
16 BookShelf/GSCellContainerView.m
@@ -186,12 +186,12 @@ - (void)addCellAtRow:(NSInteger)row addType:(AddType)type{
}
}
-- (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
+- (void)layoutSubviewsWithAvailableRect:(CGRect)availableRect {
CGFloat shelfShadowHeight = [_parentBookShelfView.dataSource cellShadowHeightOfBookShelfView:_parentBookShelfView];
- CGFloat newOriginY = fmaxf(visibleRect.origin.y - shelfShadowHeight, 0);
- CGFloat addHeight = visibleRect.origin.y - newOriginY;
- visibleRect.origin.y = newOriginY;
- visibleRect.size.height += addHeight;
+ CGFloat newOriginY = fmaxf(availableRect.origin.y - shelfShadowHeight, 0);
+ CGFloat addHeight = availableRect.origin.y - newOriginY;
+ availableRect.origin.y = newOriginY;
+ availableRect.size.height += addHeight;
NSInteger numberOfBooksInCell = [_parentBookShelfView.dataSource numberOFBooksInCellOfBookShelfView:_parentBookShelfView];
@@ -205,8 +205,8 @@ - (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
NSInteger maxNumberOfCells = MAX(numberOfCells, minNumberOfCells);
- NSInteger firstNeededRow = MAX(0, floorf(CGRectGetMinY(visibleRect) / cellHeight));
- NSInteger lastNeededRow = MIN(maxNumberOfCells - 1, floorf(CGRectGetMaxY(visibleRect) / cellHeight));
+ NSInteger firstNeededRow = MAX(0, floorf(CGRectGetMinY(availableRect) / cellHeight));
+ NSInteger lastNeededRow = MIN(maxNumberOfCells - 1, floorf(CGRectGetMaxY(availableRect) / cellHeight));
if (_firstVisibleRow == -1) {
// First time
@@ -262,7 +262,7 @@ - (void)layoutSubviewsWithVisibleRect:(CGRect)visibleRect {
- (void)layoutSubviews {
// Do nothing here
- // use layoutSubviewsWithVisibleRect: instead
+ // use layoutSubviewsWithavailableRect: instead
}
#pragma mark - convert
View
41 BookShelf/main.m
@@ -1,10 +1,37 @@
-//
-// main.m
-// BookShelf
-//
-// Created by 鑫容 郭 on 12-2-22.
-// Copyright (c) 2012年 FoOTOo. All rights reserved.
-//
+/*
+ main.m
+ BookShelf
+
+ Created by Xinrong Guo on 12-2-22.
+ Copyright (c) 2012 FoOTOo. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of the project's author nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
#import <UIKit/UIKit.h>
View
31 LICENSE
@@ -0,0 +1,31 @@
+GSBookShelf and all code associated with it is distributed under a BSD license, as listed below
+
+Created by Xinrong Guo
+Copyright (c) 2012 FoOTOo. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+Neither the name of the project's author nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

0 comments on commit a6947f3

Please sign in to comment.
Something went wrong with that request. Please try again.