Commit 95dfbaed authored by banchichen's avatar banchichen

新增导出视频代码;新增长按对图片排序的功能

parent a567b512
......@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
6D32B9BD1CD83640005CE1E0 /* LxGridViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */; };
6DC358661CC8BAFD00898D29 /* TZImagePickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */; };
900E65811C2BB8D5003D9A9E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65801C2BB8D5003D9A9E /* main.m */; };
900E65841C2BB8D5003D9A9E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65831C2BB8D5003D9A9E /* AppDelegate.m */; };
......@@ -46,6 +47,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
6D32B9BB1CD83640005CE1E0 /* LxGridViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LxGridViewFlowLayout.h; sourceTree = "<group>"; };
6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LxGridViewFlowLayout.m; sourceTree = "<group>"; };
6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TZImagePickerController.bundle; sourceTree = "<group>"; };
900E657C1C2BB8D5003D9A9E /* TZImagePickerController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TZImagePickerController.app; sourceTree = BUILT_PRODUCTS_DIR; };
900E65801C2BB8D5003D9A9E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
......@@ -146,6 +149,8 @@
900E65831C2BB8D5003D9A9E /* AppDelegate.m */,
900E65851C2BB8D5003D9A9E /* ViewController.h */,
900E65861C2BB8D5003D9A9E /* ViewController.m */,
6D32B9BB1CD83640005CE1E0 /* LxGridViewFlowLayout.h */,
6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */,
9038D58F1C3974F0007DE549 /* TZTestCell.h */,
9038D5901C3974F0007DE549 /* TZTestCell.m */,
900E65881C2BB8D5003D9A9E /* Main.storyboard */,
......@@ -346,6 +351,7 @@
90EBF5D61C2E298000CB9BCC /* UIView+Layout.m in Sources */,
90CE84B71C3BABB6003D0779 /* TZVideoPlayerController.m in Sources */,
900EF0021C2BD7E400EA709B /* TZAssetCell.m in Sources */,
6D32B9BD1CD83640005CE1E0 /* LxGridViewFlowLayout.m in Sources */,
900EF0161C2C134900EA709B /* TZPhotoPreviewCell.m in Sources */,
900E65871C2BB8D5003D9A9E /* ViewController.m in Sources */,
90CE84AE1C3A89EF003D0779 /* TZImageManager.m in Sources */,
......@@ -493,6 +499,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/TZImagePickerController",
);
INFOPLIST_FILE = TZImagePickerController/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......@@ -509,6 +519,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/TZImagePickerController",
);
INFOPLIST_FILE = TZImagePickerController/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
......
......@@ -16,30 +16,27 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 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.
// 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.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// 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.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// 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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "photo_delete@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="14F1509" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--View Controller-->
......
......@@ -20,6 +20,8 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
......
//
// LxGridViewFlowLayout.h
// LxGridView
//
#import <UIKit/UIKit.h>
@interface LxGridViewFlowLayout : UICollectionViewFlowLayout
@property (nonatomic,assign) BOOL panGestureRecognizerEnable;
@property (nonatomic, assign) NSInteger itemCount;
@end
@protocol LxGridViewDataSource <UICollectionViewDataSource>
@optional
- (void)collectionView:(UICollectionView *)collectionView
itemAtIndexPath:(NSIndexPath *)sourceIndexPath
willMoveToIndexPath:(NSIndexPath *)destinationIndexPath;
- (void)collectionView:(UICollectionView *)collectionView
itemAtIndexPath:(NSIndexPath *)sourceIndexPath
didMoveToIndexPath:(NSIndexPath *)destinationIndexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView
canMoveItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView
itemAtIndexPath:(NSIndexPath *)sourceIndexPath
canMoveToIndexPath:(NSIndexPath *)destinationIndexPath;
@end
@protocol LxGridViewDelegateFlowLayout <UICollectionViewDelegateFlowLayout>
@optional
- (void)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
willBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
didBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
willEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
didEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
@end
\ No newline at end of file
//
// LxGridViewFlowLayout.m
// LxGridView
//
#import "LxGridViewFlowLayout.h"
#import "TZTestCell.h"
#import "UIView+Layout.h"
#define stringify __STRING
static CGFloat const PRESS_TO_MOVE_MIN_DURATION = 0.1;
static CGFloat const MIN_PRESS_TO_BEGIN_EDITING_DURATION = 0.6;
CG_INLINE CGPoint CGPointOffset(CGPoint point, CGFloat dx, CGFloat dy)
{
return CGPointMake(point.x + dx, point.y + dy);
}
@interface LxGridViewFlowLayout () <UIGestureRecognizerDelegate>
@property (nonatomic,readonly) id<LxGridViewDataSource> dataSource;
@property (nonatomic,readonly) id<LxGridViewDelegateFlowLayout> delegate;
@end
@implementation LxGridViewFlowLayout
{
UILongPressGestureRecognizer * _longPressGestureRecognizer;
UIPanGestureRecognizer * _panGestureRecognizer;
NSIndexPath * _movingItemIndexPath;
UIView * _beingMovedPromptView;
CGPoint _sourceItemCollectionViewCellCenter;
CADisplayLink * _displayLink;
CFTimeInterval _remainSecondsToBeginEditing;
}
#pragma mark - setup
- (void)dealloc
{
[_displayLink invalidate];
[self removeGestureRecognizers];
[self removeObserver:self forKeyPath:@stringify(collectionView)];
}
- (instancetype)init
{
if (self = [super init]) {
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
if (self = [super initWithCoder:coder]) {
[self setup];
}
return self;
}
- (void)setup
{
[self addObserver:self forKeyPath:@stringify(collectionView) options:NSKeyValueObservingOptionNew context:nil];
}
- (void)addGestureRecognizers
{
self.collectionView.userInteractionEnabled = YES;
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressGestureRecognizerTriggerd:)];
_longPressGestureRecognizer.cancelsTouchesInView = NO;
_longPressGestureRecognizer.minimumPressDuration = PRESS_TO_MOVE_MIN_DURATION;
_longPressGestureRecognizer.delegate = self;
for (UIGestureRecognizer * gestureRecognizer in self.collectionView.gestureRecognizers) {
if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
[gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer];
}
}
[self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
_panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizerTriggerd:)];
_panGestureRecognizer.delegate = self;
[self.collectionView addGestureRecognizer:_panGestureRecognizer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
}
- (void)removeGestureRecognizers
{
if (_longPressGestureRecognizer) {
if (_longPressGestureRecognizer.view) {
[_longPressGestureRecognizer.view removeGestureRecognizer:_longPressGestureRecognizer];
}
_longPressGestureRecognizer = nil;
}
if (_panGestureRecognizer) {
if (_panGestureRecognizer.view) {
[_panGestureRecognizer.view removeGestureRecognizer:_panGestureRecognizer];
}
_panGestureRecognizer = nil;
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
}
#pragma mark - getter and setter implementation
- (id<LxGridViewDataSource>)dataSource
{
return (id<LxGridViewDataSource>)self.collectionView.dataSource;
}
- (id<LxGridViewDelegateFlowLayout>)delegate
{
return (id<LxGridViewDelegateFlowLayout>)self.collectionView.delegate;
}
#pragma mark - override UICollectionViewLayout methods
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray * layoutAttributesForElementsInRect = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes * layoutAttributes in layoutAttributesForElementsInRect) {
if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
layoutAttributes.hidden = [layoutAttributes.indexPath isEqual:_movingItemIndexPath];
}
}
return layoutAttributesForElementsInRect;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes * layoutAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
layoutAttributes.hidden = [layoutAttributes.indexPath isEqual:_movingItemIndexPath];
}
return layoutAttributes;
}
#pragma mark - gesture
- (void)setPanGestureRecognizerEnable:(BOOL)panGestureRecognizerEnable
{
_panGestureRecognizer.enabled = panGestureRecognizerEnable;
}
- (BOOL)panGestureRecognizerEnable
{
return _panGestureRecognizer.enabled;
}
- (void)longPressGestureRecognizerTriggerd:(UILongPressGestureRecognizer *)longPress
{
switch (longPress.state) {
case UIGestureRecognizerStatePossible:
break;
case UIGestureRecognizerStateBegan:
{
if (_displayLink == nil) {
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTriggered:)];
_displayLink.frameInterval = 6;
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
_remainSecondsToBeginEditing = MIN_PRESS_TO_BEGIN_EDITING_DURATION;
}
_movingItemIndexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]];
if ([self.dataSource respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] && [self.dataSource collectionView:self.collectionView canMoveItemAtIndexPath:_movingItemIndexPath] == NO) {
_movingItemIndexPath = nil;
return;
}
if ([self.delegate respondsToSelector:@selector(collectionView:layout:willBeginDraggingItemAtIndexPath:)]) {
[self.delegate collectionView:self.collectionView layout:self willBeginDraggingItemAtIndexPath:_movingItemIndexPath];
}
UICollectionViewCell *sourceCollectionViewCell = [self.collectionView cellForItemAtIndexPath:_movingItemIndexPath];
TZTestCell *sourceCell = (TZTestCell *)sourceCollectionViewCell;
_beingMovedPromptView = [[UIView alloc]initWithFrame:CGRectOffset(sourceCollectionViewCell.frame, -10, -10)];
_beingMovedPromptView.tz_width += 20;
_beingMovedPromptView.tz_height += 20;
sourceCollectionViewCell.highlighted = YES;
UIView * highlightedSnapshotView = [sourceCell snapshotView];
highlightedSnapshotView.frame = _beingMovedPromptView.bounds;
highlightedSnapshotView.alpha = 1;
sourceCollectionViewCell.highlighted = NO;
UIView * snapshotView = [sourceCell snapshotView];
snapshotView.frame = _beingMovedPromptView.bounds;
snapshotView.alpha = 0;
[_beingMovedPromptView addSubview:snapshotView];
[_beingMovedPromptView addSubview:highlightedSnapshotView];
[self.collectionView addSubview:_beingMovedPromptView];
_sourceItemCollectionViewCellCenter = sourceCollectionViewCell.center;
typeof(self) __weak weakSelf = self;
[UIView animateWithDuration:0
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
typeof(self) __strong strongSelf = weakSelf;
if (strongSelf) {
highlightedSnapshotView.alpha = 0;
snapshotView.alpha = 1;
}
}
completion:^(BOOL finished) {
typeof(self) __strong strongSelf = weakSelf;
if (strongSelf) {
[highlightedSnapshotView removeFromSuperview];
if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didBeginDraggingItemAtIndexPath:)]) {
[strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didBeginDraggingItemAtIndexPath:_movingItemIndexPath];
}
}
}];
[self invalidateLayout];
}
break;
case UIGestureRecognizerStateChanged:
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
{
[_displayLink invalidate];
_displayLink = nil;
NSIndexPath * movingItemIndexPath = _movingItemIndexPath;
if (movingItemIndexPath) {
if ([self.delegate respondsToSelector:@selector(collectionView:layout:willEndDraggingItemAtIndexPath:)]) {
[self.delegate collectionView:self.collectionView layout:self willEndDraggingItemAtIndexPath:movingItemIndexPath];
}
_movingItemIndexPath = nil;
_sourceItemCollectionViewCellCenter = CGPointZero;
UICollectionViewLayoutAttributes * movingItemCollectionViewLayoutAttributes = [self layoutAttributesForItemAtIndexPath:movingItemIndexPath];
_longPressGestureRecognizer.enabled = NO;
typeof(self) __weak weakSelf = self;
[UIView animateWithDuration:0.2
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
typeof(self) __strong strongSelf = weakSelf;
if (strongSelf) {
_beingMovedPromptView.center = movingItemCollectionViewLayoutAttributes.center;
}
}
completion:^(BOOL finished) {
_longPressGestureRecognizer.enabled = YES;
typeof(self) __strong strongSelf = weakSelf;
if (strongSelf) {
[_beingMovedPromptView removeFromSuperview];
_beingMovedPromptView = nil;
[strongSelf invalidateLayout];
if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didEndDraggingItemAtIndexPath:)]) {
[strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didEndDraggingItemAtIndexPath:movingItemIndexPath];
}
}
}];
}
}
break;
case UIGestureRecognizerStateFailed:
break;
default:
break;
}
}
- (void)panGestureRecognizerTriggerd:(UIPanGestureRecognizer *)pan
{
switch (pan.state) {
case UIGestureRecognizerStatePossible:
break;
case UIGestureRecognizerStateBegan:
case UIGestureRecognizerStateChanged:
{
CGPoint panTranslation = [pan translationInView:self.collectionView];
_beingMovedPromptView.center = CGPointOffset(_sourceItemCollectionViewCellCenter, panTranslation.x, panTranslation.y);
NSIndexPath * sourceIndexPath = _movingItemIndexPath;
NSIndexPath * destinationIndexPath = [self.collectionView indexPathForItemAtPoint:_beingMovedPromptView.center];
if ((destinationIndexPath == nil) || [destinationIndexPath isEqual:sourceIndexPath]) {
return;
}
if (sourceIndexPath.item >= self.itemCount || destinationIndexPath.item >= self.itemCount) {
return;
}
if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:canMoveToIndexPath:)] && [self.dataSource collectionView:self.collectionView itemAtIndexPath:sourceIndexPath canMoveToIndexPath:destinationIndexPath] == NO) {
return;
}
if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:willMoveToIndexPath:)]) {
[self.dataSource collectionView:self.collectionView itemAtIndexPath:sourceIndexPath willMoveToIndexPath:destinationIndexPath];
}
_movingItemIndexPath = destinationIndexPath;
typeof(self) __weak weakSelf = self;
[self.collectionView performBatchUpdates:^{
typeof(self) __strong strongSelf = weakSelf;
if (strongSelf) {
if (sourceIndexPath && destinationIndexPath) {
[strongSelf.collectionView deleteItemsAtIndexPaths:@[sourceIndexPath]];
[strongSelf.collectionView insertItemsAtIndexPaths:@[destinationIndexPath]];
}
}
} completion:^(BOOL finished) {
typeof(self) __strong strongSelf = weakSelf;
if ([strongSelf.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:didMoveToIndexPath:)]) {
[strongSelf.dataSource collectionView:strongSelf.collectionView itemAtIndexPath:sourceIndexPath didMoveToIndexPath:destinationIndexPath];
}
}];
}
break;
case UIGestureRecognizerStateEnded:
break;
case UIGestureRecognizerStateCancelled:
break;
case UIGestureRecognizerStateFailed:
break;
default:
break;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([_panGestureRecognizer isEqual:gestureRecognizer]) {
return _movingItemIndexPath != nil;
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// only _longPressGestureRecognizer and _panGestureRecognizer can recognize simultaneously
if ([_longPressGestureRecognizer isEqual:gestureRecognizer]) {
return [_panGestureRecognizer isEqual:otherGestureRecognizer];
}
if ([_panGestureRecognizer isEqual:gestureRecognizer]) {
return [_longPressGestureRecognizer isEqual:otherGestureRecognizer];
}
return NO;
}
#pragma mark - displayLink
- (void)displayLinkTriggered:(CADisplayLink *)displayLink
{
if (_remainSecondsToBeginEditing <= 0) {
[_displayLink invalidate];
_displayLink = nil;
}
_remainSecondsToBeginEditing = _remainSecondsToBeginEditing - 0.1;
}
#pragma mark - KVO and notification
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@stringify(collectionView)]) {
if (self.collectionView) {
[self addGestureRecognizers];
}
else {
[self removeGestureRecognizers];
}
}
}
- (void)applicationWillResignActive:(NSNotification *)notificaiton
{
_panGestureRecognizer.enabled = NO;
_panGestureRecognizer.enabled = YES;
}
@end
......@@ -40,6 +40,9 @@
/// Get video 获得视频
- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem * playerItem, NSDictionary * info))completion;
/// Export video 导出视频
- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion;
/// Get photo bytes 获得一组照片的大小
- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion;
......
......@@ -409,6 +409,58 @@
}
}
#pragma mark - Export video
- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion {
if ([asset isKindOfClass:[PHAsset class]]) {
PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionOriginal;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
// NSLog(@"Info:\n%@",info);
AVURLAsset* myAsset = (AVURLAsset*)avasset;
// NSLog(@"AVAsset URL: %@",myAsset.URL);
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:myAsset];
// NSLog(@"%@",compatiblePresets);
if ([compatiblePresets containsObject:AVAssetExportPresetHighestQuality]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:myAsset presetName:AVAssetExportPresetMediumQuality];
NSDateFormatter *formater = [[NSDateFormatter alloc] init];
[formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
NSLog(@"video outputPath = %@",outputPath);
exportSession.outputURL = [NSURL fileURLWithPath:outputPath];
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
switch (exportSession.status) {
case AVAssetExportSessionStatusUnknown:
NSLog(@"AVAssetExportSessionStatusUnknown"); break;
case AVAssetExportSessionStatusWaiting:
NSLog(@"AVAssetExportSessionStatusWaiting"); break;
case AVAssetExportSessionStatusExporting:
NSLog(@"AVAssetExportSessionStatusExporting"); break;
case AVAssetExportSessionStatusCompleted:
NSLog(@"AVAssetExportSessionStatusCompleted");
if (completion) {
completion(outputPath);
}
break;
case AVAssetExportSessionStatusFailed:
NSLog(@"AVAssetExportSessionStatusFailed"); break;
default: break;
}
}];
}
}];
} else {
NSLog(@"iOS8以前的系统,导出视频代码暂未更新...");
}
}
#pragma mark - Private Method
- (TZAlbumModel *)modelWithResult:(id)result name:(NSString *)name{
......@@ -434,6 +486,8 @@
else if ([name rangeOfString:@"Selfies"].location != NSNotFound) newName = @"自拍";
else if ([name rangeOfString:@"shots"].location != NSNotFound) newName = @"截屏";
else if ([name rangeOfString:@"Videos"].location != NSNotFound) newName = @"视频";
else if ([name rangeOfString:@"Panoramas"].location != NSNotFound) newName = @"全景照片";
else if ([name rangeOfString:@"Favorites"].location != NSNotFound) newName = @"个人收藏";
else newName = name;
return newName;
} else {
......@@ -442,11 +496,15 @@
}
- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
if (image.size.width > size.width) {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
} else {
return image;
}
}
- (UIImage *)fixOrientation:(UIImage *)aImage {
......
......@@ -11,6 +11,10 @@
@interface TZTestCell : UICollectionViewCell
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIButton *deleteBtn;
@property (nonatomic, assign) NSInteger row;
- (UIView *)snapshotView;
@end
......@@ -7,6 +7,7 @@
//
#import "TZTestCell.h"
#import "UIView+Layout.h"
@implementation TZTestCell
......@@ -19,6 +20,13 @@
_imageView.contentMode = UIViewContentModeScaleAspectFill;
[self addSubview:_imageView];
self.clipsToBounds = YES;
_deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_deleteBtn setImage:[UIImage imageNamed:@"photo_delete"] forState:UIControlStateNormal];
_deleteBtn.frame = CGRectMake(self.tz_width - 36, 0, 36, 36);
_deleteBtn.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 0, -10);
_deleteBtn.alpha = 0.6;
[self addSubview:_deleteBtn];
}
return self;
}
......@@ -28,4 +36,32 @@
_imageView.frame = self.bounds;
}
- (void)setRow:(NSInteger)row {
_row = row;
_deleteBtn.tag = row;
}
- (UIView *)snapshotView {
UIView *snapshotView = [[UIView alloc]init];
UIView *cellSnapshotView = nil;
if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) {
cellSnapshotView = [self snapshotViewAfterScreenUpdates:NO];
} else {
CGSize size = CGSizeMake(self.bounds.size.width + 20, self.bounds.size.height + 20);
UIGraphicsBeginImageContextWithOptions(size, self.opaque, 0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * cellSnapshotImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
cellSnapshotView = [[UIImageView alloc]initWithImage:cellSnapshotImage];
}
snapshotView.frame = CGRectMake(0, 0, cellSnapshotView.frame.size.width, cellSnapshotView.frame.size.height);
cellSnapshotView.frame = CGRectMake(0, 0, cellSnapshotView.frame.size.width, cellSnapshotView.frame.size.height);
[snapshotView addSubview:cellSnapshotView];
return snapshotView;
}
@end
......@@ -10,15 +10,20 @@
#import "TZImagePickerController.h"
#import "UIView+Layout.h"
#import "TZTestCell.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/Photos.h>
#import "LxGridViewFlowLayout.h"
#import "TZImageManager.h"
@interface ViewController ()<TZImagePickerControllerDelegate,UICollectionViewDataSource,UICollectionViewDelegate> {
UICollectionView *_collectionView;
NSMutableArray *_selectedPhotos;
NSMutableArray *_selectedAssets;
CGFloat _itemWH;
CGFloat _margin;
LxGridViewFlowLayout *_layout;
}
@property (nonatomic, strong) UICollectionView *collectionView;
@end
@implementation ViewController
......@@ -32,13 +37,13 @@
}
- (void)configCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
_layout = [[LxGridViewFlowLayout alloc] init];
_margin = 4;
_itemWH = (self.view.tz_width - 2 * _margin - 4) / 3 - _margin;
layout.itemSize = CGSizeMake(_itemWH, _itemWH);
layout.minimumInteritemSpacing = _margin;
layout.minimumLineSpacing = _margin;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(_margin, 120, self.view.tz_width - 2 * _margin, 400) collectionViewLayout:layout];
_layout.itemSize = CGSizeMake(_itemWH, _itemWH);
_layout.minimumInteritemSpacing = _margin;
_layout.minimumLineSpacing = _margin;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(_margin, 120, self.view.tz_width - 2 * _margin, 400) collectionViewLayout:_layout];
CGFloat rgb = 244 / 255.0;
_collectionView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0];
_collectionView.contentInset = UIEdgeInsetsMake(4, 0, 0, 2);
......@@ -59,9 +64,13 @@
TZTestCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZTestCell" forIndexPath:indexPath];
if (indexPath.row == _selectedPhotos.count) {
cell.imageView.image = [UIImage imageNamed:@"AlbumAddBtn.png"];
cell.deleteBtn.hidden = YES;
} else {
cell.imageView.image = _selectedPhotos[indexPath.row];
cell.deleteBtn.hidden = NO;
}
cell.deleteBtn.tag = indexPath.row;
[cell.deleteBtn addTarget:self action:@selector(deleteBtnClik:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
......@@ -69,12 +78,35 @@
if (indexPath.row == _selectedPhotos.count) { [self pickPhotoButtonClick:nil];}
}
- (void)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)sourceIndexPath didMoveToIndexPath:(NSIndexPath *)destinationIndexPath {
if (sourceIndexPath.item >= _selectedPhotos.count || destinationIndexPath.item >= _selectedPhotos.count) return;
UIImage *image = _selectedPhotos[sourceIndexPath.item];
if (image) {
[_selectedPhotos removeObjectAtIndex:sourceIndexPath.item];
[_selectedPhotos insertObject:image atIndex:destinationIndexPath.item];
[_collectionView reloadData];
}
}
#pragma mark Click Event
- (void)deleteBtnClik:(UIButton *)sender {
[_selectedPhotos removeObjectAtIndex:sender.tag];
[_selectedAssets removeObjectAtIndex:sender.tag];
_layout.itemCount = _selectedPhotos.count;
[_collectionView performBatchUpdates:^{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:sender.tag inSection:0];
[_collectionView deleteItemsAtIndexPaths:@[indexPath]];
} completion:^(BOOL finished) {
[_collectionView reloadData];
}];
}
- (IBAction)pickPhotoButtonClick:(UIButton *)sender {
TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:self];
imagePickerVc.selectedAssets = _selectedAssets; // optional, 可选的
// You can get the photos by block, the same as by delegate.
// 你可以通过block或者代理,来得到用户选择的照片.
[imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
......@@ -109,6 +141,7 @@
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto {
_selectedPhotos = [NSMutableArray arrayWithArray:photos];
_selectedAssets = [NSMutableArray arrayWithArray:assets];
_layout.itemCount = _selectedPhotos.count;
[_collectionView reloadData];
_collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
}
......@@ -117,9 +150,18 @@
/// 用户选择好了视频
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(id)asset {
[_selectedPhotos addObjectsFromArray:@[coverImage]];
_layout.itemCount = _selectedPhotos.count;
/*
// open this code to send video / 打开这段代码发送视频
[[TZImageManager manager] getVideoOutputPathWithAsset:asset completion:^(NSString *outputPath) {
NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath);
// Export completed, send video here, send by outputPath or NSData
// 导出完成,在这里写上传代码,通过路径或者通过NSData上传
}];
*/
[_collectionView reloadData];
_collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
}
@end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment