├── .gitignore
├── .idea
├── caches
│ └── build_file_checksums.ser
├── codeStyles
│ └── Project.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── freeankit
│ │ └── foldinganimation
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── freeankit
│ │ │ └── foldinganimation
│ │ │ ├── ListActivity.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── SampleAdapter.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_list.xml
│ │ ├── activity_main.xml
│ │ └── recyclerview_item.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── freeankit
│ └── foldinganimation
│ └── ExampleUnitTest.kt
├── art
├── animationgif.gif
└── video.mp4
├── build.gradle
├── foldingkit
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── freeankit
│ │ └── foldingit
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── cogitator
│ │ │ └── foldingit
│ │ │ ├── FoldingKit.kt
│ │ │ ├── animation
│ │ │ ├── AnimationEndListener.kt
│ │ │ ├── FoldAnimation.kt
│ │ │ └── HeightAnimation.kt
│ │ │ └── views
│ │ │ └── FoldingKitView.kt
│ └── res
│ │ └── values
│ │ ├── attrs.xml
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── freeankit
│ └── foldingit
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/caches/build_file_checksums.ser:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/.idea/caches/build_file_checksums.ser
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FoldingAnimationKotlin-Android
2 |
3 | An Android library to allow developers to give folding animations to the views using Kotlin.
4 |
5 | ### I have written a [Medium Post here](https://goo.gl/2erWmn) on it.
6 |
7 | # Add dependency to your project
8 |
9 | - if using maven
10 |
11 |
12 | com.cogitator.foldingkit
13 | foldingkit
14 | 1.0.0
15 | pom
16 |
17 |
18 | - in app level build.gradle latest version
19 |
20 | implementation 'com.cogitator.foldingkit:foldingkit:1.1.0'
21 |
22 |
23 |
24 |
25 |
26 | ##### credits for inspiration
27 | - [Ramotion's Folding Cell](https://github.com/Ramotion/folding-cell)
28 |
29 |
30 | ### Would you like to buy me a cup of coffee?
31 | #### I'd appreciate even your little contribution to my work, it helps me keep this Open Source updated. If this project helped you or your business and if you feel like donating some bucks, you can Paypal me - ankitdroiddeveloper@gmail.com
32 |
33 |
34 |
35 | ### Contact - Let's connect to learn together
36 | - [Twitter](https://twitter.com/KumarAnkitRKE)
37 | - [Github](https://github.com/AnkitDroidGit)
38 | - [LinkedIn](https://www.linkedin.com/in/kumarankitkumar/)
39 | - [Facebook](https://www.facebook.com/freeankit)
40 | - [Slack](https://ankitdroid.slack.com)
41 | - [Stackoverflow](https://stackoverflow.com/users/3282461/android)
42 | - [Android App](https://play.google.com/store/apps/details?id=com.freeankit.ankitprofile)
43 |
44 |
45 | ### License
46 |
47 | Copyright 2018 Ankit Kumar
48 |
49 | Licensed under the Apache License, Version 2.0 (the "License");
50 | you may not use this file except in compliance with the License.
51 | You may obtain a copy of the License at
52 |
53 | http://www.apache.org/licenses/LICENSE-2.0
54 |
55 | Unless required by applicable law or agreed to in writing, software
56 | distributed under the License is distributed on an "AS IS" BASIS,
57 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
58 | See the License for the specific language governing permissions and
59 | limitations under the License.
60 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 28
9 | defaultConfig {
10 | applicationId "com.freeankit.foldinganimation"
11 | minSdkVersion 21
12 | targetSdkVersion 28
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
28 | implementation 'com.android.support:appcompat-v7:28.0.0'
29 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
30 | implementation 'com.android.support:recyclerview-v7:28.0.0'
31 | implementation 'com.android.support:cardview-v7:28.0.0'
32 | testImplementation 'junit:junit:4.12'
33 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
35 |
36 | implementation project(':foldingkit')
37 | }
38 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/freeankit/foldinganimation/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldinganimation
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.freeankit.foldinganimation", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/freeankit/foldinganimation/ListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldinganimation
2 |
3 | import android.os.Bundle
4 | import android.support.v7.app.AppCompatActivity
5 | import android.support.v7.widget.LinearLayoutManager
6 | import kotlinx.android.synthetic.main.activity_list.*
7 |
8 | /**
9 | * @author Ankit Kumar (ankitdroiddeveloper@gmail.com) on 18/05/2018 (MM/DD/YYYY)
10 | */
11 | class ListActivity : AppCompatActivity() {
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContentView(R.layout.activity_list)
15 |
16 | recyclerview.apply {
17 | setHasFixedSize(true)
18 | recyclerview.layoutManager = LinearLayoutManager(this@ListActivity)
19 | recyclerview.adapter = SampleAdapter()
20 | }
21 |
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/freeankit/foldinganimation/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldinganimation
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.support.v7.app.AppCompatActivity
6 | import kotlinx.android.synthetic.main.activity_main.*
7 | import kotlinx.android.synthetic.main.recyclerview_item.*
8 |
9 |
10 | class MainActivity : AppCompatActivity() {
11 |
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContentView(R.layout.activity_main)
15 | // get our folding cell
16 |
17 | // attach click listener to fold btn
18 | toggle_btn.setOnClickListener({
19 | folding_cell.toggle(false)
20 | })
21 |
22 | // attach click listener to toast btn
23 | toggle_instant_btn.setOnClickListener({
24 | folding_cell.toggle(true)
25 | })
26 | see_list.setOnClickListener({
27 | startActivity(Intent(this, ListActivity::class.java))
28 | })
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/freeankit/foldinganimation/SampleAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldinganimation
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import kotlinx.android.synthetic.main.recyclerview_item.view.*
8 |
9 |
10 | /**
11 | * @author Ankit Kumar (ankitdroiddeveloper@gmail.com) on 20/05/2018 (MM/DD/YYYY)
12 | */
13 | class SampleAdapter : RecyclerView.Adapter() {
14 |
15 | val unfoldedIndexes = HashSet()
16 |
17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
18 | val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_item, parent, false)
19 | return ViewHolder(view)
20 | }
21 |
22 | override fun getItemCount(): Int {
23 | return 10
24 | }
25 |
26 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
27 | holder.bind(position)
28 | }
29 |
30 | inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
31 | fun bind(position: Int) = with(itemView) {
32 |
33 | // folding_cell.setBackgroundColor(resources.getColor(R.color.colorPrimary))
34 | folding_cell.backSideColor = resources.getColor(R.color.colorPrimary)
35 |
36 | if (unfoldedIndexes.contains(position)) {
37 | cell_title_view.visibility = View.GONE
38 | cell_content_view.visibility = View.VISIBLE
39 | } else {
40 | cell_content_view.visibility = View.GONE
41 | cell_title_view.visibility = View.VISIBLE
42 | }
43 |
44 | itemView.setOnClickListener {
45 | // toggle clicked cell state
46 | folding_cell.toggle(false)
47 | // register in adapter that state for selected cell is toggled
48 | registerToggle(position)
49 | }
50 | }
51 |
52 | private fun registerToggle(position: Int) {
53 | if (unfoldedIndexes.contains(position))
54 | registerFold(position)
55 | else
56 | registerUnfold(position)
57 | }
58 |
59 | private fun registerFold(position: Int) {
60 | unfoldedIndexes.remove(position)
61 | }
62 |
63 | private fun registerUnfold(position: Int) {
64 | unfoldedIndexes.add(position)
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
25 |
26 |
31 |
32 |
37 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/recyclerview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
20 |
21 |
25 |
26 |
32 |
33 |
39 |
40 |
46 |
47 |
53 |
54 |
60 |
61 |
62 |
63 |
64 |
71 |
72 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Folding Animation
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/freeankit/foldinganimation/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldinganimation
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/art/animationgif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/art/animationgif.gif
--------------------------------------------------------------------------------
/art/video.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/art/video.mp4
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.0'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.1'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 |
13 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4'
14 | classpath "com.github.dcendents:android-maven-gradle-plugin:1.5"
15 |
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | google()
24 | jcenter()
25 | }
26 | }
27 |
28 | task clean(type: Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/foldingkit/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/foldingkit/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 |
4 | apply plugin: 'com.jfrog.bintray'
5 | apply plugin: 'com.github.dcendents.android-maven'
6 |
7 |
8 | group = 'com.cogitator.foldingkit'
9 | version = '1.1.0'
10 |
11 | android {
12 | compileSdkVersion 28
13 | defaultConfig {
14 | minSdkVersion 19
15 | targetSdkVersion 28
16 | versionCode 1
17 | versionName "1.0"
18 |
19 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
20 |
21 | }
22 |
23 | buildTypes {
24 | release {
25 | minifyEnabled false
26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 |
30 | }
31 |
32 | dependencies {
33 | implementation fileTree(dir: 'libs', include: ['*.jar'])
34 |
35 | implementation 'com.android.support:appcompat-v7:28.0.0'
36 | testImplementation 'junit:junit:4.12'
37 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
38 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
39 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
40 | }
41 | repositories {
42 | mavenCentral()
43 | }
44 | task generateSourcesJar(type: Jar) {
45 | from android.sourceSets.main.java.srcDirs
46 | classifier 'sources'
47 | }
48 |
49 | task generateJavadocs(type: Javadoc) {
50 | source = android.sourceSets.main.java.srcDirs
51 | classpath += project.files(android.getBootClasspath()
52 | .join(File.pathSeparator))
53 | }
54 |
55 | task generateJavadocsJar(type: Jar) {
56 | from generateJavadocs.destinationDir
57 | classifier 'javadoc'
58 | }
59 |
60 | generateJavadocsJar.dependsOn generateJavadocs
61 |
62 | artifacts {
63 | archives generateSourcesJar
64 | }
65 | def siteUrl = 'https://github.com/AnkitDroidGit/FoldingAnimationKotlin-Android'
66 | def gitUrl = 'https://github.com/AnkitDroidGit/FoldingAnimationKotlin-Android'
67 | Properties properties = new Properties()
68 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
69 | bintray {
70 | user = properties.getProperty("bintray.user")
71 | key = properties.getProperty("bintray.api")
72 | configurations = ['archives']
73 | pkg {
74 | repo = "FoldingKit"
75 | name = "FoldingKit"
76 | websiteUrl = siteUrl
77 | vcsUrl = gitUrl
78 | licenses = ["Apache-2.0"]
79 | publish = true
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/foldingkit/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/foldingkit/src/androidTest/java/com/freeankit/foldingit/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldingit;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.freeankit.foldingit.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/foldingkit/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/foldingkit/src/main/java/com/cogitator/foldingit/FoldingKit.kt:
--------------------------------------------------------------------------------
1 | package com.cogitator.foldingit
2 |
3 | import android.content.Context
4 | import android.graphics.Bitmap
5 | import android.graphics.Canvas
6 | import android.graphics.Color
7 | import android.graphics.Rect
8 | import android.util.AttributeSet
9 | import android.view.View
10 | import android.view.ViewGroup
11 | import android.view.animation.Animation
12 | import android.view.animation.DecelerateInterpolator
13 | import android.widget.ImageView
14 | import android.widget.LinearLayout
15 | import android.widget.RelativeLayout
16 | import com.cogitator.foldingit.animation.AnimationEndListener
17 | import com.cogitator.foldingit.animation.FoldAnimation
18 | import com.cogitator.foldingit.animation.HeightAnimation
19 | import com.cogitator.foldingit.views.FoldingKitView
20 | import com.freeankit.foldingit.R
21 | import java.util.*
22 |
23 | /**
24 | * Created by ankit on 26/01/2018.
25 | */
26 |
27 | open class FoldingKit : RelativeLayout {
28 |
29 | private val TAG = "FoldingKit"
30 |
31 | // state variables
32 | var isUnfolded: Boolean = false
33 | private set
34 | private var mAnimationInProgress: Boolean = false
35 |
36 | // default values
37 | private val DEF_ANIMATION_DURATION = 1000
38 | private val DEF_BACK_SIDE_COLOR = Color.GRAY
39 | private val DEF_ADDITIONAL_FLIPS = 0
40 | private val DEF_CAMERA_HEIGHT = 30
41 |
42 | // current settings
43 | public var animationDuration = DEF_ANIMATION_DURATION
44 | public var backSideColor = DEF_BACK_SIDE_COLOR
45 | public var additionalFlipsCount = DEF_ADDITIONAL_FLIPS
46 | private var mCameraHeight = DEF_CAMERA_HEIGHT
47 |
48 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
49 | initializeFromAttributes(context, attrs)
50 | this.clipChildren = false
51 | this.clipToPadding = false
52 | }
53 |
54 | constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
55 | initializeFromAttributes(context, attrs)
56 | this.clipChildren = false
57 | this.clipToPadding = false
58 | }
59 |
60 | constructor(context: Context) : super(context) {
61 | this.clipChildren = false
62 | this.clipToPadding = false
63 | }
64 |
65 | /**
66 | * Initializes folding cell programmatically with custom settings
67 | *
68 | * @param animationDuration animation duration, default is 1000
69 | * @param backSideColor color of back side, default is android.graphics.Color.GREY (0xFF888888)
70 | * @param additionalFlipsCount count of additional flips (after first one), set 0 for auto
71 | */
72 | fun initialize(animationDuration: Int, backSideColor: Int, additionalFlipsCount: Int) {
73 | this.animationDuration = animationDuration
74 | this.backSideColor = backSideColor
75 | this.additionalFlipsCount = additionalFlipsCount
76 | }
77 |
78 | /**
79 | * Initializes folding cell programmatically with custom settings
80 | *
81 | * @param animationDuration animation duration, default is 1000
82 | * @param backSideColor color of back side, default is android.graphics.Color.GREY (0xFF888888)
83 | * @param additionalFlipsCount count of additional flips (after first one), set 0 for auto
84 | */
85 | fun initialize(cameraHeight: Int, animationDuration: Int, backSideColor: Int, additionalFlipsCount: Int) {
86 | this.animationDuration = animationDuration
87 | this.backSideColor = backSideColor
88 | this.additionalFlipsCount = additionalFlipsCount
89 | this.mCameraHeight = cameraHeight
90 | }
91 |
92 | /**
93 | * Unfold cell with (or without) animation
94 | *
95 | * @param skipAnimation if true - change state of cell instantly without animation
96 | */
97 | private fun unfold(skipAnimation: Boolean) {
98 | if (isUnfolded || mAnimationInProgress) return
99 |
100 | // get main content parts
101 | val contentView = getChildAt(0) ?: return
102 | val titleView = getChildAt(1) ?: return
103 |
104 | // hide title and content views
105 | titleView.visibility = View.GONE
106 | contentView.visibility = View.GONE
107 |
108 | // Measure views and take a bitmaps to replace real views with images
109 | val bitmapFromTitleView = measureViewAndGetBitmap(titleView, this.measuredWidth)
110 | val bitmapFromContentView = measureViewAndGetBitmap(contentView, this.measuredWidth)
111 |
112 | if (skipAnimation) {
113 | contentView.visibility = View.VISIBLE
114 | this@FoldingKit.isUnfolded = true
115 | this@FoldingKit.mAnimationInProgress = false
116 | this.layoutParams.height = contentView.height
117 | } else {
118 | // create layout container for animation elements
119 | val foldingLayout = createAndPrepareFoldingContainer()
120 | this.addView(foldingLayout)
121 | // calculate heights of animation parts
122 | val heights = calculateHeightsForAnimationParts(titleView.height, contentView.height, additionalFlipsCount)
123 | // create list with animation parts for animation
124 | val foldingCellElements = prepareViewsForAnimation(heights, bitmapFromTitleView, bitmapFromContentView)
125 | // start unfold animation with end listener
126 | val childCount = foldingCellElements.size
127 | val part90degreeAnimationDuration = animationDuration / (childCount * 2)
128 | startUnfoldAnimation(foldingCellElements, foldingLayout, part90degreeAnimationDuration, object : AnimationEndListener() {
129 | override fun onAnimationEnd(animation: Animation?) {
130 | contentView.visibility = View.VISIBLE
131 | foldingLayout.visibility = View.GONE
132 | this@FoldingKit.removeView(foldingLayout)
133 | this@FoldingKit.isUnfolded = true
134 | this@FoldingKit.mAnimationInProgress = false
135 | }
136 | })
137 |
138 | startExpandHeightAnimation(heights, part90degreeAnimationDuration * 2)
139 | this.mAnimationInProgress = true
140 | }
141 |
142 | }
143 |
144 | /**
145 | * Fold cell with (or without) animation
146 | *
147 | * @param skipAnimation if true - change state of cell instantly without animation
148 | */
149 | private fun fold(skipAnimation: Boolean) {
150 | if (!isUnfolded || mAnimationInProgress) return
151 |
152 | // get basic views
153 | val contentView = getChildAt(0) ?: return
154 | val titleView = getChildAt(1) ?: return
155 |
156 | // hide title and content views
157 | titleView.visibility = View.GONE
158 | contentView.visibility = View.GONE
159 |
160 | // make bitmaps from title and content views
161 | val bitmapFromTitleView = measureViewAndGetBitmap(titleView, this.measuredWidth)
162 | val bitmapFromContentView = measureViewAndGetBitmap(contentView, this.measuredWidth)
163 |
164 | if (skipAnimation) {
165 | contentView.visibility = View.GONE
166 | titleView.visibility = View.VISIBLE
167 | this@FoldingKit.mAnimationInProgress = false
168 | this@FoldingKit.isUnfolded = false
169 | this.layoutParams.height = titleView.height
170 | } else {
171 |
172 | // create empty layout for folding animation
173 | val foldingLayout = createAndPrepareFoldingContainer()
174 | // add that layout to structure
175 | this.addView(foldingLayout)
176 |
177 | // calculate heights of animation parts
178 | val heights = calculateHeightsForAnimationParts(titleView.height, contentView.height, additionalFlipsCount)
179 | // create list with animation parts for animation
180 | val foldingCellElements = prepareViewsForAnimation(heights, bitmapFromTitleView, bitmapFromContentView)
181 | val childCount = foldingCellElements.size
182 | val part90degreeAnimationDuration = animationDuration / (childCount * 2)
183 | // start fold animation with end listener
184 | startFoldAnimation(foldingCellElements, foldingLayout, part90degreeAnimationDuration, object : AnimationEndListener() {
185 | override fun onAnimationEnd(animation: Animation?) {
186 | contentView.visibility = View.GONE
187 | titleView.visibility = View.VISIBLE
188 | foldingLayout.visibility = View.GONE
189 | this@FoldingKit.removeView(foldingLayout)
190 | this@FoldingKit.mAnimationInProgress = false
191 | this@FoldingKit.isUnfolded = false
192 | }
193 | })
194 | startCollapseHeightAnimation(heights, part90degreeAnimationDuration * 2)
195 | this.mAnimationInProgress = true
196 | }
197 |
198 |
199 | }
200 |
201 |
202 | /**
203 | * Toggle current state of FoldingCellLayout
204 | */
205 | fun toggle(skipAnimation: Boolean) {
206 | if (this.isUnfolded) {
207 | this.fold(skipAnimation)
208 | } else {
209 | this.unfold(skipAnimation)
210 | this.requestLayout()
211 | }
212 | }
213 |
214 | /**
215 | * Create and prepare list of FoldingCellViews with different bitmap parts for fold animation
216 | *
217 | * @param titleViewBitmap bitmap from title view
218 | * @param contentViewBitmap bitmap from content view
219 | * @return list of FoldingCellViews with bitmap parts
220 | */
221 | private fun prepareViewsForAnimation(viewHeights: List, titleViewBitmap: Bitmap, contentViewBitmap: Bitmap): List {
222 | if (viewHeights.isEmpty())
223 | throw IllegalStateException("ViewHeights array must be not null and not empty")
224 |
225 | val partsList = ArrayList()
226 |
227 | val partWidth = titleViewBitmap.width
228 | var yOffset = 0
229 | for (i in viewHeights.indices) {
230 | val partHeight = viewHeights[i]
231 | val partBitmap = Bitmap.createBitmap(partWidth, partHeight, Bitmap.Config.ARGB_8888)
232 | val canvas = Canvas(partBitmap)
233 | val srcRect = Rect(0, yOffset, partWidth, yOffset + partHeight)
234 | val destRect = Rect(0, 0, partWidth, partHeight)
235 | canvas.drawBitmap(contentViewBitmap, srcRect, destRect, null)
236 | val backView = createImageViewFromBitmap(partBitmap)
237 | var frontView: ImageView? = null
238 | if (i < viewHeights.size - 1) {
239 | frontView = if (i == 0) createImageViewFromBitmap(titleViewBitmap) else createBackSideView(viewHeights[i + 1])
240 | }
241 | frontView?.let { FoldingKitView(it, backView, context) }?.let { partsList.add(it) }
242 | yOffset += partHeight
243 | }
244 |
245 | return partsList
246 | }
247 |
248 | /**
249 | * Calculate heights for animation parts with some logic
250 | * TODO: Add detailed descriptions for logic
251 | *
252 | * @param titleViewHeight height of title view
253 | * @param contentViewHeight height of content view
254 | * @param additionalFlipsCount count of additional flips (after first one), set 0 for auto
255 | * @return list of calculated heights
256 | */
257 | private fun calculateHeightsForAnimationParts(titleViewHeight: Int, contentViewHeight: Int, additionalFlipsCount: Int): List {
258 | val partHeights = ArrayList()
259 | val additionalPartsTotalHeight = contentViewHeight - titleViewHeight * 2
260 | if (additionalPartsTotalHeight < 0)
261 | throw IllegalStateException("Content View height is too small")
262 | // add two main parts - guarantee first flip
263 | partHeights.add(titleViewHeight)
264 | partHeights.add(titleViewHeight)
265 |
266 | // if no space left - return
267 | if (additionalPartsTotalHeight == 0)
268 | return partHeights
269 |
270 | // if some space remained - use two different logic
271 | if (additionalFlipsCount != 0) {
272 | // 1 - additional parts count is specified and it is not 0 - divide remained space
273 | val additionalPartHeight = additionalPartsTotalHeight / additionalFlipsCount
274 | val remainingHeight = additionalPartsTotalHeight % additionalFlipsCount
275 |
276 | if (additionalPartHeight + remainingHeight > titleViewHeight)
277 | throw IllegalStateException("Additional flips count is too small")
278 | for (i in 0 until additionalFlipsCount)
279 | partHeights.add(additionalPartHeight + if (i == 0) remainingHeight else 0)
280 | } else {
281 | // 2 - additional parts count isn't specified or 0 - divide remained space to parts with title view size
282 | val partsCount = additionalPartsTotalHeight / titleViewHeight
283 | val restPartHeight = additionalPartsTotalHeight % titleViewHeight
284 | for (i in 0 until partsCount)
285 | partHeights.add(titleViewHeight)
286 | if (restPartHeight > 0)
287 | partHeights.add(restPartHeight)
288 | }
289 |
290 | return partHeights
291 | }
292 |
293 | /**
294 | * Create image view for display back side of flip view
295 | *
296 | * @param height height for view
297 | * @return ImageView with selected height and default background color
298 | */
299 | private fun createBackSideView(height: Int): ImageView {
300 | val imageView = ImageView(context)
301 | imageView.setBackgroundColor(backSideColor)
302 | imageView.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height)
303 | return imageView
304 | }
305 |
306 | /**
307 | * Create image view for display selected bitmap
308 | *
309 | * @param bitmap bitmap to display in image view
310 | * @return ImageView with selected bitmap
311 | */
312 | private fun createImageViewFromBitmap(bitmap: Bitmap): ImageView {
313 | val imageView = ImageView(context)
314 | imageView.setImageBitmap(bitmap)
315 | imageView.layoutParams = RelativeLayout.LayoutParams(bitmap.width, bitmap.height)
316 | return imageView
317 | }
318 |
319 | /**
320 | * Create bitmap from specified View with specified with
321 | *
322 | * @param view source for bitmap
323 | * @param parentWidth result bitmap width
324 | * @return bitmap from specified view
325 | */
326 | private fun measureViewAndGetBitmap(view: View, parentWidth: Int): Bitmap {
327 | val specW = View.MeasureSpec.makeMeasureSpec(parentWidth, View.MeasureSpec.EXACTLY)
328 | val specH = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
329 | view.measure(specW, specH)
330 | view.layout(0, 0, view.measuredWidth, view.measuredHeight)
331 | val b = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
332 | val c = Canvas(b)
333 | c.translate((-view.scrollX).toFloat(), (-view.scrollY).toFloat())
334 | view.draw(c)
335 | return b
336 | }
337 |
338 | /**
339 | * Create layout that will be a container for animation elements
340 | *
341 | * @return Configured container for animation elements (LinearLayout)
342 | */
343 | private fun createAndPrepareFoldingContainer(): LinearLayout {
344 | val foldingContainer = LinearLayout(context)
345 | foldingContainer.clipToPadding = false
346 | foldingContainer.clipChildren = false
347 | foldingContainer.orientation = LinearLayout.VERTICAL
348 | foldingContainer.layoutParams = LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
349 | return foldingContainer
350 | }
351 |
352 | /**
353 | * Prepare and start height expand animation for FoldingKitLayout
354 | *
355 | * @param partAnimationDuration one part animate duration
356 | * @param viewHeights heights of animation parts
357 | */
358 | private fun startExpandHeightAnimation(viewHeights: List, partAnimationDuration: Int) {
359 | if (viewHeights == null || viewHeights.isEmpty())
360 | throw IllegalArgumentException("ViewHeights array must have at least 2 elements")
361 |
362 | val heightAnimations = ArrayList()
363 | var fromHeight = viewHeights[0]
364 | val delay = 0
365 | val animationDuration = partAnimationDuration - delay
366 | for (i in 1 until viewHeights.size) {
367 | val toHeight = fromHeight + viewHeights[i]
368 | val heightAnimation = HeightAnimation(this, fromHeight, toHeight, animationDuration)
369 | .withInterpolator(DecelerateInterpolator())
370 | heightAnimation.startOffset = delay.toLong()
371 | heightAnimations.add(heightAnimation)
372 | fromHeight = toHeight
373 | }
374 | createAnimationChain(heightAnimations, this)
375 | this.startAnimation(heightAnimations[0])
376 | }
377 |
378 | /**
379 | * Prepare and start height collapse animation for FoldingKitLayout
380 | *
381 | * @param partAnimationDuration one part animate duration
382 | * @param viewHeights heights of animation parts
383 | */
384 | private fun startCollapseHeightAnimation(viewHeights: List, partAnimationDuration: Int) {
385 | if (viewHeights == null || viewHeights.isEmpty())
386 | throw IllegalArgumentException("ViewHeights array must have at least 2 elements")
387 |
388 | val heightAnimations = ArrayList()
389 | var fromHeight = viewHeights[0]
390 | for (i in 1 until viewHeights.size) {
391 | val toHeight = fromHeight + viewHeights[i]
392 | heightAnimations.add(HeightAnimation(this, toHeight, fromHeight, partAnimationDuration)
393 | .withInterpolator(DecelerateInterpolator()))
394 | fromHeight = toHeight
395 | }
396 |
397 | Collections.reverse(heightAnimations)
398 | createAnimationChain(heightAnimations, this)
399 | this.startAnimation(heightAnimations[0])
400 | }
401 |
402 | /**
403 | * Create "animation chain" for selected view from list of animations objects
404 | *
405 | * @param animationList collection with animations
406 | * @param animationObject view for animations
407 | */
408 | private fun createAnimationChain(animationList: List, animationObject: View) {
409 | for (i in animationList.indices) {
410 | val animation = animationList[i]
411 | if (i + 1 < animationList.size) {
412 | animation.setAnimationListener(object : AnimationEndListener() {
413 | override fun onAnimationEnd(animation: Animation?) {
414 | animationObject.startAnimation(animationList[i + 1])
415 | }
416 | })
417 | }
418 | }
419 | }
420 |
421 | /**
422 | * Start fold animation
423 | *
424 | * @param FoldingKitElements ordered list with animation parts from top to bottom
425 | * @param foldingLayout prepared layout for animation parts
426 | * @param part90degreeAnimationDuration animation duration for 90 degree rotation
427 | * @param animationEndListener animation end callback
428 | */
429 | private fun startFoldAnimation(FoldingKitElements: List, foldingLayout: ViewGroup,
430 | part90degreeAnimationDuration: Int, animationEndListener: AnimationEndListener) {
431 | for (FoldingKitElement in FoldingKitElements)
432 | foldingLayout.addView(FoldingKitElement)
433 |
434 | Collections.reverse(FoldingKitElements)
435 |
436 | var nextDelay = 0
437 | for (i in FoldingKitElements.indices) {
438 | val cell = FoldingKitElements[i]
439 | cell.visibility = View.VISIBLE
440 | // not FIRST(BOTTOM) element - animate front view
441 | if (i != 0) {
442 | val foldAnimation = FoldAnimation(FoldAnimation.FoldAnimationMode.UNFOLD_UP, mCameraHeight, part90degreeAnimationDuration.toLong())
443 | .withStartOffset(nextDelay)
444 | .withInterpolator(DecelerateInterpolator())
445 | // if last(top) element - add end listener
446 | if (i == FoldingKitElements.size - 1) {
447 | foldAnimation.setAnimationListener(animationEndListener)
448 | }
449 | cell.animateFrontView(foldAnimation)
450 | nextDelay += part90degreeAnimationDuration
451 | }
452 | // if not last(top) element - animate whole view
453 | if (i != FoldingKitElements.size - 1) {
454 | cell.startAnimation(FoldAnimation(FoldAnimation.FoldAnimationMode.FOLD_UP, mCameraHeight, part90degreeAnimationDuration.toLong())
455 | .withStartOffset(nextDelay)
456 | .withInterpolator(DecelerateInterpolator()))
457 | nextDelay += part90degreeAnimationDuration
458 | }
459 | }
460 | }
461 |
462 | /**
463 | * Start unfold animation
464 | *
465 | * @param FoldingKitElements ordered list with animation parts from top to bottom
466 | * @param foldingLayout prepared layout for animation parts
467 | * @param part90degreeAnimationDuration animation duration for 90 degree rotation
468 | * @param animationEndListener animation end callback
469 | */
470 | private fun startUnfoldAnimation(FoldingKitElements: List, foldingLayout: ViewGroup,
471 | part90degreeAnimationDuration: Int, animationEndListener: AnimationEndListener) {
472 | var nextDelay = 0
473 | for (i in FoldingKitElements.indices) {
474 | val cell = FoldingKitElements[i]
475 | cell.visibility = View.VISIBLE
476 | foldingLayout.addView(cell)
477 | // if not first(top) element - animate whole view
478 | if (i != 0) {
479 | val foldAnimation = FoldAnimation(FoldAnimation.FoldAnimationMode.UNFOLD_DOWN, mCameraHeight, part90degreeAnimationDuration.toLong())
480 | .withStartOffset(nextDelay)
481 | .withInterpolator(DecelerateInterpolator())
482 |
483 | // if last(bottom) element - add end listener
484 | if (i == FoldingKitElements.size - 1) {
485 | foldAnimation.setAnimationListener(animationEndListener)
486 | }
487 |
488 | nextDelay += part90degreeAnimationDuration
489 | cell.startAnimation(foldAnimation)
490 |
491 | }
492 | // not last(bottom) element - animate front view
493 | if (i != FoldingKitElements.size - 1) {
494 | cell.animateFrontView(FoldAnimation(FoldAnimation.FoldAnimationMode.FOLD_DOWN, mCameraHeight, part90degreeAnimationDuration.toLong())
495 | .withStartOffset(nextDelay)
496 | .withInterpolator(DecelerateInterpolator()))
497 | nextDelay += part90degreeAnimationDuration
498 | }
499 | }
500 | }
501 |
502 | /**
503 | * Initialize folding cell with parameters from attribute
504 | *
505 | * @param context context
506 | * @param attrs attributes
507 | */
508 | private fun initializeFromAttributes(context: Context, attrs: AttributeSet) {
509 | val array = context.theme.obtainStyledAttributes(attrs, R.styleable.FoldingKit, 0, 0)
510 | try {
511 | this.animationDuration = array.getInt(R.styleable.FoldingKit_animationDuration, DEF_ANIMATION_DURATION)
512 | this.backSideColor = array.getColor(R.styleable.FoldingKit_backSideColor, DEF_BACK_SIDE_COLOR)
513 | this.additionalFlipsCount = array.getInt(R.styleable.FoldingKit_additionalFlipsCount, DEF_ADDITIONAL_FLIPS)
514 | this.mCameraHeight = array.getInt(R.styleable.FoldingKit_cameraHeight, DEF_CAMERA_HEIGHT)
515 | } finally {
516 | array.recycle()
517 | }
518 | }
519 |
520 | /**
521 | * Instantly change current state of cell to Folded without any animations
522 | */
523 | private fun setStateToFolded() {
524 | if (this.mAnimationInProgress || !this.isUnfolded) return
525 | // get basic views
526 | val contentView = getChildAt(0) ?: return
527 | val titleView = getChildAt(1) ?: return
528 | contentView.visibility = View.GONE
529 | titleView.visibility = View.VISIBLE
530 | this@FoldingKit.isUnfolded = false
531 | val layoutParams = this.layoutParams
532 | layoutParams.height = titleView.height
533 | this.layoutParams = layoutParams
534 | this.requestLayout()
535 | }
536 | }
537 |
--------------------------------------------------------------------------------
/foldingkit/src/main/java/com/cogitator/foldingit/animation/AnimationEndListener.kt:
--------------------------------------------------------------------------------
1 | package com.cogitator.foldingit.animation
2 |
3 | import android.view.animation.Animation
4 |
5 | /**
6 | * Created by ankit on 26/01/2018.
7 | */
8 | public abstract class AnimationEndListener : Animation.AnimationListener {
9 | override fun onAnimationRepeat(animation: Animation?) {
10 | }
11 |
12 | override fun onAnimationEnd(animation: Animation?) {
13 | }
14 |
15 | override fun onAnimationStart(animation: Animation?) {
16 | }
17 | }
--------------------------------------------------------------------------------
/foldingkit/src/main/java/com/cogitator/foldingit/animation/FoldAnimation.kt:
--------------------------------------------------------------------------------
1 | package com.cogitator.foldingit.animation
2 |
3 | import android.graphics.Camera
4 | import android.view.animation.Animation
5 | import android.view.animation.Interpolator
6 | import android.view.animation.Transformation
7 | import java.lang.IllegalStateException
8 |
9 |
10 | /**
11 | * Created by ankit on 26/01/2018.
12 | */
13 | class FoldAnimation(foldMode: FoldAnimationMode, cameraHeight: Int, duration: Long) : Animation() {
14 | enum class FoldAnimationMode {
15 | FOLD_UP, UNFOLD_DOWN, FOLD_DOWN, UNFOLD_UP
16 | }
17 |
18 | private var mFoldMode: FoldAnimationMode? = null
19 | private var mCameraHeight: Int = 0
20 | private var mFromDegrees: Float = 0.toFloat()
21 | private var mToDegrees: Float = 0.toFloat()
22 | private var mCenterX: Float = 0.toFloat()
23 | private var mCenterY: Float = 0.toFloat()
24 | private var mCamera: Camera? = null
25 |
26 |
27 | init {
28 | this.mFoldMode = foldMode
29 | this.fillAfter = true
30 | this.duration = duration
31 | this.mCameraHeight = cameraHeight
32 | }
33 |
34 | fun withAnimationListener(animationListener: Animation.AnimationListener): FoldAnimation {
35 | this.setAnimationListener(animationListener)
36 | return this
37 | }
38 |
39 | fun withStartOffset(offset: Int): FoldAnimation {
40 | this.startOffset = offset.toLong()
41 | return this
42 | }
43 |
44 | fun withInterpolator(interpolator: Interpolator?): FoldAnimation {
45 | if (interpolator != null) {
46 | this.interpolator = interpolator
47 | }
48 | return this
49 | }
50 |
51 | override fun initialize(width: Int, height: Int, parentWidth: Int, parentHeight: Int) {
52 | super.initialize(width, height, parentWidth, parentHeight)
53 | this.mCamera = Camera()
54 | mCamera?.setLocation(0F, 0F, (-mCameraHeight).toFloat())
55 |
56 | this.mCenterX = (width / 2).toFloat()
57 | when (mFoldMode) {
58 | FoldAnimationMode.FOLD_UP -> {
59 | this.mCenterY = 0f
60 | this.mFromDegrees = 0f
61 | this.mToDegrees = 90f
62 | }
63 | FoldAnimationMode.FOLD_DOWN -> {
64 | this.mCenterY = height.toFloat()
65 | this.mFromDegrees = 0f
66 | this.mToDegrees = -90f
67 | }
68 | FoldAnimationMode.UNFOLD_UP -> {
69 | this.mCenterY = height.toFloat()
70 | this.mFromDegrees = -90f
71 | this.mToDegrees = 0f
72 | }
73 | FoldAnimationMode.UNFOLD_DOWN -> {
74 | this.mCenterY = 0f
75 | this.mFromDegrees = 90f
76 | this.mToDegrees = 0f
77 | }
78 | else -> throw IllegalStateException("Unknown animation mode.")
79 | }
80 | }
81 |
82 | override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
83 | val camera = mCamera
84 | val matrix = t.matrix
85 | val fromDegrees = mFromDegrees
86 | val degrees = fromDegrees + (mToDegrees - fromDegrees) * interpolatedTime
87 |
88 | camera?.save()
89 | camera?.rotateX(degrees)
90 | camera?.getMatrix(matrix)
91 | camera?.restore()
92 |
93 | matrix.preTranslate(-mCenterX, -mCenterY)
94 | matrix.postTranslate(mCenterX, mCenterY)
95 | }
96 |
97 | override fun toString(): String {
98 | return "FoldAnimation{" +
99 | "mFoldMode=" + mFoldMode +
100 | ", mFromDegrees=" + mFromDegrees +
101 | ", mToDegrees=" + mToDegrees +
102 | '}'
103 | }
104 | }
--------------------------------------------------------------------------------
/foldingkit/src/main/java/com/cogitator/foldingit/animation/HeightAnimation.kt:
--------------------------------------------------------------------------------
1 | package com.cogitator.foldingit.animation
2 |
3 | import android.view.View
4 | import android.view.animation.Animation
5 | import android.view.animation.Interpolator
6 | import android.view.animation.Transformation
7 |
8 | /**
9 | * Created by ankit on 26/01/2018.
10 | */
11 | class HeightAnimation(mView: View, heightFrom: Int, heightTo: Int, duration: Int): Animation() {
12 | private val mView: View = mView
13 | private val mHeightFrom: Int = heightFrom
14 | private val mHeightTo: Int = heightTo
15 |
16 | init {
17 | this.duration = duration.toLong()
18 | }
19 |
20 | fun withInterpolator(interpolator: Interpolator?): HeightAnimation {
21 | if (interpolator != null) {
22 | this.interpolator = interpolator
23 | }
24 | return this
25 | }
26 |
27 | override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
28 | val newHeight = mHeightFrom + (mHeightTo - mHeightFrom) * interpolatedTime
29 |
30 | if (interpolatedTime == 1f) {
31 | mView.layoutParams.height = mHeightTo
32 | } else {
33 | mView.layoutParams.height = newHeight.toInt()
34 | }
35 | mView.requestLayout()
36 | }
37 |
38 | override fun willChangeBounds(): Boolean {
39 | return true
40 | }
41 |
42 | override fun isFillEnabled(): Boolean {
43 | return false
44 | }
45 |
46 | override fun toString(): String {
47 | return "HeightAnimation{" +
48 | "mHeightFrom=" + mHeightFrom +
49 | ", mHeightTo=" + mHeightTo +
50 | ", offset =" + startOffset +
51 | ", duration =" + duration +
52 | '}'.toString()
53 | }
54 | }
--------------------------------------------------------------------------------
/foldingkit/src/main/java/com/cogitator/foldingit/views/FoldingKitView.kt:
--------------------------------------------------------------------------------
1 | package com.cogitator.foldingit.views
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.View
6 | import android.view.animation.Animation
7 | import android.widget.RelativeLayout
8 |
9 | /**
10 | * Created by ankit on 26/01/2018.
11 | */
12 |
13 | class FoldingKitView : RelativeLayout {
14 |
15 | private var backView: View? = null
16 |
17 | private var frontView: View? = null
18 |
19 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
20 | val layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
21 | this.layoutParams = layoutParams
22 | this.clipToPadding = false
23 | this.clipChildren = false
24 | }
25 |
26 | constructor(frontView: View, backView: View, context: Context) : super(context) {
27 | this.frontView = frontView
28 | this.backView = backView
29 |
30 | val layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
31 |
32 | this.clipToPadding = false
33 | this.clipChildren = false
34 |
35 | if (this.backView != null) {
36 | this.addView(this.backView)
37 | val mBackViewParams = this.backView!!.layoutParams as RelativeLayout.LayoutParams
38 | mBackViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
39 | this.backView!!.layoutParams = mBackViewParams
40 | layoutParams.height = mBackViewParams.height
41 | }
42 |
43 | if (this.frontView != null) {
44 | this.addView(this.frontView)
45 | val frontViewLayoutParams = this.frontView!!.layoutParams as RelativeLayout.LayoutParams
46 | frontViewLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
47 | this.frontView!!.layoutParams = frontViewLayoutParams
48 | }
49 |
50 | this.layoutParams = layoutParams
51 | }
52 |
53 | fun withFrontView(frontView: View): FoldingKitView {
54 | this.frontView = frontView
55 |
56 | if (this.frontView != null) {
57 | this.addView(this.frontView)
58 | val frontViewLayoutParams = this.frontView!!.layoutParams as RelativeLayout.LayoutParams
59 | frontViewLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
60 | this.frontView!!.layoutParams = frontViewLayoutParams
61 | }
62 | return this
63 | }
64 |
65 | fun withBackView(backView: View): FoldingKitView {
66 | this.backView = backView
67 |
68 | if (this.backView != null) {
69 | this.addView(this.backView)
70 | val mBackViewParams = this.backView!!.layoutParams as RelativeLayout.LayoutParams
71 | mBackViewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
72 | this.backView!!.layoutParams = mBackViewParams
73 |
74 | val layoutParams = this.layoutParams as RelativeLayout.LayoutParams
75 | layoutParams.height = mBackViewParams.height
76 | this.layoutParams = layoutParams
77 | }
78 |
79 | return this
80 | }
81 |
82 | fun animateFrontView(animation: Animation) {
83 | if (this.frontView != null)
84 | frontView!!.startAnimation(animation)
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/foldingkit/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/foldingkit/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | foldingIT
3 |
4 |
--------------------------------------------------------------------------------
/foldingkit/src/test/java/com/freeankit/foldingit/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.freeankit.foldingit;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArchitectAK/FoldingAnimationKotlin-Android/763d715e37fa3afa3dc2cd9494a71c7627edb45e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Nov 23 16:30:06 MYT 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':foldingkit'
2 |
--------------------------------------------------------------------------------