Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce1d4cd8bd | ||
|
|
0e87bcfc63 | ||
|
|
3bc71e84ee | ||
|
|
4f5a0ca337 | ||
|
|
ab8c7feee8 | ||
|
|
27913fd179 | ||
|
|
775c05a1d0 | ||
|
|
2953ca5342 | ||
|
|
16ba4b27b0 | ||
|
|
36c23cf714 | ||
|
|
d6e37f7f01 | ||
|
|
38fa225507 | ||
|
|
98352afdc7 | ||
|
|
e5c63c9812 | ||
|
|
4ec5646fa1 | ||
|
|
20d7be5ca0 | ||
|
|
0871b243b3 | ||
|
|
d41c599568 | ||
|
|
e720eaf3f3 | ||
|
|
4c3d646349 | ||
|
|
4d41164378 | ||
|
|
aa490544c2 | ||
|
|
835ff54cbb | ||
|
|
f65b92ffdf | ||
|
|
c6d63eb1e4 | ||
|
|
fa758c23a3 | ||
|
|
163f297fe9 | ||
|
|
93a228b087 | ||
|
|
b0f92dbe6b | ||
|
|
8d5eff7bfc | ||
|
|
00eee3a352 | ||
|
|
840cc0a1a3 | ||
|
|
7d18125ed5 | ||
|
|
a2226608b1 | ||
|
|
bc0fda8abb | ||
|
|
3bfd692759 | ||
|
|
230c28ad5e | ||
|
|
ac1c852b6c | ||
|
|
7dc02ae65f | ||
|
|
ab4b6f97a4 | ||
|
|
8961b01a9a |
@@ -0,0 +1,6 @@
|
||||
osx_image: xcode7.2
|
||||
language: objective-c
|
||||
|
||||
xcode_project: FoldingCell/FoldingCell.xcodeproj
|
||||
xcode_scheme: FoldingCell
|
||||
xcode_sdk: iphonesimulator
|
||||
@@ -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
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'FoldingCell'
|
||||
s.version = '0.2'
|
||||
s.version = '0.6'
|
||||
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 = 34MUF9YXTA;
|
||||
};
|
||||
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 */;
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "847A58031C294F750028FB84"
|
||||
BuildableName = "FoldingCell.app"
|
||||
BlueprintName = "FoldingCell"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8498513B1C5639F9006FA400"
|
||||
BuildableName = "FoldingCellTests.xctest"
|
||||
BlueprintName = "FoldingCellTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
<LocationScenarioReference
|
||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||
referenceType = "1">
|
||||
</LocationScenarioReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "847A58031C294F750028FB84"
|
||||
BuildableName = "FoldingCell.app"
|
||||
BlueprintName = "FoldingCell"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "847A58031C294F750028FB84"
|
||||
BuildableName = "FoldingCell.app"
|
||||
BlueprintName = "FoldingCell"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "847A58031C294F750028FB84"
|
||||
BuildableName = "FoldingCell.app"
|
||||
BlueprintName = "FoldingCell"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
+34
-13
@@ -14,9 +14,9 @@
|
||||
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>
|
||||
@@ -28,7 +28,26 @@
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8498513B1C5639F9006FA400"
|
||||
BuildableName = "FoldingCellTests.xctest"
|
||||
BlueprintName = "FoldingCellTests"
|
||||
ReferencedContainer = "container:FoldingCell.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "847A58031C294F750028FB84"
|
||||
BuildableName = "FoldingCell.app"
|
||||
BlueprintName = "FoldingCell"
|
||||
ReferencedContainer = "container:FoldingCell.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
@@ -42,15 +61,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 +80,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">
|
||||
@@ -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"/>
|
||||
|
||||
@@ -24,457 +24,468 @@
|
||||
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 var itemCount: NSInteger = 2 //count of folding
|
||||
|
||||
@IBInspectable 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() {
|
||||
let anAnimationView = UIView(frame: containerView.frame)
|
||||
anAnimationView.layer.cornerRadius = foregroundView.layer.cornerRadius
|
||||
anAnimationView.backgroundColor = UIColor.clearColor()
|
||||
anAnimationView.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.contentView.addSubview(anAnimationView)
|
||||
|
||||
public func isAnimating()->Bool {
|
||||
guard animationItemViews != nil
|
||||
else {
|
||||
return false
|
||||
}
|
||||
// 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 var index = 2; index < itemCount; index++ {
|
||||
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++;
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
// 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 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?) {
|
||||
|
||||
if animationView?.subviews.count == 0 { // added animation items if need
|
||||
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 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
|
||||
|
||||
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?) {
|
||||
|
||||
if animationView?.subviews.count == 0 { // added animation items if need
|
||||
addImageItemsToAnimationView()
|
||||
}
|
||||
|
||||
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)
|
||||
for var index = 0; index < animationItemViews?.count; index++ {
|
||||
|
||||
guard let animatedView = animationItemViews?.reverse()[index] else {
|
||||
continue
|
||||
}
|
||||
|
||||
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.masksToBounds = false
|
||||
if let durationLast = durations.last {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64((delay - durationLast * 1.5) * 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
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
@@ -1,4 +1,9 @@
|
||||
# FoldingCell
|
||||
[](https://cocoapods.org/pods/FoldingCell)
|
||||
[](http://cocoapods.org/pods/FoldingCell)
|
||||
[](http://twitter.com/Ramotion)
|
||||
[](https://travis-ci.org/Ramotion/folding-cell)
|
||||
[](https://codebeat.co/projects/github-com-ramotion-folding-cell)
|
||||
|
||||
[shot on dribbble](https://dribbble.com/shots/2121350-Delivery-Card):
|
||||

|
||||
@@ -14,7 +19,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.6'
|
||||
```
|
||||
|
||||
|
||||
@@ -43,7 +48,9 @@ property `containerView`. Add constraints from this view to the superview like i
|
||||
Your result should be something like this picture:
|
||||

|
||||
|
||||
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 +133,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.
|
||||
|
||||
[](https://twitter.com/intent/tweet?text=https://github.com/ramotion/foolding-cell)
|
||||
[](https://twitter.com/ramotion)
|
||||
|
||||
Reference in New Issue
Block a user