├── .DS_Store ├── images ├── .DS_Store └── detail.gif ├── MDetailFramework ├── .DS_Store ├── testDetail │ ├── .DS_Store │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── 1.imageset │ │ │ ├── 1.jpg │ │ │ └── Contents.json │ │ ├── l.imageset │ │ │ ├── l.jpg │ │ │ └── Contents.json │ │ ├── w.imageset │ │ │ ├── w.jpg │ │ │ └── Contents.json │ │ ├── xt.imageset │ │ │ ├── xt.jpg │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── DetailWapViewController.h │ ├── DetailTableViewController.h │ ├── RootTableViewController.h │ ├── DetailScrollViewController.h │ ├── AppDelegate.h │ ├── SingleOneSectionTableViewController.h │ ├── main.m │ ├── Base.lproj │ │ ├── Localizable.strings │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── SingleOneSectionTableViewController.m │ ├── Info.plist │ ├── AppDelegate.m │ ├── UIImage+extend.h │ ├── RootTableViewController.m │ ├── DetailScrollViewController.m │ ├── DetailWapViewController.m │ ├── DetailTableViewController.m │ └── UIImage+extend.m ├── MDetailFramework │ ├── .DS_Store │ ├── Detail.bundle │ │ ├── en.lproj │ │ │ └── Root.strings │ │ ├── images │ │ │ ├── detail_down_loading.png │ │ │ └── detail_left_loading.png │ │ ├── zh-Hans.lproj │ │ │ └── Root.strings │ │ └── Root.plist │ ├── DetailControl │ │ ├── DetailTipView.h │ │ ├── DetailLocalizable.h │ │ ├── DetailLocalizable.m │ │ ├── DetailRefreshView.h │ │ ├── DetailTipView.m │ │ ├── DetailPictureView.h │ │ ├── DetailView.h │ │ ├── DetailRefreshView.m │ │ ├── DetailPictureView.m │ │ └── DetailView.m │ ├── MDetailFramework.h │ └── Info.plist ├── MFullScreenFramework.framework │ ├── .DS_Store │ ├── Info.plist │ ├── MFullScreenFramework │ └── Headers │ │ ├── UIImage+Full.h │ │ ├── UIScrollView+PageControl.h │ │ ├── MFullScreenView.h │ │ ├── MFullScreenFramework.h │ │ ├── MFullScreenControl.h │ │ └── UIScrollPageControlView.h ├── MDetailFramework.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj └── testDetailTests │ ├── Info.plist │ └── testDetailTests.m ├── LICENSE ├── .gitignore ├── README.md └── README.html /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/.DS_Store -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/images/.DS_Store -------------------------------------------------------------------------------- /images/detail.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/images/detail.gif -------------------------------------------------------------------------------- /MDetailFramework/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/.DS_Store -------------------------------------------------------------------------------- /MDetailFramework/testDetail/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/testDetail/.DS_Store -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MDetailFramework/.DS_Store -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MFullScreenFramework.framework/.DS_Store -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MFullScreenFramework.framework/Info.plist -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/1.imageset/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/testDetail/Assets.xcassets/1.imageset/1.jpg -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/l.imageset/l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/testDetail/Assets.xcassets/l.imageset/l.jpg -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/w.imageset/w.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/testDetail/Assets.xcassets/w.imageset/w.jpg -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/xt.imageset/xt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/testDetail/Assets.xcassets/xt.imageset/xt.jpg -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/Detail.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MDetailFramework/Detail.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/MFullScreenFramework: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MFullScreenFramework.framework/MFullScreenFramework -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/Detail.bundle/images/detail_down_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MDetailFramework/Detail.bundle/images/detail_down_loading.png -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/Detail.bundle/images/detail_left_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/was0107/MDetailFramework/HEAD/MDetailFramework/MDetailFramework/Detail.bundle/images/detail_left_loading.png -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailTipView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailTipView.h 3 | // DW 4 | // 5 | // Created by boguang on 15/6/23. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailTipView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/DetailWapViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailWapViewController.h 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailWapViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/DetailTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailTableViewController.h 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailTableViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/RootTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RootTableViewController.h 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RootTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/DetailScrollViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailScrollViewController.h 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailScrollViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Headers/UIImage+Full.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Full.h 3 | // MFullScreenFramework 4 | // 5 | // Created by Micker on 16/3/1. 6 | // Copyright © 2016年 b5m. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (Full) 12 | 13 | - (CGRect) getRectWithSize:(CGSize) size; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // testDetail 4 | // 5 | // Created by Micker on 16/4/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/SingleOneSectionTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SingleOneSectionTableViewController.h 3 | // B5MDetailFramework 4 | // 5 | // Created by Micker on 16/4/13. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailWapViewController.h" 10 | 11 | @interface SingleOneSectionTableViewController : DetailWapViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // testDetail 4 | // 5 | // Created by Micker on 16/4/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailLocalizable.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailLocalizable.h 3 | // MDetailFramework 4 | // 5 | // Created by Micker on 16/6/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailLocalizable : NSObject 12 | 13 | + (NSString *) localizStringKey:(NSString *) key comment:(NSString *) comment; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Base.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | MDetailFramework 4 | 5 | Created by Micker on 16/6/14. 6 | Copyright © 2016年 micker. All rights reserved. 7 | */ 8 | 9 | "detail_picture_default" = "滑动,查看图文详情"; 10 | "detail_picture_release" = "释放,查看图文详情"; 11 | "detail_pull_default" = "下拉,返回宝贝详情"; 12 | "detail_pull_release" = "释放,返回宝贝详情"; 13 | "detail_section_default" = "继续拖动,查看图文详情"; -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/Detail.bundle/zh-Hans.lproj/Root.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | MDetailFramework 4 | 5 | Created by Micker on 16/6/14. 6 | Copyright © 2016年 micker. All rights reserved. 7 | */ 8 | 9 | 10 | "detail_picture_default" = "滑动,查看图文详情"; 11 | "detail_picture_release" = "释放,查看图文详情"; 12 | "detail_pull_default" = "下拉,返回宝贝详情"; 13 | "detail_pull_release" = "释放,返回宝贝详情"; 14 | "detail_section_default" = "继续拖动,查看图文详情"; -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "1.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/l.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "l.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/w.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "w.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/xt.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "xt.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MDetailFramework/testDetail/SingleOneSectionTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SingleOneSectionTableViewController.m 3 | // B5MDetailFramework 4 | // 5 | // Created by Micker on 16/4/13. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import "SingleOneSectionTableViewController.h" 10 | 11 | @implementation SingleOneSectionTableViewController 12 | 13 | - (void) dealloc { 14 | NSLog(@"SingleOneSectionTableViewController.h dealloc"); 15 | } 16 | 17 | //仅返回1 18 | - (NSUInteger ) numberOfSections { 19 | return 1; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/MDetailFramework.h: -------------------------------------------------------------------------------- 1 | // 2 | // MDetailFramework.h 3 | // MDetailFramework 4 | // 5 | // Created by Micker on 16/4/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for MDetailFramework. 12 | FOUNDATION_EXPORT double MDetailFrameworkVersionNumber; 13 | 14 | //! Project version string for MDetailFramework. 15 | FOUNDATION_EXPORT const unsigned char MDetailFrameworkVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Headers/UIScrollView+PageControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+PageControl.h 3 | // DW 4 | // 5 | // Created by boguang on 15/7/3. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIScrollView (PageControl) 12 | 13 | @property (nonatomic, strong, readonly) UIPageControl *pageControl; 14 | 15 | /** 16 | * 显示Page控件 17 | * 18 | * @return 19 | * 20 | */ 21 | - (void) showPageControl; 22 | 23 | /** 24 | * 根据当前的contentSize 及 frame.size.width,计算页数 25 | * 26 | * @return 27 | * 28 | */ 29 | - (void) computePageControlPages; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Headers/MFullScreenView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFullScreenView.h 3 | // MFullScreenFramework 4 | // 5 | // Created by Micker on 16/2/14. 6 | // Copyright © 2016年 b5m. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MFullScreenView : UIView 12 | 13 | @property (nonatomic, strong) UIScrollView *scrollView; //容器 14 | @property (nonatomic, strong) UIImageView *imageView; //执行动画的图片视图 15 | @property (nonatomic, assign, setter=enableDoubleTap:) BOOL isDoubleTapEnabled; //是否允许双击放大 16 | @property (nonatomic, strong) void (^singleTapBlock)(UITapGestureRecognizer *recognizer); //单击的回调处理 17 | 18 | /** 19 | * 重新加载数据 20 | * 21 | * @parames 22 | * 23 | * @return 24 | * 25 | */ 26 | - (void) reloadData; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailLocalizable.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailLocalizable.m 3 | // MDetailFramework 4 | // 5 | // Created by Micker on 16/6/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailLocalizable.h" 10 | 11 | @implementation DetailLocalizable 12 | 13 | + (NSString *) localizStringKey:(NSString *)key comment:(NSString *) comment{ 14 | NSString *resourceBundlePath = [[NSBundle mainBundle] pathForResource:@"Detail" ofType:@"bundle"]; 15 | NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath]; 16 | 17 | NSString *result = NSLocalizedStringFromTableInBundle(key, @"Root", resourceBundle, comment); 18 | if ([result length] == 0) { 19 | result = comment; 20 | } 21 | return result; 22 | } 23 | @end 24 | -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Headers/MFullScreenFramework.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFullScreenFramework.h 3 | // MFullScreenFramework 4 | // 5 | // Created by Micker on 16/4/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for MFullScreenFramework. 12 | FOUNDATION_EXPORT double MFullScreenFrameworkVersionNumber; 13 | 14 | //! Project version string for MFullScreenFramework. 15 | FOUNDATION_EXPORT const unsigned char MFullScreenFrameworkVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | #import "MFullScreenControl.h" 21 | #import "UIScrollPageControlView.h" 22 | #import "UIScrollPageControlView.h" 23 | #import "MFullScreenView.h" 24 | 25 | -------------------------------------------------------------------------------- /MDetailFramework/testDetailTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Headers/MFullScreenControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFullScreenControl.h 3 | // MFullScreenFramework 4 | // 5 | // Created by boguang on 15/8/20. 6 | // Copyright (c) 2015年 b5m. All rights reserved. 7 | // 8 | 9 | #include 10 | #import "UIScrollPageControlView.h" 11 | 12 | @interface MFullScreenControl : NSObject 13 | 14 | @property (nonatomic, strong) UIScrollPageControlView *screenPageView; //滚动视图 15 | @property (nonatomic, assign) BOOL isAppear; //记录当前状态 16 | 17 | /** 18 | * 从指定视图中,展开全屏浏览模式 19 | * 20 | * @parames 21 | * @param view 一般为UIImageView的对象 22 | * 23 | * @return 24 | * 25 | */ 26 | - (void) appearOnView:(UIView *) view; 27 | 28 | 29 | /** 30 | * 从指定视图中,取消全屏浏览模式,带有动画效果 31 | * 32 | * @parames 33 | * @param view 一般为UIImageView的对象 34 | * 35 | * @return 36 | * 37 | */ 38 | - (void) disAppearOnView:(UIView *) view; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /MDetailFramework/testDetailTests/testDetailTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // testDetailTests.m 3 | // testDetailTests 4 | // 5 | // Created by Micker on 16/4/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface testDetailTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation testDetailTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Allen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailRefreshView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailRefreshView.h 3 | // DW 4 | // 5 | // Created by boguang on 15/6/23. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, DetailRefreshState) { 12 | DetailRefreshStateNormal, 13 | DetailRefreshStateLoading, 14 | DetailRefreshStateTriggerd 15 | }; 16 | 17 | typedef NS_ENUM(NSInteger, DetailRefreshViewAnimateType) { 18 | DetailRefreshViewAnimateTypeAttachTop, //吸顶, 默认值 19 | DetailRefreshViewAnimateTypeAttachBottom, //跟随底部 20 | DetailRefreshViewAnimateTypeSpeed1, //差速,速度是底部的1/3速度;难于滑动 21 | DetailRefreshViewAnimateTypeSpeed2, //差速,是底部的1/2速度;易于滑动 22 | }; 23 | 24 | #pragma mark -- 25 | #pragma mark DetailRefreshView 26 | 27 | @interface DetailRefreshView : UIView 28 | @property (nonatomic, strong) UILabel *bottomLabel; 29 | @property (nonatomic, strong) UIImageView *topImageView; 30 | @property (nonatomic, assign) UIScrollView *scrollView; 31 | @property (nonatomic, assign) DetailRefreshState state; 32 | @property (nonatomic, assign) DetailRefreshViewAnimateType animateType; 33 | @property (nonatomic, copy) void (^handler)(void); 34 | 35 | @end 36 | 37 | 38 | #pragma mark -- 39 | #pragma mark __DetailRefreshView 40 | 41 | 42 | @interface UIScrollView(__DetailRefreshView) 43 | 44 | @property (nonatomic, strong, readonly) DetailRefreshView *refreshView; 45 | 46 | - (void) addDetailRefreshWithHandler:(void (^)(void)) handler; 47 | 48 | @end -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/Detail.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StringsTable 6 | Root 7 | PreferenceSpecifiers 8 | 9 | 10 | Type 11 | PSGroupSpecifier 12 | Title 13 | Group 14 | 15 | 16 | Type 17 | PSTextFieldSpecifier 18 | Title 19 | Name 20 | Key 21 | name_preference 22 | DefaultValue 23 | 24 | IsSecure 25 | 26 | KeyboardType 27 | Alphabet 28 | AutocapitalizationType 29 | None 30 | AutocorrectionType 31 | No 32 | 33 | 34 | Type 35 | PSToggleSwitchSpecifier 36 | Title 37 | Enabled 38 | Key 39 | enabled_preference 40 | DefaultValue 41 | 42 | 43 | 44 | Type 45 | PSSliderSpecifier 46 | Key 47 | slider_preference 48 | DefaultValue 49 | 0.5 50 | MinimumValue 51 | 0 52 | MaximumValue 53 | 1 54 | MinimumValueImage 55 | 56 | MaximumValueImage 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | zh_CN 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailTipView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailTipView.m 3 | // DW 4 | // 5 | // Created by boguang on 15/6/23. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailTipView.h" 10 | #import "DetailLocalizable.h" 11 | 12 | @implementation DetailTipView { 13 | UIView *_leftLine , *_rightLine; 14 | CGFloat layerWidth; 15 | CGFloat layerSpace; 16 | } 17 | 18 | - (id) initWithFrame:(CGRect)frame { 19 | layerSpace = 15.0f; 20 | self = [super initWithFrame:frame]; 21 | if (self) { 22 | 23 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; 24 | label.textAlignment = NSTextAlignmentCenter; 25 | label.backgroundColor = [UIColor clearColor]; 26 | self.backgroundColor = [UIColor colorWithRed:241.0f/255.0f green:241.0f/255.0f blue:241.0f/255.0f alpha:1]; 27 | label.text = [DetailLocalizable localizStringKey:@"detail_section_default" comment:@"继续拖动,查看图文详情"]; 28 | label.font = [UIFont systemFontOfSize:13.0f]; 29 | [self addSubview:label]; 30 | 31 | CGSize size = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}]; 32 | layerWidth = (self.bounds.size.width - size.width - layerSpace * 4) / 2 ; 33 | [self addLeftRightLayer]; 34 | } 35 | return self; 36 | } 37 | 38 | - (void) addLeftRightLayer { 39 | UIColor *lineColor = [UIColor colorWithRed:206.0f/255.0f green:206.0f/255.0f blue:206.0f/255.0f alpha:0.7f]; 40 | _leftLine = [[UIView alloc] initWithFrame:CGRectMake(layerSpace, self.bounds.size.height/2 - 1, layerWidth, 1)]; 41 | _leftLine.backgroundColor = lineColor; 42 | [self addSubview:_leftLine]; 43 | 44 | _rightLine = [[UIView alloc] initWithFrame:CGRectMake((self.bounds.size.width - layerSpace - layerWidth), self.bounds.size.height/2 - 1, layerWidth, 1)]; 45 | _rightLine.backgroundColor = lineColor; 46 | [self addSubview:_rightLine]; 47 | } 48 | @end 49 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // testDetail 4 | // 5 | // Created by Micker on 16/4/14. 6 | // Copyright © 2016年 micker. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailPictureView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailPictureView.h 3 | // DW 4 | // 5 | // Created by boguang on 15/6/24. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, DetailPictureViewState) { 12 | DetailPictureViewStateNormal, 13 | DetailPictureViewStateLoading, 14 | DetailPictureViewStateTriggerd 15 | }; 16 | 17 | typedef NS_ENUM(NSInteger, DetailPictureViewAnimateType) { 18 | DetailPictureViewAnimateTypeAttachRight, //右边吸住,靠近边框, 默认值 19 | DetailPictureViewAnimateTypeAttachLeft, //左边吸住,跟随变化 20 | DetailPictureViewAnimateTypeSpeed1, //差速1 21 | DetailPictureViewAnimateTypeSpeed2, //差速2 22 | }; 23 | 24 | #pragma mark -- 25 | #pragma mark DetailPictureView 26 | 27 | @interface DetailPictureView : UIView 28 | 29 | @property (nonatomic, strong) UILabel *rightLabel; 30 | @property (nonatomic, strong) UIImageView *leftImageView; 31 | @property (nonatomic, assign) UIScrollView *scrollView; 32 | @property (nonatomic, assign) DetailPictureViewState state; 33 | @property (nonatomic, assign) DetailPictureViewAnimateType animateType; 34 | @property (nonatomic, copy) void (^handler)(void); 35 | 36 | @end 37 | 38 | 39 | 40 | #pragma mark -- 41 | #pragma mark __DetailPictureView 42 | 43 | @interface UIScrollView(__DetailPictureView) 44 | 45 | @property (nonatomic, strong, readonly) DetailPictureView *pictureView; 46 | 47 | - (void) addDetaiPictureViewWithHandler:(void (^)(void)) handler; 48 | 49 | @end 50 | 51 | 52 | 53 | #pragma mark -- 54 | #pragma mark --Parallas 55 | 56 | @interface ParallasObject : NSObject 57 | 58 | @property (nonatomic, strong) UIScrollView *scrollView; 59 | @property (nonatomic, weak) UIView *targetView; 60 | @property (nonatomic, assign) BOOL isVertical; 61 | @property (nonatomic, copy) void (^handler)(void); 62 | 63 | @end 64 | 65 | 66 | #pragma mark -- 67 | #pragma mark --UIScrollView(__Parallas) 68 | 69 | @interface UIScrollView(__Parallas) 70 | 71 | @property (nonatomic, strong) ParallasObject *parallas; 72 | 73 | - (void) addHorizeParallas:(UIView *) targetView block:(void (^)(void))block ; 74 | 75 | - (void) addVerticalParallas:(UIView *) targetView block:(void (^)(void))block ; 76 | 77 | @end -------------------------------------------------------------------------------- /MDetailFramework/testDetail/UIImage+extend.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage-Extensions.h 3 | // 4 | // Created by Hardy Macia on 7/1/09. 5 | // Copyright 2009 Catamount Software. All rights reserved. 6 | // 7 | #import 8 | #import 9 | //CGFloat DegreesToRadians(CGFloat degrees); 10 | //CGFloat RadiansToDegrees(CGFloat radians); 11 | CGFloat RadiansToDegrees(CGFloat radians); 12 | 13 | NS_INLINE UIImage *InlineScaledImageToMiniumuSize(UIImage *sourceImage,CGSize targetSize) 14 | { 15 | // UIImage *sourceImage = sourceImage; 16 | UIImage *newImage = nil; 17 | 18 | CGSize imageSize = sourceImage.size; 19 | CGFloat width = imageSize.width; 20 | CGFloat height = imageSize.height; 21 | 22 | CGFloat targetWidth = targetSize.width; 23 | CGFloat targetHeight = targetSize.height; 24 | 25 | CGFloat scaleFactor = 0.0; 26 | 27 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) 28 | { 29 | 30 | CGFloat widthFactor = targetWidth / width; 31 | CGFloat heightFactor = targetHeight / height; 32 | 33 | if (widthFactor > heightFactor) 34 | scaleFactor = widthFactor; 35 | else 36 | scaleFactor = heightFactor; 37 | } 38 | else 39 | { 40 | return sourceImage; 41 | } 42 | 43 | newImage = [[UIImage alloc] initWithCGImage:sourceImage.CGImage scale:scaleFactor orientation:UIImageOrientationUp]; 44 | 45 | if(!newImage) 46 | NSLog(@"could not scale image"); 47 | 48 | return newImage ; 49 | } 50 | 51 | 52 | @interface UIImage (extend) 53 | - (UIImage *)subImageAtRect:(CGRect)rect; 54 | - (UIImage *)imageScaledToSize:(CGSize)size; 55 | - (UIImage *)imageScaledToWidth:(CGFloat)value; 56 | - (UIImage *)imageScaledToHeight:(CGFloat)value; 57 | - (UIImage *)imageScaledToSizeEx:(CGSize)size; 58 | - (UIImage *)imageAtRect:(CGRect)rect; 59 | - (UIImage *)imageByScalingProportionallyToMinimumSize:(CGSize)targetSize; 60 | - (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize; 61 | - (UIImage *)imageByScalingToSize:(CGSize)targetSize; 62 | - (UIImage *)imageRotatedByRadians:(CGFloat)radians; 63 | - (UIImage *)imageRotatedByDegrees:(CGFloat)degrees; 64 | 65 | - (UIImage *)imageWithShadowColor:(UIColor *)color offset:(CGSize)offset blur:(CGFloat)blur; 66 | - (UIImage *)imageWithCornerRadius:(CGFloat)radius; 67 | 68 | - (UIImage *)gaussianBlur; 69 | 70 | - (UIImage *)fixOrientation; 71 | 72 | - (CGFloat)resizableHeightWithFixedwidth:(CGFloat)width; 73 | 74 | - (UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize; 75 | 76 | -(UIImage*)getGrayImage:(UIImage*)sourceImage; 77 | 78 | + (UIImage *) getLaunchImage; 79 | @end; 80 | -------------------------------------------------------------------------------- /MDetailFramework/MFullScreenFramework.framework/Headers/UIScrollPageControlView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollPageControlView.h 3 | // DW 4 | // 5 | // Created by boguang on 15/6/25. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIScrollView+PageControl.h" 11 | 12 | 13 | @class UIScrollPageControlView; 14 | 15 | #pragma mark UIView(_reuseIdentifier) 16 | 17 | @interface UIView(_reuseIdentifier) 18 | 19 | @property (nonatomic, copy) NSString *reuseIdentifier; //复用标识 20 | 21 | @end 22 | 23 | #pragma mark UIScrollPageControlViewDelegate 24 | 25 | @protocol UIScrollPageControlViewDelegate 26 | 27 | @required 28 | 29 | /** 30 | * 配置复用视图总数 31 | * 32 | * @parames control 复用控件 33 | * 34 | * @return 回当前控件的数量 35 | * 36 | */ 37 | - (NSUInteger) numberOfView:(UIScrollPageControlView *) control; 38 | 39 | /** 40 | * 配置索引位置的视图,类似于UITableViewCell的生成方式 41 | * 42 | * @parames control 复用控件 43 | * @parames index 索引位置 44 | * 45 | * @return 生成视图 46 | * 47 | */ 48 | - (UIView *) configItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index ; 49 | 50 | @optional 51 | 52 | /** 53 | * 设置视图之间的间隙 54 | * 55 | * @parames control 复用控件 56 | * 57 | * @return 默认为0 58 | * 59 | */ 60 | - (CGFloat) minimumRowSpacing:(UIScrollPageControlView *) control; 61 | 62 | /** 63 | * 配置正常呈现的视图,主要用于图片失去焦点时,进行场景还原操作,此方法有待优化 64 | * 65 | * @parames control 复用控件 66 | * @parames index 索引位置 67 | * @parames view 对应的视图 68 | * 69 | * @return 70 | * 71 | */ 72 | - (void) reconfigItemOfControl:(UIScrollPageControlView *)control at:(NSUInteger) index withView:(UIView *)view; 73 | 74 | @end 75 | 76 | #pragma mark UIScrollPageControlView 77 | 78 | @interface UIScrollPageControlView : UIView 79 | 80 | @property (nonatomic, strong) UIScrollView *scrollView; 81 | @property (nonatomic, assign) BOOL enablePageControl; //默认为YES 82 | @property (nonatomic, assign) NSInteger currentIndex; //当前展示 83 | @property (nonatomic, assign, readonly) UIView *currentView; //当前展示的视图 84 | @property (nonatomic, assign) id delegate; 85 | 86 | /** 87 | * 获取当前视图的宽度,此宽度会计算间隙 88 | * 89 | * @parames 90 | * 91 | * @return 宽度 92 | * 93 | */ 94 | - (CGFloat) itemWidth; 95 | 96 | /** 97 | * 获取复用视图 98 | * 99 | * @parames identifier 复用标识 100 | * 101 | * @return 如果复用池中存在可复用的视图,则返回复用对象,否则返回nil 102 | * 103 | */ 104 | - (UIView *) dequeueReusableViewWithIdentifier:(NSString *) identifier; 105 | 106 | /** 107 | * 重新加载数据 108 | * 109 | * @parames 110 | * 111 | * @return 112 | * 113 | */ 114 | - (void) reloadData; 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/RootTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RootTableViewController.m 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "RootTableViewController.h" 10 | 11 | 12 | @interface RootTableViewController () 13 | @property (nonatomic, strong) NSMutableArray *data; 14 | 15 | @end 16 | 17 | @implementation RootTableViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | [self.tableView reloadData]; 22 | // Do any additional setup after loading the view, typically from a nib. 23 | } 24 | 25 | - (void) dealloc { 26 | 27 | NSLog(@"RootTableViewController dealloc"); 28 | } 29 | 30 | - (NSMutableArray *) data { 31 | if (!_data) { 32 | _data = [NSMutableArray array]; 33 | [_data addObject:@{@"title":@"Wap商品详情",@"author":@"伯光",@"class":@"DetailWapViewController"}]; 34 | [_data addObject:@{@"title":@"Wap商品详情(单个隐藏Section)",@"author":@"伯光",@"class":@"SingleOneSectionTableViewController"}]; 35 | [_data addObject:@{@"title":@"TableView商品详情",@"author":@"伯光",@"class":@"DetailTableViewController"}]; 36 | [_data addObject:@{@"title":@"ScrollView商品详情",@"author":@"伯光",@"class":@"DetailScrollViewController"}]; 37 | } 38 | return _data; 39 | } 40 | - (void)didReceiveMemoryWarning { 41 | [super didReceiveMemoryWarning]; 42 | // Dispose of any resources that can be recreated. 43 | } 44 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 45 | return 1; 46 | } 47 | 48 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 49 | return [self.data count]; 50 | } 51 | 52 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 53 | static NSString *dequeueReusableCellWithIdentifier = @"dequeueReusableCellWithIdentifier"; 54 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dequeueReusableCellWithIdentifier]; 55 | if(!cell) { 56 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:dequeueReusableCellWithIdentifier]; 57 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 58 | } 59 | 60 | cell.textLabel.text = self.data[indexPath.row][@"title"]; 61 | cell.detailTextLabel.text = self.data[indexPath.row][@"author"]; 62 | return cell; 63 | } 64 | 65 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 66 | return 45; 67 | } 68 | 69 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 70 | NSString *classString = self.data[indexPath.row][@"class"]; 71 | Class newClass = NSClassFromString(classString); 72 | UIViewController *controller = [[newClass alloc] init]; 73 | controller.title = self.data[indexPath.row][@"title"]; 74 | if (controller) 75 | [self.navigationController pushViewController:controller animated:YES]; 76 | } 77 | @end 78 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailView.h 3 | // DW 4 | // 5 | // Created by boguang on 15/6/23. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DetailTipView.h" 11 | #import 12 | 13 | /** 14 | * Detail View Section Delegate 15 | */ 16 | @protocol DetailViewSectionDelegate 17 | 18 | @required 19 | 20 | /** 21 | * 顶部的滚动视图,此视图可以为如下值,UIWebView, UIScrollView及其之类 22 | * 23 | * @return 视图 24 | */ 25 | - (UIView *) viewAtTop; 26 | 27 | /** 28 | * 配置中间区间值的数量 29 | * 30 | * @return 具体数量 31 | */ 32 | - (NSUInteger ) numberOfSections; 33 | 34 | /** 35 | * 配置中间区间的标题 36 | * 37 | * @param index 索引 38 | * 39 | * @return 具体的标题 40 | */ 41 | - (NSString *) titleOfSectionAt:(NSUInteger )index; 42 | 43 | @optional 44 | 45 | /** 46 | * 配置区间中某个索引对应的视图,可以为空 47 | * 48 | * @param index 索引 49 | * 50 | * @return 具体的值,此视图可以为如下值,UIWebView, UIScrollView及其之类 51 | */ 52 | - (UIView *) viewOfSectionAt:(NSUInteger ) index; 53 | 54 | /** 55 | * 配置区间之间,是否可以进行页面切换,若不能切换,则在此编写具体的业务逻辑 56 | * 57 | * @param index 索引 58 | * 59 | * @return 是否能够切换 60 | */ 61 | - (BOOL) canChangeToSection:(NSUInteger) index; 62 | 63 | /** 64 | * 将要切换到某个区间 65 | * 66 | * @param index 索引 67 | * @param view 区间视图 68 | */ 69 | - (void) willChangeToSection:(NSUInteger) index view:(UIView *) view; 70 | 71 | /** 72 | * 已经切换到某个区间 73 | * 74 | * @param index 索引 75 | * @param view 区间视图 76 | */ 77 | - (void) didChangeToSection:(NSUInteger) index view:(UIView *) view; 78 | 79 | 80 | /** 81 | * 弹出层将要出现或者消失 82 | * 83 | * @param appear 是否显示 84 | */ 85 | - (void) floatViewIsGoingTo:(BOOL) appear; 86 | 87 | @end 88 | 89 | 90 | #pragma mark -- 91 | #pragma mark -- DetailView 92 | 93 | @interface DetailView : UIView 94 | @property (nonatomic, weak) UIScrollView *topScrollView; //最重要的视图,用于作各种效果 95 | @property (nonatomic, weak) UIScrollView *imageScrollView; //banner上的图片滚动视图 96 | @property (nonatomic, strong, readonly) DetailTipView *tipView; //中间的提示视图 97 | @property (nonatomic, strong, readonly) UIScrollPageControlView *topScrollPageView; //banner视图,包含滚动视图和页面控件 98 | @property (nonatomic, strong, readonly) MFullScreenControl *fullScreencontrol; //全屏浏览控件,内聚有查看更多功能,即将底部的section上移; 99 | @property (nonatomic, strong, readonly) UIView *topView; //顶部视图的容器 100 | @property (nonatomic, strong, readonly) UIView *bottomView; //底部视图的容器 101 | @property (nonatomic, assign) CGFloat startYPosition; //Section与顶部的间隙,全屏是设置为64.0f,默认为0.0f 102 | @property (nonatomic, assign) CGFloat topScrollViewTopInset; //banner的高度设置,默认为370.0f 103 | @property (nonatomic, weak ) id delegate; //代理 104 | 105 | /** 106 | * 底部视图是否已经显示 107 | * 108 | * @param appear 是否显示 109 | */ 110 | - (BOOL) isBottomViewShowed; 111 | 112 | /** 113 | * 触发底部视图消失 114 | * 115 | * @param appear 是否显示 116 | */ 117 | - (void) disappearBottomView; 118 | 119 | /** 120 | * 显示图片的全屏浏览 121 | * 122 | * @param view 触发的视图 123 | */ 124 | - (void) showFullScreenOnView:(UIView *) view; 125 | 126 | /** 127 | * 隐藏图片的全屏浏览模式, 128 | * 129 | * @param view 触发的视图 || 如果view为空,则不显示动画效果,否则展示缩放的效果; 130 | */ 131 | - (void) hideFullScreenOnView:(UIView *) view; 132 | 133 | /** 134 | * 刷新页面 135 | * 136 | */ 137 | - (void) reloadData; 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/DetailScrollViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailScrollViewController.m 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailScrollViewController.h" 10 | #import "DetailView.h" 11 | #import "UIImage+extend.h" 12 | 13 | static NSString *titles[] = {@"图文详情",@"商品评论",@"店铺推荐"}; 14 | static NSString *urls[] = { 15 | @"http://micker.cn/2016/04/14/%E6%B7%98%E5%AE%9D%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%E6%8E%A7%E4%BB%B6/", 16 | @"http://micker.cn/2016/04/14/%E5%85%A8%E5%B1%8F%E6%B5%8F%E8%A7%88%E6%8E%A7%E4%BB%B6/", 17 | @"http://micker.cn"}; 18 | 19 | @interface DetailScrollViewController () 20 | @property (nonatomic, strong) DetailView *detailView; 21 | @property (nonatomic, strong) UIScrollView *scrollView; 22 | @end 23 | 24 | @implementation DetailScrollViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | self.automaticallyAdjustsScrollViewInsets = NO; 29 | 30 | [self scrollView]; 31 | [self.view addSubview:self.detailView]; 32 | self.view.backgroundColor = [UIColor lightGrayColor]; 33 | [self.detailView reloadData]; 34 | [_scrollView setContentSize:CGSizeMake(self.view.bounds.size.width, (self.view.bounds.size.height - 64) * 2)]; 35 | _detailView.imageScrollView.pageControl.pageIndicatorTintColor = [UIColor whiteColor]; 36 | _detailView.imageScrollView.pageControl.currentPageIndicatorTintColor = [UIColor redColor]; 37 | } 38 | 39 | - (void) dealloc { 40 | NSLog(@"DetailScrollViewController dealloc"); 41 | 42 | } 43 | 44 | - (DetailView *) detailView { 45 | if (!_detailView) { 46 | _detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 47 | _detailView.delegate = self; 48 | _detailView.topScrollPageView.delegate = self; 49 | } 50 | return _detailView; 51 | } 52 | 53 | - (UIScrollView *) scrollView { 54 | if (!_scrollView) { 55 | _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 56 | [_scrollView setContentSize:CGSizeMake(self.view.bounds.size.width, (self.view.bounds.size.height - 64) * 1 + 1.0f) ]; 57 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 58 | label.backgroundColor = [UIColor colorWithWhite:0.7 alpha:0.4f]; 59 | label.text = @"Label 1"; 60 | label.textAlignment = NSTextAlignmentCenter; 61 | [_scrollView addSubview:label]; 62 | label = [[UILabel alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height-64, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 63 | label.backgroundColor = [UIColor redColor]; 64 | label.text = @"Label 2"; 65 | label.textAlignment = NSTextAlignmentCenter; 66 | [_scrollView addSubview:label]; 67 | } 68 | return _scrollView; 69 | } 70 | 71 | 72 | #pragma mark UIScrollPageControlViewDelegate 73 | 74 | - (NSUInteger) numberOfView:(UIScrollPageControlView *) control { 75 | return 10; 76 | } 77 | 78 | - (UIView *) configItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 79 | UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuse"]; 80 | NSString *reuse = @"复用来的"; 81 | UILabel *label = nil; 82 | if (!cellItem) { 83 | cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 370)]; 84 | cellItem.userInteractionEnabled = YES; 85 | cellItem.backgroundColor = [UIColor colorWithWhite:0.7f alpha:0.4f]; 86 | cellItem.reuseIdentifier = @"reuse"; 87 | label = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, 100)]; 88 | reuse = @"=====新生成的"; 89 | label.textAlignment = NSTextAlignmentCenter; 90 | label.tag = 1000; 91 | [cellItem addSubview:label]; 92 | } else { 93 | label = (UILabel *) [cellItem viewWithTag:1000]; 94 | } 95 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic_%d",(int)(index+1) %4]]; 96 | image = [image imageScaledToSizeEx:CGSizeMake(cellItem.frame.size.width * 2, cellItem.frame.size.height * 2)]; 97 | cellItem.image = image; 98 | 99 | label.text = [NSString stringWithFormat:@"item = %ld || reuse = %@", index,reuse]; 100 | return cellItem; 101 | } 102 | 103 | 104 | #pragma mark DetailViewSectionDelegate 105 | 106 | 107 | - (UIView *) viewAtTop { 108 | return self.scrollView; 109 | } 110 | 111 | - (NSUInteger ) numberOfSections { 112 | return 3; 113 | } 114 | 115 | 116 | - (NSString *) titleOfSectionAt:(NSUInteger )index { 117 | return titles[index]; 118 | } 119 | 120 | - (UIView *) viewOfSectionAt:(NSUInteger ) index { 121 | UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectZero]; 122 | return webview; 123 | } 124 | 125 | - (void) didChangeToSection:(NSUInteger) index view:(UIView *) view { 126 | NSString *url = urls[index]; 127 | UIWebView *webView = (UIWebView *) view; 128 | if (!webView.request) { 129 | [webView stopLoading]; 130 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]]; 131 | } 132 | } 133 | 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #MDetailFramework控件 2 | ##前言 3 | [MDetailFramework](https://github.com/was0107/MDetailFramework),为实现淘宝中的商品详情页面中, 商品的基本信息、图文详情、评论、商家推荐的效果; 4 | 5 | ##效果图展示 6 | 为更好的展示效果,请耐心等待
7 | 8 | 9 | ##简介 10 | * 1、此包提供商品详情的展示,支持全屏、导航2种模式; 11 | * 2、支持图片左滑到一定距离时,侧滑展示图文详情、评论,其中图片详情、评论可通过Delegate配置; 12 | * 3、支持视图上拉到一定距离时,上移展示图文详情、评论,其中图片详情、评论可通过Delegate配置; 13 | * 4、banner图片支持点击,全屏展示,且全屏展示模式下,亦支持左滑\点击缩小; 14 | * 5、当Section个数为一个时,不显示SectionBar 15 | * 6、testDetail,提供了四种展示展示方式,UITableView\UITableView(无sectionbar)\UIScrollView\UIWebView; 16 | 17 | ##依赖 18 | * 1、此项目依赖[MFullScreenFramework](https://github.com/was0107/MFullScreenFramework) 19 | 20 | ##举例 21 | 22 | ``` 23 | - (DetailView *) detailView { 24 | if (!_detailView) { 25 | _detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 26 | _detailView.delegate = self; 27 | _detailView.startYPosition = 0.0f; 28 | _detailView.topScrollViewTopInset = 300.0f; 29 | _detailView.topScrollPageView.delegate = self; 30 | } 31 | return _detailView; 32 | } 33 | 34 | - (UIWebView *) topWebView { 35 | if (!_topWebView) { 36 | _topWebView = [[UIWebView alloc] initWithFrame:_detailView.bounds]; 37 | _topWebView.scrollView.showsVerticalScrollIndicator = NO; 38 | _topWebView.backgroundColor = [UIColor whiteColor]; 39 | [_topWebView setOpaque:NO]; 40 | } 41 | return _topWebView; 42 | } 43 | 44 | - (MFullScreenControl *) control { 45 | if(!_control) { 46 | _control = self.detailView.fullScreencontrol; 47 | _control.screenPageView.delegate = self; 48 | } 49 | return _control; 50 | } 51 | 52 | 53 | #pragma mark UIScrollPageControlViewDelegate 54 | 55 | - (NSUInteger) numberOfView:(UIScrollPageControlView *) control { 56 | return 4; 57 | } 58 | 59 | - (UIView *) configBannerItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 60 | UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuse"]; 61 | if (!cellItem) { 62 | cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, _detailView.topScrollViewTopInset)]; 63 | cellItem.userInteractionEnabled = YES; 64 | cellItem.backgroundColor = [UIColor colorWithWhite:0.7f alpha:0.4f]; 65 | cellItem.reuseIdentifier = @"reuse"; 66 | [cellItem addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTaped:)]]; 67 | } 68 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic_%d",(int)(index+1) %4]]; 69 | image = [image imageScaledToSizeEx:CGSizeMake(cellItem.frame.size.width * 2, cellItem.frame.size.height * 2)]; 70 | cellItem.image = image; 71 | return cellItem; 72 | } 73 | 74 | - (UIView *) configFullItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 75 | UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuseFull"]; 76 | if (!cellItem) { 77 | cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, _detailView.topScrollViewTopInset)]; 78 | cellItem.userInteractionEnabled = YES; 79 | cellItem.backgroundColor = [UIColor colorWithWhite:0.7f alpha:0.4f]; 80 | cellItem.reuseIdentifier = @"reuseFull"; 81 | [cellItem addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTaped:)]]; 82 | } 83 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic_%d",(int)(index+1) %4]]; 84 | image = [image imageScaledToSizeEx:CGSizeMake(cellItem.frame.size.width * 2, cellItem.frame.size.height * 2)]; 85 | // cellItem.image = image; 86 | return cellItem; 87 | } 88 | 89 | - (UIView *) configItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 90 | if (control == _control.screenPageView) { 91 | return [self configFullItemOfControl:_control.screenPageView at:index]; 92 | } 93 | return [self configBannerItemOfControl:control at:index]; 94 | } 95 | 96 | - (void) imageViewDidTaped:(UIGestureRecognizer *) recognizer { 97 | if (self.control.isAppear) { 98 | [self.detailView hideFullScreenOnView:recognizer.view]; 99 | return; 100 | } 101 | [self.detailView showFullScreenOnView:recognizer.view]; 102 | } 103 | 104 | #pragma mark DetailViewSectionDelegate 105 | 106 | - (UIView *) viewAtTop { 107 | return self.topWebView; 108 | } 109 | 110 | - (NSUInteger ) numberOfSections { 111 | // __totalNumber = (1 == __totalNumber) ? 2 : 1; 112 | return __totalNumber; 113 | } 114 | 115 | - (NSString *) titleOfSectionAt:(NSUInteger )index { 116 | return titles[index]; 117 | } 118 | 119 | - (UIView *) viewOfSectionAt:(NSUInteger ) index { 120 | UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectZero]; 121 | return webview; 122 | } 123 | 124 | - (void) didChangeToSection:(NSUInteger) index view:(UIView *) view { 125 | NSString *url = urls[index]; 126 | UIWebView *webView = (UIWebView *) view; 127 | if (!webView.request) { 128 | [webView stopLoading]; 129 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]]; 130 | } 131 | } 132 | 133 | - (void) floatViewIsGoingTo:(BOOL) appear { 134 | NSLog(@"floatViewIsGoingTo = %d", appear); 135 | } 136 | 137 | ``` 138 | 139 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/DetailWapViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailWapViewController.m 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailWapViewController.h" 10 | #import "DetailView.h" 11 | #import "UIImage+extend.h" 12 | 13 | static NSUInteger __totalNumber = 3; 14 | 15 | static NSString * images[] = {@"1.jpg", @"l.jpg", @"w.jpg",@"xt.jpg"}; 16 | static NSString *titles[] = {@"图文详情",@"商品评论",@"百度"}; 17 | static NSString *urls[] = { 18 | @"http://micker.cn/2016/04/14/%E6%B7%98%E5%AE%9D%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%E6%8E%A7%E4%BB%B6/", 19 | @"http://micker.cn/2016/04/14/%E5%85%A8%E5%B1%8F%E6%B5%8F%E8%A7%88%E6%8E%A7%E4%BB%B6/", 20 | @"http://micker.cn"}; 21 | 22 | @interface DetailWapViewController () 23 | @property (nonatomic, strong) DetailView *detailView; 24 | @property (nonatomic, strong) UIWebView *topWebView; 25 | 26 | @property (nonatomic, strong) MFullScreenControl *control; 27 | @end 28 | 29 | @implementation DetailWapViewController 30 | 31 | - (void)viewDidLoad { 32 | [super viewDidLoad]; 33 | self.automaticallyAdjustsScrollViewInsets = NO; 34 | [self.view addSubview:self.detailView]; 35 | self.view.backgroundColor = [UIColor lightGrayColor]; 36 | [self.topWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://micker.cn/2016/04/14/%E6%B7%98%E5%AE%9D%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%E6%8E%A7%E4%BB%B6/"]]]; 37 | [self.detailView reloadData]; 38 | } 39 | 40 | - (void) dealloc { 41 | NSLog(@"DetailWapViewController dealloc"); 42 | 43 | } 44 | 45 | - (DetailView *) detailView { 46 | if (!_detailView) { 47 | _detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 48 | _detailView.delegate = self; 49 | _detailView.startYPosition = 0.0f; 50 | _detailView.topScrollViewTopInset = 300.0f; 51 | _detailView.topScrollPageView.delegate = self; 52 | } 53 | return _detailView; 54 | } 55 | 56 | - (UIWebView *) topWebView { 57 | if (!_topWebView) { 58 | _topWebView = [[UIWebView alloc] initWithFrame:_detailView.bounds]; 59 | _topWebView.scrollView.showsVerticalScrollIndicator = NO; 60 | _topWebView.backgroundColor = [UIColor whiteColor]; 61 | [_topWebView setOpaque:NO]; 62 | } 63 | return _topWebView; 64 | } 65 | 66 | - (MFullScreenControl *) control { 67 | if(!_control) { 68 | _control = self.detailView.fullScreencontrol; 69 | _control.screenPageView.delegate = self; 70 | } 71 | return _control; 72 | } 73 | 74 | 75 | #pragma mark UIScrollPageControlViewDelegate 76 | 77 | - (NSUInteger) numberOfView:(UIScrollPageControlView *) control { 78 | return 4; 79 | } 80 | 81 | - (UIView *) configBannerItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 82 | UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuse"]; 83 | if (!cellItem) { 84 | cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, _detailView.topScrollViewTopInset)]; 85 | cellItem.userInteractionEnabled = YES; 86 | cellItem.clipsToBounds = YES; 87 | cellItem.contentMode = UIViewContentModeScaleAspectFill; 88 | cellItem.backgroundColor = [UIColor colorWithWhite:0.7f alpha:0.4f]; 89 | cellItem.reuseIdentifier = @"reuse"; 90 | [cellItem addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTaped:)]]; 91 | } 92 | UIImage *image = [UIImage imageNamed:images[index % 4]]; 93 | cellItem.image = image; 94 | return cellItem; 95 | } 96 | 97 | - (UIView *) configFullItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 98 | MFullScreenView *cellItem = (MFullScreenView *)[control dequeueReusableViewWithIdentifier:@"reuse"]; 99 | if (!cellItem) { 100 | cellItem = [[MFullScreenView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 101 | cellItem.userInteractionEnabled = YES; 102 | cellItem.reuseIdentifier = @"reuse"; 103 | [cellItem enableDoubleTap:YES]; 104 | __weak typeof(self) blockSelf = self; 105 | cellItem.singleTapBlock = ^(UIGestureRecognizer * recognizer) { 106 | [blockSelf.detailView hideFullScreenOnView:recognizer.view]; 107 | }; 108 | } 109 | cellItem.imageView.image = [UIImage imageNamed:images[index % 4]]; 110 | [cellItem reloadData]; 111 | return cellItem; 112 | } 113 | 114 | - (void) reconfigItemOfControl:(UIScrollPageControlView *)control at:(NSUInteger) index withView:(UIView *)view { 115 | if (control == _control.screenPageView) { 116 | MFullScreenView *cellItem = (MFullScreenView *)view; 117 | [cellItem reloadData]; 118 | } 119 | } 120 | 121 | - (UIView *) configItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 122 | if (control == _control.screenPageView) { 123 | return [self configFullItemOfControl:_control.screenPageView at:index]; 124 | } 125 | return [self configBannerItemOfControl:control at:index]; 126 | } 127 | 128 | 129 | - (CGFloat) minimumRowSpacing:(UIScrollPageControlView *) control { 130 | return (control == _control.screenPageView) ? 20.0f : 0.0f; 131 | } 132 | 133 | 134 | - (void) imageViewDidTaped:(UIGestureRecognizer *) recognizer { 135 | if (self.control.isAppear) { 136 | [self.detailView hideFullScreenOnView:recognizer.view]; 137 | return; 138 | } 139 | [self.detailView showFullScreenOnView:recognizer.view]; 140 | } 141 | 142 | 143 | #pragma mark DetailViewSectionDelegate 144 | 145 | 146 | - (UIView *) viewAtTop { 147 | return self.topWebView; 148 | } 149 | 150 | - (NSUInteger ) numberOfSections { 151 | return __totalNumber; 152 | } 153 | 154 | 155 | - (NSString *) titleOfSectionAt:(NSUInteger )index { 156 | return titles[index]; 157 | } 158 | 159 | - (UIView *) viewOfSectionAt:(NSUInteger ) index { 160 | UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectZero]; 161 | return webview; 162 | } 163 | 164 | - (void) didChangeToSection:(NSUInteger) index view:(UIView *) view { 165 | NSString *url = urls[index]; 166 | UIWebView *webView = (UIWebView *) view; 167 | if (!webView.request) { 168 | [webView stopLoading]; 169 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]]; 170 | } 171 | } 172 | 173 | - (void) floatViewIsGoingTo:(BOOL) appear { 174 | NSLog(@"floatViewIsGoingTo = %d", appear); 175 | } 176 | 177 | @end 178 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/DetailTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailTableViewController.m 3 | // B5MDetailFramework 4 | // 5 | // Created by boguang on 15/8/21. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailTableViewController.h" 10 | 11 | #import "DetailView.h" 12 | #import "UIImage+extend.h" 13 | 14 | static NSString *titles[] = {@"图文详情",@"商品评论",@"店铺推荐"}; 15 | static NSString *urls[] = { 16 | @"http://micker.cn/2016/04/14/%E6%B7%98%E5%AE%9D%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%E6%8E%A7%E4%BB%B6/", 17 | @"http://micker.cn/2016/04/14/%E5%85%A8%E5%B1%8F%E6%B5%8F%E8%A7%88%E6%8E%A7%E4%BB%B6/", 18 | @"http://micker.cn"}; 19 | 20 | @interface DetailTableViewController () 21 | @property (nonatomic, strong) DetailView *detailView; 22 | @property (nonatomic, strong) UITableView *tableView; 23 | @property (nonatomic, strong) NSMutableArray *data; 24 | 25 | @end 26 | 27 | @implementation DetailTableViewController 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | self.automaticallyAdjustsScrollViewInsets = NO; 32 | [self.view addSubview:self.detailView]; 33 | self.view.backgroundColor = [UIColor lightGrayColor]; 34 | [self.detailView reloadData]; 35 | [self.tableView reloadData]; 36 | } 37 | 38 | - (void) dealloc { 39 | NSLog(@"DetailTableViewController dealloc"); 40 | 41 | } 42 | 43 | - (DetailView *) detailView { 44 | if (!_detailView) { 45 | _detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height-64)]; 46 | _detailView.delegate = self; 47 | _detailView.topScrollPageView.delegate = self; 48 | } 49 | return _detailView; 50 | } 51 | 52 | - (UITableView *) tableView { 53 | if (!_tableView) { 54 | _tableView = [[UITableView alloc] initWithFrame:_detailView.bounds]; 55 | _tableView.delegate = self; 56 | _tableView.dataSource = self; 57 | } 58 | return _tableView; 59 | } 60 | 61 | 62 | #pragma mark UIScrollPageControlViewDelegate 63 | 64 | - (NSUInteger) numberOfView:(UIScrollPageControlView *) control { 65 | return 8; 66 | } 67 | 68 | - (UIView *) configItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index { 69 | UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuse"]; 70 | NSString *reuse = @"复用来的"; 71 | UILabel *label = nil; 72 | if (!cellItem) { 73 | cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 370)]; 74 | cellItem.userInteractionEnabled = YES; 75 | cellItem.backgroundColor = [UIColor colorWithWhite:0.7f alpha:0.4f]; 76 | cellItem.reuseIdentifier = @"reuse"; 77 | label = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, 100)]; 78 | reuse = @"=====新生成的"; 79 | label.textAlignment = NSTextAlignmentCenter; 80 | label.tag = 1000; 81 | [cellItem addSubview:label]; 82 | } else { 83 | label = (UILabel *) [cellItem viewWithTag:1000]; 84 | } 85 | UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic_%d",(int)(index+1) %4]]; 86 | image = [image imageScaledToSizeEx:CGSizeMake(cellItem.frame.size.width * 2, cellItem.frame.size.height * 2)]; 87 | cellItem.image = image; 88 | 89 | label.text = [NSString stringWithFormat:@"item = %ld || reuse = %@", index,reuse]; 90 | return cellItem; 91 | } 92 | 93 | #pragma mark DetailViewSectionDelegate 94 | 95 | 96 | - (UIView *) viewAtTop { 97 | return self.tableView; 98 | } 99 | 100 | - (NSUInteger ) numberOfSections { 101 | return 3; 102 | } 103 | 104 | 105 | - (NSString *) titleOfSectionAt:(NSUInteger )index { 106 | return titles[index]; 107 | } 108 | 109 | - (UIView *) viewOfSectionAt:(NSUInteger ) index { 110 | UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectZero]; 111 | return webview; 112 | } 113 | 114 | - (void) didChangeToSection:(NSUInteger) index view:(UIView *) view { 115 | NSString *url = urls[index]; 116 | UIWebView *webView = (UIWebView *) view; 117 | if (!webView.request) { 118 | [webView stopLoading]; 119 | [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]]; 120 | } 121 | } 122 | 123 | 124 | #pragma mark == 125 | #pragma mark == tableView 126 | 127 | 128 | - (NSMutableArray *) data { 129 | if (!_data) { 130 | _data = [NSMutableArray array]; 131 | [_data addObject:@{@"title":@"Wap商品详情",@"author":@"伯光",@"class":@"DetailWapViewController"}]; 132 | [_data addObject:@{@"title":@"TableView商品详情",@"author":@"伯光",@"class":@"DetailTableViewController"}]; 133 | [_data addObject:@{@"title":@"ScrollView商品详情",@"author":@"伯光",@"class":@"DetailScrollViewController"}]; 134 | [_data addObject:@{@"title":@"Wap商品详情",@"author":@"伯光",@"class":@"DetailWapViewController"}]; 135 | [_data addObject:@{@"title":@"TableView商品详情",@"author":@"伯光",@"class":@"DetailTableViewController"}]; 136 | [_data addObject:@{@"title":@"ScrollView商品详情",@"author":@"伯光",@"class":@"DetailScrollViewController"}]; 137 | } 138 | return _data; 139 | } 140 | 141 | 142 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 143 | return 1; 144 | } 145 | 146 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 147 | return [self.data count]; 148 | } 149 | 150 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 151 | static NSString *dequeueReusableCellWithIdentifier = @"dequeueReusableCellWithIdentifier"; 152 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dequeueReusableCellWithIdentifier]; 153 | if(!cell) { 154 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:dequeueReusableCellWithIdentifier]; 155 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 156 | } 157 | 158 | cell.textLabel.text = self.data[indexPath.row][@"title"]; 159 | cell.detailTextLabel.text = self.data[indexPath.row][@"author"]; 160 | return cell; 161 | } 162 | 163 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 164 | return 85; 165 | } 166 | 167 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 168 | NSString *classString = self.data[indexPath.row][@"class"]; 169 | Class newClass = NSClassFromString(classString); 170 | UIViewController *controller = [[newClass alloc] init]; 171 | controller.title = self.data[indexPath.row][@"title"]; 172 | if (controller) 173 | [self.navigationController pushViewController:controller animated:YES]; 174 | } 175 | 176 | @end 177 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailRefreshView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailRefreshView.m 3 | // DW 4 | // 5 | // Created by boguang on 15/6/23. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailRefreshView.h" 10 | #include 11 | #import "DetailLocalizable.h" 12 | 13 | #pragma mark -- 14 | #pragma mark DetailRefreshView 15 | 16 | @interface DetailRefreshView() 17 | @property (nonatomic, assign) CGFloat originalTopInset; 18 | @property (nonatomic, assign) CGFloat thresHold; 19 | 20 | @end 21 | 22 | @implementation DetailRefreshView 23 | 24 | 25 | - (id) initWithFrame:(CGRect)frame { 26 | self = [super initWithFrame:frame]; 27 | if (self) { 28 | [self addSubview:self.topImageView]; 29 | [self addSubview:self.bottomLabel]; 30 | self.thresHold = frame.size.height + 5; 31 | self.backgroundColor = [UIColor clearColor]; 32 | self.animateType = DetailRefreshViewAnimateTypeAttachTop; 33 | } 34 | return self; 35 | } 36 | 37 | - (UILabel *) bottomLabel { 38 | if (!_bottomLabel) { 39 | _bottomLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 35, self.bounds.size.width, 18)]; 40 | _bottomLabel.font = [UIFont systemFontOfSize:12.0f]; 41 | _bottomLabel.textAlignment = NSTextAlignmentCenter; 42 | _bottomLabel.text = [DetailLocalizable localizStringKey:@"detail_pull_default" comment:@"下拉,返回宝贝详情"]; 43 | _bottomLabel.backgroundColor = [UIColor clearColor]; 44 | } 45 | return _bottomLabel; 46 | } 47 | 48 | - (UIImageView *) topImageView { 49 | if (!_topImageView) { 50 | _topImageView = [[UIImageView alloc] initWithFrame:CGRectMake((self.bounds.size.width - 25) / 2, 9, 22, 22)]; 51 | _topImageView.backgroundColor = [UIColor clearColor]; 52 | _topImageView.image = [UIImage imageNamed:@"Detail.bundle/images/detail_down_loading"]; 53 | } 54 | return _topImageView; 55 | } 56 | 57 | - (void) didMoveToSuperview { 58 | if (!self.superview) { 59 | [_scrollView removeObserver:self forKeyPath:@"contentOffset"]; 60 | } else { 61 | [_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; 62 | } 63 | } 64 | 65 | - (void) setScrollView:(UIScrollView *)scrollView { 66 | _scrollView = scrollView; 67 | self.originalTopInset = scrollView.contentInset.top; 68 | [self setState:DetailRefreshStateNormal]; 69 | } 70 | 71 | #pragma mark - Observing 72 | 73 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 74 | if([keyPath isEqualToString:@"contentOffset"]) 75 | [self scrollViewDidScroll:[[change valueForKey:NSKeyValueChangeNewKey] CGPointValue]]; 76 | } 77 | 78 | 79 | - (void)scrollViewDidScroll:(CGPoint)contentOffset { 80 | if (contentOffset.y > 0) { 81 | return; 82 | } 83 | CGFloat scrollOffsetThreshold = self.bottomLabel.bounds.size.height - self.thresHold - self.scrollView.contentInset.top; 84 | if(!self.scrollView.isDragging && self.state == DetailRefreshStateLoading) 85 | self.state = DetailRefreshStateTriggerd; 86 | else if(contentOffset.y < scrollOffsetThreshold && self.scrollView.isDragging && self.state != DetailRefreshStateLoading) 87 | self.state = DetailRefreshStateLoading; 88 | else if(contentOffset.y >= scrollOffsetThreshold && self.state != DetailRefreshStateNormal) 89 | self.state = DetailRefreshStateNormal; 90 | 91 | CGFloat offset = contentOffset.y + self.scrollView.contentInset.top; 92 | // NSLog(@"offset = %f | contentOffset= %f", offset, contentOffset.y); 93 | 94 | //move when cross the points 95 | if (offset <= -self.bounds.size.height && contentOffset.y <= -self.bounds.size.height) { 96 | switch (self.animateType) { 97 | case DetailRefreshViewAnimateTypeAttachTop: //吸顶 98 | break; 99 | case DetailRefreshViewAnimateTypeAttachBottom: 100 | offset -= (offset + self.bounds.size.height) ; //开启,则跟随底部 101 | break; 102 | case DetailRefreshViewAnimateTypeSpeed1: 103 | offset -= (offset + self.bounds.size.height) /3.0f ; //开启,则速度是底部的1/3速度;差速 104 | break; 105 | case DetailRefreshViewAnimateTypeSpeed2: 106 | offset -= (offset + self.bounds.size.height) /2.0f ; //开启,则速度是底部的一半速度;差速 107 | break; 108 | default: //吸顶 109 | break; 110 | } 111 | } 112 | self.frame = CGRectMake(0,offset - self.scrollView.contentInset.top + self.originalTopInset, 113 | self.bounds.size.width, self.bounds.size.height); 114 | self.alpha = (offset < 0) ? (fabs(offset * 1.5f)/self.bounds.size.height) : 0; 115 | } 116 | 117 | 118 | - (void) setState:(DetailRefreshState)state { 119 | if (_state != state) { 120 | _state = state; 121 | __weak typeof(self) blockSelf = self; 122 | 123 | switch (_state) { 124 | case DetailRefreshStateTriggerd: { 125 | if (self.handler) { 126 | self.handler(); 127 | } 128 | } 129 | break; 130 | case DetailRefreshStateLoading: { 131 | _bottomLabel.text = [DetailLocalizable localizStringKey:@"detail_pull_release" comment:@"释放,返回宝贝详情"]; 132 | [UIView animateWithDuration:0.2f animations:^{ 133 | [blockSelf.topImageView setTransform:CGAffineTransformMakeRotation(M_PI)]; 134 | }]; 135 | } 136 | 137 | break; 138 | case DetailRefreshStateNormal:{ 139 | _bottomLabel.text = [DetailLocalizable localizStringKey:@"detail_pull_default" comment:@"下拉,返回宝贝详情"]; 140 | [UIView animateWithDuration:0.2f animations:^{ 141 | [blockSelf.topImageView setTransform:CGAffineTransformIdentity]; 142 | }]; 143 | } 144 | break; 145 | 146 | default: 147 | break; 148 | } 149 | } 150 | } 151 | @end 152 | 153 | 154 | #pragma mark -- 155 | #pragma mark -- __DetailRefreshView 156 | 157 | @implementation UIScrollView(__DetailRefreshView) 158 | 159 | - (void)setRefreshView:(DetailRefreshView *)refreshView{ 160 | objc_setAssociatedObject(self, @selector(refreshView), refreshView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 161 | } 162 | 163 | - (DetailRefreshView *) refreshView { 164 | return objc_getAssociatedObject(self, _cmd); 165 | } 166 | 167 | - (void) addDetailRefreshWithHandler:(void (^)(void)) handler { 168 | if (!self.refreshView) { 169 | DetailRefreshView *detailRefreshView = [[DetailRefreshView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, 64)]; 170 | [self setRefreshView:detailRefreshView]; 171 | self.refreshView.scrollView = self; 172 | } 173 | 174 | self.refreshView.handler = handler; 175 | [self addSubview:self.refreshView]; 176 | [self sendSubviewToBack:self.refreshView]; 177 | } 178 | 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailPictureView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailPictureView.m 3 | // DW 4 | // 5 | // Created by boguang on 15/6/24. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailPictureView.h" 10 | #include 11 | #import "DetailLocalizable.h" 12 | 13 | 14 | #pragma mark -- 15 | #pragma mark DetailPictureView 16 | 17 | @interface DetailPictureView() 18 | @property (nonatomic, assign) CGFloat originInsetY; 19 | @property (nonatomic, assign) CGFloat thresHold; 20 | 21 | @end 22 | 23 | @implementation DetailPictureView 24 | 25 | - (id) initWithFrame:(CGRect)frame { 26 | self = [super initWithFrame:frame]; 27 | if (self) { 28 | [self addSubview:self.leftImageView]; 29 | [self addSubview:self.rightLabel]; 30 | self.thresHold = self.rightLabel.frame.origin.x + self.rightLabel.frame.size.width; 31 | self.animateType = DetailPictureViewAnimateTypeAttachRight; 32 | } 33 | return self; 34 | } 35 | 36 | - (UILabel *) rightLabel { 37 | if (!_rightLabel) { 38 | _rightLabel = [[UILabel alloc] initWithFrame:CGRectMake(32, 0, 18, self.bounds.size.height)]; 39 | _rightLabel.font = [UIFont systemFontOfSize:12.0f]; 40 | _rightLabel.numberOfLines = 0; 41 | _rightLabel.textAlignment = NSTextAlignmentCenter; 42 | _rightLabel.text = [DetailLocalizable localizStringKey:@"detail_picture_default" comment:@"滑动,查看图文详情"]; 43 | _rightLabel.backgroundColor = [UIColor clearColor]; 44 | } 45 | return _rightLabel; 46 | } 47 | 48 | - (UIImageView *) leftImageView { 49 | if (!_leftImageView) { 50 | _leftImageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, (self.bounds.size.height - 25) / 2, 22, 22)]; 51 | _leftImageView.backgroundColor = [UIColor clearColor]; 52 | _leftImageView.image = [UIImage imageNamed:@"Detail.bundle/images/detail_left_loading"]; 53 | } 54 | return _leftImageView; 55 | } 56 | 57 | 58 | - (void) didMoveToSuperview { 59 | if (!self.superview) { 60 | [_scrollView removeObserver:self forKeyPath:@"contentOffset"]; 61 | [_scrollView removeObserver:self forKeyPath:@"contentSize"]; 62 | } else { 63 | [_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; 64 | [_scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil]; 65 | } 66 | } 67 | 68 | - (void) setScrollView:(UIScrollView *)scrollView { 69 | _scrollView = scrollView; 70 | self.originInsetY = scrollView.contentInset.top; 71 | [self setState:DetailPictureViewStateNormal]; 72 | } 73 | 74 | #pragma mark - Observing 75 | 76 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 77 | if([keyPath isEqualToString:@"contentOffset"]) 78 | [self scrollViewDidScroll:[[change valueForKey:NSKeyValueChangeNewKey] CGPointValue]]; 79 | else if ([keyPath isEqualToString:@"contentSize"]) { 80 | [self scrollViewDidScroll:self.scrollView.contentOffset]; 81 | } 82 | } 83 | 84 | 85 | - (void)scrollViewDidScroll:(CGPoint)contentOffset { 86 | CGFloat scrollOffsetThreshold = self.scrollView.contentSize.width + self.thresHold - self.scrollView.bounds.size.width; 87 | if(!self.scrollView.isDragging && self.state == DetailPictureViewStateLoading) 88 | self.state = DetailPictureViewStateTriggerd; 89 | else if(contentOffset.x > scrollOffsetThreshold && self.scrollView.isDragging && self.state != DetailPictureViewStateLoading) 90 | self.state = DetailPictureViewStateLoading; 91 | else if(contentOffset.x <= scrollOffsetThreshold && self.state != DetailPictureViewStateNormal) 92 | self.state = DetailPictureViewStateNormal; 93 | 94 | CGFloat offset = contentOffset.x + self.scrollView.contentInset.right + self.scrollView.bounds.size.width - self.scrollView.contentSize.width; 95 | 96 | //move when cross the points 97 | if (offset >= self.bounds.size.width) { 98 | switch (self.animateType) { 99 | case DetailPictureViewAnimateTypeAttachRight: 100 | offset = self.bounds.size.width; 101 | break; 102 | case DetailPictureViewAnimateTypeAttachLeft: 103 | break; 104 | case DetailPictureViewAnimateTypeSpeed1: 105 | offset += (self.bounds.size.width - offset)/2 ; 106 | break; 107 | case DetailPictureViewAnimateTypeSpeed2: 108 | offset += (self.bounds.size.width - offset)/4 ; 109 | break; 110 | 111 | default: 112 | break; 113 | } 114 | } 115 | 116 | self.frame = CGRectMake(contentOffset.x + self.scrollView.bounds.size.width - offset,0, self.bounds.size.width, self.bounds.size.height); 117 | } 118 | 119 | 120 | - (void) setState:(DetailPictureViewState)state { 121 | if (_state != state) { 122 | _state = state; 123 | switch (_state) { 124 | case DetailPictureViewStateTriggerd: { 125 | if (self.handler) { 126 | self.handler(); 127 | } 128 | } 129 | break; 130 | case DetailPictureViewStateLoading: { 131 | _rightLabel.text = [DetailLocalizable localizStringKey:@"detail_picture_release" comment:@"释放,查看图文详情"]; 132 | [UIView animateWithDuration:0.2f animations:^{ 133 | [_leftImageView setTransform:CGAffineTransformMakeRotation(M_PI)]; 134 | }]; 135 | } 136 | 137 | break; 138 | case DetailPictureViewStateNormal:{ 139 | _rightLabel.text = [DetailLocalizable localizStringKey:@"detail_picture_default" comment:@"滑动,查看图文详情"]; 140 | 141 | [UIView animateWithDuration:0.2f animations:^{ 142 | [_leftImageView setTransform:CGAffineTransformIdentity]; 143 | }]; 144 | } 145 | break; 146 | 147 | default: 148 | break; 149 | } 150 | } 151 | } 152 | 153 | 154 | 155 | @end 156 | 157 | 158 | #pragma mark -- 159 | #pragma mark -- UIScrollView(__DetailPictureView) 160 | 161 | @implementation UIScrollView(__DetailPictureView) 162 | 163 | - (void)setPictureView:(DetailPictureView *)pictureView { 164 | objc_setAssociatedObject(self, @selector(pictureView), pictureView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 165 | } 166 | 167 | - (DetailPictureView *) pictureView { 168 | return objc_getAssociatedObject(self, _cmd); 169 | } 170 | 171 | - (void) addDetaiPictureViewWithHandler:(void (^)(void)) handler { 172 | if (!self.pictureView) { 173 | DetailPictureView *detailRefreshView = [[DetailPictureView alloc] initWithFrame:CGRectMake(0, self.bounds.size.width, 64, self.bounds.size.height)]; 174 | [self setPictureView:detailRefreshView]; 175 | detailRefreshView.scrollView = self; 176 | } 177 | 178 | self.pictureView.handler = handler; 179 | [self addSubview:self.pictureView]; 180 | [self bringSubviewToFront:self.pictureView]; 181 | } 182 | 183 | @end 184 | 185 | 186 | #pragma mark -- 187 | #pragma mark --Paralles 188 | 189 | @implementation ParallasObject 190 | 191 | - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 192 | if ([keyPath isEqualToString:@"contentOffset"] && self.targetView ) { 193 | [self scrollViewDidVerticalScroll:[[change valueForKey:NSKeyValueChangeNewKey] CGPointValue]]; 194 | } 195 | } 196 | 197 | - (void)scrollViewDidVerticalScroll:(CGPoint)contentOffset { 198 | CGRect targetFrame = self.targetView.frame; 199 | UIEdgeInsets contentInsets = self.scrollView.contentInset; 200 | if (self.isVertical) { 201 | CGFloat frameY = - targetFrame.size.height; 202 | CGFloat offset = - contentOffset.y - contentInsets.top; 203 | // if (offset< 0) { 204 | // offset *= -2.0f;// -2.0f the imageview will stop at the top; 匀速 | remove offset charge ,then will adapter to all direction 205 | // offset *= -3.0f;// -3.0f the imageview will stop at the top; 差速 | remove offset charge ,then will adapter to all direction 206 | // offset *= -4.0f;// -4.0f the imageview will stop at the top; 吸顶 | remove offset charge ,then will adapter to all direction 207 | // } 208 | targetFrame.origin.y = frameY + offset/4; 209 | _targetView.frame = targetFrame; 210 | } 211 | } 212 | 213 | - (void) dealloc { 214 | [_scrollView removeObserver:self forKeyPath:@"contentOffset"]; 215 | } 216 | 217 | - (void) setScrollView:(UIScrollView *)scrollView { 218 | _scrollView = scrollView; 219 | [_scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:NULL]; 220 | } 221 | 222 | @end 223 | 224 | #pragma mark -- 225 | #pragma mark --UIScrollView(__Parallas) 226 | 227 | @implementation UIScrollView(__Parallas) 228 | 229 | - (void) setParallas:(ParallasObject *)parallas { 230 | objc_setAssociatedObject(self, @selector(parallas), parallas, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 231 | } 232 | 233 | - (ParallasObject *) parallas { 234 | return objc_getAssociatedObject(self, _cmd); 235 | } 236 | 237 | - (void) addHorizeParallas:(UIView *) targetView block:(void (^)(void))block { 238 | if (!self.parallas) { 239 | ParallasObject *object = [[ParallasObject alloc] init]; 240 | object.targetView = targetView; 241 | object.scrollView = self; 242 | object.handler = block; 243 | object.isVertical = NO; 244 | [self setParallas:object]; 245 | } 246 | } 247 | 248 | - (void) addVerticalParallas:(UIView *) targetView block:(void (^)(void))block { 249 | if (!self.parallas) { 250 | ParallasObject *object = [[ParallasObject alloc] init]; 251 | object.targetView = targetView; 252 | object.scrollView = self; 253 | object.handler = block; 254 | object.isVertical = YES; 255 | [self setParallas:object]; 256 | } 257 | } 258 | 259 | @end -------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework/DetailControl/DetailView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailView.m 3 | // DW 4 | // 5 | // Created by boguang on 15/6/23. 6 | // Copyright (c) 2015年 micker. All rights reserved. 7 | // 8 | 9 | #import "DetailView.h" 10 | #import "DetailTipView.h" 11 | #import "DetailRefreshView.h" 12 | #import "DetailPictureView.h" 13 | 14 | static CGFloat animateTime = 0.25f; 15 | static CGFloat paddingSpace = 60.0f; 16 | static CGFloat tipHeight = 44.0f; 17 | 18 | 19 | @interface DetailView () 20 | @property (nonatomic, strong) UIView *sectionView; 21 | @property (nonatomic, strong) UIView *alphaView; 22 | @property (nonatomic, strong) UIView *sectionLineView; 23 | @property (nonatomic, assign) BOOL isTriggerd; 24 | @property (nonatomic, assign) BOOL hidesForSingleTitle; //中间的Section,是否对单个Ttitle的进行隐藏 25 | 26 | 27 | @end 28 | 29 | @implementation DetailView { 30 | __block CGFloat width, height, _middleHeight; 31 | NSInteger _currentIndex; 32 | NSUInteger _sectionTotal; 33 | __block NSTimeInterval _timeInterval; 34 | } 35 | @synthesize topView = _topView; 36 | @synthesize bottomView = _bottomView; 37 | @synthesize tipView = _tipView; 38 | @synthesize fullScreencontrol = _fullScreencontrol; 39 | @synthesize topScrollPageView = _topScrollPageView; 40 | 41 | - (id) initWithFrame:(CGRect)frame { 42 | self = [super initWithFrame:frame]; 43 | if (self) { 44 | _currentIndex = -1; 45 | _sectionTotal = 0; 46 | width = frame.size.width; 47 | height = frame.size.height; 48 | _middleHeight = 44.0f; 49 | _startYPosition = 0.0f; 50 | self.topScrollViewTopInset = 370.0f; 51 | self.hidesForSingleTitle = YES; 52 | _timeInterval = [[NSDate date] timeIntervalSince1970]; 53 | self.backgroundColor = [UIColor whiteColor]; 54 | } 55 | return self; 56 | } 57 | 58 | - (void) dealloc { 59 | _topScrollPageView.delegate = nil; 60 | _fullScreencontrol.screenPageView.delegate = nil; 61 | [_topScrollView removeObserver:self forKeyPath:@"contentOffset"]; 62 | [_topScrollView removeObserver:self forKeyPath:@"contentSize"]; 63 | } 64 | 65 | - (void) reloadData { 66 | self.isTriggerd = NO; 67 | if (_delegate && [_delegate respondsToSelector:@selector(viewAtTop)]) { 68 | _sectionTotal = [_delegate numberOfSections]; 69 | [self initTopScrollView]; 70 | [self addSubview:self.topView]; 71 | [self addSubview:self.bottomView]; 72 | [self configBottmSectionViews]; 73 | } 74 | 75 | if (self.topScrollPageView.delegate) { 76 | [self configTopScrollView]; 77 | [self.topScrollPageView reloadData]; 78 | } 79 | } 80 | 81 | - (BOOL) isBottomViewShowed { 82 | if (_isTriggerd && self.topView.frame.origin.y >=0.0f) { 83 | return YES; 84 | } 85 | return NO; 86 | } 87 | 88 | - (void) disappearBottomView { 89 | if ([self isBottomViewShowed]) { 90 | [self hideBottomView]; 91 | } 92 | } 93 | 94 | - (void) initTopScrollView { 95 | if (self.topScrollView) { 96 | return; 97 | } 98 | UIView *view = [self.delegate viewAtTop]; 99 | if ([view isKindOfClass:[UIScrollView class]]) { 100 | self.topScrollView = (UIScrollView *)view; 101 | } 102 | else if ([view isKindOfClass:[UIWebView class]]) { 103 | self.topScrollView = ((UIWebView *) view).scrollView; 104 | } 105 | else { 106 | assert(0); 107 | NSLog(@"scrollViewAtTop needs to be implemented"); 108 | return; 109 | } 110 | 111 | [self.topScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL]; 112 | [self.topScrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL]; 113 | [self.topScrollView addSubview:self.tipView]; 114 | [self.topScrollView setContentInset:UIEdgeInsetsMake(0, 0, tipHeight, 0)]; 115 | [self.topView addSubview:view]; 116 | } 117 | 118 | - (void) configTopScrollView { 119 | [self.topScrollView setContentInset:UIEdgeInsetsMake(_topScrollViewTopInset-20, 0, tipHeight, 0)]; 120 | // [self.topScrollView addDetailRefreshWithHandler:nil]; 121 | [self.topScrollView addVerticalParallas:self.topScrollPageView block:nil]; 122 | [self.topScrollView addSubview:self.topScrollPageView]; 123 | // [self.topScrollView addSubview:self.alphaView]; //add shadow effect 124 | [self.topScrollView sendSubviewToBack:self.topScrollPageView]; 125 | [self.topScrollView setContentOffset:CGPointMake(0, 20-_topScrollViewTopInset)]; 126 | __weak typeof(self) blockSelf = self; 127 | [self.imageScrollView addDetaiPictureViewWithHandler:^{ 128 | [blockSelf addDetailPictureViewHandler]; 129 | }]; 130 | } 131 | 132 | - (void) addDetailPictureViewHandler { 133 | if (_sectionTotal == 0) { 134 | return ; 135 | } 136 | CGRect rect = self.bottomView.frame; 137 | rect.origin = CGPointMake(width, 0); 138 | [self.bottomView setFrame:rect]; 139 | [self bringSubviewToFront:_bottomView]; 140 | [self didFirstShowOnBottomView]; 141 | self.isTriggerd = YES; 142 | [self animateContent]; 143 | __weak typeof(self) blockSelf = self; 144 | [UIView animateWithDuration:animateTime animations:^{ 145 | [blockSelf.bottomView setFrame:CGRectMake(0, 0, width, height)]; 146 | } completion:^(BOOL finished) { 147 | }]; 148 | } 149 | 150 | - (void) hideBottomView { 151 | 152 | __weak typeof(self) blockSelf = self; 153 | self.isTriggerd = NO; 154 | [UIView animateWithDuration:animateTime animations:^{ 155 | [blockSelf animateContent]; 156 | [blockSelf.topView setFrame:CGRectMake(0, 0, width, height)]; 157 | [blockSelf.bottomView setFrame:CGRectMake(0, height, width, height - _middleHeight - _startYPosition)]; 158 | } completion:^(BOOL finished) { 159 | if(blockSelf.delegate && [blockSelf.delegate respondsToSelector:@selector(floatViewIsGoingTo:)]) { 160 | [blockSelf.delegate floatViewIsGoingTo:NO]; 161 | } 162 | }]; 163 | } 164 | 165 | - (void) configBottomView:(UIScrollView *) scrollView { 166 | __weak typeof(self) weakSelf = self; 167 | [scrollView addDetailRefreshWithHandler:^{ 168 | [weakSelf hideBottomView]; 169 | }]; 170 | } 171 | 172 | 173 | - (void) configBottmSectionViews { 174 | [[[self bottomView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; 175 | if (_delegate) { 176 | NSUInteger titleTotal = [_delegate numberOfSections]; 177 | if (titleTotal == 0 || ![_delegate respondsToSelector:@selector(titleOfSectionAt:)]) { 178 | _middleHeight = 0.0f; 179 | return; 180 | } 181 | [[[self sectionView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; 182 | CGFloat itemWidth = width/titleTotal; 183 | CGRect rect = self.sectionView.frame; 184 | 185 | if (titleTotal == 1 && self.hidesForSingleTitle ) { 186 | _middleHeight = 0.0f; 187 | rect.size.height = _middleHeight; 188 | self.sectionView.frame = rect; 189 | } else { 190 | _middleHeight = 44.0f; 191 | rect.origin.y = _startYPosition; 192 | rect.size.height = _middleHeight; 193 | self.sectionView.frame = rect; 194 | [_bottomView addSubview:self.sectionView]; 195 | 196 | rect = self.sectionLineView.frame; 197 | rect.size.width = itemWidth; 198 | self.sectionLineView.frame = rect; 199 | } 200 | 201 | for (NSUInteger i = 0 ; i < titleTotal; i++) { 202 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 203 | button.frame = CGRectMake(itemWidth * i, 0, width/titleTotal, _middleHeight); 204 | button.backgroundColor = [UIColor whiteColor]; 205 | [button setTitle:[_delegate titleOfSectionAt:i] forState:UIControlStateNormal]; 206 | button.titleLabel.font = [UIFont systemFontOfSize:15.0f]; 207 | [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; 208 | [button setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; 209 | button.tag = 20140830 + i; 210 | [button addTarget:self action:@selector(sectionButtonAction:) forControlEvents:UIControlEventTouchUpInside]; 211 | [[self sectionView] addSubview:button]; 212 | } 213 | 214 | if (_middleHeight > 1.0f) { 215 | UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, _middleHeight - 1, width, 1)]; 216 | lineView.backgroundColor = [UIColor lightGrayColor]; 217 | lineView.alpha = 0.5f; 218 | [[self sectionView] addSubview:lineView]; 219 | } 220 | 221 | rect = self.bottomView.frame; 222 | float sectionHeight = _startYPosition; 223 | if (self.sectionView.superview) { 224 | sectionHeight = self.sectionView.frame.origin.y + self.sectionView.frame.size.height; 225 | } 226 | for (NSUInteger i = 0 ; i < titleTotal; i++) { 227 | UIView *view = nil; 228 | if ([_delegate respondsToSelector:@selector(viewOfSectionAt:)]) { 229 | view = [_delegate viewOfSectionAt:i]; 230 | CGRect rect1 = CGRectMake(0, sectionHeight, width, height - sectionHeight); 231 | [view setFrame:rect1]; 232 | [self configBottomView:[self firstScrollViewOfView:view]]; 233 | view.tag = 20150830 + i; 234 | [self.bottomView addSubview:view]; 235 | } 236 | } 237 | 238 | } 239 | } 240 | 241 | - (void) didFirstShowOnBottomView { 242 | if (!self.sectionLineView.superview) { 243 | [_sectionView addSubview:self.sectionLineView]; 244 | } 245 | if (-1 == _currentIndex) { 246 | [self sectionButtonAction:[self.sectionView viewWithTag:20140830]]; 247 | } 248 | if(_delegate && [_delegate respondsToSelector:@selector(floatViewIsGoingTo:)]) { 249 | [_delegate floatViewIsGoingTo:YES]; 250 | } 251 | } 252 | 253 | #pragma mark -- 254 | #pragma mark Getter & Setter 255 | 256 | - (UIScrollPageControlView *) topScrollPageView { 257 | if (!_topScrollPageView) { 258 | _topScrollPageView = [[UIScrollPageControlView alloc] initWithFrame:CGRectMake(0, -_topScrollViewTopInset, width, _topScrollViewTopInset)]; 259 | _topScrollPageView.scrollView.frame = CGRectMake(0, 10, width, _topScrollViewTopInset); 260 | _topScrollPageView.layer.masksToBounds = NO; 261 | [_topScrollPageView enablePanGesture:NO]; 262 | } 263 | return _topScrollPageView; 264 | } 265 | 266 | - (MFullScreenControl *) fullScreencontrol { 267 | if (!_fullScreencontrol) { 268 | _fullScreencontrol = [[MFullScreenControl alloc] init]; 269 | __weak typeof(self) blockSelf = self; 270 | [_fullScreencontrol.screenPageView.scrollView addDetaiPictureViewWithHandler:^{ 271 | [blockSelf hideFullScreenOnView:nil]; 272 | [blockSelf addDetailPictureViewHandler]; 273 | }]; 274 | _fullScreencontrol.onPanFinshed = ^(UIView *view) { 275 | [blockSelf hideFullScreenOnView:view]; 276 | }; 277 | [_fullScreencontrol.screenPageView enablePanGesture:NO]; 278 | 279 | _fullScreencontrol.screenPageView.scrollView.pictureView.rightLabel.textColor = [UIColor whiteColor]; 280 | _fullScreencontrol.screenPageView.scrollView.pictureView.leftImageView.image = [UIImage imageNamed:@"detail_left_loading_white"]; 281 | } 282 | return _fullScreencontrol; 283 | } 284 | 285 | - (UIView *) alphaView { 286 | if (!_alphaView) { 287 | _alphaView = [[UIView alloc] initWithFrame:CGRectMake(0, -2, width, 4)]; 288 | _alphaView.backgroundColor = [UIColor clearColor]; 289 | _alphaView.layer.masksToBounds = NO; 290 | _alphaView.layer.shadowRadius = 2.0f; 291 | _alphaView.layer.shadowOpacity = 0.25f; 292 | _alphaView.layer.shadowColor = [[UIColor blackColor] CGColor]; 293 | _alphaView.layer.shadowOffset = CGSizeZero; 294 | _alphaView.layer.shadowPath = [[UIBezierPath bezierPathWithRect:CGRectMake(-4, 0, width+8, 4)] CGPath]; 295 | } 296 | return _alphaView; 297 | } 298 | 299 | 300 | - (DetailTipView *) tipView { 301 | if (!_tipView) { 302 | _tipView = [[DetailTipView alloc] initWithFrame:CGRectMake(0, height, width, tipHeight)]; 303 | } 304 | return _tipView; 305 | } 306 | 307 | - (UIView *) topView { 308 | if (!_topView) { 309 | _topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; 310 | } 311 | return _topView; 312 | } 313 | 314 | - (CGRect) bottomSectionFrame { 315 | return CGRectMake(0, _middleHeight, width, height - _middleHeight - _startYPosition); 316 | } 317 | 318 | 319 | - (UIView *) bottomView { 320 | if (!_bottomView) { 321 | _bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, height, width, height - _startYPosition)]; 322 | } 323 | return _bottomView; 324 | } 325 | 326 | - (UIScrollView *) imageScrollView { 327 | return self.topScrollPageView.scrollView; 328 | } 329 | 330 | - (UIView *) sectionView { 331 | if (!_sectionView) { 332 | _sectionView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, _middleHeight)]; 333 | _sectionView.backgroundColor = [UIColor whiteColor]; 334 | } 335 | return _sectionView; 336 | } 337 | 338 | - (UIView *) sectionLineView { 339 | if (!_sectionLineView) { 340 | _sectionLineView = [[UIView alloc] initWithFrame:CGRectMake(width, _middleHeight - 2, width, 2)]; 341 | _sectionLineView.backgroundColor = [UIColor redColor]; 342 | } 343 | return _sectionLineView; 344 | } 345 | 346 | - (UIScrollView *) firstScrollViewOfView:(UIView *) rootView { 347 | if ([rootView isKindOfClass:[UIScrollView class]]) { 348 | return (UIScrollView *)rootView; 349 | } 350 | else { 351 | __weak typeof(self) blockSelf = self; 352 | __block UIScrollView *scrollView = nil; 353 | [rootView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 354 | if ([blockSelf firstScrollViewOfView:obj]) { 355 | scrollView = obj; 356 | *stop = YES; 357 | } 358 | }]; 359 | return scrollView; 360 | } 361 | return nil; 362 | } 363 | 364 | - (void) animateContent { 365 | float contentStartY = _startYPosition; 366 | if (fabsf(contentStartY) < 1) { 367 | return; 368 | } 369 | if (_sectionView.superview) { 370 | contentStartY = _sectionView.frame.origin.y + _sectionView.frame.size.height; 371 | } 372 | if (!_isTriggerd) { 373 | contentStartY -= _startYPosition; 374 | } 375 | for (NSUInteger i = 0, total = [self.delegate numberOfSections]; i < total; i++) { 376 | UIView *view = (UIView *) [self.bottomView viewWithTag:20150830 + i]; 377 | CGRect rect = CGRectMake(0, contentStartY, width, height - contentStartY); 378 | [view setFrame:rect]; 379 | } 380 | 381 | } 382 | 383 | 384 | #pragma mark -- 385 | #pragma mark Action 386 | 387 | 388 | 389 | - (void) showFullScreenOnView:(UIView *) view { 390 | [self.fullScreencontrol.screenPageView reloadData]; 391 | self.fullScreencontrol.screenPageView.currentIndex = self.topScrollPageView.currentIndex; 392 | [self.fullScreencontrol appearOnView:view]; 393 | } 394 | 395 | - (void) hideFullScreenOnView:(UIView *) view { 396 | [self.topScrollPageView.scrollView setContentOffset:CGPointMake(self.fullScreencontrol.screenPageView.currentIndex * [self.topScrollPageView itemWidth], 0)]; 397 | [self.topScrollPageView reloadData]; 398 | [self.fullScreencontrol disAppearOnView:view]; 399 | } 400 | 401 | - (IBAction)sectionButtonAction:(id)sender { 402 | 403 | UIButton *button = (UIButton *) sender; 404 | if (!button) { 405 | return; 406 | } 407 | __weak typeof(self) blockSelf = self; 408 | NSUInteger index = button.tag - 20140830; 409 | 410 | UIView *theSectionView = [self.bottomView viewWithTag:20150830 + index]; 411 | 412 | if (self.delegate && [self.delegate respondsToSelector:@selector(willChangeToSection:view:)]) { 413 | [self.delegate willChangeToSection:index view:theSectionView]; 414 | } 415 | 416 | if (self.delegate && [self.delegate respondsToSelector:@selector(canChangeToSection:)]) { 417 | if (![self.delegate canChangeToSection:index]) { 418 | return; 419 | } 420 | } 421 | for (NSUInteger i = 0 ; i < [self.delegate numberOfSections]; i++) { 422 | UIButton *buttonTmp = (UIButton *) [self.sectionView viewWithTag:20140830 + i]; 423 | [buttonTmp setSelected:i == index]; 424 | } 425 | if (button.isSelected) { 426 | CGRect rect = self.sectionLineView.frame; 427 | rect.origin.x = button.frame.size.width * index; 428 | [UIView animateWithDuration:animateTime animations:^{ 429 | [blockSelf.sectionLineView setFrame:rect]; 430 | } completion:nil]; 431 | } 432 | for (NSUInteger i = 0 ; i < [self.delegate numberOfSections]; i++) { 433 | UIView *view = (UIView *) [self.bottomView viewWithTag:20150830 + i]; 434 | [view setHidden:i != index]; 435 | } 436 | _currentIndex = index; 437 | if (self.delegate && [self.delegate respondsToSelector:@selector(didChangeToSection:view:)]) { 438 | [self.delegate didChangeToSection:index view:theSectionView]; 439 | } 440 | 441 | } 442 | 443 | 444 | #pragma mark -- 445 | #pragma mark Observer 446 | 447 | - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 448 | if ([@"contentSize" isEqualToString:keyPath]) { 449 | [self __scrollTipView:self.topScrollView]; 450 | } else if ([@"contentOffset" isEqualToString:keyPath]) { 451 | [self __scrollAction:self.topScrollView]; 452 | } 453 | } 454 | 455 | - (BOOL) __isNeedToAdjustTopScrollViewContentSize { 456 | CGFloat scrollSizeHeight = self.topScrollView.contentSize.height + self.topScrollView.contentInset.top + self.topScrollView.contentInset.bottom ; 457 | if (scrollSizeHeight < height) { 458 | return YES; 459 | } 460 | return NO; 461 | } 462 | 463 | - (void) __adjustTopScrollViewContentSize { 464 | CGSize size = self.topScrollView.contentSize; 465 | size.height = height - (self.topScrollView.contentInset.top + self.topScrollView.contentInset.bottom); 466 | [self.topScrollView setContentSize:size]; 467 | } 468 | 469 | - (void) __scrollTipView:(UIScrollView *)scrollView { 470 | if ([self __isNeedToAdjustTopScrollViewContentSize]) { 471 | [self __adjustTopScrollViewContentSize]; 472 | return; 473 | } 474 | [self.tipView setFrame:CGRectMake(0, self.topScrollView.contentSize.height , width, tipHeight)]; 475 | } 476 | 477 | - (void)__scrollAction:(UIScrollView *)scrollView { 478 | 479 | if (scrollView == self.topScrollView && _sectionTotal > 0 && ![self __isNeedToAdjustTopScrollViewContentSize]) { 480 | CGSize contentSize = scrollView.contentSize; 481 | CGPoint contentOffset = scrollView.contentOffset; 482 | UIEdgeInsets contentInsets = scrollView.contentInset; 483 | if (!_isTriggerd) { 484 | CGFloat startY = (contentSize.height + contentInsets.bottom) - (contentOffset.y + height); 485 | [self.bottomView setFrame:CGRectMake(0, startY + height, width, height)]; 486 | } 487 | if (!scrollView.isDragging && !_isTriggerd) { 488 | float value = self.topScrollView.contentOffset.y + height - self.topScrollView.contentSize.height; 489 | if (value > paddingSpace) { 490 | self.isTriggerd = YES; 491 | [self didFirstShowOnBottomView]; 492 | __weak typeof(self) blockSelf = self; 493 | [UIView animateWithDuration:animateTime animations:^{ 494 | [blockSelf.bottomView setFrame:CGRectMake(0, 0, width, height)]; 495 | [blockSelf.topView setFrame:CGRectMake(0, -height, width, height)]; 496 | [blockSelf animateContent]; 497 | } completion:nil]; 498 | } 499 | } 500 | } 501 | 502 | } 503 | 504 | @end 505 | -------------------------------------------------------------------------------- /MDetailFramework/testDetail/UIImage+extend.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage-Extensions.m 3 | // 4 | // Created by Hardy Macia on 7/1/09. 5 | // Copyright 2009 Catamount Software. All rights reserved. 6 | // 7 | #import "UIImage+extend.h" 8 | #import 9 | 10 | #define DegreesToRadians(degrees) (degrees * M_PI / 180) 11 | #define RadiansToDegrees(radians) (radians * 180/M_PI) 12 | 13 | //CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;}; 14 | //CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180/M_PI;}; 15 | 16 | 17 | static int16_t gaussianblur_kernel[25] = { 18 | 1, 4, 6, 4, 1, 19 | 4, 16, 24, 16, 4, 20 | 6, 24, 36, 24, 6, 21 | 4, 16, 24, 16, 4, 22 | 1, 4, 6, 4, 1 23 | }; 24 | 25 | @implementation UIImage (extend) 26 | 27 | //截取部分图像 28 | -(UIImage*)subImageAtRect:(CGRect)rect 29 | { 30 | CGImageRef subImageRef = CGImageCreateWithImageInRect(self.CGImage, rect); 31 | CGRect smallBounds = CGRectMake(0, 0, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef)); 32 | 33 | UIGraphicsBeginImageContext(smallBounds.size); 34 | CGContextRef context = UIGraphicsGetCurrentContext(); 35 | CGContextDrawImage(context, smallBounds, subImageRef); 36 | 37 | // 设置图片旋转方向 38 | // UIImage* smallImage = [UIImage imageWithCGImage:subImageRef]; 39 | UIImage* smallImage = [UIImage imageWithCGImage:subImageRef scale:1.0f orientation:self.imageOrientation]; 40 | 41 | UIGraphicsEndImageContext(); 42 | CGImageRelease(subImageRef); 43 | 44 | return smallImage; 45 | } 46 | 47 | //等比例缩放 48 | -(UIImage*)imageScaledToSize:(CGSize)size 49 | { 50 | CGFloat width = CGImageGetWidth(self.CGImage); 51 | CGFloat height = CGImageGetHeight(self.CGImage); 52 | 53 | float verticalRadio = size.height*1.0/height; 54 | float horizontalRadio = size.width*1.0/width; 55 | 56 | float radio = 1; 57 | if(verticalRadio>1 && horizontalRadio>1) 58 | { 59 | radio = verticalRadio > horizontalRadio ? horizontalRadio : verticalRadio; 60 | } 61 | else 62 | { 63 | radio = verticalRadio < horizontalRadio ? verticalRadio : horizontalRadio; 64 | } 65 | 66 | width = width*radio; 67 | height = height*radio; 68 | 69 | int xPos = (size.width - width)/2; 70 | int yPos = (size.height-height)/2; 71 | 72 | // 创建一个bitmap的context 73 | // 并把它设置成为当前正在使用的context 74 | UIGraphicsBeginImageContext(size); 75 | 76 | // 绘制改变大小的图片 77 | [self drawInRect:CGRectMake(xPos, yPos, width, height)]; 78 | 79 | // 从当前context中创建一个改变大小后的图片 80 | UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); 81 | 82 | // 使当前的context出堆栈 83 | UIGraphicsEndImageContext(); 84 | 85 | // 返回新的改变大小后的图片 86 | return scaledImage; 87 | } 88 | 89 | - (UIImage *)imageScaledToWidth:(CGFloat)value 90 | { 91 | // NSLog(@"self.size=%f, %f", self.size.width , self.size.height); 92 | return [self imageScaledToSize: CGSizeMake(value, self.size.height * value / self.size.width)]; 93 | } 94 | 95 | - (UIImage *)imageScaledToHeight:(CGFloat)value 96 | { 97 | return [self imageScaledToSize: CGSizeMake(self.size.width * value / self.size.height, value)]; 98 | } 99 | 100 | // 指定大小的图片显示,高度超出的截取指定高度,宽度超出的截取指定宽度 101 | - (UIImage *)imageScaledToSizeEx:(CGSize)size 102 | { 103 | CGSize imageSize = self.size; 104 | CGFloat height = imageSize.width * size.height / size.width; 105 | CGFloat width = imageSize.height * size.width / size.height; 106 | if (height < imageSize.height) 107 | { 108 | CGFloat originY = (imageSize.height - height)/2; 109 | return [self subImageAtRect:CGRectMake(0, (originY > 50) ? 50 : originY, imageSize.width, height)]; 110 | } 111 | else if (width < imageSize.width) 112 | { 113 | CGFloat originX = (imageSize.width - width)/2; 114 | //DEBUGLOG(@"width == %f ==== %f", width, imageSize.width); 115 | return [self subImageAtRect:CGRectMake(originX, 0, width, imageSize.height)]; 116 | } 117 | 118 | return self; 119 | 120 | /* 121 | CGFloat width = CGImageGetWidth(self.CGImage); 122 | CGFloat height = CGImageGetHeight(self.CGImage); 123 | 124 | height = height*size.width/width; 125 | 126 | if (height < size.height) { 127 | width = width * size.height / height; 128 | height = size.height; 129 | } else { 130 | width = size.width; 131 | } 132 | 133 | UIGraphicsBeginImageContext(CGSizeMake(width, height)); 134 | [self drawInRect:CGRectMake(0, 0, width, height)]; 135 | UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); 136 | UIGraphicsEndImageContext(); 137 | return [scaledImage subImageAtRect:CGRectMake(0, 0, size.width, size.height)]; 138 | */ 139 | } 140 | 141 | 142 | -(UIImage *)imageAtRect:(CGRect)rect 143 | { 144 | 145 | CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect); 146 | UIImage* subImage = [UIImage imageWithCGImage: imageRef]; 147 | CGImageRelease(imageRef); 148 | 149 | return subImage; 150 | 151 | } 152 | - (UIImage *)imageByScalingProportionallyToMinimumSize:(CGSize)targetSize { 153 | 154 | UIImage *sourceImage = self; 155 | UIImage *newImage = nil; 156 | 157 | CGSize imageSize = sourceImage.size; 158 | CGFloat width = imageSize.width; 159 | CGFloat height = imageSize.height; 160 | 161 | CGFloat targetWidth = targetSize.width; 162 | CGFloat targetHeight = targetSize.height; 163 | 164 | CGFloat scaleFactor = 0.0; 165 | 166 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) 167 | { 168 | 169 | CGFloat widthFactor = targetWidth / width; 170 | CGFloat heightFactor = targetHeight / height; 171 | 172 | if (widthFactor > heightFactor) 173 | scaleFactor = widthFactor; 174 | else 175 | scaleFactor = heightFactor; 176 | } 177 | else 178 | { 179 | return sourceImage; 180 | } 181 | 182 | newImage = [[UIImage alloc] initWithCGImage:sourceImage.CGImage scale:scaleFactor orientation:UIImageOrientationUp]; 183 | 184 | if(!newImage) 185 | NSLog(@"could not scale image"); 186 | 187 | return newImage ; 188 | } 189 | 190 | - (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize { 191 | 192 | UIImage *sourceImage = self; 193 | UIImage *newImage = nil; 194 | 195 | CGSize imageSize = sourceImage.size; 196 | CGFloat width = imageSize.width; 197 | CGFloat height = imageSize.height; 198 | 199 | CGFloat targetWidth = targetSize.width; 200 | CGFloat targetHeight = targetSize.height; 201 | 202 | CGFloat scaleFactor = 0.0; 203 | CGFloat scaledWidth = targetWidth; 204 | CGFloat scaledHeight = targetHeight; 205 | 206 | CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 207 | 208 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) { 209 | 210 | CGFloat widthFactor = targetWidth / width; 211 | CGFloat heightFactor = targetHeight / height; 212 | 213 | if (widthFactor < heightFactor) 214 | scaleFactor = widthFactor; 215 | else 216 | scaleFactor = heightFactor; 217 | 218 | scaledWidth = width * scaleFactor; 219 | scaledHeight = height * scaleFactor; 220 | 221 | // center the image 222 | 223 | if (widthFactor < heightFactor) { 224 | thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 225 | } else if (widthFactor > heightFactor) { 226 | thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; 227 | } 228 | } 229 | 230 | 231 | // this is actually the interesting part: 232 | 233 | UIGraphicsBeginImageContext(targetSize); 234 | 235 | CGRect thumbnailRect = CGRectZero; 236 | thumbnailRect.origin = thumbnailPoint; 237 | thumbnailRect.size.width = scaledWidth; 238 | thumbnailRect.size.height = scaledHeight; 239 | 240 | [sourceImage drawInRect:thumbnailRect]; 241 | 242 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 243 | UIGraphicsEndImageContext(); 244 | 245 | if(newImage == nil) NSLog(@"could not scale image"); 246 | 247 | 248 | return newImage ; 249 | } 250 | - (UIImage *)imageByScalingToSize:(CGSize)targetSize { 251 | 252 | UIImage *sourceImage = self; 253 | UIImage *newImage = nil; 254 | 255 | // CGSize imageSize = sourceImage.size; 256 | // CGFloat width = imageSize.width; 257 | // CGFloat height = imageSize.height; 258 | 259 | CGFloat targetWidth = targetSize.width; 260 | CGFloat targetHeight = targetSize.height; 261 | 262 | // CGFloat scaleFactor = 0.0; 263 | CGFloat scaledWidth = targetWidth; 264 | CGFloat scaledHeight = targetHeight; 265 | 266 | CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 267 | 268 | // this is actually the interesting part: 269 | 270 | UIGraphicsBeginImageContext(targetSize); 271 | 272 | CGRect thumbnailRect = CGRectZero; 273 | thumbnailRect.origin = thumbnailPoint; 274 | thumbnailRect.size.width = scaledWidth; 275 | thumbnailRect.size.height = scaledHeight; 276 | 277 | [sourceImage drawInRect:thumbnailRect]; 278 | 279 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 280 | UIGraphicsEndImageContext(); 281 | 282 | if(newImage == nil) NSLog(@"could not scale image"); 283 | 284 | 285 | return newImage ; 286 | } 287 | - (UIImage *)imageRotatedByRadians:(CGFloat)radians 288 | { 289 | return [self imageRotatedByDegrees:RadiansToDegrees(radians)]; 290 | } 291 | - (UIImage *)imageRotatedByDegrees:(CGFloat)degrees 292 | { 293 | // calculate the size of the rotated view's containing box for our drawing space 294 | UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)]; 295 | CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees)); 296 | rotatedViewBox.transform = t; 297 | CGSize rotatedSize = rotatedViewBox.frame.size; 298 | //[rotatedViewBox release]; 299 | 300 | // Create the bitmap context 301 | UIGraphicsBeginImageContext(rotatedSize); 302 | CGContextRef bitmap = UIGraphicsGetCurrentContext(); 303 | 304 | // Move the origin to the middle of the image so we will rotate and scale around the center. 305 | CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2); 306 | 307 | // // Rotate the image context 308 | CGContextRotateCTM(bitmap, DegreesToRadians(degrees)); 309 | 310 | // Now, draw the rotated/scaled image into the context 311 | CGContextScaleCTM(bitmap, 1.0, -1.0); 312 | CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]); 313 | 314 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 315 | UIGraphicsEndImageContext(); 316 | return newImage; 317 | 318 | } 319 | 320 | - (UIImage *)imageWithShadowColor:(UIColor *)color offset:(CGSize)offset blur:(CGFloat)blur 321 | { 322 | //get size 323 | CGSize border = CGSizeMake(fabs(offset.width) + blur, fabs(offset.height) + blur); 324 | CGSize size = CGSizeMake(self.size.width + border.width * 2.0f, self.size.height + border.height * 2.0f); 325 | 326 | //create drawing context 327 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f); 328 | CGContextRef context = UIGraphicsGetCurrentContext(); 329 | 330 | //set up shadow 331 | CGContextSetShadowWithColor(context, offset, blur, color.CGColor); 332 | 333 | //draw with shadow 334 | [self drawAtPoint:CGPointMake(border.width, border.height)]; 335 | 336 | //capture resultant image 337 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 338 | UIGraphicsEndImageContext(); 339 | 340 | //return image 341 | return image; 342 | } 343 | 344 | - (UIImage *)imageWithCornerRadius:(CGFloat)radius 345 | { 346 | //create drawing context 347 | UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f); 348 | CGContextRef context = UIGraphicsGetCurrentContext(); 349 | 350 | //clip image 351 | CGContextBeginPath(context); 352 | CGContextMoveToPoint(context, 0.0f, radius); 353 | CGContextAddLineToPoint(context, 0.0f, self.size.height - radius); 354 | CGContextAddArc(context, radius, self.size.height - radius, radius, M_PI, M_PI / 2.0f, 1); 355 | CGContextAddLineToPoint(context, self.size.width - radius, self.size.height); 356 | CGContextAddArc(context, self.size.width - radius, self.size.height - radius, radius, M_PI / 2.0f, 0.0f, 1); 357 | CGContextAddLineToPoint(context, self.size.width, radius); 358 | CGContextAddArc(context, self.size.width - radius, radius, radius, 0.0f, -M_PI / 2.0f, 1); 359 | CGContextAddLineToPoint(context, radius, 0.0f); 360 | CGContextAddArc(context, radius, radius, radius, -M_PI / 2.0f, M_PI, 1); 361 | CGContextClip(context); 362 | 363 | //draw image 364 | [self drawAtPoint:CGPointZero]; 365 | 366 | //capture resultant image 367 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 368 | UIGraphicsEndImageContext(); 369 | 370 | //return image 371 | return image; 372 | } 373 | 374 | 375 | //高斯图像处理 376 | - (UIImage *)gaussianBlur 377 | { 378 | const size_t width = self.size.width; 379 | const size_t height = self.size.height; 380 | const size_t bytesPerRow = width * 4; 381 | 382 | CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); 383 | CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, bytesPerRow, space, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); 384 | CGColorSpaceRelease(space); 385 | if (!bmContext) 386 | return nil; 387 | 388 | CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = height}, self.CGImage); 389 | 390 | UInt8* data = (UInt8*)CGBitmapContextGetData(bmContext); 391 | if (!data) 392 | { 393 | CGContextRelease(bmContext); 394 | return nil; 395 | } 396 | 397 | const size_t n = sizeof(UInt8) * width * height * 4; 398 | void* outt = malloc(n); 399 | vImage_Buffer src = {data, height, width, bytesPerRow}; 400 | vImage_Buffer dest = {outt, height, width, bytesPerRow}; 401 | 402 | vImageConvolve_ARGB8888(&src, &dest, NULL, 0, 0, gaussianblur_kernel, 5, 5, 256, NULL, kvImageCopyInPlace); 403 | 404 | memcpy(data, outt, n); 405 | free(outt); 406 | 407 | CGImageRef blurredImageRef = CGBitmapContextCreateImage(bmContext); 408 | UIImage* blurred = [UIImage imageWithCGImage:blurredImageRef]; 409 | 410 | CGImageRelease(blurredImageRef); 411 | CGContextRelease(bmContext); 412 | 413 | return blurred; 414 | } 415 | 416 | - (UIImage *)fixOrientation { 417 | 418 | // No-op if the orientation is already correct 419 | if (self.imageOrientation == UIImageOrientationUp) return self; 420 | 421 | // We need to calculate the proper transformation to make the image upright. 422 | // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. 423 | CGAffineTransform transform = CGAffineTransformIdentity; 424 | 425 | switch (self.imageOrientation) { 426 | case UIImageOrientationDown: 427 | case UIImageOrientationDownMirrored: 428 | transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height); 429 | transform = CGAffineTransformRotate(transform, M_PI); 430 | break; 431 | 432 | case UIImageOrientationLeft: 433 | case UIImageOrientationLeftMirrored: 434 | transform = CGAffineTransformTranslate(transform, self.size.width, 0); 435 | transform = CGAffineTransformRotate(transform, M_PI_2); 436 | break; 437 | 438 | case UIImageOrientationRight: 439 | case UIImageOrientationRightMirrored: 440 | transform = CGAffineTransformTranslate(transform, 0, self.size.height); 441 | transform = CGAffineTransformRotate(transform, -M_PI_2); 442 | break; 443 | default: 444 | break; 445 | } 446 | 447 | switch (self.imageOrientation) { 448 | case UIImageOrientationUpMirrored: 449 | case UIImageOrientationDownMirrored: 450 | transform = CGAffineTransformTranslate(transform, self.size.width, 0); 451 | transform = CGAffineTransformScale(transform, -1, 1); 452 | break; 453 | 454 | case UIImageOrientationLeftMirrored: 455 | case UIImageOrientationRightMirrored: 456 | transform = CGAffineTransformTranslate(transform, self.size.height, 0); 457 | transform = CGAffineTransformScale(transform, -1, 1); 458 | break; 459 | default: 460 | break; 461 | } 462 | 463 | // Now we draw the underlying CGImage into a new context, applying the transform 464 | // calculated above. 465 | CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height, 466 | CGImageGetBitsPerComponent(self.CGImage), 0, 467 | CGImageGetColorSpace(self.CGImage), 468 | CGImageGetBitmapInfo(self.CGImage)); 469 | CGContextConcatCTM(ctx, transform); 470 | switch (self.imageOrientation) { 471 | case UIImageOrientationLeft: 472 | case UIImageOrientationLeftMirrored: 473 | case UIImageOrientationRight: 474 | case UIImageOrientationRightMirrored: 475 | // Grr... 476 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage); 477 | break; 478 | 479 | default: 480 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage); 481 | break; 482 | } 483 | 484 | // And now we just create a new UIImage from the drawing context 485 | CGImageRef cgimg = CGBitmapContextCreateImage(ctx); 486 | UIImage *img = [UIImage imageWithCGImage:cgimg]; 487 | CGContextRelease(ctx); 488 | CGImageRelease(cgimg); 489 | return img; 490 | } 491 | 492 | - (CGFloat)resizableHeightWithFixedwidth:(CGFloat)width 493 | { 494 | return (width * [self size].height)/[self size].width; 495 | } 496 | 497 | - (UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize 498 | { 499 | UIGraphicsBeginImageContext(CGSizeMake(reSize.width, reSize.height)); 500 | [image drawInRect:CGRectMake(0, 0, reSize.width, reSize.height)]; 501 | UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext(); 502 | UIGraphicsEndImageContext(); 503 | return reSizeImage; 504 | 505 | } 506 | 507 | -(UIImage*)getGrayImage:(UIImage*)sourceImage 508 | { 509 | int width = sourceImage.size.width; 510 | int height = sourceImage.size.height; 511 | 512 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 513 | CGContextRef context = CGBitmapContextCreate (nil,width,height,8,0,colorSpace,kCGBitmapByteOrder16Little); 514 | CGColorSpaceRelease(colorSpace); 515 | 516 | if (context != NULL) { 517 | CGContextDrawImage(context,CGRectMake(0, 0, width, height), sourceImage.CGImage); 518 | CGImageRef cgImageRef = CGBitmapContextCreateImage(context); 519 | UIImage *grayImage = [UIImage imageWithCGImage:cgImageRef]; 520 | CGContextRelease(context); 521 | CGImageRelease(cgImageRef); 522 | return grayImage; 523 | } 524 | return nil; 525 | } 526 | 527 | + (UIImage *) getLaunchImage { 528 | // Default-568h@2x.png 640*1136 529 | // Default.png 320*480 530 | // Default@2x.png 640*960 531 | // LaunchImage-800-667h@2x.png 750*1334 532 | // LaunchImage-800-Portrait-736h@3x.png 1242*2208 533 | // LaunchImage-800-Landscape-736h@3x.png 2208*1242 534 | // Default-Landscape@2x~ipad.png 2048*1536 535 | // Default-Landscape~ipad.png 1024*768 536 | // Default-Portrait@2x~ipad.png 1536*2048 537 | // Default-Portrait~ipad.png 768*1024 538 | 539 | UIImage *image = nil; 540 | 541 | int screenWidth = (int)[[UIScreen mainScreen] currentMode].size.width; 542 | int screenHeight = (int)[[UIScreen mainScreen] currentMode].size.height; 543 | 544 | if (screenWidth == 640 && screenHeight == 1136) { 545 | image = [UIImage imageNamed:@"Default-568h@2x.png"]; 546 | } 547 | else if (screenWidth == 320 && screenHeight == 480) { 548 | image = [UIImage imageNamed:@"Default.png"]; 549 | } 550 | else if (screenWidth == 640 && screenHeight == 960) { 551 | image = [UIImage imageNamed:@"Default@2x.png"]; 552 | } 553 | else if (screenWidth == 750 && screenHeight == 1334) { 554 | image = [UIImage imageNamed:@"LaunchImage-800-667h@2x.png"]; 555 | } 556 | else if (screenWidth == 1242 && screenHeight == 2208) { 557 | image = [UIImage imageNamed:@"LaunchImage-800-Portrait-736h@3x.png"]; 558 | } 559 | else if (screenWidth == 2208 && screenHeight == 1242) { 560 | image = [UIImage imageNamed:@"LaunchImage-800-Landscape-736h@3x.png"]; 561 | } 562 | else if (screenWidth == 2048 && screenHeight == 1536) { 563 | image = [UIImage imageNamed:@"Default-Landscape@2x~ipad.png"]; 564 | } 565 | else if (screenWidth == 1024 && screenHeight == 768) { 566 | image = [UIImage imageNamed:@"Default-Landscape~ipad.png"]; 567 | } 568 | else if (screenWidth == 1536 && screenHeight == 2048) { 569 | image = [UIImage imageNamed:@"Default-Portrait@2x~ipad.png"]; 570 | } 571 | else if (screenWidth == 768 && screenHeight == 1024) { 572 | image = [UIImage imageNamed:@"Default-Portrait~ipad.png"]; 573 | } 574 | if (!image) { 575 | image = [UIImage imageNamed:@"LaunchImage"]; 576 | } 577 | return image; 578 | } 579 | 580 | @end; 581 | -------------------------------------------------------------------------------- /README.html: -------------------------------------------------------------------------------- 1 | README

MDetailFramework控件

1018 |

前言

1019 |

MDetailFramework,为实现淘宝中的商品详情页面中, 商品的基本信息、图文详情、评论、商家推荐的效果;

1020 |

简介

1021 |
    1022 |
  • 1、此包提供商品详情的展示,支持全屏、导航2种模式;
  • 1023 |
  • 2、支持图片左滑到一定距离时,侧滑展示图文详情、评论,其中图片详情、评论可通过Delegate配置;
  • 1024 |
  • 3、支持视图上拉到一定距离时,上移展示图文详情、评论,其中图片详情、评论可通过Delegate配置;
  • 1025 |
  • 4、banner图片支持点击,全屏展示,且全屏展示模式下,亦支持左滑\点击缩小;
  • 1026 |
  • 5、当Section个数为一个时,不显示SectionBar
  • 1027 |
  • 6、testDetail,提供了四种展示展示方式,UITableView\UITableView(无sectionbar)\UIScrollView\UIWebView;
  • 1028 |
1029 |

依赖

1030 |
    1031 |
  • 1、此项目依赖MFullScreenFramework
  • 1032 |
1033 |

举例

1034 |
- (DetailView *) detailView {
1035 |     if (!_detailView) {
1036 |         _detailView = [[DetailView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height-64)];
1037 |         _detailView.delegate = self;
1038 |         _detailView.startYPosition = 0.0f;
1039 |         _detailView.topScrollViewTopInset = 300.0f;
1040 |         _detailView.topScrollPageView.delegate = self;
1041 |     }
1042 |     return _detailView;
1043 | }
1044 | 
1045 | - (UIWebView *) topWebView {
1046 |     if (!_topWebView) {
1047 |         _topWebView = [[UIWebView alloc] initWithFrame:_detailView.bounds];
1048 |         _topWebView.scrollView.showsVerticalScrollIndicator = NO;
1049 |         _topWebView.backgroundColor = [UIColor whiteColor];
1050 |         [_topWebView setOpaque:NO];
1051 |     }
1052 |     return _topWebView;
1053 | }
1054 | 
1055 | - (MFullScreenControl *) control {
1056 |     if(!_control) {
1057 |         _control = self.detailView.fullScreencontrol;
1058 |         _control.screenPageView.delegate = self;
1059 |     }
1060 |     return _control;
1061 | }
1062 | 
1063 | 
1064 | #pragma mark UIScrollPageControlViewDelegate
1065 | 
1066 | - (NSUInteger) numberOfView:(UIScrollPageControlView *) control {
1067 |     return 4;
1068 | }
1069 | 
1070 | - (UIView *) configBannerItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index {
1071 |     UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuse"];
1072 |     if (!cellItem) {
1073 |         cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, _detailView.topScrollViewTopInset)];
1074 |         cellItem.userInteractionEnabled = YES;
1075 |         cellItem.backgroundColor  = [UIColor colorWithWhite:0.7f alpha:0.4f];
1076 |         cellItem.reuseIdentifier = @"reuse";
1077 |         [cellItem  addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTaped:)]];
1078 |     }
1079 |     UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic_%d",(int)(index+1) %4]];
1080 |     image = [image imageScaledToSizeEx:CGSizeMake(cellItem.frame.size.width * 2, cellItem.frame.size.height * 2)];
1081 |     cellItem.image = image;
1082 |     return cellItem;
1083 | }
1084 | 
1085 | - (UIView *) configFullItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index {
1086 |     UIImageView *cellItem = (UIImageView *)[control dequeueReusableViewWithIdentifier:@"reuseFull"];
1087 |     if (!cellItem) {
1088 |         cellItem = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, _detailView.topScrollViewTopInset)];
1089 |         cellItem.userInteractionEnabled = YES;
1090 |         cellItem.backgroundColor  = [UIColor colorWithWhite:0.7f alpha:0.4f];
1091 |         cellItem.reuseIdentifier = @"reuseFull";
1092 |         [cellItem  addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDidTaped:)]];
1093 |     }
1094 |     UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic_%d",(int)(index+1) %4]];
1095 |     image = [image imageScaledToSizeEx:CGSizeMake(cellItem.frame.size.width * 2, cellItem.frame.size.height * 2)];
1096 | //    cellItem.image = image;
1097 |     return cellItem;
1098 | }
1099 | 
1100 | - (UIView *) configItemOfControl:(UIScrollPageControlView *) control at:(NSUInteger) index  {
1101 |     if (control == _control.screenPageView) {
1102 |         return [self configFullItemOfControl:_control.screenPageView at:index];
1103 |     }
1104 |     return [self configBannerItemOfControl:control at:index];    
1105 | }
1106 | 
1107 | - (void) imageViewDidTaped:(UIGestureRecognizer *) recognizer {
1108 |     if (self.control.isAppear) {
1109 |         [self.detailView hideFullScreenOnView:recognizer.view];
1110 |         return;
1111 |     }
1112 |     [self.detailView showFullScreenOnView:recognizer.view];
1113 | }
1114 | 
1115 | #pragma mark DetailViewSectionDelegate
1116 | 
1117 | - (UIView *) viewAtTop {
1118 |     return self.topWebView;
1119 | }
1120 | 
1121 | - (NSUInteger ) numberOfSections {
1122 | //    __totalNumber = (1 == __totalNumber) ? 2 : 1;
1123 |     return __totalNumber;
1124 | }
1125 | 
1126 | - (NSString *) titleOfSectionAt:(NSUInteger )index {
1127 |     return titles[index];
1128 | }
1129 | 
1130 | - (UIView *) viewOfSectionAt:(NSUInteger ) index {
1131 |     UIWebView *webview = [[UIWebView alloc] initWithFrame:CGRectZero];
1132 |     return webview;
1133 | }
1134 | 
1135 | - (void) didChangeToSection:(NSUInteger) index view:(UIView *) view {
1136 |     NSString *url = urls[index];
1137 |     UIWebView *webView = (UIWebView *) view;
1138 |     if (!webView.request) {
1139 |         [webView stopLoading];
1140 |         [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
1141 |     }
1142 | }
1143 | 
1144 | - (void) floatViewIsGoingTo:(BOOL) appear {
1145 |     NSLog(@"floatViewIsGoingTo = %d", appear);
1146 | }
1147 | 
1148 | 
1149 | 1150 |

效果图展示

1151 |

为更好的展示效果,请耐心等待
1152 |

-------------------------------------------------------------------------------- /MDetailFramework/MDetailFramework.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 6272E1FF1CBEB6BF00D15853 /* DetailAggregate */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 6272E2001CBEB6BF00D15853 /* Build configuration list for PBXAggregateTarget "DetailAggregate" */; 13 | buildPhases = ( 14 | 6272E2031CBEB6C300D15853 /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | ); 18 | name = DetailAggregate; 19 | productName = DetailAggregate; 20 | }; 21 | /* End PBXAggregateTarget section */ 22 | 23 | /* Begin PBXBuildFile section */ 24 | 626ED5DA1E8BAEF00056B833 /* MFullScreenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6272E22E1CBEB70000D15853 /* MFullScreenFramework.framework */; }; 25 | 6272E1F81CBEB6A500D15853 /* MDetailFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 6272E1F71CBEB6A500D15853 /* MDetailFramework.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | 6272E20C1CBEB6DA00D15853 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E20B1CBEB6DA00D15853 /* main.m */; }; 27 | 6272E20F1CBEB6DA00D15853 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E20E1CBEB6DA00D15853 /* AppDelegate.m */; }; 28 | 6272E2151CBEB6DA00D15853 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6272E2131CBEB6DA00D15853 /* Main.storyboard */; }; 29 | 6272E2171CBEB6DA00D15853 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6272E2161CBEB6DA00D15853 /* Assets.xcassets */; }; 30 | 6272E21A1CBEB6DA00D15853 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6272E2181CBEB6DA00D15853 /* LaunchScreen.storyboard */; }; 31 | 6272E2251CBEB6DA00D15853 /* testDetailTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2241CBEB6DA00D15853 /* testDetailTests.m */; }; 32 | 6272E22D1CBEB6E000D15853 /* MDetailFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6272E1F41CBEB6A500D15853 /* MDetailFramework.framework */; }; 33 | 6272E22F1CBEB70000D15853 /* MFullScreenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6272E22E1CBEB70000D15853 /* MFullScreenFramework.framework */; }; 34 | 6272E23A1CBEB72D00D15853 /* DetailPictureView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6272E2321CBEB72D00D15853 /* DetailPictureView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 35 | 6272E23B1CBEB72D00D15853 /* DetailPictureView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2331CBEB72D00D15853 /* DetailPictureView.m */; }; 36 | 6272E23C1CBEB72D00D15853 /* DetailRefreshView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6272E2341CBEB72D00D15853 /* DetailRefreshView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37 | 6272E23D1CBEB72D00D15853 /* DetailRefreshView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2351CBEB72D00D15853 /* DetailRefreshView.m */; }; 38 | 6272E23E1CBEB72D00D15853 /* DetailTipView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6272E2361CBEB72D00D15853 /* DetailTipView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 39 | 6272E23F1CBEB72D00D15853 /* DetailTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2371CBEB72D00D15853 /* DetailTipView.m */; }; 40 | 6272E2401CBEB72D00D15853 /* DetailView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6272E2381CBEB72D00D15853 /* DetailView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 41 | 6272E2411CBEB72D00D15853 /* DetailView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2391CBEB72D00D15853 /* DetailView.m */; }; 42 | 6272E2421CBEB76F00D15853 /* MDetailFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6272E1F41CBEB6A500D15853 /* MDetailFramework.framework */; }; 43 | 6272E24F1CBEB7E000D15853 /* DetailScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2441CBEB7E000D15853 /* DetailScrollViewController.m */; }; 44 | 6272E2501CBEB7E000D15853 /* DetailTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2461CBEB7E000D15853 /* DetailTableViewController.m */; }; 45 | 6272E2511CBEB7E000D15853 /* DetailWapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E2481CBEB7E000D15853 /* DetailWapViewController.m */; }; 46 | 6272E2521CBEB7E000D15853 /* RootTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E24A1CBEB7E000D15853 /* RootTableViewController.m */; }; 47 | 6272E2531CBEB7E000D15853 /* SingleOneSectionTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E24C1CBEB7E000D15853 /* SingleOneSectionTableViewController.m */; }; 48 | 6272E2541CBEB7E000D15853 /* UIImage+extend.m in Sources */ = {isa = PBXBuildFile; fileRef = 6272E24E1CBEB7E000D15853 /* UIImage+extend.m */; }; 49 | 6277EEC01D0FB4A900A386A5 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6277EEBF1D0FB4A900A386A5 /* Info.plist */; }; 50 | 6277EEC81D0FB64B00A386A5 /* Detail.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6277EEC71D0FB64B00A386A5 /* Detail.bundle */; }; 51 | 6277EEC91D0FB64B00A386A5 /* Detail.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6277EEC71D0FB64B00A386A5 /* Detail.bundle */; }; 52 | 6277EECE1D0FC98800A386A5 /* DetailLocalizable.h in Headers */ = {isa = PBXBuildFile; fileRef = 6277EECC1D0FC98800A386A5 /* DetailLocalizable.h */; }; 53 | 6277EECF1D0FC98800A386A5 /* DetailLocalizable.m in Sources */ = {isa = PBXBuildFile; fileRef = 6277EECD1D0FC98800A386A5 /* DetailLocalizable.m */; }; 54 | /* End PBXBuildFile section */ 55 | 56 | /* Begin PBXContainerItemProxy section */ 57 | 6272E2211CBEB6DA00D15853 /* PBXContainerItemProxy */ = { 58 | isa = PBXContainerItemProxy; 59 | containerPortal = 6272E1EB1CBEB6A500D15853 /* Project object */; 60 | proxyType = 1; 61 | remoteGlobalIDString = 6272E2071CBEB6DA00D15853; 62 | remoteInfo = testDetail; 63 | }; 64 | /* End PBXContainerItemProxy section */ 65 | 66 | /* Begin PBXFileReference section */ 67 | 626ED5D71E8BA3250056B833 /* MFullScreenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MFullScreenFramework.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Dallas-bfvukggundgcexadogozzcxgjwze/Build/Products/Debug-iphonesimulator/MFullScreenFramework.framework"; sourceTree = ""; }; 68 | 6272E1F41CBEB6A500D15853 /* MDetailFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MDetailFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 6272E1F71CBEB6A500D15853 /* MDetailFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MDetailFramework.h; sourceTree = ""; }; 70 | 6272E1F91CBEB6A500D15853 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 71 | 6272E2081CBEB6DA00D15853 /* testDetail.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testDetail.app; sourceTree = BUILT_PRODUCTS_DIR; }; 72 | 6272E20B1CBEB6DA00D15853 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 73 | 6272E20D1CBEB6DA00D15853 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 74 | 6272E20E1CBEB6DA00D15853 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 75 | 6272E2141CBEB6DA00D15853 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 76 | 6272E2161CBEB6DA00D15853 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 77 | 6272E2191CBEB6DA00D15853 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 78 | 6272E2201CBEB6DA00D15853 /* testDetailTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = testDetailTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | 6272E2241CBEB6DA00D15853 /* testDetailTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = testDetailTests.m; sourceTree = ""; }; 80 | 6272E2261CBEB6DA00D15853 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 81 | 6272E22E1CBEB70000D15853 /* MFullScreenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MFullScreenFramework.framework; sourceTree = ""; }; 82 | 6272E2321CBEB72D00D15853 /* DetailPictureView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailPictureView.h; sourceTree = ""; }; 83 | 6272E2331CBEB72D00D15853 /* DetailPictureView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailPictureView.m; sourceTree = ""; }; 84 | 6272E2341CBEB72D00D15853 /* DetailRefreshView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailRefreshView.h; sourceTree = ""; }; 85 | 6272E2351CBEB72D00D15853 /* DetailRefreshView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailRefreshView.m; sourceTree = ""; }; 86 | 6272E2361CBEB72D00D15853 /* DetailTipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailTipView.h; sourceTree = ""; }; 87 | 6272E2371CBEB72D00D15853 /* DetailTipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailTipView.m; sourceTree = ""; }; 88 | 6272E2381CBEB72D00D15853 /* DetailView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailView.h; sourceTree = ""; }; 89 | 6272E2391CBEB72D00D15853 /* DetailView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailView.m; sourceTree = ""; }; 90 | 6272E2431CBEB7E000D15853 /* DetailScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailScrollViewController.h; sourceTree = ""; }; 91 | 6272E2441CBEB7E000D15853 /* DetailScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailScrollViewController.m; sourceTree = ""; }; 92 | 6272E2451CBEB7E000D15853 /* DetailTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailTableViewController.h; sourceTree = ""; }; 93 | 6272E2461CBEB7E000D15853 /* DetailTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailTableViewController.m; sourceTree = ""; }; 94 | 6272E2471CBEB7E000D15853 /* DetailWapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailWapViewController.h; sourceTree = ""; }; 95 | 6272E2481CBEB7E000D15853 /* DetailWapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailWapViewController.m; sourceTree = ""; }; 96 | 6272E2491CBEB7E000D15853 /* RootTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootTableViewController.h; sourceTree = ""; }; 97 | 6272E24A1CBEB7E000D15853 /* RootTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootTableViewController.m; sourceTree = ""; }; 98 | 6272E24B1CBEB7E000D15853 /* SingleOneSectionTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SingleOneSectionTableViewController.h; sourceTree = ""; }; 99 | 6272E24C1CBEB7E000D15853 /* SingleOneSectionTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SingleOneSectionTableViewController.m; sourceTree = ""; }; 100 | 6272E24D1CBEB7E000D15853 /* UIImage+extend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+extend.h"; sourceTree = ""; }; 101 | 6272E24E1CBEB7E000D15853 /* UIImage+extend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+extend.m"; sourceTree = ""; }; 102 | 6277EEBF1D0FB4A900A386A5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 103 | 6277EEC71D0FB64B00A386A5 /* Detail.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Detail.bundle; sourceTree = ""; }; 104 | 6277EECC1D0FC98800A386A5 /* DetailLocalizable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailLocalizable.h; sourceTree = ""; }; 105 | 6277EECD1D0FC98800A386A5 /* DetailLocalizable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailLocalizable.m; sourceTree = ""; }; 106 | /* End PBXFileReference section */ 107 | 108 | /* Begin PBXFrameworksBuildPhase section */ 109 | 6272E1F01CBEB6A500D15853 /* Frameworks */ = { 110 | isa = PBXFrameworksBuildPhase; 111 | buildActionMask = 2147483647; 112 | files = ( 113 | 6272E22F1CBEB70000D15853 /* MFullScreenFramework.framework in Frameworks */, 114 | ); 115 | runOnlyForDeploymentPostprocessing = 0; 116 | }; 117 | 6272E2051CBEB6DA00D15853 /* Frameworks */ = { 118 | isa = PBXFrameworksBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 626ED5DA1E8BAEF00056B833 /* MFullScreenFramework.framework in Frameworks */, 122 | 6272E2421CBEB76F00D15853 /* MDetailFramework.framework in Frameworks */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | 6272E21D1CBEB6DA00D15853 /* Frameworks */ = { 127 | isa = PBXFrameworksBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | 6272E22D1CBEB6E000D15853 /* MDetailFramework.framework in Frameworks */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXFrameworksBuildPhase section */ 135 | 136 | /* Begin PBXGroup section */ 137 | 626ED5D61E8BA3250056B833 /* Frameworks */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 626ED5D71E8BA3250056B833 /* MFullScreenFramework.framework */, 141 | ); 142 | name = Frameworks; 143 | sourceTree = ""; 144 | }; 145 | 6272E1EA1CBEB6A500D15853 = { 146 | isa = PBXGroup; 147 | children = ( 148 | 6272E22E1CBEB70000D15853 /* MFullScreenFramework.framework */, 149 | 6272E1F61CBEB6A500D15853 /* MDetailFramework */, 150 | 6272E2091CBEB6DA00D15853 /* testDetail */, 151 | 6272E2231CBEB6DA00D15853 /* testDetailTests */, 152 | 6272E1F51CBEB6A500D15853 /* Products */, 153 | 626ED5D61E8BA3250056B833 /* Frameworks */, 154 | ); 155 | sourceTree = ""; 156 | }; 157 | 6272E1F51CBEB6A500D15853 /* Products */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 6272E1F41CBEB6A500D15853 /* MDetailFramework.framework */, 161 | 6272E2081CBEB6DA00D15853 /* testDetail.app */, 162 | 6272E2201CBEB6DA00D15853 /* testDetailTests.xctest */, 163 | ); 164 | name = Products; 165 | sourceTree = ""; 166 | }; 167 | 6272E1F61CBEB6A500D15853 /* MDetailFramework */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 6272E2311CBEB72D00D15853 /* DetailControl */, 171 | 6272E1F71CBEB6A500D15853 /* MDetailFramework.h */, 172 | 6272E1F91CBEB6A500D15853 /* Info.plist */, 173 | 6277EEC71D0FB64B00A386A5 /* Detail.bundle */, 174 | ); 175 | path = MDetailFramework; 176 | sourceTree = ""; 177 | }; 178 | 6272E2091CBEB6DA00D15853 /* testDetail */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | 6272E2431CBEB7E000D15853 /* DetailScrollViewController.h */, 182 | 6272E2441CBEB7E000D15853 /* DetailScrollViewController.m */, 183 | 6272E2451CBEB7E000D15853 /* DetailTableViewController.h */, 184 | 6272E2461CBEB7E000D15853 /* DetailTableViewController.m */, 185 | 6272E2471CBEB7E000D15853 /* DetailWapViewController.h */, 186 | 6272E2481CBEB7E000D15853 /* DetailWapViewController.m */, 187 | 6272E2491CBEB7E000D15853 /* RootTableViewController.h */, 188 | 6272E24A1CBEB7E000D15853 /* RootTableViewController.m */, 189 | 6272E24B1CBEB7E000D15853 /* SingleOneSectionTableViewController.h */, 190 | 6272E24C1CBEB7E000D15853 /* SingleOneSectionTableViewController.m */, 191 | 6272E24D1CBEB7E000D15853 /* UIImage+extend.h */, 192 | 6272E24E1CBEB7E000D15853 /* UIImage+extend.m */, 193 | 6272E20D1CBEB6DA00D15853 /* AppDelegate.h */, 194 | 6272E20E1CBEB6DA00D15853 /* AppDelegate.m */, 195 | 6272E2131CBEB6DA00D15853 /* Main.storyboard */, 196 | 6277EEBF1D0FB4A900A386A5 /* Info.plist */, 197 | 6272E2161CBEB6DA00D15853 /* Assets.xcassets */, 198 | 6272E2181CBEB6DA00D15853 /* LaunchScreen.storyboard */, 199 | 6272E20A1CBEB6DA00D15853 /* Supporting Files */, 200 | ); 201 | path = testDetail; 202 | sourceTree = ""; 203 | }; 204 | 6272E20A1CBEB6DA00D15853 /* Supporting Files */ = { 205 | isa = PBXGroup; 206 | children = ( 207 | 6272E20B1CBEB6DA00D15853 /* main.m */, 208 | ); 209 | name = "Supporting Files"; 210 | sourceTree = ""; 211 | }; 212 | 6272E2231CBEB6DA00D15853 /* testDetailTests */ = { 213 | isa = PBXGroup; 214 | children = ( 215 | 6272E2241CBEB6DA00D15853 /* testDetailTests.m */, 216 | 6272E2261CBEB6DA00D15853 /* Info.plist */, 217 | ); 218 | path = testDetailTests; 219 | sourceTree = ""; 220 | }; 221 | 6272E2311CBEB72D00D15853 /* DetailControl */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | 6272E2321CBEB72D00D15853 /* DetailPictureView.h */, 225 | 6272E2331CBEB72D00D15853 /* DetailPictureView.m */, 226 | 6272E2341CBEB72D00D15853 /* DetailRefreshView.h */, 227 | 6272E2351CBEB72D00D15853 /* DetailRefreshView.m */, 228 | 6272E2361CBEB72D00D15853 /* DetailTipView.h */, 229 | 6272E2371CBEB72D00D15853 /* DetailTipView.m */, 230 | 6272E2381CBEB72D00D15853 /* DetailView.h */, 231 | 6272E2391CBEB72D00D15853 /* DetailView.m */, 232 | 6277EECC1D0FC98800A386A5 /* DetailLocalizable.h */, 233 | 6277EECD1D0FC98800A386A5 /* DetailLocalizable.m */, 234 | ); 235 | path = DetailControl; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXGroup section */ 239 | 240 | /* Begin PBXHeadersBuildPhase section */ 241 | 6272E1F11CBEB6A500D15853 /* Headers */ = { 242 | isa = PBXHeadersBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | 6272E23E1CBEB72D00D15853 /* DetailTipView.h in Headers */, 246 | 6272E1F81CBEB6A500D15853 /* MDetailFramework.h in Headers */, 247 | 6277EECE1D0FC98800A386A5 /* DetailLocalizable.h in Headers */, 248 | 6272E2401CBEB72D00D15853 /* DetailView.h in Headers */, 249 | 6272E23A1CBEB72D00D15853 /* DetailPictureView.h in Headers */, 250 | 6272E23C1CBEB72D00D15853 /* DetailRefreshView.h in Headers */, 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | }; 254 | /* End PBXHeadersBuildPhase section */ 255 | 256 | /* Begin PBXNativeTarget section */ 257 | 6272E1F31CBEB6A500D15853 /* MDetailFramework */ = { 258 | isa = PBXNativeTarget; 259 | buildConfigurationList = 6272E1FC1CBEB6A500D15853 /* Build configuration list for PBXNativeTarget "MDetailFramework" */; 260 | buildPhases = ( 261 | 6272E1EF1CBEB6A500D15853 /* Sources */, 262 | 6272E1F01CBEB6A500D15853 /* Frameworks */, 263 | 6272E1F11CBEB6A500D15853 /* Headers */, 264 | 6272E1F21CBEB6A500D15853 /* Resources */, 265 | ); 266 | buildRules = ( 267 | ); 268 | dependencies = ( 269 | ); 270 | name = MDetailFramework; 271 | productName = MDetailFramework; 272 | productReference = 6272E1F41CBEB6A500D15853 /* MDetailFramework.framework */; 273 | productType = "com.apple.product-type.framework"; 274 | }; 275 | 6272E2071CBEB6DA00D15853 /* testDetail */ = { 276 | isa = PBXNativeTarget; 277 | buildConfigurationList = 6272E2271CBEB6DA00D15853 /* Build configuration list for PBXNativeTarget "testDetail" */; 278 | buildPhases = ( 279 | 6272E2041CBEB6DA00D15853 /* Sources */, 280 | 6272E2051CBEB6DA00D15853 /* Frameworks */, 281 | 6272E2061CBEB6DA00D15853 /* Resources */, 282 | ); 283 | buildRules = ( 284 | ); 285 | dependencies = ( 286 | ); 287 | name = testDetail; 288 | productName = testDetail; 289 | productReference = 6272E2081CBEB6DA00D15853 /* testDetail.app */; 290 | productType = "com.apple.product-type.application"; 291 | }; 292 | 6272E21F1CBEB6DA00D15853 /* testDetailTests */ = { 293 | isa = PBXNativeTarget; 294 | buildConfigurationList = 6272E22A1CBEB6DA00D15853 /* Build configuration list for PBXNativeTarget "testDetailTests" */; 295 | buildPhases = ( 296 | 6272E21C1CBEB6DA00D15853 /* Sources */, 297 | 6272E21D1CBEB6DA00D15853 /* Frameworks */, 298 | 6272E21E1CBEB6DA00D15853 /* Resources */, 299 | ); 300 | buildRules = ( 301 | ); 302 | dependencies = ( 303 | 6272E2221CBEB6DA00D15853 /* PBXTargetDependency */, 304 | ); 305 | name = testDetailTests; 306 | productName = testDetailTests; 307 | productReference = 6272E2201CBEB6DA00D15853 /* testDetailTests.xctest */; 308 | productType = "com.apple.product-type.bundle.unit-test"; 309 | }; 310 | /* End PBXNativeTarget section */ 311 | 312 | /* Begin PBXProject section */ 313 | 6272E1EB1CBEB6A500D15853 /* Project object */ = { 314 | isa = PBXProject; 315 | attributes = { 316 | LastUpgradeCheck = 0730; 317 | ORGANIZATIONNAME = micker; 318 | TargetAttributes = { 319 | 6272E1F31CBEB6A500D15853 = { 320 | CreatedOnToolsVersion = 7.3; 321 | }; 322 | 6272E1FF1CBEB6BF00D15853 = { 323 | CreatedOnToolsVersion = 7.3; 324 | }; 325 | 6272E2071CBEB6DA00D15853 = { 326 | CreatedOnToolsVersion = 7.3; 327 | DevelopmentTeam = 432R882V66; 328 | ProvisioningStyle = Automatic; 329 | }; 330 | 6272E21F1CBEB6DA00D15853 = { 331 | CreatedOnToolsVersion = 7.3; 332 | TestTargetID = 6272E2071CBEB6DA00D15853; 333 | }; 334 | }; 335 | }; 336 | buildConfigurationList = 6272E1EE1CBEB6A500D15853 /* Build configuration list for PBXProject "MDetailFramework" */; 337 | compatibilityVersion = "Xcode 3.2"; 338 | developmentRegion = English; 339 | hasScannedForEncodings = 0; 340 | knownRegions = ( 341 | en, 342 | Base, 343 | ); 344 | mainGroup = 6272E1EA1CBEB6A500D15853; 345 | productRefGroup = 6272E1F51CBEB6A500D15853 /* Products */; 346 | projectDirPath = ""; 347 | projectRoot = ""; 348 | targets = ( 349 | 6272E1F31CBEB6A500D15853 /* MDetailFramework */, 350 | 6272E1FF1CBEB6BF00D15853 /* DetailAggregate */, 351 | 6272E2071CBEB6DA00D15853 /* testDetail */, 352 | 6272E21F1CBEB6DA00D15853 /* testDetailTests */, 353 | ); 354 | }; 355 | /* End PBXProject section */ 356 | 357 | /* Begin PBXResourcesBuildPhase section */ 358 | 6272E1F21CBEB6A500D15853 /* Resources */ = { 359 | isa = PBXResourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | 6277EEC81D0FB64B00A386A5 /* Detail.bundle in Resources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | 6272E2061CBEB6DA00D15853 /* Resources */ = { 367 | isa = PBXResourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | 6277EEC91D0FB64B00A386A5 /* Detail.bundle in Resources */, 371 | 6277EEC01D0FB4A900A386A5 /* Info.plist in Resources */, 372 | 6272E21A1CBEB6DA00D15853 /* LaunchScreen.storyboard in Resources */, 373 | 6272E2171CBEB6DA00D15853 /* Assets.xcassets in Resources */, 374 | 6272E2151CBEB6DA00D15853 /* Main.storyboard in Resources */, 375 | ); 376 | runOnlyForDeploymentPostprocessing = 0; 377 | }; 378 | 6272E21E1CBEB6DA00D15853 /* Resources */ = { 379 | isa = PBXResourcesBuildPhase; 380 | buildActionMask = 2147483647; 381 | files = ( 382 | ); 383 | runOnlyForDeploymentPostprocessing = 0; 384 | }; 385 | /* End PBXResourcesBuildPhase section */ 386 | 387 | /* Begin PBXShellScriptBuildPhase section */ 388 | 6272E2031CBEB6C300D15853 /* ShellScript */ = { 389 | isa = PBXShellScriptBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | ); 393 | inputPaths = ( 394 | ); 395 | outputPaths = ( 396 | ); 397 | runOnlyForDeploymentPostprocessing = 0; 398 | shellPath = /bin/sh; 399 | shellScript = "# Sets the target folders and the final framework product.\n# 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME\n# 例如: FMK_NAME = \"MyFramework\"\nFMK_NAME=${PROJECT_NAME}\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nINSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework\n# -configuration ${CONFIGURATION}\n# Clean and Building both architectures.\nxcodebuild -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos clean build\nxcodebuild -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator clean build\n# Cleaning the oldest.\nif [ -d \"${INSTALL_DIR}\" ]\nthen\nrm -rf \"${INSTALL_DIR}\"\nfi\nmkdir -p \"${INSTALL_DIR}\"\ncp -R \"${DEVICE_DIR}/\" \"${INSTALL_DIR}/\"\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/${FMK_NAME}\" \"${SIMULATOR_DIR}/${FMK_NAME}\" -output \"${INSTALL_DIR}/${FMK_NAME}\"\nrm -r \"${WRK_DIR}\"\nopen \"${INSTALL_DIR}\"\n"; 400 | }; 401 | /* End PBXShellScriptBuildPhase section */ 402 | 403 | /* Begin PBXSourcesBuildPhase section */ 404 | 6272E1EF1CBEB6A500D15853 /* Sources */ = { 405 | isa = PBXSourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | 6272E23B1CBEB72D00D15853 /* DetailPictureView.m in Sources */, 409 | 6272E2411CBEB72D00D15853 /* DetailView.m in Sources */, 410 | 6272E23F1CBEB72D00D15853 /* DetailTipView.m in Sources */, 411 | 6272E23D1CBEB72D00D15853 /* DetailRefreshView.m in Sources */, 412 | 6277EECF1D0FC98800A386A5 /* DetailLocalizable.m in Sources */, 413 | ); 414 | runOnlyForDeploymentPostprocessing = 0; 415 | }; 416 | 6272E2041CBEB6DA00D15853 /* Sources */ = { 417 | isa = PBXSourcesBuildPhase; 418 | buildActionMask = 2147483647; 419 | files = ( 420 | 6272E2511CBEB7E000D15853 /* DetailWapViewController.m in Sources */, 421 | 6272E2501CBEB7E000D15853 /* DetailTableViewController.m in Sources */, 422 | 6272E24F1CBEB7E000D15853 /* DetailScrollViewController.m in Sources */, 423 | 6272E2521CBEB7E000D15853 /* RootTableViewController.m in Sources */, 424 | 6272E20F1CBEB6DA00D15853 /* AppDelegate.m in Sources */, 425 | 6272E20C1CBEB6DA00D15853 /* main.m in Sources */, 426 | 6272E2531CBEB7E000D15853 /* SingleOneSectionTableViewController.m in Sources */, 427 | 6272E2541CBEB7E000D15853 /* UIImage+extend.m in Sources */, 428 | ); 429 | runOnlyForDeploymentPostprocessing = 0; 430 | }; 431 | 6272E21C1CBEB6DA00D15853 /* Sources */ = { 432 | isa = PBXSourcesBuildPhase; 433 | buildActionMask = 2147483647; 434 | files = ( 435 | 6272E2251CBEB6DA00D15853 /* testDetailTests.m in Sources */, 436 | ); 437 | runOnlyForDeploymentPostprocessing = 0; 438 | }; 439 | /* End PBXSourcesBuildPhase section */ 440 | 441 | /* Begin PBXTargetDependency section */ 442 | 6272E2221CBEB6DA00D15853 /* PBXTargetDependency */ = { 443 | isa = PBXTargetDependency; 444 | target = 6272E2071CBEB6DA00D15853 /* testDetail */; 445 | targetProxy = 6272E2211CBEB6DA00D15853 /* PBXContainerItemProxy */; 446 | }; 447 | /* End PBXTargetDependency section */ 448 | 449 | /* Begin PBXVariantGroup section */ 450 | 6272E2131CBEB6DA00D15853 /* Main.storyboard */ = { 451 | isa = PBXVariantGroup; 452 | children = ( 453 | 6272E2141CBEB6DA00D15853 /* Base */, 454 | ); 455 | name = Main.storyboard; 456 | sourceTree = ""; 457 | }; 458 | 6272E2181CBEB6DA00D15853 /* LaunchScreen.storyboard */ = { 459 | isa = PBXVariantGroup; 460 | children = ( 461 | 6272E2191CBEB6DA00D15853 /* Base */, 462 | ); 463 | name = LaunchScreen.storyboard; 464 | sourceTree = ""; 465 | }; 466 | /* End PBXVariantGroup section */ 467 | 468 | /* Begin XCBuildConfiguration section */ 469 | 6272E1FA1CBEB6A500D15853 /* Debug */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ALWAYS_SEARCH_USER_PATHS = NO; 473 | CLANG_ANALYZER_NONNULL = YES; 474 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 475 | CLANG_CXX_LIBRARY = "libc++"; 476 | CLANG_ENABLE_MODULES = YES; 477 | CLANG_ENABLE_OBJC_ARC = YES; 478 | CLANG_WARN_BOOL_CONVERSION = YES; 479 | CLANG_WARN_CONSTANT_CONVERSION = YES; 480 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 481 | CLANG_WARN_EMPTY_BODY = YES; 482 | CLANG_WARN_ENUM_CONVERSION = YES; 483 | CLANG_WARN_INT_CONVERSION = YES; 484 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 485 | CLANG_WARN_UNREACHABLE_CODE = YES; 486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 487 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 488 | COPY_PHASE_STRIP = NO; 489 | CURRENT_PROJECT_VERSION = 1; 490 | DEBUG_INFORMATION_FORMAT = dwarf; 491 | ENABLE_STRICT_OBJC_MSGSEND = YES; 492 | ENABLE_TESTABILITY = YES; 493 | GCC_C_LANGUAGE_STANDARD = gnu99; 494 | GCC_DYNAMIC_NO_PIC = NO; 495 | GCC_NO_COMMON_BLOCKS = YES; 496 | GCC_OPTIMIZATION_LEVEL = 0; 497 | GCC_PREPROCESSOR_DEFINITIONS = ( 498 | "DEBUG=1", 499 | "$(inherited)", 500 | ); 501 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 502 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 503 | GCC_WARN_UNDECLARED_SELECTOR = YES; 504 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 505 | GCC_WARN_UNUSED_FUNCTION = YES; 506 | GCC_WARN_UNUSED_VARIABLE = YES; 507 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 508 | MTL_ENABLE_DEBUG_INFO = YES; 509 | ONLY_ACTIVE_ARCH = YES; 510 | SDKROOT = iphoneos; 511 | TARGETED_DEVICE_FAMILY = "1,2"; 512 | VERSIONING_SYSTEM = "apple-generic"; 513 | VERSION_INFO_PREFIX = ""; 514 | }; 515 | name = Debug; 516 | }; 517 | 6272E1FB1CBEB6A500D15853 /* Release */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | ALWAYS_SEARCH_USER_PATHS = NO; 521 | CLANG_ANALYZER_NONNULL = YES; 522 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 523 | CLANG_CXX_LIBRARY = "libc++"; 524 | CLANG_ENABLE_MODULES = YES; 525 | CLANG_ENABLE_OBJC_ARC = YES; 526 | CLANG_WARN_BOOL_CONVERSION = YES; 527 | CLANG_WARN_CONSTANT_CONVERSION = YES; 528 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 529 | CLANG_WARN_EMPTY_BODY = YES; 530 | CLANG_WARN_ENUM_CONVERSION = YES; 531 | CLANG_WARN_INT_CONVERSION = YES; 532 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 533 | CLANG_WARN_UNREACHABLE_CODE = YES; 534 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 535 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 536 | COPY_PHASE_STRIP = NO; 537 | CURRENT_PROJECT_VERSION = 1; 538 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 539 | ENABLE_NS_ASSERTIONS = NO; 540 | ENABLE_STRICT_OBJC_MSGSEND = YES; 541 | GCC_C_LANGUAGE_STANDARD = gnu99; 542 | GCC_NO_COMMON_BLOCKS = YES; 543 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 544 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 545 | GCC_WARN_UNDECLARED_SELECTOR = YES; 546 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 547 | GCC_WARN_UNUSED_FUNCTION = YES; 548 | GCC_WARN_UNUSED_VARIABLE = YES; 549 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 550 | MTL_ENABLE_DEBUG_INFO = NO; 551 | SDKROOT = iphoneos; 552 | TARGETED_DEVICE_FAMILY = "1,2"; 553 | VALIDATE_PRODUCT = YES; 554 | VERSIONING_SYSTEM = "apple-generic"; 555 | VERSION_INFO_PREFIX = ""; 556 | }; 557 | name = Release; 558 | }; 559 | 6272E1FD1CBEB6A500D15853 /* Debug */ = { 560 | isa = XCBuildConfiguration; 561 | buildSettings = { 562 | DEFINES_MODULE = YES; 563 | DYLIB_COMPATIBILITY_VERSION = 1; 564 | DYLIB_CURRENT_VERSION = 1; 565 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 566 | FRAMEWORK_SEARCH_PATHS = ( 567 | "$(inherited)", 568 | "$(PROJECT_DIR)", 569 | ); 570 | INFOPLIST_FILE = MDetailFramework/Info.plist; 571 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 572 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 573 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 574 | MACH_O_TYPE = staticlib; 575 | PRODUCT_BUNDLE_IDENTIFIER = cn.micker.MDetailFramework; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | SKIP_INSTALL = YES; 578 | }; 579 | name = Debug; 580 | }; 581 | 6272E1FE1CBEB6A500D15853 /* Release */ = { 582 | isa = XCBuildConfiguration; 583 | buildSettings = { 584 | DEFINES_MODULE = YES; 585 | DYLIB_COMPATIBILITY_VERSION = 1; 586 | DYLIB_CURRENT_VERSION = 1; 587 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 588 | FRAMEWORK_SEARCH_PATHS = ( 589 | "$(inherited)", 590 | "$(PROJECT_DIR)", 591 | ); 592 | INFOPLIST_FILE = MDetailFramework/Info.plist; 593 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 594 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 595 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 596 | MACH_O_TYPE = staticlib; 597 | PRODUCT_BUNDLE_IDENTIFIER = cn.micker.MDetailFramework; 598 | PRODUCT_NAME = "$(TARGET_NAME)"; 599 | SKIP_INSTALL = YES; 600 | }; 601 | name = Release; 602 | }; 603 | 6272E2011CBEB6BF00D15853 /* Debug */ = { 604 | isa = XCBuildConfiguration; 605 | buildSettings = { 606 | PRODUCT_NAME = "$(TARGET_NAME)"; 607 | }; 608 | name = Debug; 609 | }; 610 | 6272E2021CBEB6BF00D15853 /* Release */ = { 611 | isa = XCBuildConfiguration; 612 | buildSettings = { 613 | PRODUCT_NAME = "$(TARGET_NAME)"; 614 | }; 615 | name = Release; 616 | }; 617 | 6272E2281CBEB6DA00D15853 /* Debug */ = { 618 | isa = XCBuildConfiguration; 619 | buildSettings = { 620 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 621 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 622 | DEVELOPMENT_TEAM = 432R882V66; 623 | ENABLE_BITCODE = NO; 624 | FRAMEWORK_SEARCH_PATHS = ( 625 | "$(inherited)", 626 | "$(PROJECT_DIR)", 627 | ); 628 | INFOPLIST_FILE = testDetail/Info.plist; 629 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 630 | OTHER_LDFLAGS = "-all_load"; 631 | PRODUCT_BUNDLE_IDENTIFIER = cn.micker.testDetail; 632 | PRODUCT_NAME = "$(TARGET_NAME)"; 633 | PROVISIONING_PROFILE = ""; 634 | PROVISIONING_PROFILE_SPECIFIER = ""; 635 | }; 636 | name = Debug; 637 | }; 638 | 6272E2291CBEB6DA00D15853 /* Release */ = { 639 | isa = XCBuildConfiguration; 640 | buildSettings = { 641 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 642 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 643 | DEVELOPMENT_TEAM = 432R882V66; 644 | ENABLE_BITCODE = NO; 645 | FRAMEWORK_SEARCH_PATHS = ( 646 | "$(inherited)", 647 | "$(PROJECT_DIR)", 648 | ); 649 | INFOPLIST_FILE = testDetail/Info.plist; 650 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 651 | OTHER_LDFLAGS = "-all_load"; 652 | PRODUCT_BUNDLE_IDENTIFIER = cn.micker.testDetail; 653 | PRODUCT_NAME = "$(TARGET_NAME)"; 654 | }; 655 | name = Release; 656 | }; 657 | 6272E22B1CBEB6DA00D15853 /* Debug */ = { 658 | isa = XCBuildConfiguration; 659 | buildSettings = { 660 | BUNDLE_LOADER = "$(TEST_HOST)"; 661 | INFOPLIST_FILE = testDetailTests/Info.plist; 662 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 663 | PRODUCT_BUNDLE_IDENTIFIER = cn.micker.testDetailTests; 664 | PRODUCT_NAME = "$(TARGET_NAME)"; 665 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/testDetail.app/testDetail"; 666 | }; 667 | name = Debug; 668 | }; 669 | 6272E22C1CBEB6DA00D15853 /* Release */ = { 670 | isa = XCBuildConfiguration; 671 | buildSettings = { 672 | BUNDLE_LOADER = "$(TEST_HOST)"; 673 | INFOPLIST_FILE = testDetailTests/Info.plist; 674 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 675 | PRODUCT_BUNDLE_IDENTIFIER = cn.micker.testDetailTests; 676 | PRODUCT_NAME = "$(TARGET_NAME)"; 677 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/testDetail.app/testDetail"; 678 | }; 679 | name = Release; 680 | }; 681 | /* End XCBuildConfiguration section */ 682 | 683 | /* Begin XCConfigurationList section */ 684 | 6272E1EE1CBEB6A500D15853 /* Build configuration list for PBXProject "MDetailFramework" */ = { 685 | isa = XCConfigurationList; 686 | buildConfigurations = ( 687 | 6272E1FA1CBEB6A500D15853 /* Debug */, 688 | 6272E1FB1CBEB6A500D15853 /* Release */, 689 | ); 690 | defaultConfigurationIsVisible = 0; 691 | defaultConfigurationName = Release; 692 | }; 693 | 6272E1FC1CBEB6A500D15853 /* Build configuration list for PBXNativeTarget "MDetailFramework" */ = { 694 | isa = XCConfigurationList; 695 | buildConfigurations = ( 696 | 6272E1FD1CBEB6A500D15853 /* Debug */, 697 | 6272E1FE1CBEB6A500D15853 /* Release */, 698 | ); 699 | defaultConfigurationIsVisible = 0; 700 | defaultConfigurationName = Release; 701 | }; 702 | 6272E2001CBEB6BF00D15853 /* Build configuration list for PBXAggregateTarget "DetailAggregate" */ = { 703 | isa = XCConfigurationList; 704 | buildConfigurations = ( 705 | 6272E2011CBEB6BF00D15853 /* Debug */, 706 | 6272E2021CBEB6BF00D15853 /* Release */, 707 | ); 708 | defaultConfigurationIsVisible = 0; 709 | defaultConfigurationName = Release; 710 | }; 711 | 6272E2271CBEB6DA00D15853 /* Build configuration list for PBXNativeTarget "testDetail" */ = { 712 | isa = XCConfigurationList; 713 | buildConfigurations = ( 714 | 6272E2281CBEB6DA00D15853 /* Debug */, 715 | 6272E2291CBEB6DA00D15853 /* Release */, 716 | ); 717 | defaultConfigurationIsVisible = 0; 718 | defaultConfigurationName = Release; 719 | }; 720 | 6272E22A1CBEB6DA00D15853 /* Build configuration list for PBXNativeTarget "testDetailTests" */ = { 721 | isa = XCConfigurationList; 722 | buildConfigurations = ( 723 | 6272E22B1CBEB6DA00D15853 /* Debug */, 724 | 6272E22C1CBEB6DA00D15853 /* Release */, 725 | ); 726 | defaultConfigurationIsVisible = 0; 727 | defaultConfigurationName = Release; 728 | }; 729 | /* End XCConfigurationList section */ 730 | }; 731 | rootObject = 6272E1EB1CBEB6A500D15853 /* Project object */; 732 | } 733 | --------------------------------------------------------------------------------