Commit 15c2bff6 by iOS-肖乐乐

add project

parent b8d6aee5
//
// AppDelegate.h
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong) NSPersistentContainer *persistentContainer;
- (void)saveContext;
@end
//
// AppDelegate.m
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (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 invalidate graphics rendering callbacks. 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 active 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:.
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
#pragma mark - Core Data stack
@synthesize persistentContainer = _persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"XLLDragCollectionView"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}
@end
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
}
],
"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="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
//
// ViewController.h
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
//
// ViewController.m
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import "ViewController.h"
#import "XLLDragCollectionView.h"
#import "XLLTestCell.h"
@interface ViewController () <XLLDragCollectionViewDelegate, XLLDragCollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic, weak) XLLDragCollectionView *collectionView;
@property (nonatomic, strong) NSMutableArray *sourceArray;
@end
@implementation ViewController
#pragma mark - lazy loading
- (NSMutableArray *)sourceArray
{
if (_sourceArray == nil)
{
NSMutableArray *tempArr = [NSMutableArray array];
for (NSInteger i = 0; i < 12; i++)
{
[tempArr addObject:@(i)];
}
_sourceArray = tempArr;
}
return _sourceArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
XLLDragCollectionView *collectionView = [[XLLDragCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
collectionView.delegate = self;
collectionView.dataSource = self;
[collectionView registerClass:[XLLTestCell class] forCellWithReuseIdentifier:@"lalala"];
[self.view addSubview:collectionView];
self.collectionView = collectionView;
}
#pragma mark - XLLDragCollectionViewDelegate
- (void)dragCollectionView:(XLLDragCollectionView *)collectionView newDataArrayAfterMove:(NSArray *)newDataArray
{
self.sourceArray = [newDataArray mutableCopy];
}
#pragma mark - XLLDragCollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.sourceArray.count;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(([UIScreen mainScreen].bounds.size.width - 5 * 15)/4.0, 90);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(15, 15, 15, 15);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 15.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 15.0;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
XLLTestCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"lalala" forIndexPath:indexPath];
cell.content = [self.sourceArray[indexPath.item] stringValue];
return cell;
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.collectionView.frame = self.view.bounds;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
//
// XLLDragCollectionView.h
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import <UIKit/UIKit.h>
@class XLLDragCollectionView;
@protocol XLLDragCollectionViewDataSource <UICollectionViewDataSource>
@required
- (NSArray *)dataSourceArrayOfCollectionView:(UICollectionView *)collectionView;
@end
@protocol XLLDragCollectionViewDelegate <UICollectionViewDelegate>
@required
- (void)dragCollectionView:(XLLDragCollectionView *)collectionView newDataArrayAfterMove:(NSArray *)newDataArray;
@end
@interface XLLDragCollectionView : UICollectionView
/**
collectionView数据源代理
*/
@property (nonatomic, weak) id <XLLDragCollectionViewDataSource> dataSource;
/**
collectionView回调代理
*/
@property (nonatomic, weak) id <XLLDragCollectionViewDelegate> delegate;
/**
触发拖动的最小时间
*/
@property (nonatomic, assign) NSTimeInterval minimumTriggerTime;
@end
//
// XLLDragCollectionView.m
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import "XLLDragCollectionView.h"
//角度
#define angelToRandian(x) ((x)/180.0*M_PI)
@interface XLLDragCollectionView ()
// 长按手势
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressGesture;
// 长按的indexPath
@property (nonatomic, strong) NSIndexPath *currentIndexPath;
// 移动的cell快照
@property (nonatomic, strong) UIView *tempMoveView;
// 记录开始长按的点位
@property (nonatomic, assign) CGPoint touchPoint;
@end
@implementation XLLDragCollectionView
@dynamic dataSource, delegate;
#pragma mark - setter
- (void)setMinimumTriggerTime:(NSTimeInterval)minimumTriggerTime
{
_minimumTriggerTime = minimumTriggerTime;
self.longPressGesture.minimumPressDuration = minimumTriggerTime;
}
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
if (self = [super initWithFrame:frame collectionViewLayout:layout])
{
self.minimumTriggerTime = 1.0;
// 增加长按手势
[self addLongPressGesture];
}
return self;
}
// 添加长按手势
- (void)addLongPressGesture
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
longPress.minimumPressDuration = self.minimumTriggerTime;
self.longPressGesture = longPress;
[self addGestureRecognizer:longPress];
}
// 长按手势响应
- (void)longPressed:(UILongPressGestureRecognizer *)longPressGesture
{
if (longPressGesture.state == UIGestureRecognizerStateBegan) {
[self gestureBegin:longPressGesture];
} else if (longPressGesture.state == UIGestureRecognizerStateChanged) {
[self gestureChange:longPressGesture];
} else if (longPressGesture.state == UIGestureRecognizerStateEnded || longPressGesture.state == UIGestureRecognizerStateCancelled) {
[self gestureCancelOrEnd:longPressGesture];
}
}
// 不同手势状态下的操作
- (void)gestureBegin:(UILongPressGestureRecognizer *)longPressGesture
{
// - (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView*)view; 触摸点相对于指定视图的位置
// - (CGPoint)locationInView:(UIView*)view; 在指定视图的相对位置
// 1.根据当前collectionView长按位置,获取indexPath
CGPoint touchPoint = [longPressGesture locationOfTouch:0 inView:longPressGesture.view];
self.touchPoint = touchPoint;
self.currentIndexPath = [self indexPathForItemAtPoint:touchPoint];
// 2.根据indexPath,获取UICollectionViewCell
UICollectionViewCell *cell = [self cellForItemAtIndexPath:self.currentIndexPath];
// 3.创建一个这个cell的快照 snapshotViewAfterScreenUpdates
UIView *tempMoveView = [cell snapshotViewAfterScreenUpdates:NO];
cell.hidden = YES;
tempMoveView.frame = cell.frame;
self.tempMoveView = tempMoveView;
[self addSubview:tempMoveView];
// 4.开启边缘滚动定时器
// ..
// 5.开始抖动
[self beginShakeAllCell];
// 6.KVO观察collectionView的偏移量
// ..
// 7.回执
}
- (void)gestureChange:(UILongPressGestureRecognizer *)longPressGesture
{
// x轴移动的距离
CGFloat transformX = [longPressGesture locationOfTouch:0 inView:longPressGesture.view].x - _touchPoint.x;
// y轴移动的距离
CGFloat transformY = [longPressGesture locationOfTouch:0 inView:longPressGesture.view].y - _touchPoint.y;
// 得到快照的中心点通过矩阵移动之后的位置
self.tempMoveView.center = CGPointApplyAffineTransform(self.tempMoveView.center, CGAffineTransformMakeTranslation(transformX, transformY));
// 更新点位
self.touchPoint = [longPressGesture locationOfTouch:0 inView:longPressGesture.view];
[self moveCell];
}
- (void)gestureCancelOrEnd:(UILongPressGestureRecognizer *)longPressGesture
{
// 1.获取移动的cell
UICollectionViewCell *cell = [self cellForItemAtIndexPath:self.currentIndexPath];
self.userInteractionEnabled = NO;
[UIView animateWithDuration:0.25 animations:^{
// 此时cell已经move到正确位置,快照可能还有偏移。所以纠正位置
self.tempMoveView.center = cell.center;
} completion:^(BOOL finished) {
[self stopShakeAllCell];
[self.tempMoveView removeFromSuperview];
cell.hidden = NO;
self.userInteractionEnabled = YES;
}];
}
// 开始移动cell
- (void)moveCell
{
for (UICollectionViewCell *cell in self.visibleCells) {
// 过滤掉隐藏的cell
if ([self indexPathForCell:cell] == self.currentIndexPath) continue;
// 计算cell与快照中心点X方向距离
CGFloat spacingX = fabs(self.tempMoveView.center.x - cell.center.x);
// 计算cell与快照中心点Y方向的距离
CGFloat spacingY = fabs(self.tempMoveView.center.y - cell.center.y);
// 如果view的身位已经与这个cell距离过去超过一半了
if (spacingX <= self.tempMoveView.bounds.size.width / 2.0 && spacingY <= self.tempMoveView.bounds.size.height)
{
NSIndexPath *indexPath = [self indexPathForCell:cell];
// 更新数据源 (模型数组顺序调整)
[self updateDataSource:indexPath];
// cell视图位置调整
[self moveItemAtIndexPath:self.currentIndexPath toIndexPath:indexPath];
self.currentIndexPath = indexPath;
break;
}
}
}
- (void)updateDataSource:(NSIndexPath *)indexPath
{
if (self.dataSource && [self.dataSource respondsToSelector:@selector(dataSourceArrayOfCollectionView:)])
{
NSMutableArray *sourceArray = [[self.dataSource dataSourceArrayOfCollectionView:self] mutableCopy];
// 判断数据源是单个数组 还是 多组section形式
BOOL isMultiSection = ([self numberOfSections] > 1) || ([self numberOfSections] == 1 && [sourceArray.firstObject isKindOfClass:[NSArray class]]);
if (isMultiSection)
{
// 如果里面内嵌的是数据,将里面的数据也进行深拷贝
[sourceArray enumerateObjectsUsingBlock:^(NSArray *obj, NSUInteger idx, BOOL * _Nonnull stop) {
[sourceArray replaceObjectAtIndex:idx withObject:[obj mutableCopy]];
}];
}
// 如果拖动到同一组
if (indexPath.section == self.currentIndexPath.section) {
// 取出这一组的数据源
NSMutableArray *originSection = isMultiSection?sourceArray[self.currentIndexPath.section]:sourceArray;
// 如果当前cell的item大于起始cell的话
if (indexPath.item > self.currentIndexPath.item)
{
for (NSInteger i = self.currentIndexPath.item; i < indexPath.item; i++)
{
// ?
[originSection exchangeObjectAtIndex:i withObjectAtIndex:i+1];
}
} else {
for (NSInteger i = self.currentIndexPath.item; i > indexPath.item; i--)
{
[originSection exchangeObjectAtIndex:i withObjectAtIndex:i - 1];
}
}
} else { // 拖到了非同组中,所以肯定是数组套数组
// 起始组数据源
NSMutableArray *originSection = sourceArray[self.currentIndexPath.section];
// 当前组数据源
NSMutableArray *currentSection = sourceArray[indexPath.section];
// 将此cell的数据加入到当前组中,并将其从原始组数据源中删除
[currentSection insertObject:originSection[self.currentIndexPath.item] atIndex:indexPath.item];
[originSection removeObject:originSection[self.currentIndexPath.item]];
}
// 将重排好的数据回执,以更新外部数据源。reload的时候不至于cell又变回来
// ..回执
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCollectionView:newDataArrayAfterMove:)])
{
[self.delegate dragCollectionView:self newDataArrayAfterMove:[sourceArray copy]];
}
}
}
// 抖动所有cell
- (void)beginShakeAllCell
{
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"transform.rotation";
anim.values=@[
@(angelToRandian(4)),
@(angelToRandian(-4)),
@(angelToRandian(4))
];
anim.repeatCount=MAXFLOAT;
anim.duration=0.2;
NSArray *cells = [self visibleCells];
/******删除设置cell的晃动**************/
NSMutableArray *lastCells = cells.mutableCopy;
for (UICollectionViewCell *cell in lastCells) {
// 添加动画
if (![cell.layer animationForKey:@"shake"])
{
[cell.layer addAnimation:anim forKey:@"shake"];
}
}
// 给快照也添加动画
if (![self.tempMoveView.layer animationForKey:@"shake"]) {
[self.tempMoveView.layer addAnimation:anim forKey:@"shake"];
}
}
- (void)stopShakeAllCell
{
for (UICollectionViewCell *cell in [self visibleCells]) {
[cell.layer removeAllAnimations];
}
[self.tempMoveView.layer removeAllAnimations];
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>XLLDragCollectionView.xcdatamodel</string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<elements/>
</model>
\ No newline at end of file
//
// XLLTestCell.h
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface XLLTestCell : UICollectionViewCell
@property (nonatomic, copy) NSString *content;
@end
//
// XLLTestCell.m
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import "XLLTestCell.h"
@interface XLLTestCell ()
@property (nonatomic, weak) UILabel *descLabel;
@end
@implementation XLLTestCell
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
self.contentView.backgroundColor = [UIColor colorWithRed:(random()%256)/255.0 green:(random()%256)/255.0 blue:(random()%256)/255.0 alpha:1];
UILabel *descLabel = [[UILabel alloc] init];
descLabel.textColor = [UIColor blackColor];
descLabel.textAlignment = NSTextAlignmentCenter;
descLabel.font = [UIFont systemFontOfSize:15.0];
[self.contentView addSubview:descLabel];
self.descLabel = descLabel;
}
return self;
}
- (void)setContent:(NSString *)content
{
_content = [content copy];
self.descLabel.text = content;
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.descLabel.frame = CGRectMake((self.contentView.frame.size.width - 25)/2.0, (self.contentView.frame.size.height - 15)/2.0, 25, 15);
}
@end
//
// main.m
// XLLDragCollectionView
//
// Created by 肖乐 on 2018/3/22.
// Copyright © 2018年 IMMoveMobile. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
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