Compare commits

...
64 Commits
Author SHA1 Message Date
Alex.k 01b09a94ea update podspec 2016-04-08 17:03:47 +03:00
Alex.k 8c234e4e0d fixing bug with corners 2016-04-08 17:02:56 +03:00
Alex.k 974ab5eed5 Merge branch 'master' of https://github.com/Ramotion/folding-cell 2016-04-08 16:42:50 +03:00
Alex.k 8e7bb1ee35 remove xcschemes 2016-04-08 16:42:43 +03:00
Alex 5d6c1b6dad Update README.md 2016-04-08 16:36:44 +03:00
Alex.k 982c9e1b30 update files 2016-04-08 16:32:29 +03:00
Alex.k 6956f385b3 remove ++ operator 2016-04-08 16:30:23 +03:00
Alex 4f641597d7 Update README.md 2016-03-09 12:07:44 +03:00
Alex.k 878a473b02 update podspec 2016-03-09 12:05:18 +03:00
Alex.k 1ebd9b3e6f Fixes #26 2016-03-09 12:00:55 +03:00
Alex.k b7dc1f1d75 podspec updated 2016-03-09 09:16:43 +03:00
Artem Kyslicyn 21e64f72c1 Merge pull request #24 from Ramotion/develop
upd
2016-02-26 12:07:15 +03:00
Artem Kislitsyn 33dfe08a96 upd 2016-02-26 12:02:34 +03:00
Alex 9d0982e62d Merge pull request #23 from Ramotion/develop
update doc
2016-02-26 11:48:39 +03:00
Artem Kislitsyn b1b564e1e9 update doc 2016-02-26 11:40:55 +03:00
Alex 3ca2172098 Update README.md 2016-02-24 10:22:58 +03:00
Alex.k 9ea71b64eb public properties: itemCount, backViewColor 2016-02-24 10:12:26 +03:00
Alex 306632b484 Update README.md 2016-02-15 14:47:02 +03:00
Alex.k def7ad435b update podspec 2016-02-15 14:45:30 +03:00
Alex.k 9db9073217 Merge branch 'master' of https://github.com/Ramotion/folding-cell 2016-02-15 14:42:33 +03:00
Alex.k a5efd73115 code improved 2016-02-15 14:42:26 +03:00
Juri Vasylenko 882ef88655 add header 2016-02-15 11:26:28 +03:00
Alex.k 216a62c6ab update podspec 2016-02-11 12:06:14 +03:00
Alex.k ce1d4cd8bd common code improves 2016-02-11 11:45:37 +03:00
Alex.k 0e87bcfc63 common code improves 2016-02-11 11:34:32 +03:00
Alex.k 3bc71e84ee common code fixed 2016-02-11 11:23:15 +03:00
Alex 4f5a0ca337 Update README.md 2016-02-11 10:11:42 +03:00
Alex ab8c7feee8 Update README.md
Fixes#12
2016-02-11 10:09:49 +03:00
Juri Vasylenko 27913fd179 Merge pull request #11 from grodowski/master
Add code quality badge from codebeat
2016-02-10 15:54:51 +03:00
Jan Grodowski 775c05a1d0 Update README.md 2016-02-10 13:30:17 +01:00
Alex 2953ca5342 Merge pull request #7 from radarhere/patch-1
Fixed typo
2016-02-09 14:10:26 +03:00
Andrew Murray 16ba4b27b0 Fixed typo 2016-02-09 21:52:13 +11:00
Juri Vasylenko 36c23cf714 Update README.md 2016-02-09 10:32:40 +03:00
Alex.k d6e37f7f01 Merge branch 'master' of https://github.com/Ramotion/folding-cell 2016-02-08 12:38:08 +03:00
Alex.k 38fa225507 update podspec 2016-02-08 12:38:01 +03:00
Alex 98352afdc7 Update README.md 2016-02-05 11:13:50 +03:00
Alex.k e5c63c9812 Fixes #5 2016-02-05 11:04:55 +03:00
Alex.k 4ec5646fa1 Revert "Fixes #45"
This reverts commit 20d7be5ca0.
2016-02-05 11:03:06 +03:00
Alex.k 20d7be5ca0 Fixes #45 2016-02-05 11:02:30 +03:00
Alex 0871b243b3 Update README.md 2016-02-04 17:11:35 +03:00
Alex.k d41c599568 update podspect 2016-02-04 17:08:45 +03:00
Alex.k e720eaf3f3 common improves 2016-02-04 17:07:20 +03:00
Alex 4c3d646349 Update .travis.yml 2016-02-03 15:41:06 +03:00
Alex.k 4d41164378 changed version 2016-02-03 14:14:27 +03:00
Alex.k aa490544c2 improve isAnimating method 2016-02-03 10:24:43 +03:00
Juri Vasylenko 835ff54cbb Update README.md 2016-02-01 12:12:31 +03:00
Alex f65b92ffdf Merge pull request #1 from Ramotion/docs_update
Docs update
2016-02-01 11:22:42 +03:00
Juri Vasylenko c6d63eb1e4 Update README.md 2016-02-01 11:19:07 +03:00
Juri Vasylenko fa758c23a3 add contributing guide, add badges and update docs 2016-02-01 11:14:28 +03:00
Alex.k 163f297fe9 change travis 2016-01-25 15:51:14 +03:00
Alex 93a228b087 Update .travis.yml 2016-01-25 15:38:18 +03:00
Alex.k b0f92dbe6b Merge branch 'develop' 2016-01-25 15:26:02 +03:00
Alex.k 8d5eff7bfc added unit test 2016-01-25 15:25:42 +03:00
Alex.k 00eee3a352 shared shame 2016-01-25 14:42:49 +03:00
Alex.k 840cc0a1a3 Merge branch 'develop' 2016-01-25 14:38:40 +03:00
Alex.k 7d18125ed5 added travis file 2016-01-25 14:37:52 +03:00
Alex.k a2226608b1 added unit tests 2016-01-25 14:21:44 +03:00
Alex bc0fda8abb Update README.md 2016-01-18 16:41:23 +03:00
Alex 3bfd692759 Update README.md 2016-01-18 16:36:00 +03:00
Alex 230c28ad5e Update README.md 2016-01-18 16:34:05 +03:00
Alex ac1c852b6c Update FoldingCell.podspec 2016-01-14 09:58:00 +03:00
Alex.k 7dc02ae65f Merge branch 'master' into develop 2016-01-13 10:28:38 +03:00
Alex ab4b6f97a4 Update README.md 2016-01-12 16:36:36 +03:00
Alex 8961b01a9a update pod spec 2016-01-12 16:27:38 +03:00
14 changed files with 730 additions and 439 deletions
+6
View File
@@ -0,0 +1,6 @@
osx_image: xcode7.3
language: objective-c
xcode_project: FoldingCell/FoldingCell.xcodeproj
xcode_scheme: FoldingCell
xcode_sdk: iphonesimulator
View File
+33
View File
@@ -0,0 +1,33 @@
# Contributing to a Project
Now that you’ve found the material for understanding the project, here is how you can take action.
### Create an Issue
If you find a bug in a project you’re using (and you don’t know how to fix it), have trouble following the documentation or have a question about the project – create an issue! There’s nothing to it and whatever issue you’re having, you’re likely not the only one, so others will find your issue helpful, too. For more information on how issues work, check out our Issues guide.
#### Issues Pro Tips
Check existing issues for your issue. Duplicating an issue is slower for both parties so search through open and closed issues to see if what you’re running into has been addressed already.
Be clear about what your problem is: what was the expected outcome, what happened instead? Detail how someone else can recreate the problem.
Link to demos recreating the problem on things like JSFiddle or CodePen.
Include system details like what the browser, library or operating system you’re using and its version.
Paste error output or logs in your issue or in a Gist. If pasting them in the issue, wrap it in three backticks: ``` so that it renders nicely.
### Pull Request
If you’re able to patch the bug or add the feature yourself – fantastic, make a pull request with the code! Be sure you’ve read any documents on contributing, understand the license and have signed a CLA if required. Once you’ve submitted a pull request the maintainer(s) can compare your branch to the existing one and decide whether or not to incorporate (pull in) your changes.
#### Pull Request Pro Tips
Fork the repository and clone it locally. Connect your local to the original ‘upstream’ repository by adding it as a remote. Pull in changes from ‘upstream’ often so that you stay up to date so that when you submit your pull request, merge conflicts will be less likely. See more detailed instructions here.
Create a branch for your edits.
Be clear about what problem is occurring and how someone can recreate that problem or why your feature will help. Then be equally as clear about the steps you took to make your changes.
It’s best to test. Run your changes against any existing tests if they exist and create new ones when needed. Whether tests exist or not, make sure your changes don’t break the existing project.
Include screenshots of the before and after if your changes include differences in HTML/CSS. Drag and drop the images into the body of your pull request.
Contribute in the style of the project to the best of your abilities. This may mean using indents, semi colons or comments differently than you would in your own repository, but makes it easier for the maintainer to merge, others to understand and maintain in the future.
#### Open Pull Requests
Once you’ve opened a pull request a discussion will start around your proposed changes. Other contributors and users may chime in, but ultimately the decision is made by the maintainer(s). You may be asked to make some changes to your pull request, if so, add more commits to your branch and push them – they’ll automatically go into the existing pull request.
If your pull request is merged – great! If it is not, no sweat, it may not be what the project maintainer had in mind, or they were already working on it. This happens, so our recommendation is to take any feedback you’ve received and go forth and pull request again – or create your own open source project.
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'FoldingCell'
s.version = '0.2'
s.version = '0.8.1'
s.summary = 'UITableViewCell with folding animation.'
s.homepage = 'https://github.com/Ramotion/folding-cell'
s.license = 'MIT'
@@ -13,6 +13,8 @@
847A58121C294F750028FB84 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 847A58101C294F750028FB84 /* LaunchScreen.storyboard */; };
847A581B1C294FAB0028FB84 /* FoldingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847A581A1C294FAB0028FB84 /* FoldingCell.swift */; };
847A581F1C29500B0028FB84 /* MainTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847A581E1C29500B0028FB84 /* MainTableViewController.swift */; };
848B463B1C56458C00D49B45 /* FoldingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847A581A1C294FAB0028FB84 /* FoldingCell.swift */; };
8498513F1C5639F9006FA400 /* FoldingCellTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8498513E1C5639F9006FA400 /* FoldingCellTests.swift */; };
8499F5DD1C2A83F70027D5D2 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8499F5D31C2A83F70027D5D2 /* OpenSans-Bold.ttf */; };
8499F5DE1C2A83F70027D5D2 /* OpenSans-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8499F5D41C2A83F70027D5D2 /* OpenSans-BoldItalic.ttf */; };
8499F5DF1C2A83F70027D5D2 /* OpenSans-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8499F5D51C2A83F70027D5D2 /* OpenSans-ExtraBold.ttf */; };
@@ -26,6 +28,16 @@
84CDB15A1C2D416400FCD7C8 /* DemoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CDB1591C2D416400FCD7C8 /* DemoCell.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
849851411C5639F9006FA400 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 847A57FC1C294F750028FB84 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 847A58031C294F750028FB84;
remoteInfo = FoldingCell;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
840B98551C33FE660081B926 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
@@ -50,6 +62,9 @@
847A58131C294F750028FB84 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
847A581A1C294FAB0028FB84 /* FoldingCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoldingCell.swift; sourceTree = "<group>"; };
847A581E1C29500B0028FB84 /* MainTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewController.swift; sourceTree = "<group>"; };
8498513C1C5639F9006FA400 /* FoldingCellTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FoldingCellTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8498513E1C5639F9006FA400 /* FoldingCellTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FoldingCellTests.swift; sourceTree = "<group>"; };
849851401C5639F9006FA400 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8499F5D31C2A83F70027D5D2 /* OpenSans-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-Bold.ttf"; sourceTree = "<group>"; };
8499F5D41C2A83F70027D5D2 /* OpenSans-BoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-BoldItalic.ttf"; sourceTree = "<group>"; };
8499F5D51C2A83F70027D5D2 /* OpenSans-ExtraBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "OpenSans-ExtraBold.ttf"; sourceTree = "<group>"; };
@@ -71,6 +86,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
849851391C5639F9006FA400 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -88,6 +110,7 @@
children = (
847A58061C294F750028FB84 /* FoldingCell */,
840B984A1C33FE660081B926 /* FoldingCellFramework */,
8498513D1C5639F9006FA400 /* FoldingCellTests */,
847A58051C294F750028FB84 /* Products */,
);
sourceTree = "<group>";
@@ -96,6 +119,7 @@
isa = PBXGroup;
children = (
847A58041C294F750028FB84 /* FoldingCell.app */,
8498513C1C5639F9006FA400 /* FoldingCellTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -124,6 +148,15 @@
path = FoldingCell;
sourceTree = "<group>";
};
8498513D1C5639F9006FA400 /* FoldingCellTests */ = {
isa = PBXGroup;
children = (
8498513E1C5639F9006FA400 /* FoldingCellTests.swift */,
849851401C5639F9006FA400 /* Info.plist */,
);
path = FoldingCellTests;
sourceTree = "<group>";
};
8499F5D21C2A83D90027D5D2 /* Fonts */ = {
isa = PBXGroup;
children = (
@@ -162,6 +195,24 @@
productReference = 847A58041C294F750028FB84 /* FoldingCell.app */;
productType = "com.apple.product-type.application";
};
8498513B1C5639F9006FA400 /* FoldingCellTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 849851431C5639F9006FA400 /* Build configuration list for PBXNativeTarget "FoldingCellTests" */;
buildPhases = (
849851381C5639F9006FA400 /* Sources */,
849851391C5639F9006FA400 /* Frameworks */,
8498513A1C5639F9006FA400 /* Resources */,
);
buildRules = (
);
dependencies = (
849851421C5639F9006FA400 /* PBXTargetDependency */,
);
name = FoldingCellTests;
productName = FoldingCellTests;
productReference = 8498513C1C5639F9006FA400 /* FoldingCellTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -174,6 +225,11 @@
TargetAttributes = {
847A58031C294F750028FB84 = {
CreatedOnToolsVersion = 7.2;
DevelopmentTeam = LEAZS7L33U;
};
8498513B1C5639F9006FA400 = {
CreatedOnToolsVersion = 7.2;
TestTargetID = 847A58031C294F750028FB84;
};
};
};
@@ -191,6 +247,7 @@
projectRoot = "";
targets = (
847A58031C294F750028FB84 /* FoldingCell */,
8498513B1C5639F9006FA400 /* FoldingCellTests */,
);
};
/* End PBXProject section */
@@ -216,6 +273,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
8498513A1C5639F9006FA400 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -230,8 +294,25 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
849851381C5639F9006FA400 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8498513F1C5639F9006FA400 /* FoldingCellTests.swift in Sources */,
848B463B1C56458C00D49B45 /* FoldingCell.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
849851421C5639F9006FA400 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 847A58031C294F750028FB84 /* FoldingCell */;
targetProxy = 849851411C5639F9006FA400 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
847A580B1C294F750028FB84 /* Main.storyboard */ = {
isa = PBXVariantGroup;
@@ -337,6 +418,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = FoldingCell/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -350,6 +432,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = FoldingCell/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -359,6 +442,32 @@
};
name = Release;
};
849851441C5639F9006FA400 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEFINES_MODULE = YES;
INFOPLIST_FILE = FoldingCellTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.FoldingCellTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FoldingCell.app/FoldingCell";
};
name = Debug;
};
849851451C5639F9006FA400 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEFINES_MODULE = YES;
INFOPLIST_FILE = FoldingCellTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.FoldingCellTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FoldingCell.app/FoldingCell";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -380,6 +489,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
849851431C5639F9006FA400 /* Build configuration list for PBXNativeTarget "FoldingCellTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
849851441C5639F9006FA400 /* Debug */,
849851451C5639F9006FA400 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 847A57FC1C294F750028FB84 /* Project object */;
@@ -14,9 +14,23 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840B98481C33FE660081B926"
BuildableName = "FoldingCellFramework.framework"
BlueprintName = "FoldingCellFramework"
BlueprintIdentifier = "847A58031C294F750028FB84"
BuildableName = "FoldingCell.app"
BlueprintName = "FoldingCell"
ReferencedContainer = "container:FoldingCell.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8498513B1C5639F9006FA400"
BuildableName = "FoldingCellTests.xctest"
BlueprintName = "FoldingCellTests"
ReferencedContainer = "container:FoldingCell.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -29,6 +43,15 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "847A58031C294F750028FB84"
BuildableName = "FoldingCell.app"
BlueprintName = "FoldingCell"
ReferencedContainer = "container:FoldingCell.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
@@ -42,15 +65,16 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840B98481C33FE660081B926"
BuildableName = "FoldingCellFramework.framework"
BlueprintName = "FoldingCellFramework"
BlueprintIdentifier = "847A58031C294F750028FB84"
BuildableName = "FoldingCell.app"
BlueprintName = "FoldingCell"
ReferencedContainer = "container:FoldingCell.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
@@ -60,15 +84,16 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840B98481C33FE660081B926"
BuildableName = "FoldingCellFramework.framework"
BlueprintName = "FoldingCellFramework"
BlueprintIdentifier = "847A58031C294F750028FB84"
BuildableName = "FoldingCell.app"
BlueprintName = "FoldingCell"
ReferencedContainer = "container:FoldingCell.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="0cn-rv-Emg">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9532" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="0cn-rv-Emg">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9530"/>
</dependencies>
<customFonts key="customFonts">
<mutableArray key="OpenSans-Light.ttf">
@@ -50,7 +50,7 @@
<!--Main Table View Controller-->
<scene sceneID="Q2d-BE-geS">
<objects>
<tableViewController id="0cn-rv-Emg" customClass="MainTableViewController" customModule="FoldingCell" customModuleProvider="target" sceneMemberID="viewController">
<tableViewController storyboardIdentifier="MainTableViewController" id="0cn-rv-Emg" customClass="MainTableViewController" customModule="FoldingCell" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" style="plain" separatorStyle="none" showsSelectionImmediatelyOnTouchBegin="NO" rowHeight="667" sectionHeaderHeight="28" sectionFooterHeight="28" id="MwZ-K3-six">
<rect key="frame" x="0.0" y="0.0" width="600" height="695"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+1 -2
View File
@@ -21,8 +21,7 @@ class DemoCell: FoldingCell {
override func animationDuration(itemIndex:NSInteger, type:AnimationType)-> NSTimeInterval {
let durations = [0.33, 0.26, 0.26]
let durations = [0.26, 0.2, 0.2]
return durations[itemIndex]
}
@@ -24,457 +24,482 @@
import UIKit
public class FoldingCell: UITableViewCell {
public typealias CompletionHandler = () -> Void
@IBOutlet weak public var containerView: UIView!
@IBOutlet weak public var foregroundView: RotatedView!
var animationView: UIView?
@IBInspectable public var itemCount: NSInteger = 2 //count of folding
@IBInspectable public var backViewColor: UIColor = UIColor.brownColor()
var animationItemViews: [RotatedView]?
public enum AnimationType {
case Open
case Close
}
// MARK: life cicle
override public func awakeFromNib() {
super.awakeFromNib()
public typealias CompletionHandler = () -> Void
@IBOutlet weak var containerView: UIView!
@IBOutlet weak var foregroundView: RotatedView!
var animationView: UIView?
configureDefaultState()
@IBInspectable var itemCount: NSInteger = 2 //count of folding
self.selectionStyle = .None
@IBInspectable var backViewColor: UIColor = UIColor.brownColor()
containerView.layer.cornerRadius = foregroundView.layer.cornerRadius
containerView.layer.masksToBounds = true
}
// MARK: configure
func configureDefaultState() {
let foregroundTopConstraint = self.contentView.constraints.filter{ $0.identifier == "ForegroundViewTop"}.first
let containerViewTopConstraint = self.contentView.constraints.filter{ $0.identifier == "ContainerViewTop"}.first
var animationItemViews: [RotatedView]?
public enum AnimationType {
case Open
case Close
guard let foregroundConstraint = foregroundTopConstraint else {
fatalError("set identifier")
}
// MARK: life cicle
override public func awakeFromNib() {
super.awakeFromNib()
configureDefaultState()
self.selectionStyle = .None
containerView.layer.cornerRadius = foregroundView.layer.cornerRadius
containerView.layer.masksToBounds = true
}
// MARK: configure
func configureDefaultState() {
let foregroundTopConstraint = self.contentView.constraints.filter{ $0.identifier == "ForegroundViewTop"}.first
let containerViewTopConstraint = self.contentView.constraints.filter{ $0.identifier == "ContainerViewTop"}.first
assert(foregroundTopConstraint != nil, "set identifier")
assert(containerViewTopConstraint != nil, "set identifier")
containerViewTopConstraint!.constant = foregroundTopConstraint!.constant
containerView.alpha = 0;
foregroundView.layer.anchorPoint = CGPoint.init(x: 0.5, y: 1)
foregroundTopConstraint!.constant += foregroundView.bounds.height / 2
foregroundView.layer.transform = foregroundView.transform3d()
createAnimationView();
self.contentView.bringSubviewToFront(foregroundView)
guard let containerConstraint = containerViewTopConstraint else {
fatalError("set identifier")
}
func createAnimationItemView()->[RotatedView] {
var items = [RotatedView]()
items.append(foregroundView)
var rotatedViews = [RotatedView]()
for itemView in animationView!.subviews.filter({$0 is RotatedView}).sort({ $0.tag < $1.tag }) as! [RotatedView] {
rotatedViews.append(itemView)
if itemView.backView != nil {
rotatedViews.append(itemView.backView!)
}
}
items.appendContentsOf(rotatedViews)
return items
containerConstraint.constant = foregroundConstraint.constant
containerView.alpha = 0;
foregroundView.layer.anchorPoint = CGPoint.init(x: 0.5, y: 1)
foregroundConstraint.constant += foregroundView.bounds.height / 2
foregroundView.layer.transform = foregroundView.transform3d()
createAnimationView();
self.contentView.bringSubviewToFront(foregroundView)
}
func createAnimationItemView()->[RotatedView] {
guard let animationView = self.animationView else {
fatalError()
}
func configureAnimationItems(animationType: AnimationType) {
var items = [RotatedView]()
items.append(foregroundView)
var rotatedViews = [RotatedView]()
for case let itemView as RotatedView in animationView.subviews.filter({$0 is RotatedView}).sort({ $0.tag < $1.tag }){
rotatedViews.append(itemView)
if let backView = itemView.backView {
rotatedViews.append(backView)
}
}
items.appendContentsOf(rotatedViews)
return items
}
func configureAnimationItems(animationType: AnimationType) {
guard let animationViewSuperView = animationView?.subviews else {
fatalError()
}
if animationType == .Open {
for view in animationViewSuperView.filter({$0 is RotatedView}) {
view.alpha = 0;
}
} else { // close
for case let view as RotatedView in animationViewSuperView.filter({$0 is RotatedView}) {
if animationType == .Open {
for view in animationView!.subviews.filter({$0 is RotatedView}) {
view.alpha = 0;
}
} else { // close
for view: RotatedView in animationView!.subviews.filter({$0 is RotatedView}) as! [RotatedView] {
if animationType == .Open {
view.alpha = 0
} else {
view.alpha = 1
view.backView?.alpha = 0
}
}
}
}
func createAnimationView() {
let anAnimationView = UIView(frame: containerView.frame)
anAnimationView.layer.cornerRadius = foregroundView.layer.cornerRadius
anAnimationView.backgroundColor = UIColor.clearColor()
anAnimationView.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(anAnimationView)
// copy constraints from containerView
var newConstraints = [NSLayoutConstraint]()
for constraint in self.contentView.constraints {
if let item: UIView = constraint.firstItem as? UIView {
if item == containerView {
let newConstraint = NSLayoutConstraint(
item: anAnimationView,
attribute: constraint.firstAttribute,
relatedBy: constraint.relation,
toItem: constraint.secondItem,
attribute: constraint.secondAttribute,
multiplier: constraint.multiplier,
constant: constraint.constant)
newConstraints.append(newConstraint)
} else if let item: UIView = constraint.secondItem as? UIView {
if item == containerView {
let newConstraint = NSLayoutConstraint(
item: constraint.firstItem,
attribute: constraint.firstAttribute,
relatedBy: constraint.relation,
toItem: anAnimationView,
attribute: constraint.secondAttribute,
multiplier: constraint.multiplier,
constant: constraint.constant)
newConstraints.append(newConstraint)
}
}
}
}
self.contentView.addConstraints(newConstraints)
for constraint in containerView.constraints { // added height constraint
if constraint.firstAttribute == .Height {
let newConstraint = NSLayoutConstraint(
item: anAnimationView,
attribute: constraint.firstAttribute,
relatedBy: constraint.relation,
toItem: nil,
attribute: constraint.secondAttribute,
multiplier: constraint.multiplier,
constant: constraint.constant)
anAnimationView.addConstraint(newConstraint)
}
}
animationView = anAnimationView
}
func addImageItemsToAnimationView() {
containerView.alpha = 1;
// added first item
var image = containerView.pb_takeSnapshot(CGRect(x: 0, y: 0, width: containerView.bounds.size.width, height: foregroundView.bounds.size.height))
var imageView = UIImageView(image: image)
imageView.tag = 0
imageView.layer.cornerRadius = foregroundView.layer.cornerRadius
animationView?.addSubview(imageView)
// added secod item
image = containerView.pb_takeSnapshot(
CGRect(x: 0,
y: foregroundView.bounds.size.height,
width: containerView.bounds.size.width,
height: foregroundView.bounds.size.height))
imageView = UIImageView(image: image)
let rotatedView = RotatedView(frame: imageView.frame)
rotatedView.tag = 1
rotatedView.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0)
rotatedView.layer.transform = rotatedView.transform3d()
rotatedView.addSubview(imageView)
animationView?.addSubview(rotatedView)
rotatedView.frame = CGRect(x: imageView.frame.origin.x,
y: foregroundView.bounds.size.height,
width: containerView.bounds.size.width,
height: foregroundView.bounds.size.height)
// added other views
let itemHeight = (containerView.bounds.size.height - 2 * foregroundView.bounds.size.height) / CGFloat(itemCount - 2)
if itemCount == 2 {
// decrease containerView height or increase itemCount
assert(containerView.bounds.size.height - 2 * foregroundView.bounds.size.height == 0, "contanerView.height too high")
}
// decrease containerView height or increase itemCount
assert(containerView.bounds.size.height - 2 * foregroundView.bounds.size.height >= itemHeight, "contanerView.height too high")
var yPosition = 2 * foregroundView.bounds.size.height
var tag = 2
for var index = 2; index < itemCount; index++ {
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: yPosition, width: containerView.bounds.size.width, height: itemHeight))
imageView = UIImageView(image: image)
let rotatedView = RotatedView(frame: imageView.frame)
rotatedView.addSubview(imageView)
rotatedView.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0)
rotatedView.layer.transform = rotatedView.transform3d()
animationView?.addSubview(rotatedView)
rotatedView.frame = CGRect(x: 0, y: yPosition, width: rotatedView.bounds.size.width, height: itemHeight)
rotatedView.tag = tag
yPosition += itemHeight
tag++;
}
containerView.alpha = 0;
// added back view
var previusView: RotatedView?
for contener in animationView!.subviews.sort({ $0.tag < $1.tag }) {
if contener is RotatedView && contener.tag > 0 && contener.tag < animationView!.subviews.count {
let rotatedView = contener as! RotatedView
previusView?.addBackView(rotatedView.bounds.size.height, color: backViewColor)
previusView = rotatedView
}
}
animationItemViews = createAnimationItemView()
}
// MARK: public
public func selectedAnimation(isSelected: Bool, animated: Bool, completion: CompletionHandler?) {
if isSelected {
if animated {
containerView.alpha = 0;
openAnimation(completion: completion)
} else {
foregroundView.alpha = 0
containerView.alpha = 1;
}
view.alpha = 0
} else {
if animated {
closeAnimation(completion: completion)
} else {
foregroundView.alpha = 1;
containerView.alpha = 0;
}
view.alpha = 1
view.backView?.alpha = 0
}
}
}
}
func createAnimationView() {
public func isAnimating()->Bool {
guard animationItemViews != nil
else {
return false
}
let anAnimationView = UIView(frame: containerView.frame)
anAnimationView.layer.cornerRadius = foregroundView.layer.cornerRadius
anAnimationView.backgroundColor = UIColor.clearColor()
anAnimationView.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(anAnimationView)
// copy constraints from containerView
var newConstraints = [NSLayoutConstraint]()
for constraint in self.contentView.constraints {
if let item = constraint.firstItem as? UIView where item == containerView {
let newConstraint = NSLayoutConstraint( item: anAnimationView, attribute: constraint.firstAttribute,
relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute,
multiplier: constraint.multiplier, constant: constraint.constant)
for item in animationItemViews! {
if item.layer.animationKeys()?.count > 0 {
return true
}
}
return false
}
// MARK: animations
public func animationDuration(itemIndex:NSInteger, type:AnimationType)-> NSTimeInterval {
assert(false, "added this method to cell")
return 0
}
func durationSequence(type: AnimationType)-> [NSTimeInterval] {
var durations = [NSTimeInterval]()
for var index = 0; index < itemCount-1; index++ {
let duration = animationDuration(index, type: .Open)
durations.append(NSTimeInterval(duration / 2.0))
durations.append(NSTimeInterval(duration / 2.0))
}
return durations
}
func openAnimation(completion completion: CompletionHandler?) {
newConstraints.append(newConstraint)
} else if let item: UIView = constraint.secondItem as? UIView where item == containerView {
let newConstraint = NSLayoutConstraint(item: constraint.firstItem, attribute: constraint.firstAttribute,
relatedBy: constraint.relation, toItem: anAnimationView, attribute: constraint.secondAttribute,
multiplier: constraint.multiplier, constant: constraint.constant)
if animationView?.subviews.count == 0 { // added animation items if need
addImageItemsToAnimationView()
}
newConstraints.append(newConstraint)
}
}
self.contentView.addConstraints(newConstraints)
for constraint in containerView.constraints { // added height constraint
if constraint.firstAttribute == .Height {
let newConstraint = NSLayoutConstraint(item: anAnimationView, attribute: constraint.firstAttribute,
relatedBy: constraint.relation, toItem: nil, attribute: constraint.secondAttribute,
multiplier: constraint.multiplier, constant: constraint.constant)
animationView?.alpha = 1;
anAnimationView.addConstraint(newConstraint)
}
}
animationView = anAnimationView
}
func addImageItemsToAnimationView() {
containerView.alpha = 1;
let contSize = containerView.bounds.size
let forgSize = foregroundView.bounds.size
// added first item
var image = containerView.pb_takeSnapshot(CGRect(x: 0, y: 0, width: contSize.width, height: forgSize.height))
var imageView = UIImageView(image: image)
imageView.tag = 0
imageView.layer.cornerRadius = foregroundView.layer.cornerRadius
animationView?.addSubview(imageView)
// added secod item
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: forgSize.height, width: contSize.width, height: forgSize.height))
imageView = UIImageView(image: image)
let rotatedView = RotatedView(frame: imageView.frame)
rotatedView.tag = 1
rotatedView.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0)
rotatedView.layer.transform = rotatedView.transform3d()
rotatedView.addSubview(imageView)
animationView?.addSubview(rotatedView)
rotatedView.frame = CGRect(x: imageView.frame.origin.x, y: forgSize.height, width: contSize.width, height: forgSize.height)
// added other views
let itemHeight = (contSize.height - 2 * forgSize.height) / CGFloat(itemCount - 2)
if itemCount == 2 {
// decrease containerView height or increase itemCount
assert(contSize.height - 2 * forgSize.height == 0, "contanerView.height too high")
}
// decrease containerView height or increase itemCount
assert(contSize.height - 2 * forgSize.height >= itemHeight, "contanerView.height too high")
var yPosition = 2 * forgSize.height
var tag = 2
for _ in 2..<itemCount {
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: yPosition, width: contSize.width, height: itemHeight))
imageView = UIImageView(image: image)
let rotatedView = RotatedView(frame: imageView.frame)
rotatedView.addSubview(imageView)
rotatedView.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0)
rotatedView.layer.transform = rotatedView.transform3d()
animationView?.addSubview(rotatedView)
rotatedView.frame = CGRect(x: 0, y: yPosition, width: rotatedView.bounds.size.width, height: itemHeight)
rotatedView.tag = tag
yPosition += itemHeight
tag += 1;
}
containerView.alpha = 0;
if let animationView = self.animationView {
// added back view
var previusView: RotatedView?
for case let contener as RotatedView in animationView.subviews.sort({ $0.tag < $1.tag })
where contener.tag > 0 && contener.tag < animationView.subviews.count {
previusView?.addBackView(contener.bounds.size.height, color: backViewColor)
previusView = contener
}
}
animationItemViews = createAnimationItemView()
}
private func removeImageItemsFromAnimationView() {
guard let animationView = self.animationView else {
return
}
animationView.subviews.forEach({ $0.removeFromSuperview() })
}
// MARK: public
public func selectedAnimation(isSelected: Bool, animated: Bool, completion: CompletionHandler?) {
if isSelected {
if animated {
containerView.alpha = 0;
let durations = durationSequence(.Open)
var delay: NSTimeInterval = 0
var timing = kCAMediaTimingFunctionEaseIn
var from: CGFloat = 0.0;
var to: CGFloat = CGFloat(-M_PI / 2)
var hidden = true
configureAnimationItems(.Open)
for var index = 0; index < animationItemViews?.count; index++ {
let animatedView = animationItemViews![index]
animatedView.foldingAnimation(timing, from: from, to: to, duration: durations[index], delay: delay, hidden: hidden)
from = from == 0.0 ? CGFloat(M_PI / 2) : 0.0;
to = to == 0.0 ? CGFloat(-M_PI / 2) : 0.0;
timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn;
hidden = !hidden
delay += durations[index]
}
let firstItemView = animationView!.subviews.filter{$0.tag == 0}.first
firstItemView!.layer.masksToBounds = true
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(durations[0] * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
firstItemView!.layer.cornerRadius = 0
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
self.animationView?.alpha = 0
self.containerView.alpha = 1
completion?()
}
openAnimation(completion: completion)
} else {
foregroundView.alpha = 0
containerView.alpha = 1;
}
} else {
if animated {
closeAnimation(completion: completion)
} else {
foregroundView.alpha = 1;
containerView.alpha = 0;
}
}
}
public func isAnimating()->Bool {
guard let animationItemViews = self.animationItemViews else {
return false
}
func closeAnimation(completion completion: CompletionHandler?) {
if animationView?.subviews.count == 0 { // added animation items if need
addImageItemsToAnimationView()
}
animationView?.alpha = 1;
containerView.alpha = 0;
var durations = durationSequence(.Close)
durations = durations.reverse()
var delay: NSTimeInterval = 0
var timing = kCAMediaTimingFunctionEaseIn
var from: CGFloat = 0.0;
var to: CGFloat = CGFloat(M_PI / 2)
var hidden = true
configureAnimationItems(.Close)
for var index = 0; index < animationItemViews?.count; index++ {
let animatedView = animationItemViews?.reverse()[index]
animatedView!.foldingAnimation(timing, from: from, to: to, duration: durations[index], delay: delay, hidden: hidden)
to = to == 0.0 ? CGFloat(M_PI / 2) : 0.0;
from = from == 0.0 ? CGFloat(-M_PI / 2) : 0.0;
timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn;
hidden = !hidden
delay += durations[index]
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
self.animationView!.alpha = 0
completion?()
}
let firstItemView = animationView!.subviews.filter{$0.tag == 0}.first
firstItemView!.layer.masksToBounds = false
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((delay - durations.last! * 1.5) * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
firstItemView!.layer.cornerRadius = self.foregroundView.layer.cornerRadius
}
for item in animationItemViews {
if item.layer.animationKeys()?.count > 0 {
return true
}
}
if animationView?.alpha == 1 {
return true
}
return false
}
// MARK: animations
public func animationDuration(itemIndex:NSInteger, type:AnimationType)-> NSTimeInterval {
assert(false, "added this method to cell")
return 0
}
func durationSequence(type: AnimationType)-> [NSTimeInterval] {
var durations = [NSTimeInterval]()
for index in 0..<itemCount-1 {
let duration = animationDuration(index, type: .Open)
durations.append(NSTimeInterval(duration / 2.0))
durations.append(NSTimeInterval(duration / 2.0))
}
return durations
}
func openAnimation(completion completion: CompletionHandler?) {
removeImageItemsFromAnimationView()
addImageItemsToAnimationView()
guard let animationView = self.animationView else {
return
}
animationView.alpha = 1;
containerView.alpha = 0;
let durations = durationSequence(.Open)
var delay: NSTimeInterval = 0
var timing = kCAMediaTimingFunctionEaseIn
var from: CGFloat = 0.0;
var to: CGFloat = CGFloat(-M_PI / 2)
var hidden = true
configureAnimationItems(.Open)
guard let animationItemViews = self.animationItemViews else {
return
}
for index in 0..<animationItemViews.count {
let animatedView = animationItemViews[index]
animatedView.foldingAnimation(timing, from: from, to: to, duration: durations[index], delay: delay, hidden: hidden)
from = from == 0.0 ? CGFloat(M_PI / 2) : 0.0;
to = to == 0.0 ? CGFloat(-M_PI / 2) : 0.0;
timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn;
hidden = !hidden
delay += durations[index]
}
let firstItemView = animationView.subviews.filter{$0.tag == 0}.first
if let first = firstItemView {
first.layer.masksToBounds = true
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(durations[0] * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
first.layer.cornerRadius = 0
}
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
self.animationView?.alpha = 0
self.containerView.alpha = 1
completion?()
}
}
func closeAnimation(completion completion: CompletionHandler?) {
removeImageItemsFromAnimationView()
addImageItemsToAnimationView()
guard let animationItemViews = self.animationItemViews else {
fatalError()
}
animationView?.alpha = 1;
containerView.alpha = 0;
var durations: [NSTimeInterval] = durationSequence(.Close).reverse()
var delay: NSTimeInterval = 0
var timing = kCAMediaTimingFunctionEaseIn
var from: CGFloat = 0.0;
var to: CGFloat = CGFloat(M_PI / 2)
var hidden = true
configureAnimationItems(.Close)
if durations.count < animationItemViews.count {
fatalError("wrong override func animationDuration(itemIndex:NSInteger, type:AnimationType)-> NSTimeInterval")
}
for index in 0..<animationItemViews.count {
let animatedView = animationItemViews.reverse()[index]
animatedView.foldingAnimation(timing, from: from, to: to, duration: durations[index], delay: delay, hidden: hidden)
to = to == 0.0 ? CGFloat(M_PI / 2) : 0.0;
from = from == 0.0 ? CGFloat(-M_PI / 2) : 0.0;
timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn;
hidden = !hidden
delay += durations[index]
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
if let animationView = self.animationView {
animationView.alpha = 0
}
completion?()
}
if let animationView = self.animationView {
let firstItemView = animationView.subviews.filter{$0.tag == 0}.first
firstItemView?.layer.cornerRadius = 0
if let durationLast = durations.last {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((delay - durationLast - durationLast / 2.0) * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
firstItemView?.layer.cornerRadius = self.foregroundView.layer.cornerRadius
}
}
}
}
}
// MARK: RotatedView
public class RotatedView: UIView {
var hiddenAfterAnimation = false
var backView: RotatedView?
var hiddenAfterAnimation = false
var backView: RotatedView?
func addBackView(height: CGFloat, color:UIColor) {
let view = RotatedView(frame: CGRect.zero)
view.backgroundColor = color
view.layer.anchorPoint = CGPoint.init(x: 0.5, y: 1)
view.layer.transform = view.transform3d()
view.translatesAutoresizingMaskIntoConstraints = false;
self.addSubview(view)
backView = view
func addBackView(height: CGFloat, color:UIColor) {
let view = RotatedView(frame: CGRect.zero)
view.backgroundColor = color
view.layer.anchorPoint = CGPoint.init(x: 0.5, y: 1)
view.layer.transform = view.transform3d()
view.translatesAutoresizingMaskIntoConstraints = false;
self.addSubview(view)
backView = view
view.addConstraint(NSLayoutConstraint(item: view,
attribute: .Height,
relatedBy: .Equal,
toItem: nil,
attribute: .Height,
multiplier: 1,
constant: height))
self.addConstraints([
NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: self.bounds.size.height - height + height / 2),
NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading, multiplier: 1, constant: 0),
NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1, constant: 0)
])
}
view.addConstraint(NSLayoutConstraint(item: view, attribute: .Height, relatedBy: .Equal, toItem: nil,attribute: .Height,
multiplier: 1, constant: height))
self.addConstraints([
NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1,
constant: self.bounds.size.height - height + height / 2),
NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading,
multiplier: 1, constant: 0),
NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing,
multiplier: 1, constant: 0)
])
}
}
extension RotatedView {
func rotatedX(angle : CGFloat) {
var allTransofrom = CATransform3DIdentity;
let rotateTransform = CATransform3DMakeRotation(angle, 1, 0, 0)
allTransofrom = CATransform3DConcat(allTransofrom, rotateTransform)
allTransofrom = CATransform3DConcat(allTransofrom, transform3d())
self.layer.transform = allTransofrom
}
func transform3d() -> CATransform3D {
var transform = CATransform3DIdentity
transform.m34 = 2.5 / -2000;
return transform
}
// MARK: animations
func foldingAnimation(timing: String, from: CGFloat, to: CGFloat, duration: NSTimeInterval, delay:NSTimeInterval, hidden:Bool) {
func rotatedX(angle : CGFloat) {
var allTransofrom = CATransform3DIdentity;
let rotateTransform = CATransform3DMakeRotation(angle, 1, 0, 0)
allTransofrom = CATransform3DConcat(allTransofrom, rotateTransform)
allTransofrom = CATransform3DConcat(allTransofrom, transform3d())
self.layer.transform = allTransofrom
}
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.x")
rotateAnimation.timingFunction = CAMediaTimingFunction(name: timing)
rotateAnimation.fromValue = (from)
rotateAnimation.toValue = (to)
rotateAnimation.duration = duration
rotateAnimation.delegate = self;
rotateAnimation.fillMode = kCAFillModeForwards
rotateAnimation.removedOnCompletion = false;
rotateAnimation.beginTime = CACurrentMediaTime() + delay
func transform3d()-> CATransform3D {
var transform = CATransform3DIdentity
transform.m34 = 2.5 / -2000;
return transform
}
self.hiddenAfterAnimation = hidden
// MARK: animations
func foldingAnimation(timing: String, from: CGFloat, to: CGFloat, duration: NSTimeInterval, delay:NSTimeInterval, hidden:Bool) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.x")
rotateAnimation.timingFunction = CAMediaTimingFunction(name: timing)
rotateAnimation.fromValue = (from)
rotateAnimation.toValue = (to)
rotateAnimation.duration = duration
rotateAnimation.delegate = self;
rotateAnimation.fillMode = kCAFillModeForwards;
rotateAnimation.removedOnCompletion = false;
rotateAnimation.beginTime = CACurrentMediaTime() + delay
self.hiddenAfterAnimation = hidden
self.layer.addAnimation(rotateAnimation, forKey: "rotation.x")
}
override public func animationDidStart(anim: CAAnimation) {
self.layer.shouldRasterize = true
self.alpha = 1
}
override public func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if hiddenAfterAnimation {
self.alpha = 0
}
self.layer.removeAllAnimations()
self.layer.shouldRasterize = false
self.rotatedX(CGFloat(0))
self.layer.addAnimation(rotateAnimation, forKey: "rotation.x")
}
override public func animationDidStart(anim: CAAnimation) {
self.layer.shouldRasterize = true
self.alpha = 1
}
override public func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if hiddenAfterAnimation {
self.alpha = 0
}
self.layer.removeAllAnimations()
self.layer.shouldRasterize = false
self.rotatedX(CGFloat(0))
}
}
extension UIView {
func pb_takeSnapshot(frame: CGRect) -> UIImage {
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0.0);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, frame.origin.x * -1, frame.origin.y * -1);
self.layer.renderInContext(UIGraphicsGetCurrentContext()!);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image
func pb_takeSnapshot(frame: CGRect) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0.0)
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, frame.origin.x * -1, frame.origin.y * -1)
guard let currentContext = UIGraphicsGetCurrentContext() else {
return nil
}
self.layer.renderInContext(currentContext)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
@@ -94,7 +94,7 @@ class MainTableViewController: UITableViewController {
} else {// close cell
cellHeights[indexPath.row] = kCloseCellHeight
cell.selectedAnimation(false, animated: true, completion: nil)
duration = 1.1
duration = 0.8
}
UIView.animateWithDuration(duration, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
@@ -0,0 +1,45 @@
//
// FoldingCellTests.swift
// FoldingCellTests
//
// Created by Alex K. on 25/01/16.
// Copyright © 2016 Alex K. All rights reserved.
//
import XCTest
class FoldingCellTests: XCTestCase {
var viewController : UITableViewController!
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
viewController = storyboard.instantiateViewControllerWithIdentifier("MainTableViewController") as! UITableViewController
viewController.beginAppearanceTransition(true, animated: false)
}
override func tearDown() {
viewController.endAppearanceTransition()
super.tearDown()
}
func testExample() {
let tableView = viewController.tableView
for case let cell as FoldingCell in tableView.visibleCells {
XCTAssertTrue(cell.itemCount >= 2)
}
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.
}
}
}
+24
View File
@@ -0,0 +1,24 @@
<?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>en</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>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
+22 -6
View File
@@ -1,8 +1,16 @@
![header](./header.png)
# FoldingCell
[![CocoaPods](https://img.shields.io/cocoapods/p/FoldingCell.svg)](https://cocoapods.org/pods/FoldingCell)
[![CocoaPods](https://img.shields.io/cocoapods/v/FoldingCell.svg)](http://cocoapods.org/pods/FoldingCell)
[![Twitter](https://img.shields.io/badge/Twitter-@Ramotion-blue.svg?style=flat)](http://twitter.com/Ramotion)
[![Travis](https://img.shields.io/travis/Ramotion/folding-cell.svg)](https://travis-ci.org/Ramotion/folding-cell)
[![codebeat badge](https://codebeat.co/badges/6f67da5d-c416-4bac-9fb7-c2dc938feedc)](https://codebeat.co/projects/github-com-ramotion-folding-cell)
[shot on dribbble](https://dribbble.com/shots/2121350-Delivery-Card):
![Animation](Screenshots/folding-cell.gif)
The [iPhone mockup](https://store.ramotion.com/product/iphone-6-mockups?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell) available [here](https://store.ramotion.com/product/iphone-6-mockups?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell).
## Requirements
- iOS 8.0+
@@ -14,7 +22,7 @@ Just add the FoldingCell.swift file to your project.
or use [CocoaPods](https://cocoapods.org) with Podfile:
``` ruby
pod 'FoldingCell', '~> 0.2'
pod 'FoldingCell', '~> 0.8.0'
```
@@ -43,7 +51,9 @@ property `containerView`. Add constraints from this view to the superview like i
Your result should be something like this picture:
![1.3](/Tutorial-resources/1.3.png)
4) Set ``` @IBInspectable var itemCount: NSInteger ``` property is a count of folding (it IBInspectable you can set in storyborad). range 2 or greater. Default value is 2
[Demonstration adding constraints for foregroundView, containerView](https://vimeo.com/154954299)
4) Set ``` @IBInspectable var itemCount: NSInteger ``` property is a count of folding (it IBInspectable you can set in storyboard). range 2 or greater. Default value is 2
Ok, we've finished configuring the cell.
@@ -126,9 +136,15 @@ Ok, we've finished configuring the cell.
}
```
## [About Us](http://ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell)
## Licence
[Ramotion - digital product design agency](http://ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell)
We are ready for new interesting iOS app development projects.
Folding cell is released under the MIT license.
See [LICENSE](./LICENSE) for details.
Follow us on [Twitter](http://twitter.com/ramotion).
## About
The project maintained by [app development agency](https://ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=foolding-cell) [Ramotion Inc.](https://ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=foolding-cell)
See our other [open-source projects](https://github.com/ramotion) or [hire](https://ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=foolding-cell) us to design, develop, and grow your product.
[![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=https://github.com/ramotion/foolding-cell)
[![Twitter Follow](https://img.shields.io/twitter/follow/ramotion.svg?style=social)](https://twitter.com/ramotion)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB