├── .idea ├── .name ├── copyright │ └── profiles_settings.xml ├── vcs.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml ├── compiler.xml └── misc.xml ├── mobile ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable-hdpi │ │ │ │ ├── ic_chat.png │ │ │ │ ├── ic_list.png │ │ │ │ └── ic_connect.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── ic_chat.png │ │ │ │ ├── ic_list.png │ │ │ │ └── ic_connect.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── phone2.png │ │ │ │ ├── ic_chat.png │ │ │ │ ├── ic_list.png │ │ │ │ └── ic_connect.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── ic_chat.png │ │ │ │ ├── ic_list.png │ │ │ │ └── ic_connect.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── ic_chat.png │ │ │ │ ├── ic_list.png │ │ │ │ ├── ic_connect.png │ │ │ │ └── ripple_selector_white.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── lv_ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── lv_ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── lv_ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── lv_ic_launcher.png │ │ │ ├── drawable-v21 │ │ │ │ └── list_selector_white.xml │ │ │ ├── values │ │ │ │ ├── dimensions.xml │ │ │ │ ├── strings.xml │ │ │ │ ├── attrs.xml │ │ │ │ ├── styles.xml │ │ │ │ └── colors.xml │ │ │ ├── drawable │ │ │ │ ├── toolbar_shadow_pre_lolipop.xml │ │ │ │ ├── card_stack_bg_shadow3.xml │ │ │ │ ├── card_stack_bg_shadow2.xml │ │ │ │ ├── card_stack_bg_shadow.xml │ │ │ │ └── list_selector_white.xml │ │ │ ├── menu │ │ │ │ └── menu_main.xml │ │ │ ├── values-v21 │ │ │ │ └── styles.xml │ │ │ └── layout │ │ │ │ ├── fragment_discover.xml │ │ │ │ ├── fragment_chat.xml │ │ │ │ ├── custom_tab_view.xml │ │ │ │ ├── fragment_connect.xml │ │ │ │ ├── background_ripple_layout.xml │ │ │ │ ├── card_stack_item.xml │ │ │ │ └── activity_home.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── tinderview │ │ │ │ ├── fragments │ │ │ │ ├── Discover.java │ │ │ │ ├── Chat.java │ │ │ │ └── Connect.java │ │ │ │ ├── adapters │ │ │ │ └── CardStackAdapter.java │ │ │ │ ├── cardstatck │ │ │ │ ├── cardstack │ │ │ │ │ ├── DefaultStackEventListener.java │ │ │ │ │ ├── DragGestureDetector.java │ │ │ │ │ ├── CardUtils.java │ │ │ │ │ ├── CardStack.java │ │ │ │ │ └── CardAnimator.java │ │ │ │ └── animation │ │ │ │ │ └── RelativeLayoutParamsEvaluator.java │ │ │ │ ├── util │ │ │ │ ├── CustomViewPager.java │ │ │ │ └── CircularImageView.java │ │ │ │ ├── tabbarview │ │ │ │ ├── TabView.java │ │ │ │ ├── CheatSheet.java │ │ │ │ └── TabBarView.java │ │ │ │ ├── activities │ │ │ │ └── MainScreenActivity.java │ │ │ │ └── animation │ │ │ │ └── RippleAnimation.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── com │ │ └── tinderview │ │ └── ApplicationTest.java ├── proguard-rules.pro ├── build.gradle └── mobile.iml ├── wear ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── values │ │ │ └── strings.xml │ │ └── layout │ │ │ ├── rect_activity_main.xml │ │ │ ├── activity_main.xml │ │ │ └── round_activity_main.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── letsventure │ │ └── MainActivity.java ├── proguard-rules.pro ├── build.gradle └── wear.iml ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── TinderView.iml ├── README.md ├── gradlew.bat └── gradlew /.idea/.name: -------------------------------------------------------------------------------- 1 | TinderView -------------------------------------------------------------------------------- /mobile/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /wear/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':mobile', ':wear' 2 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-hdpi/ic_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-hdpi/ic_chat.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-hdpi/ic_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-hdpi/ic_list.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-mdpi/ic_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-mdpi/ic_chat.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-mdpi/ic_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-mdpi/ic_list.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xhdpi/phone2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xhdpi/phone2.png -------------------------------------------------------------------------------- /wear/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/wear/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /wear/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/wear/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xhdpi/ic_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xhdpi/ic_chat.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xhdpi/ic_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xhdpi/ic_list.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxhdpi/ic_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xxhdpi/ic_chat.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxhdpi/ic_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xxhdpi/ic_list.png -------------------------------------------------------------------------------- /wear/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/wear/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /wear/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/wear/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-hdpi/ic_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-hdpi/ic_connect.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-mdpi/ic_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-mdpi/ic_connect.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xhdpi/ic_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xhdpi/ic_connect.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxhdpi/ic_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xxhdpi/ic_connect.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxxhdpi/ic_chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xxxhdpi/ic_chat.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxxhdpi/ic_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xxxhdpi/ic_list.png -------------------------------------------------------------------------------- /mobile/src/main/res/mipmap-hdpi/lv_ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/mipmap-hdpi/lv_ic_launcher.png -------------------------------------------------------------------------------- /mobile/src/main/res/mipmap-mdpi/lv_ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/mipmap-mdpi/lv_ic_launcher.png -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxxhdpi/ic_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/drawable-xxxhdpi/ic_connect.png -------------------------------------------------------------------------------- /mobile/src/main/res/mipmap-xhdpi/lv_ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/mipmap-xhdpi/lv_ic_launcher.png -------------------------------------------------------------------------------- /mobile/src/main/res/mipmap-xxhdpi/lv_ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GadgetCheck/TinderView/HEAD/mobile/src/main/res/mipmap-xxhdpi/lv_ic_launcher.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-v21/list_selector_white.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /wear/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | tinderview 3 | Hello Round World! 4 | Hello Square World! 5 | 6 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable-xxxhdpi/ripple_selector_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mobile/src/main/res/values/dimensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | //sets some default properties for rippleBackgroundAnimation 5 | 2dp 6 | 64dp 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Sep 30 14:06:07 IST 2015 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-2.4-all.zip 7 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable/toolbar_shadow_pre_lolipop.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | -------------------------------------------------------------------------------- /mobile/src/androidTest/java/com/tinderview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.tinderview; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /mobile/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /mobile/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable/card_stack_bg_shadow3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable/card_stack_bg_shadow2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/fragment_discover.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | -------------------------------------------------------------------------------- /mobile/src/main/res/drawable/card_stack_bg_shadow.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /wear/src/main/res/layout/rect_activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/fragment_chat.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/custom_tab_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /wear/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /wear/src/main/res/layout/round_activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /wear/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Aradh/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /mobile/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Aradh/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /wear/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | 4 | android { 5 | compileSdkVersion 22 6 | buildToolsVersion "22.0.1" 7 | 8 | defaultConfig { 9 | applicationId "com.tinderview" 10 | minSdkVersion 20 11 | targetSdkVersion 22 12 | versionCode 1 13 | versionName "1.0" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | compile 'com.google.android.support:wearable:1.2.0' 26 | compile 'com.google.android.gms:play-services-wearable:7.8.0' 27 | } 28 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /mobile/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.tinderview" 9 | minSdkVersion 19 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "0.1" 13 | } 14 | buildTypes { 15 | release { 16 | 17 | minifyEnabled true 18 | shrinkResources true 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | /*repositories { 25 | flatDir { 26 | dirs 'libs' 27 | } 28 | }*/ 29 | 30 | dependencies { 31 | compile fileTree(dir: 'libs', include: ['*.jar']) 32 | wearApp project(':wear') 33 | compile 'com.android.support:appcompat-v7:23.0.1' 34 | 35 | } 36 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/fragments/Discover.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.fragments;// Created by Sanat Dutta on 2/17/2015. 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.tinderview.R; 11 | 12 | /** 13 | * Created by Aradh Pillai on 1/10/15. 14 | */ 15 | public class Discover extends Fragment { 16 | 17 | private String TAG = "fragment_discover"; 18 | 19 | @Override 20 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 21 | View view = inflater.inflate(R.layout.fragment_discover, container, false); 22 | 23 | Log.i(TAG, "fragment_discover: onCreateView"); 24 | 25 | return view; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wear/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/fragment_connect.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 10 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /mobile/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | tinderview 3 | 4 | Hello world! 5 | Settings 6 | 7 | Discover 8 | The fastest way to connect with startups in a single tap 9 | 10 | Connect 11 | Simply swipe to connect with a startup. Chat freely & take informed decisions 12 | 13 | Invest 14 | Add friends to your group and invest together, We will help you keep track of everything 15 | 16 | Connect 17 | Discover 18 | Chat 19 | 20 | 21 | -------------------------------------------------------------------------------- /wear/src/main/java/com/letsventure/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.tinderview; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.wearable.view.WatchViewStub; 6 | import android.widget.TextView; 7 | 8 | public class MainActivity extends Activity { 9 | 10 | private TextView mTextView; 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_main); 16 | final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub); 17 | stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() { 18 | @Override 19 | public void onLayoutInflated(WatchViewStub stub) { 20 | mTextView = (TextView) stub.findViewById(R.id.text); 21 | } 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/fragments/Chat.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.fragments;// Created by Sanat Dutta on 2/17/2015. 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.util.Log; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.tinderview.R; 11 | 12 | /** 13 | * Created by Aradh Pillai on 1/10/15. 14 | */ 15 | /* 16 | * this fragment is using for chat tab option 17 | * */ 18 | public class Chat extends Fragment { 19 | 20 | private String TAG = "fragment_chat"; 21 | 22 | @Override 23 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 24 | View view = inflater.inflate(R.layout.fragment_chat, container, false); 25 | 26 | Log.i(TAG, "fragment_chat: onCreateView"); 27 | 28 | return view; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mobile/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /mobile/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /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 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /mobile/src/main/res/drawable/list_selector_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/background_ripple_layout.xml: -------------------------------------------------------------------------------- 1 | 3 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /TinderView.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /mobile/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/adapters/CardStackAdapter.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.adapters; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ArrayAdapter; 7 | import android.widget.TextView; 8 | 9 | import com.tinderview.R; 10 | 11 | 12 | /** 13 | * Created by Aradh Pillaion 07/10/15. 14 | */ 15 | 16 | /* 17 | * cardStackAdapter which is going to hold list of information and setting it into CardStack 18 | * 19 | * */ 20 | public class CardStackAdapter extends ArrayAdapter { 21 | 22 | 23 | public CardStackAdapter(Context context, int resource) { 24 | 25 | super(context, 0); 26 | } 27 | 28 | @Override 29 | public View getView(int position, final View contentView, ViewGroup parent) { 30 | //supply the layout for your card 31 | TextView v = (TextView) (contentView.findViewById(R.id.helloText)); 32 | v.setText(getItem(position)); 33 | return contentView; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/cardstatck/cardstack/DefaultStackEventListener.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.cardstatck.cardstack; 2 | 3 | 4 | /*this is using to put the listener event into cardStack 5 | 6 | */ 7 | public class DefaultStackEventListener implements CardStack.CardEventListener { 8 | 9 | private float mThreshold = 0; 10 | 11 | public DefaultStackEventListener(int i) { 12 | mThreshold = i; 13 | } 14 | 15 | @Override 16 | public boolean swipeEnd(int section, float distance) { 17 | return distance > mThreshold; 18 | } 19 | 20 | @Override 21 | public boolean swipeStart(int section, float distance) { 22 | 23 | return true; 24 | } 25 | 26 | @Override 27 | public boolean swipeContinue(int section, float distanceX, float distanceY) { 28 | return true; 29 | } 30 | 31 | @Override 32 | public void discarded(int mIndex, int direction) { 33 | 34 | } 35 | 36 | @Override 37 | public void topCardTapped() { 38 | 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/cardstatck/animation/RelativeLayoutParamsEvaluator.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.cardstatck.animation; 2 | 3 | import android.animation.TypeEvaluator; 4 | import android.widget.RelativeLayout.LayoutParams; 5 | 6 | /* 7 | * when card discard or reverse then this animation class is calling 8 | * and this class is overloading the evaluate method of TypeEvaluator class 9 | * */ 10 | public class RelativeLayoutParamsEvaluator implements TypeEvaluator { 11 | 12 | 13 | @Override 14 | public LayoutParams evaluate(float fraction, LayoutParams start, 15 | LayoutParams end) { 16 | 17 | LayoutParams result = new LayoutParams(start); 18 | result.leftMargin += ((end.leftMargin - start.leftMargin) * fraction); 19 | result.rightMargin += ((end.rightMargin - start.rightMargin) * fraction); 20 | result.topMargin += ((end.topMargin - start.topMargin) * fraction); 21 | result.bottomMargin += ((end.bottomMargin - start.bottomMargin) * fraction); 22 | return result; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /mobile/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | //ripple color for Tabs 6 | #77ffffff 7 | 8 | //color for background 9 | #e6e6e6 10 | 11 | //theme properties mentioned here 12 | #3498db 13 | #2980b9 14 | #FFFFFF 15 | 16 | #000000 17 | #ffffff 18 | 19 | #b6b6b6 20 | 21 | //for ripple background animation 22 | #993498db 23 | 24 | //stroke color for CardStack 25 | #B1B1B1 26 | 27 | //these three different shadow colors for CardStack 28 | #fbfcfc 29 | #f8f8f8 30 | #f2f2f2 31 | 32 | 33 | //for pre-lollipop gradient color 34 | #40000000 35 | 36 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/card_stack_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/util/CustomViewPager.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.util; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * Created by Aradh Pillai on 09/10/15. 10 | *

11 | *

12 | * this class is created to avoid the swipe gesture from ViewPager 13 | * this is customized ViewPager class to override the specific methods of ViewPager to avoid swipe feature. 14 | */ 15 | 16 | 17 | public class CustomViewPager extends ViewPager { 18 | 19 | public CustomViewPager(Context context) { 20 | super(context); 21 | } 22 | 23 | 24 | public CustomViewPager(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | } 27 | 28 | 29 | /* when user will touch viewPager in intercept motion then this method will 30 | * invoke and it will return "false" it means it won't work so using this method we can avoid this feather from ViewPager 31 | * 32 | */ 33 | @Override 34 | public boolean onInterceptTouchEvent(MotionEvent event) { 35 | // Never allow swiping to switch between pages 36 | return false; 37 | } 38 | 39 | /* even user will touch viewPager scope then this method will invoke and it will return false value ... 40 | * so using this method we can avoid touch event of ViewPager. 41 | */ 42 | 43 | @Override 44 | public boolean onTouchEvent(MotionEvent event) { 45 | // Never allow swiping to switch between pages 46 | return false; 47 | } 48 | } -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/util/CircularImageView.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.util; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | 7 | import android.graphics.drawable.Drawable; 8 | import android.support.v4.graphics.drawable.RoundedBitmapDrawable; 9 | import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; 10 | 11 | /** 12 | * Created by Aradh Pillaion 07/10/15. 13 | *

14 | * setting the context and image resource from drawable and converting it into bitmap 15 | */ 16 | public class CircularImageView { 17 | 18 | public static Drawable makeCircleFromResources(Context context, int resource) { 19 | Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource); 20 | 21 | RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create( 22 | context.getResources(), bitmapToSquare(bitmap)); 23 | roundedBitmapDrawable.setCornerRadius(bitmap.getWidth() / 2); 24 | roundedBitmapDrawable.setAntiAlias(true); 25 | return roundedBitmapDrawable; 26 | } 27 | 28 | 29 | // 30 | private static Bitmap bitmapToSquare(Bitmap bitmap) { 31 | if (bitmap.getWidth() >= bitmap.getHeight()) { 32 | bitmap = Bitmap.createBitmap(bitmap, 33 | bitmap.getWidth() / 2 - bitmap.getHeight() / 2, 0, 34 | bitmap.getHeight(), bitmap.getHeight()); 35 | } else { 36 | bitmap = Bitmap.createBitmap(bitmap, 0, bitmap.getHeight() / 2 37 | - bitmap.getWidth() / 2, bitmap.getWidth(), 38 | bitmap.getWidth()); 39 | } 40 | 41 | return bitmap; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TinderView 2 | ======== 3 | 4 | Created A Simple and Beautiful Tinder like card deck & Captain Train like toolbar. 5 | 6 | This is heavily based on [AndroidSwipeableCardStack](https://github.com/wenchaojiang/AndroidSwipeableCardStack), wenchaojiang has written the library very well but i faced a lot of difficulty integrating it & that's the reason i built this app so that you dont waste time. Use this repo as a base for your app & build on top :). 7 | 8 | API 16 and UP. (Support for API 16 is now live thanks to [#4] (https://github.com/GadgetCheck/TinderView/pull/4)) 9 | 10 | In Action 11 | ========= 12 | 13 | [Click here to watch the app in action on youtube!](https://youtu.be/ccnkq9HmyVY) 14 | 15 | ![Screen 3](http://s4.postimg.org/x9bamw3yl/image.png)![Screen1](http://s4.postimg.org/7b7oguyh9/image.png) 16 | 17 | Get it on Google Play 18 | 19 | The demo is now available, dont forget to give it 5 stats if it helped you. Oh if you can contribute to development of the library in anyway i would love to see your pull request. 20 | 21 | Happy Coding! 22 | 23 | Developed By 24 | ============ 25 | 26 | * Aradh Pillai 27 | 28 | 29 | License 30 | ======= 31 | 32 | Copyright 2015 Aradh Pillai 33 | 34 | Licensed under the Apache License, Version 2.0 (the "License"); 35 | you may not use this file except in compliance with the License. 36 | You may obtain a copy of the License at 37 | 38 | http://www.apache.org/licenses/LICENSE-2.0 39 | 40 | Unless required by applicable law or agreed to in writing, software 41 | distributed under the License is distributed on an "AS IS" BASIS, 42 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 43 | See the License for the specific language governing permissions and 44 | limitations under the License. 45 | 46 | 47 | -------------------------------------------------------------------------------- /mobile/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 14 | 28 | 29 | 31 | 36 | 37 | 38 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/tabbarview/TabView.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.tabbarview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.Drawable; 6 | import android.util.AttributeSet; 7 | import android.util.TypedValue; 8 | import android.view.Gravity; 9 | import android.view.View; 10 | import android.widget.ImageView; 11 | import android.widget.ImageView.ScaleType; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | 15 | import com.tinderview.R; 16 | 17 | /* 18 | * created by Aradh Pillai on 1.10.15 19 | * This TabView class using to create tab and setting ImageView and Text into TabView 20 | * and adding ripple animation into View. 21 | * 22 | * 23 | * */ 24 | 25 | 26 | public class TabView extends LinearLayout { 27 | 28 | private ImageView mImageView; 29 | private TextView mTextView; 30 | 31 | public TabView(Context context) { 32 | this(context, null); 33 | } 34 | 35 | public TabView(Context context, AttributeSet attrs) { 36 | this(context, attrs, android.R.attr.actionBarTabStyle); 37 | } 38 | 39 | public TabView(Context context, AttributeSet attrs, int defStyle) { 40 | super(context, attrs, defStyle); 41 | 42 | TypedValue outValue = new TypedValue(); 43 | context.getTheme().resolveAttribute(android.R.attr.actionBarTabTextStyle, outValue, true); 44 | 45 | int txtstyle = outValue.data; 46 | 47 | int pad = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources() 48 | .getDisplayMetrics()); 49 | 50 | 51 | mImageView = new ImageView(context);//dynamically create an object of imageView and setting param into it... 52 | mImageView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 53 | mImageView.setScaleType(ScaleType.CENTER_INSIDE); 54 | 55 | mTextView = new TextView(context); //dynamically create a text view and setting these properties into it... 56 | mTextView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 57 | mTextView.setGravity(Gravity.CENTER); 58 | mTextView.setCompoundDrawablePadding(pad); 59 | mTextView.setTextAppearance(context, txtstyle); 60 | 61 | 62 | this.addView(mImageView);// adding the imageview object into view 63 | this.addView(mTextView);// adding textview object into view 64 | this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));//setting param into view 65 | 66 | this.setBackgroundResource(R.drawable.list_selector_white);//setting ripple animation into this View. 67 | 68 | 69 | } 70 | 71 | public void setIcon(int resId) { 72 | setIcon(getContext().getResources().getDrawable(resId)); 73 | } 74 | 75 | public void setIcon(Drawable icon) { 76 | if (icon != null) { 77 | mImageView.setVisibility(View.VISIBLE); 78 | mImageView.setImageDrawable(icon); 79 | } else { 80 | mImageView.setImageResource(View.GONE); 81 | } 82 | } 83 | 84 | public void setText(int resId, int ico) { 85 | setText(getContext().getString(resId), ico); 86 | } 87 | 88 | public void setText(CharSequence text, int ico) { 89 | mTextView.setText(text); 90 | mTextView.setCompoundDrawablesWithIntrinsicBounds(ico, 0, 0, 0); 91 | } 92 | 93 | } -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/cardstatck/cardstack/DragGestureDetector.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.cardstatck.cardstack; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.GestureDetectorCompat; 5 | import android.support.v4.view.MotionEventCompat; 6 | import android.util.Log; 7 | import android.view.GestureDetector; 8 | import android.view.MotionEvent; 9 | 10 | 11 | //detect both tap and drag based on the gesture 12 | /* 13 | * in this class DragListener interface is defined which is going to use to return the boolean value based on the scope of CardStack 14 | * whether card is start, dragging , dum, etc. 15 | * 16 | * 17 | * 18 | * */ 19 | 20 | 21 | public class DragGestureDetector { 22 | public static String DEBUG_TAG = "DragGestureDetector"; 23 | GestureDetectorCompat mGestrueDetector; 24 | DragListener mListener; 25 | private boolean mStarted = false; 26 | private boolean mDown = false; 27 | 28 | private MotionEvent mOriginalEvent; 29 | 30 | public DragGestureDetector(Context context, DragListener myDragListener) { 31 | mGestrueDetector = new GestureDetectorCompat(context, new MyGestureListener()); 32 | mListener = myDragListener; 33 | } 34 | 35 | public void onTouchEvent(MotionEvent event) { 36 | mGestrueDetector.onTouchEvent(event); 37 | int action = MotionEventCompat.getActionMasked(event); 38 | switch (action) { 39 | case (MotionEvent.ACTION_UP): 40 | Log.d(DEBUG_TAG, "Action was UP " + mStarted); 41 | if (mStarted) { 42 | mListener.onDragEnd(mOriginalEvent, event); 43 | mStarted = false; 44 | } 45 | break; 46 | 47 | case (MotionEvent.ACTION_DOWN): 48 | Log.d(DEBUG_TAG, "Action was down " + mStarted); 49 | 50 | 51 | if (mDown) { 52 | mListener.onDragEnd(mOriginalEvent, event); 53 | mDown = false; 54 | 55 | } 56 | break; 57 | case (MotionEvent.ACTION_SCROLL): 58 | Log.d(DEBUG_TAG, "Scroll " + mStarted); 59 | if (mStarted) { 60 | mListener.onDragEnd(mOriginalEvent, event); 61 | 62 | } 63 | // break; 64 | 65 | //need to set this, quick tap will not generate drap event, so the 66 | //originalEvent may be null for case action_up 67 | //which lead to null pointer 68 | mOriginalEvent = event; 69 | 70 | } 71 | } 72 | 73 | public interface DragListener { 74 | boolean onDragStart(MotionEvent e1, MotionEvent e2, float distanceX, 75 | float distanceY); 76 | 77 | boolean onDragContinue(MotionEvent e1, MotionEvent e2, float distanceX, 78 | float distanceY); 79 | 80 | boolean onDragEnd(MotionEvent e1, MotionEvent e2); 81 | 82 | boolean onTapUp(); 83 | } 84 | 85 | class MyGestureListener extends GestureDetector.SimpleOnGestureListener { 86 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, 87 | float distanceY) { 88 | if (mListener == null) { 89 | Log.d(DEBUG_TAG, "NULL"); 90 | return true; 91 | } 92 | if (mStarted == false) { 93 | Log.d(DEBUG_TAG, "onDragStart " + mStarted); 94 | mListener.onDragStart(e1, e2, distanceX, distanceY); 95 | mStarted = true; 96 | } else { 97 | Log.d(DEBUG_TAG, "onDragContinue " + mStarted); 98 | mListener.onDragContinue(e1, e2, distanceX, distanceY); 99 | //mOriginalEvent = e1; 100 | return true; 101 | } 102 | mOriginalEvent = e1; 103 | return true; 104 | } 105 | 106 | @Override 107 | public boolean onSingleTapUp(MotionEvent e) { 108 | Log.d(DEBUG_TAG, "OnSingTapUp" + mStarted); 109 | return mListener.onTapUp(); 110 | } 111 | } 112 | 113 | 114 | } 115 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/fragments/Connect.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.fragments; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.tinderview.R; 11 | import com.tinderview.adapters.CardStackAdapter; 12 | import com.tinderview.animation.RippleAnimation; 13 | import com.tinderview.cardstatck.cardstack.CardStack; 14 | import com.tinderview.cardstatck.cardstack.DefaultStackEventListener; 15 | 16 | /** 17 | * Created by Aradh Pillai on 2/10/15. 18 | */ 19 | 20 | /* 21 | * this fragment class is using to show the list of connection into stackCard based on users location 22 | * and user will have option to discard and like the connection. 23 | * 24 | * 25 | * */ 26 | public class Connect extends Fragment { 27 | RippleAnimation rippleBackground1, rippleBackground2; 28 | 29 | CardStack cardStack; 30 | //this class is using for swipe the AdapterView 31 | CardStackAdapter mCardAdapter; 32 | 33 | 34 | @Override 35 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 36 | View view = inflater.inflate(R.layout.fragment_connect, container, false); 37 | 38 | init(view);// to initialize widgets 39 | doRippleBackground(); //start ripple background work.. 40 | return view; 41 | } 42 | 43 | private void init(View view) { 44 | //root ripple background initialization 45 | rippleBackground1 = (RippleAnimation) view.findViewById(R.id.content); 46 | 47 | //child ripple background initialization 48 | // rippleBackground2 = (RippleBackground) view.findViewById(R.id.content2); 49 | 50 | //cardStack initialization 51 | cardStack = (CardStack) view.findViewById(R.id.frame); 52 | 53 | //at begin setting rippleBackground visibility as VISIBLE and setting CardStack visibility as GONE 54 | rippleBackground1.setVisibility(View.VISIBLE); 55 | cardStack.setVisibility(View.GONE); 56 | 57 | //creating adapter 58 | mCardAdapter = new CardStackAdapter(getActivity().getApplicationContext(), 0); 59 | } 60 | 61 | public void doRippleBackground() { 62 | 63 | 64 | //start ripple background animations 65 | startAnimation(); 66 | 67 | //handler created to handle cardStack as well as timer... 68 | new Handler().postDelayed(new Runnable() { 69 | @Override 70 | public void run() { 71 | 72 | callCardStack(); 73 | } 74 | }, 8000); 75 | 76 | } 77 | 78 | //start the background ripple animation... 79 | private void startAnimation() { 80 | //if it's not running 81 | if (!rippleBackground1.isRippleAnimationRunning()) { 82 | rippleBackground1.startRippleAnimation();//start root ripple animation 83 | // rippleBackground2.startRippleAnimation();//start child ripple animation 84 | } 85 | } 86 | 87 | //this method will stop background ripple animation. if it's running. 88 | private void stopAnimation() { 89 | if (rippleBackground1.isRippleAnimationRunning()) { 90 | rippleBackground1.stopRippleAnimation(); 91 | // rippleBackground2.stopRippleAnimation(); 92 | } 93 | } 94 | 95 | //cardStack view will set it as visible and load the information into stack. 96 | public void callCardStack() { 97 | 98 | cardStack.setVisibility(View.VISIBLE); 99 | rippleBackground1.setVisibility(View.GONE); 100 | 101 | stopAnimation();//start the ripple background animation. 102 | 103 | //Setting Resource of CardStack 104 | cardStack.setContentResource(R.layout.card_stack_item); 105 | 106 | //Adding 30 dummy info for CardStack 107 | for (int i = 0; i <= 30; i++) 108 | mCardAdapter.add("" + i); 109 | cardStack.setAdapter(mCardAdapter); 110 | 111 | //Setting Listener and passing distance as a parameter , 112 | //based on the distance card will discard 113 | //if dragging card distance would be more than specified distance(100) then card will discard or else card will reverse on same position. 114 | cardStack.setListener(new DefaultStackEventListener(300)); 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/cardstatck/cardstack/CardUtils.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.cardstatck.cardstack; 2 | 3 | import android.util.Log; 4 | import android.view.View; 5 | import android.widget.RelativeLayout; 6 | import android.widget.RelativeLayout.LayoutParams; 7 | 8 | 9 | /* 10 | * CardUtils is using for set the card scale , get the selected layout param, scaleFrom, moveFrom and direction of card. 11 | * All these method are static which means it is going to access from some others classes and it returns the value based on the 12 | * passed parameter. 13 | * 14 | * */ 15 | public class CardUtils { 16 | final static int DIRECTION_TOP_LEFT = 0; 17 | final static int DIRECTION_TOP_RIGHT = 1; 18 | final static int DIRECTION_BOTTOM_LEFT = 2; 19 | final static int DIRECTION_BOTTOM_RIGHT = 3; 20 | 21 | //it remove some pixels from the each sides of given view and then set that layout to view using setLayoutParams method. 22 | public static void scale(View v, int pixel) { 23 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams(); 24 | params.leftMargin -= pixel; 25 | params.rightMargin -= pixel; 26 | params.topMargin -= pixel; 27 | params.bottomMargin -= pixel; 28 | v.setLayoutParams(params); 29 | } 30 | 31 | 32 | //setting the layout margin dynamically to make it as stack view and returning the layoutParams object. 33 | public static LayoutParams getMoveParams(View v, int upDown, int leftRight) { 34 | RelativeLayout.LayoutParams original = (RelativeLayout.LayoutParams) v.getLayoutParams(); 35 | //RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(original); 36 | RelativeLayout.LayoutParams params = cloneParams(original); 37 | params.leftMargin += leftRight; 38 | params.rightMargin -= leftRight; 39 | Log.d("moving...", params.leftMargin + ""); 40 | 41 | params.topMargin -= upDown; 42 | params.bottomMargin += upDown; 43 | return params; 44 | } 45 | 46 | //used to move the card based on parameter, from this method again it's calling the getMoveParams(v,upDown,leftRight) methods 47 | public static void move(View v, int upDown, int leftRight) { 48 | RelativeLayout.LayoutParams params = getMoveParams(v, upDown, leftRight); 49 | v.setLayoutParams(params); 50 | } 51 | 52 | 53 | //setting the scale of card dynamically based on the parameters 54 | public static LayoutParams scaleFrom(View v, LayoutParams params, int pixel) { 55 | Log.d("pixel", "onScroll: " + pixel); 56 | params = cloneParams(params); 57 | params.leftMargin -= pixel; 58 | params.rightMargin -= pixel; 59 | params.topMargin -= pixel; 60 | params.bottomMargin -= pixel; 61 | Log.d("pixel", "onScroll: " + pixel); 62 | v.setLayoutParams(params); 63 | 64 | return params; 65 | } 66 | 67 | 68 | //setting the card margin based on the values using leftRight and Updown variables 69 | //this method is calling for secondary view 70 | 71 | public static LayoutParams moveFrom(View v, LayoutParams params, int leftRight, int upDown) { 72 | params = cloneParams(params); 73 | params.leftMargin += leftRight; 74 | params.rightMargin -= leftRight; 75 | params.topMargin -= upDown; 76 | params.bottomMargin += upDown; 77 | v.setLayoutParams(params); 78 | 79 | return params; 80 | } 81 | 82 | //a copy method for RelativeLayout.LayoutParams for backward compatibility 83 | public static RelativeLayout.LayoutParams cloneParams(RelativeLayout.LayoutParams params) { 84 | RelativeLayout.LayoutParams copy = new RelativeLayout.LayoutParams(params.width, params.height); 85 | copy.leftMargin = params.leftMargin; 86 | copy.topMargin = params.topMargin; 87 | copy.rightMargin = params.rightMargin; 88 | copy.bottomMargin = params.bottomMargin; 89 | int[] rules = params.getRules(); 90 | for (int i = 0; i < rules.length; i++) { 91 | copy.addRule(i, rules[i]); 92 | } 93 | copy.setMarginStart(params.getMarginStart()); 94 | copy.setMarginEnd(params.getMarginEnd()); 95 | 96 | return copy; 97 | } 98 | 99 | 100 | //giving the distance in between the cards 101 | public static float distance(float x1, float y1, float x2, float y2) { 102 | Log.d("Data: ", "" + Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))); 103 | return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); 104 | } 105 | 106 | 107 | // in which direction user dum card, that location this method will return ... 108 | // we can get to know that whether user has liked or dislike the card... 109 | //eg: 110 | // 0 | 1 111 | //-------- 112 | // 2 | 3 113 | // dislike value : even this method return the 0 or 2 114 | // like value: 1 or 3 115 | 116 | public static int direction(float x1, float y1, float x2, float y2) { 117 | if (x2 > x1) {//RIGHT 118 | if (y2 > y1) {//BOTTOM 119 | return DIRECTION_BOTTOM_RIGHT; 120 | } else {//TOP 121 | return DIRECTION_TOP_RIGHT; 122 | } 123 | } else {//LEFT 124 | if (y2 > y1) {//BOTTOM 125 | return DIRECTION_BOTTOM_LEFT; 126 | } else {//TOP 127 | return DIRECTION_TOP_LEFT; 128 | } 129 | } 130 | } 131 | 132 | 133 | } 134 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/tabbarview/CheatSheet.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.tabbarview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.text.TextUtils; 6 | import android.view.Gravity; 7 | import android.view.View; 8 | import android.widget.Toast; 9 | 10 | /** 11 | * Helper class for showing cheat sheets (tooltips) for icon-only UI elements on long-press. This is 12 | * already default platform behavior for icon-only {@link android.app.ActionBar} items and tabs. 13 | * This class provides this behavior for any other such UI element. 14 | */ 15 | public class CheatSheet { 16 | /** 17 | * The estimated height of a toast, in dips (density-independent pixels). This is used to 18 | * determine whether or not the toast should appear above or below the UI element. 19 | */ 20 | private static final int ESTIMATED_TOAST_HEIGHT_DIPS = 48; 21 | 22 | /** 23 | * Sets up a cheat sheet (tooltip) for the given view by setting its {@link 24 | * View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with 25 | * the view's {@link View#getContentDescription() content description} will be 26 | * shown either above (default) or below the view (if there isn't room above it). 27 | * 28 | * @param view The view to add a cheat sheet for. 29 | */ 30 | public static void setup(View view) { 31 | view.setOnLongClickListener(new View.OnLongClickListener() { 32 | @Override 33 | public boolean onLongClick(View view) { 34 | return showCheatSheet(view, view.getContentDescription()); 35 | } 36 | }); 37 | } 38 | 39 | /** 40 | * Sets up a cheat sheet (tooltip) for the given view by setting its {@link 41 | * View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with 42 | * the given text will be shown either above (default) or below the view (if there isn't room 43 | * above it). 44 | * 45 | * @param view The view to add a cheat sheet for. 46 | * @param textResId The string resource containing the text to show on long-press. 47 | */ 48 | public static void setup(View view, final int textResId) { 49 | view.setOnLongClickListener(new View.OnLongClickListener() { 50 | @Override 51 | public boolean onLongClick(View view) { 52 | return showCheatSheet(view, view.getContext().getString(textResId)); 53 | } 54 | }); 55 | } 56 | 57 | /** 58 | * Sets up a cheat sheet (tooltip) for the given view by setting its {@link 59 | * View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with 60 | * the given text will be shown either above (default) or below the view (if there isn't room 61 | * above it). 62 | * 63 | * @param view The view to add a cheat sheet for. 64 | * @param text The text to show on long-press. 65 | */ 66 | public static void setup(View view, final CharSequence text) { 67 | view.setOnLongClickListener(new View.OnLongClickListener() { 68 | @Override 69 | public boolean onLongClick(View view) { 70 | return showCheatSheet(view, text); 71 | } 72 | }); 73 | } 74 | 75 | /** 76 | * Removes the cheat sheet for the given view by removing the view's {@link 77 | * View.OnLongClickListener}. 78 | * 79 | * @param view The view whose cheat sheet should be removed. 80 | */ 81 | public static void remove(final View view) { 82 | view.setOnLongClickListener(null); 83 | } 84 | 85 | /** 86 | * Internal helper method to show the cheat sheet toast. 87 | */ 88 | private static boolean showCheatSheet(View view, CharSequence text) { 89 | if (TextUtils.isEmpty(text)) { 90 | return false; 91 | } 92 | 93 | final int[] screenPos = new int[2]; // origin is device display 94 | final Rect displayFrame = new Rect(); // includes decorations (e.g. status bar) 95 | view.getLocationOnScreen(screenPos); 96 | view.getWindowVisibleDisplayFrame(displayFrame); 97 | 98 | final Context context = view.getContext(); 99 | final int viewWidth = view.getWidth(); 100 | final int viewHeight = view.getHeight(); 101 | final int viewCenterX = screenPos[0] + viewWidth / 2; 102 | final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; 103 | final int estimatedToastHeight = (int) (ESTIMATED_TOAST_HEIGHT_DIPS 104 | * context.getResources().getDisplayMetrics().density); 105 | 106 | Toast cheatSheet = Toast.makeText(context, text, Toast.LENGTH_SHORT); 107 | boolean showBelow = screenPos[1] < estimatedToastHeight; 108 | if (showBelow) { 109 | // Show below 110 | // Offsets are after decorations (e.g. status bar) are factored in 111 | cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 112 | viewCenterX - screenWidth / 2, 113 | screenPos[1] - displayFrame.top + viewHeight); 114 | } else { 115 | // Show above 116 | // Offsets are after decorations (e.g. status bar) are factored in 117 | // NOTE: We can't use Gravity.BOTTOM because when the keyboard is up 118 | // its height isn't factored in. 119 | cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 120 | viewCenterX - screenWidth / 2, 121 | screenPos[1] - displayFrame.top - estimatedToastHeight); 122 | } 123 | 124 | cheatSheet.show(); 125 | return true; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /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 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /mobile/mobile.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/activities/MainScreenActivity.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.activities; 2 | 3 | 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentManager; 8 | import android.support.v4.app.FragmentStatePagerAdapter; 9 | import android.support.v4.view.ViewPager; 10 | import android.support.v7.app.ActionBar; 11 | import android.support.v7.widget.Toolbar; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.util.Log; 14 | import android.view.LayoutInflater; 15 | import android.view.Menu; 16 | import android.view.MenuItem; 17 | import android.view.View; 18 | 19 | import com.tinderview.R; 20 | import com.tinderview.fragments.Connect; 21 | import com.tinderview.fragments.Discover; 22 | import com.tinderview.fragments.Chat; 23 | 24 | import com.tinderview.tabbarview.TabBarView; 25 | import com.tinderview.util.CustomViewPager; 26 | 27 | /* created by Aradh Pillai on 05/10/15 28 | * 29 | * this class is our home Screen in which all tabs has define 30 | * Toolbar I have used 31 | * Customized ViewPager 32 | * CardStack 33 | */ 34 | public class MainScreenActivity extends AppCompatActivity { 35 | 36 | //this context using in 37 | public static Context context; 38 | public static CustomViewPager mViewPager; 39 | /*Toolbar use and set the tab dynamically 40 | setting custom design to Toolbar 41 | */ 42 | Toolbar toolbar; 43 | private String TAG = "MainScreenActivity"; 44 | private TabBarView mTabBarView; 45 | private MainScreenPagerAdapter mMainScreenPagerAdapter; 46 | //Data 47 | private int PAGE_COUNT = 3; 48 | 49 | 50 | @Override 51 | protected void onCreate(Bundle savedInstanceState) { 52 | super.onCreate(savedInstanceState); 53 | 54 | Log.i(TAG, "MainScreenActivity: onCreate()"); 55 | context = this; 56 | //using sharedPreference to check whether this is using first time on not... 57 | //even this app is starting first time than from here it will call the OnBoardActivity and updated the value 58 | //even this app is already started than this screen will work... 59 | 60 | //from here it's started 61 | 62 | //setting the layout 63 | setContentView(R.layout.activity_home); 64 | 65 | //checking sdk version and giving shadow effect 66 | 67 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { 68 | findViewById(R.id.shadow_prelollipop).setVisibility(View.GONE); 69 | } else { 70 | findViewById(R.id.shadow_prelollipop).setVisibility(View.VISIBLE); 71 | } 72 | 73 | 74 | //Setting Custom Toolbar 75 | setToolBar(); 76 | 77 | //Setting all 3 Customized Tabs 78 | setUpCustomTabs(); 79 | 80 | //Setting the pagerListener 81 | setPagerListener(); 82 | 83 | } 84 | 85 | //using to set custom design , actions and tabView into toolbar 86 | private void setToolBar() { 87 | toolbar = (Toolbar) findViewById(R.id.toolbar); 88 | setSupportActionBar(toolbar); 89 | 90 | LayoutInflater mLayoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 91 | 92 | //setting TabBarView 93 | View customTabView = mLayoutInflater.inflate(R.layout.custom_tab_view, null); 94 | mTabBarView = (TabBarView) customTabView.findViewById(R.id.customTabBar); 95 | mTabBarView.setStripHeight(7); 96 | 97 | mTabBarView.setStripColor(getResources().getColor(R.color.white)); 98 | 99 | //setting the properties of ActionBar 100 | 101 | getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); 102 | getSupportActionBar().setDisplayHomeAsUpEnabled(false); 103 | getSupportActionBar().setHomeButtonEnabled(false); 104 | 105 | //Setting the Customized Toolbar into toolbar object 106 | toolbar.addView(customTabView); 107 | } 108 | 109 | 110 | private void setUpCustomTabs() { 111 | 112 | //setting of ViewPager 113 | mMainScreenPagerAdapter = new MainScreenPagerAdapter(getSupportFragmentManager()); 114 | mViewPager = (CustomViewPager) findViewById(R.id.pager); 115 | mViewPager.setAdapter(mMainScreenPagerAdapter); 116 | 117 | //Setting the CustomizedViewPager into Toolbar for tabOption 118 | mTabBarView.setViewPager(mViewPager); 119 | 120 | 121 | } 122 | 123 | 124 | @Override 125 | public boolean onCreateOptionsMenu(Menu menu) { 126 | // Inflate the menu; this adds items to the action bar if it is present. 127 | getMenuInflater().inflate(R.menu.menu_main, menu); 128 | return true; 129 | } 130 | 131 | @Override 132 | public boolean onOptionsItemSelected(MenuItem item) { 133 | // Handle action bar card_stack_item clicks here. The action bar will 134 | // automatically handle clicks on the Home/Up button, so long 135 | // as you specify a parent activity in AndroidManifest.xml. 136 | int id = item.getItemId(); 137 | 138 | //noinspection SimplifiableIfStatement 139 | if (id == R.id.action_settings) { 140 | return true; 141 | } 142 | 143 | return super.onOptionsItemSelected(item); 144 | } 145 | 146 | 147 | private void setPagerListener() { 148 | mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 149 | @Override 150 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 151 | mTabBarView.onPageScrolled(position, positionOffset, positionOffsetPixels); 152 | } 153 | 154 | @Override 155 | public void onPageSelected(int position) { 156 | Log.i(TAG, "Page: " + position); 157 | mTabBarView.onPageSelected(position); 158 | } 159 | 160 | @Override 161 | public void onPageScrollStateChanged(int state) { 162 | mTabBarView.onPageScrollStateChanged(state); 163 | } 164 | }); 165 | } 166 | 167 | 168 | // class is implemented with IconTabProvider Interface as well as extends with FragmentStateAdapter for ViewPager 169 | //with different tabIcons 170 | public class MainScreenPagerAdapter extends FragmentStatePagerAdapter implements TabBarView.IconTabProvider { 171 | 172 | 173 | //Defining the array for Tab icons..which is going to call dynamically and load it into tabBar of toolbar 174 | private int[] tab_icons = { 175 | R.drawable.ic_connect, 176 | R.drawable.ic_list, 177 | R.drawable.ic_chat 178 | }; 179 | 180 | public MainScreenPagerAdapter(FragmentManager fm) { 181 | super(fm); 182 | } 183 | 184 | 185 | //this method is returning the ref of our fragments 186 | @Override 187 | public Fragment getItem(int pos) { 188 | switch (pos) { 189 | case 0: 190 | return new Connect(); 191 | case 1: 192 | return new Discover(); 193 | case 2: 194 | return new Chat(); 195 | default: 196 | return null; 197 | } 198 | } 199 | 200 | //returning the number of pages 201 | @Override 202 | public int getCount() { 203 | return PAGE_COUNT; 204 | } 205 | 206 | 207 | //this is TabBarView.IconTabProvider's method to return the position of icon to load into tabBar of Toolbar 208 | @Override 209 | public int getPageIconResId(int position) { 210 | return tab_icons[position]; 211 | } 212 | 213 | @Override 214 | public CharSequence getPageTitle(int position) { 215 | switch (position) { 216 | case 0: 217 | return "Connect"; 218 | case 1: 219 | return "Discover"; 220 | case 2: 221 | return "Chat"; 222 | } 223 | return null; 224 | } 225 | } 226 | } -------------------------------------------------------------------------------- /wear/wear.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/animation/RippleAnimation.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.animation; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorSet; 5 | import android.animation.ObjectAnimator; 6 | import android.content.Context; 7 | import android.content.res.TypedArray; 8 | import android.graphics.Canvas; 9 | import android.graphics.Paint; 10 | import android.util.AttributeSet; 11 | import android.view.View; 12 | import android.view.animation.AccelerateDecelerateInterpolator; 13 | import android.widget.RelativeLayout; 14 | 15 | import com.tinderview.R; 16 | 17 | import java.util.ArrayList; 18 | 19 | /** 20 | * Created by Aradh Pillai on 14/10/15. 21 | *

22 | * This class is creating for Background Ripple Animation 23 | */ 24 | 25 | public class RippleAnimation extends RelativeLayout { 26 | 27 | private static final int DEFAULT_RIPPLE_COUNT = 6; 28 | private static final int DEFAULT_DURATION_TIME = 3000; 29 | private static final float DEFAULT_SCALE = 6.0f; 30 | private static final int DEFAULT_FILL_TYPE = 0; 31 | 32 | private int rippleColor; 33 | private float rippleStrokeWidth; 34 | private float rippleRadius; 35 | private int rippleDurationTime; 36 | private int rippleAmount; 37 | private int rippleDelay; 38 | private float rippleScale; 39 | private int rippleType; 40 | private Paint paint; 41 | private boolean animationRunning = false; 42 | private AnimatorSet animatorSet; 43 | private ArrayList animatorList; 44 | private LayoutParams rippleParams; 45 | private ArrayList rippleViewList = new ArrayList(); 46 | 47 | 48 | //constructor with single parameter 49 | public RippleAnimation(Context context) { 50 | super(context); 51 | } 52 | 53 | public RippleAnimation(Context context, AttributeSet attrs) { 54 | super(context, attrs); 55 | init(context, attrs); 56 | } 57 | 58 | //Parameter Constructor 59 | public RippleAnimation(Context context, AttributeSet attrs, int defStyleAttr) { 60 | super(context, attrs, defStyleAttr); 61 | init(context, attrs); 62 | } 63 | 64 | //initialized and sets all the properties of RippleAnimation 65 | private void init(final Context context, final AttributeSet attrs) { 66 | if (isInEditMode()) 67 | return; 68 | 69 | if (null == attrs) { 70 | throw new IllegalArgumentException("Attributes should be provided to this view,"); 71 | } 72 | 73 | //created typedArray and setting all properties to typedArray object 74 | final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RippleAnimation); 75 | 76 | //it will return ripple color even we have specified into xml or else it will get the default ripple Color 77 | rippleColor = typedArray.getColor(R.styleable.RippleAnimation_rb_color, getResources().getColor(R.color.rippleColor)); 78 | 79 | //getting rippleStrokeWidth from typedArray object and putting it into rippleStrokeWidth variable 80 | rippleStrokeWidth = typedArray.getDimension(R.styleable.RippleAnimation_rb_strokeWidth, getResources().getDimension(R.dimen.rippleStrokeWidth)); 81 | 82 | //rippleRadius contains the default the specified radius even we specified or else it takes default radius...which is 64dp 83 | rippleRadius = typedArray.getDimension(R.styleable.RippleAnimation_rb_radius, getResources().getDimension(R.dimen.rippleRadius)); 84 | 85 | //setting rippleAnimation duration is specified or else it takes default Duration Time. 86 | rippleDurationTime = typedArray.getInt(R.styleable.RippleAnimation_rb_duration, DEFAULT_DURATION_TIME); 87 | 88 | //number of ripple if we have specified into design part or else default value it will take. 89 | rippleAmount = typedArray.getInt(R.styleable.RippleAnimation_rb_rippleAmount, DEFAULT_RIPPLE_COUNT); 90 | 91 | //setting scale of ripple 92 | rippleScale = typedArray.getFloat(R.styleable.RippleAnimation_rb_scale, DEFAULT_SCALE); 93 | 94 | //its getting the ripple type and putting it into rippleType variable. 95 | rippleType = typedArray.getInt(R.styleable.RippleAnimation_rb_type, DEFAULT_FILL_TYPE); 96 | 97 | /** 98 | * Recycles the TypedArray, to be re-used by a later caller. After calling 99 | * this function you must not ever touch the typed array again. 100 | * 101 | * @throws RuntimeException if the TypedArray has already been recycled. 102 | */ 103 | typedArray.recycle(); 104 | 105 | rippleDelay = rippleDurationTime / rippleAmount; 106 | 107 | paint = new Paint();//creating an object of paint to make ripple based on the ripple type 108 | paint.setAntiAlias(true); 109 | if (rippleType == DEFAULT_FILL_TYPE) { 110 | rippleStrokeWidth = 0; 111 | paint.setStyle(Paint.Style.FILL); 112 | } else 113 | paint.setStyle(Paint.Style.STROKE); 114 | paint.setColor(rippleColor); 115 | 116 | rippleParams = new LayoutParams((int) (2 * (rippleRadius + rippleStrokeWidth)), (int) (2 * (rippleRadius + rippleStrokeWidth))); 117 | rippleParams.addRule(CENTER_IN_PARENT, TRUE);//setting ripple into center 118 | 119 | animatorSet = new AnimatorSet();// creates animationSet object 120 | animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); 121 | animatorList = new ArrayList(); 122 | 123 | 124 | /*based on the number of ripple this for loop create ripple View and put three different animation for this view.. 125 | * 126 | * */ 127 | for (int i = 0; i < rippleAmount; i++) { 128 | RippleView rippleView = new RippleView(getContext());//created ripple 129 | addView(rippleView, rippleParams);//adding view 130 | rippleViewList.add(rippleView);//putting this view into rippleViewList object 131 | 132 | 133 | //creating objectAnimator object and setting some X Scale properties to object and putting it into animatorList 134 | final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(rippleView, "ScaleX", 1.0f, rippleScale); 135 | scaleXAnimator.setRepeatCount(ObjectAnimator.INFINITE); 136 | scaleXAnimator.setRepeatMode(ObjectAnimator.RESTART); 137 | scaleXAnimator.setStartDelay(i * rippleDelay); 138 | scaleXAnimator.setDuration(rippleDurationTime); 139 | animatorList.add(scaleXAnimator); 140 | 141 | //creating objectAnimator object and setting some Y Scale properties to object and putting it into animatorList 142 | final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(rippleView, "ScaleY", 1.0f, rippleScale); 143 | scaleYAnimator.setRepeatCount(ObjectAnimator.INFINITE); 144 | scaleYAnimator.setRepeatMode(ObjectAnimator.RESTART); 145 | scaleYAnimator.setStartDelay(i * rippleDelay); 146 | scaleYAnimator.setDuration(rippleDurationTime); 147 | animatorList.add(scaleYAnimator); 148 | 149 | //setting alpha of the animation and putting it into animatorList 150 | final ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rippleView, "Alpha", 1.0f, 0f); 151 | alphaAnimator.setRepeatCount(ObjectAnimator.INFINITE); 152 | alphaAnimator.setRepeatMode(ObjectAnimator.RESTART); 153 | alphaAnimator.setStartDelay(i * rippleDelay); 154 | alphaAnimator.setDuration(rippleDurationTime); 155 | animatorList.add(alphaAnimator); 156 | } 157 | 158 | //played animator 159 | animatorSet.playTogether(animatorList); 160 | } 161 | 162 | //used to start ripple Animation 163 | public void startRippleAnimation() { 164 | if (!isRippleAnimationRunning()) { 165 | for (RippleView rippleView : rippleViewList) { 166 | rippleView.setVisibility(VISIBLE); 167 | } 168 | animatorSet.start();//animation started 169 | animationRunning = true;//setting value as true... this will support to check isRippleAnimation is running or not. 170 | } 171 | } 172 | 173 | public void stopRippleAnimation() { 174 | if (isRippleAnimationRunning()) { 175 | animatorSet.end(); 176 | animationRunning = false; 177 | } 178 | } 179 | 180 | //stopping ripple Animation using end() method and setting boolean value false to animationRunning 181 | 182 | /*call this method to check whether animation is running or not. 183 | * then basically it return the animationRunning boolean value. 184 | * 185 | * even we have stopped animation then it will return false value. 186 | * or even we have not stopped animation then it will return true value. 187 | */ 188 | public boolean isRippleAnimationRunning() { 189 | return animationRunning; 190 | } 191 | 192 | //this class is using to draw the circle 193 | private class RippleView extends View { 194 | 195 | public RippleView(Context context) { 196 | super(context); 197 | this.setVisibility(View.INVISIBLE); 198 | } 199 | 200 | //it's drawing ripple based on radius value. 201 | @Override 202 | protected void onDraw(Canvas canvas) { 203 | int radius = (Math.min(getWidth(), getHeight())) / 2; 204 | canvas.drawCircle(radius, radius, radius - rippleStrokeWidth, paint); 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/tabbarview/TabBarView.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.tabbarview; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.support.v4.view.ViewPager; 9 | import android.support.v4.view.ViewPager.OnPageChangeListener; 10 | import android.util.AttributeSet; 11 | import android.view.View; 12 | import android.view.ViewTreeObserver.OnGlobalLayoutListener; 13 | import android.widget.LinearLayout; 14 | 15 | import com.tinderview.R; 16 | 17 | /* 18 | * created by Aradh Pillai on 1.10.15 19 | * this class is inheriting features of LinearLayout 20 | * using this it's creating TabBarView dynamically 21 | * 22 | * 23 | * */ 24 | 25 | public class TabBarView extends LinearLayout { 26 | //strip height has defined here 27 | private static final int STRIP_HEIGHT = 6; 28 | public static int mSelectedTab = 0; 29 | public static int tabCount;//hold the number of tabs 30 | public static int a; 31 | public final Paint mPaint; 32 | //this pager will hold the instance of viewPager 33 | //and rearrange the pages using the object 34 | public ViewPager pager; 35 | public OnPageChangeListener delegatePageListener; 36 | // TabView class objects 37 | private TabView tabView1, tabView2, tabView3; 38 | private int mStripHeight; 39 | private float mOffset = 0f; 40 | private View child; 41 | 42 | private View nextChild; 43 | 44 | public TabBarView(Context context) { 45 | this(context, null); 46 | } 47 | 48 | public TabBarView(Context context, AttributeSet attrs) { 49 | this(context, attrs, R.attr.actionBarTabBarStyle); 50 | } 51 | 52 | public TabBarView(Context context, AttributeSet attrs, int defStyle) { 53 | super(context, attrs, defStyle); 54 | 55 | setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 56 | LayoutParams.MATCH_PARENT)); 57 | 58 | setWillNotDraw(false); 59 | 60 | mPaint = new Paint(); 61 | mPaint.setColor(Color.WHITE); 62 | 63 | mPaint.setAntiAlias(false); 64 | 65 | mStripHeight = (int) (STRIP_HEIGHT * getResources().getDisplayMetrics().density + .5f); 66 | } 67 | 68 | //use to set StripColor 69 | public void setStripColor(int color) { 70 | if (mPaint.getColor() != color) { 71 | mPaint.setColor(color); 72 | invalidate(); 73 | } 74 | } 75 | 76 | //Use to set the height of strip 77 | public void setStripHeight(int height) { 78 | if (mStripHeight != height) { 79 | mStripHeight = height; 80 | invalidate(); 81 | } 82 | } 83 | 84 | //using to set the tab based on Tabindex which is need to pass as parameter. 85 | public void setSelectedTab(int tabIndex) { 86 | if (tabIndex < 0) { 87 | tabIndex = 0; 88 | } 89 | final int childCount = getChildCount(); 90 | if (tabIndex >= childCount) { 91 | tabIndex = childCount - 1; 92 | } 93 | if (mSelectedTab != tabIndex) { 94 | mSelectedTab = tabIndex; 95 | invalidate(); 96 | } 97 | } 98 | 99 | public void setOffset(int position, float offset) { 100 | if (mOffset != offset) { 101 | mOffset = offset; 102 | invalidate(); 103 | } 104 | } 105 | 106 | //this method is using to draw the strip 107 | @Override 108 | protected void onDraw(Canvas canvas) { 109 | super.onDraw(canvas); 110 | // Draw the strip manually 111 | child = getChildAt(mSelectedTab); 112 | int height = getHeight(); 113 | if (child != null) { 114 | float left = child.getLeft(); 115 | float right = child.getRight(); 116 | if (mOffset > 0f && mSelectedTab < tabCount - 1) { 117 | nextChild = getChildAt(mSelectedTab + 1); 118 | if (nextChild != null) { 119 | final float nextTabLeft = nextChild.getLeft(); 120 | final float nextTabRight = nextChild.getRight(); 121 | left = (mOffset * nextTabLeft + (1f - mOffset) * left); 122 | right = (mOffset * nextTabRight + (1f - mOffset) * right); 123 | } 124 | } 125 | canvas.drawRect(left, height - mStripHeight, right, height, mPaint); 126 | } 127 | } 128 | 129 | //this method is used to set the pager reference to this.pager object and call the notifyDataSetChanged() method 130 | // 131 | public void setViewPager(ViewPager pager) { 132 | this.pager = pager; 133 | 134 | if (pager.getAdapter() == null) { 135 | throw new IllegalStateException("ViewPager does not have adapter instance."); 136 | } 137 | 138 | notifyDataSetChanged(); 139 | } 140 | 141 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 142 | 143 | mSelectedTab = position; 144 | mOffset = positionOffset; 145 | 146 | invalidate(); 147 | 148 | if (delegatePageListener != null) { 149 | delegatePageListener.onPageScrolled(position, positionOffset, positionOffsetPixels); 150 | } 151 | 152 | //based on the position setting tab alpha as 1 if it's selected or others set is as 0.5f 153 | if (position == 0) { 154 | tabView1.setAlpha(1.0f); 155 | tabView2.setAlpha(0.5f); 156 | tabView3.setAlpha(0.5f); 157 | 158 | } else if (position == 1) { 159 | tabView1.setAlpha(0.5f); 160 | tabView2.setAlpha(1.0f); 161 | tabView3.setAlpha(0.5f); 162 | 163 | } else if (position == 2) { 164 | tabView1.setAlpha(0.5f); 165 | tabView2.setAlpha(0.5f); 166 | tabView3.setAlpha(1.0f); 167 | 168 | } 169 | } 170 | 171 | public void onPageScrollStateChanged(int state) { 172 | if (state == ViewPager.SCROLL_STATE_IDLE) { 173 | 174 | } 175 | 176 | if (delegatePageListener != null) { 177 | delegatePageListener.onPageScrollStateChanged(state); 178 | } 179 | } 180 | 181 | public void onPageSelected(int position) { 182 | if (delegatePageListener != null) { 183 | delegatePageListener.onPageSelected(position); 184 | } 185 | } 186 | 187 | // it will remove all previous views and creating new view for tab 188 | public void notifyDataSetChanged() { 189 | 190 | int resId; 191 | 192 | this.removeAllViews(); 193 | 194 | tabCount = pager.getAdapter().getCount(); 195 | 196 | for (int i = 0; i < tabCount; i++) { 197 | 198 | resId = ((IconTabProvider) pager.getAdapter()).getPageIconResId(i); 199 | 200 | if (getResources().getConfiguration().orientation == 1) 201 | addTabViewP(i, pager.getAdapter().getPageTitle(i).toString(), resId); 202 | else 203 | addTabViewL(i, pager.getAdapter().getPageTitle(i).toString(), resId); 204 | } 205 | 206 | //removing swiping animation effect from viewPager 207 | 208 | 209 | getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 210 | 211 | @SuppressLint("NewApi") 212 | @Override 213 | public void onGlobalLayout() { 214 | 215 | getViewTreeObserver().removeOnGlobalLayoutListener(this); 216 | 217 | mSelectedTab = pager.getCurrentItem(); 218 | 219 | } 220 | }); 221 | 222 | } 223 | 224 | //used to set the properties for landscape screen like icon,text and click-event into tab and then add this tab into View using addView(tab) method 225 | private void addTabViewL(final int i, String string, int pageIconResId) { 226 | // TODO Auto-generated method stub 227 | TabView tab = new TabView(getContext()); 228 | // tab.setIcon(pageIconResId); 229 | tab.setText(string, pageIconResId); 230 | tab.setOnClickListener(new OnClickListener() { 231 | @Override 232 | public void onClick(View v) { 233 | pager.setCurrentItem(i, false); 234 | } 235 | }); 236 | 237 | this.addView(tab); 238 | } 239 | 240 | private void addTabViewP(final int i, final String string, int pageIconResId) { 241 | // TODO Auto-generated method stub 242 | 243 | if (i == 0) { 244 | tabView1 = new TabView(getContext()); 245 | 246 | tabView1.setIcon(pageIconResId); 247 | tabView1.setOnClickListener(new OnClickListener() { 248 | @Override 249 | public void onClick(View v) { 250 | pager.setCurrentItem(i); 251 | 252 | 253 | } 254 | }); 255 | CheatSheet.setup(tabView1, string); 256 | this.addView(tabView1); 257 | } else if (i == 1) { 258 | tabView2 = new TabView(getContext()); 259 | tabView2.setIcon(pageIconResId); 260 | tabView2.setOnClickListener(new OnClickListener() { 261 | @Override 262 | public void onClick(View v) { 263 | pager.setCurrentItem(i); 264 | 265 | } 266 | }); 267 | CheatSheet.setup(tabView2, string); 268 | this.addView(tabView2); 269 | } else if (i == 2) { 270 | tabView3 = new TabView(getContext()); 271 | tabView3.setIcon(pageIconResId); 272 | tabView3.setOnClickListener(new OnClickListener() { 273 | @Override 274 | public void onClick(View v) { 275 | pager.setCurrentItem(i); 276 | 277 | } 278 | }); 279 | CheatSheet.setup(tabView3, string); 280 | this.addView(tabView3); 281 | } 282 | 283 | 284 | } 285 | 286 | //used to set the properties for portrait screen like icon and click-event into tabView objects 287 | // and then add this tab object into View using addView(tabView1) method 288 | //here we setup the tabs properties 289 | 290 | public void setOnPageChangeListener(OnPageChangeListener listener) { 291 | this.delegatePageListener = listener; 292 | } 293 | 294 | public interface IconTabProvider { 295 | int getPageIconResId(int position); 296 | } 297 | } -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/cardstatck/cardstack/CardStack.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.cardstatck.cardstack; 2 | 3 | import java.util.ArrayList; 4 | 5 | import android.animation.Animator; 6 | import android.animation.AnimatorListenerAdapter; 7 | import android.content.Context; 8 | import android.util.AttributeSet; 9 | import android.util.Log; 10 | import android.view.LayoutInflater; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.ArrayAdapter; 15 | import android.widget.FrameLayout; 16 | import android.widget.RelativeLayout; 17 | import android.database.DataSetObserver; 18 | 19 | 20 | public class CardStack extends RelativeLayout { 21 | ArrayList viewCollection = new ArrayList(); 22 | private int mIndex = 0; 23 | private int mNumVisible = 4; 24 | private ArrayAdapter mAdapter; 25 | private OnTouchListener mOnTouchListener; 26 | //private Queue mIdleStack = new Queue; 27 | private CardAnimator mCardAnimator; 28 | private CardEventListener mEventListener = new DefaultStackEventListener(10); 29 | private int mContentResource = 0; 30 | 31 | //method used to descard the top view based on direction...which is going to use by other widget 32 | //eg: using button we can call this method and we can pass the direction as parameter eg: 0 or 2 to discard the card... 33 | private DataSetObserver mOb = new DataSetObserver() { 34 | @Override 35 | public void onChanged() { 36 | reset(false); 37 | } 38 | }; 39 | 40 | 41 | //return the current index of card 42 | 43 | //only necessary when I need the attrs from xml, this will be used when inflating layout 44 | public CardStack(Context context, AttributeSet attrs) { 45 | super(context, attrs); 46 | 47 | 48 | //get attrs assign minVisiableNum 49 | for (int i = 0; i < mNumVisible; i++) { 50 | addContainerViews(); 51 | } 52 | setupAnimation(); 53 | } 54 | 55 | public CardStack(Context context) { 56 | super(context); 57 | } 58 | 59 | public void discardTop(final int direction) { 60 | mCardAnimator.discard(direction, new AnimatorListenerAdapter() { 61 | @Override 62 | public void onAnimationEnd(Animator arg0) { 63 | mCardAnimator.initLayout(); 64 | mIndex++; 65 | mEventListener.discarded(mIndex, direction); 66 | 67 | //mIndex = mIndex%mAdapter.getCount(); 68 | loadLast(); 69 | 70 | viewCollection.get(0).setOnTouchListener(null); 71 | viewCollection.get(viewCollection.size() - 1) 72 | .setOnTouchListener(mOnTouchListener); 73 | } 74 | }); 75 | } 76 | 77 | public int getCurrIndex() { 78 | //sync? 79 | return mIndex; 80 | } 81 | 82 | private void addContainerViews() { 83 | FrameLayout v = new FrameLayout(getContext()); 84 | viewCollection.add(v); 85 | addView(v); 86 | } 87 | 88 | public void setStackMargin(int margin) { 89 | mCardAnimator.setStackMargin(margin); 90 | mCardAnimator.initLayout(); 91 | } 92 | 93 | public void setContentResource(int res) { 94 | mContentResource = res; 95 | } 96 | 97 | //when need to reset the card into stack 98 | public void reset(boolean resetIndex) { 99 | if (resetIndex) mIndex = 0; 100 | removeAllViews(); 101 | viewCollection.clear(); 102 | for (int i = 0; i < mNumVisible; i++) { 103 | addContainerViews(); 104 | } 105 | setupAnimation(); 106 | loadData(); 107 | } 108 | 109 | public void setVisibleCardNum(int visiableNum) { 110 | mNumVisible = visiableNum; 111 | reset(false); 112 | } 113 | 114 | 115 | //setting the card animator and putting GestureDetectorListener and overriding the methods of DragListener interface 116 | //using this method can get to know the dragged card location 117 | //see the animation effect on that selected card 118 | 119 | public void setThreshold(int t) { 120 | mEventListener = new DefaultStackEventListener(t); 121 | } 122 | 123 | public void setListener(CardEventListener cel) { 124 | mEventListener = cel; 125 | } 126 | 127 | 128 | //ArrayList 129 | 130 | private void setupAnimation() { 131 | final View cardView = viewCollection.get(viewCollection.size() - 1); 132 | mCardAnimator = new CardAnimator(viewCollection); //creating an object of cardAnimator 133 | mCardAnimator.initLayout(); //initialize the cardAnimator using object 134 | 135 | final DragGestureDetector dd = new DragGestureDetector(CardStack.this.getContext(), new DragGestureDetector.DragListener() { 136 | 137 | 138 | //when drag of card will start this method invoke first 139 | @Override 140 | public boolean onDragStart(MotionEvent e1, MotionEvent e2, 141 | float distanceX, float distanceY) { 142 | mCardAnimator.drag(e1, e2, distanceX, distanceY); 143 | return true; 144 | } 145 | 146 | //user dragging the card continue then this method will invoke 147 | @Override 148 | public boolean onDragContinue(MotionEvent e1, MotionEvent e2, 149 | float distanceX, float distanceY) { 150 | float x1 = e1.getRawX(); 151 | float y1 = e1.getRawY(); 152 | float x2 = e2.getRawX(); 153 | float y2 = e2.getRawY(); 154 | //float distance = CardUtils.distance(x1,y1,x2,y2); 155 | final int direction = CardUtils.direction(x1, y1, x2, y2); 156 | mCardAnimator.drag(e1, e2, distanceX, distanceY); 157 | mEventListener.swipeContinue(direction, Math.abs(x2 - x1), Math.abs(y2 - y1)); 158 | return true; 159 | } 160 | 161 | /*when user dum the card then this method will invoke 162 | * here it will check the distance between the direction and the distance of the card 163 | *and based on that this method discard or reverse the card 164 | */ 165 | @Override 166 | public boolean onDragEnd(MotionEvent e1, MotionEvent e2) { 167 | //reverse(e1,e2); 168 | float x1 = e1.getRawX(); 169 | float y1 = e1.getRawY(); 170 | float x2 = e2.getRawX(); 171 | float y2 = e2.getRawY(); 172 | Log.d("onDragEndMethod", "dis:s"); 173 | float distance = CardUtils.distance(x1, y1, x2, y2); 174 | final int direction = CardUtils.direction(x1, y1, x2, y2); 175 | Log.d("onDragEndMethod", "dis: " + distance + " direction: " + direction); 176 | boolean discard = mEventListener.swipeEnd(direction, distance); 177 | if (discard) { 178 | Log.d("onDragEndMethod", "deleted"); 179 | mCardAnimator.discard(direction, new AnimatorListenerAdapter() { 180 | 181 | @Override 182 | public void onAnimationEnd(Animator arg0) { 183 | mCardAnimator.initLayout(); 184 | mIndex++; 185 | mEventListener.discarded(mIndex, direction); 186 | 187 | //mIndex = mIndex%mAdapter.getCount(); 188 | loadLast(); 189 | 190 | viewCollection.get(0).setOnTouchListener(null); 191 | viewCollection.get(viewCollection.size() - 1) 192 | .setOnTouchListener(mOnTouchListener); 193 | } 194 | 195 | }); 196 | } else { 197 | Log.d("onDragEndMethod", "reverse"); 198 | mCardAnimator.reverse(e1, e2); 199 | } 200 | return true; 201 | } 202 | 203 | @Override 204 | public boolean onTapUp() { 205 | mEventListener.topCardTapped(); 206 | return true; 207 | } 208 | } 209 | ); 210 | 211 | mOnTouchListener = new OnTouchListener() { 212 | private static final String DEBUG_TAG = "MotionEvents"; 213 | 214 | @Override 215 | public boolean onTouch(View arg0, MotionEvent event) { 216 | dd.onTouchEvent(event); 217 | return true; 218 | } 219 | }; 220 | cardView.setOnTouchListener(mOnTouchListener); 221 | } 222 | 223 | //used to set Adapter 224 | public void setAdapter(final ArrayAdapter adapter) { 225 | if (mAdapter != null) { 226 | mAdapter.unregisterDataSetObserver(mOb); 227 | } 228 | mAdapter = adapter; 229 | adapter.registerDataSetObserver(mOb); 230 | 231 | loadData(); 232 | } 233 | 234 | //call to load data based on index 235 | //this method will put Gone or visible property to view... 236 | private void loadData() { 237 | for (int i = mNumVisible - 1; i >= 0; i--) { 238 | ViewGroup parent = (ViewGroup) viewCollection.get(i); 239 | int index = (mIndex + mNumVisible - 1) - i; 240 | if (index > mAdapter.getCount() - 1) { 241 | parent.setVisibility(View.GONE); 242 | } else { 243 | View child = mAdapter.getView(index, getContentView(), this); 244 | parent.addView(child); 245 | parent.setVisibility(View.VISIBLE); 246 | } 247 | } 248 | } 249 | 250 | //returning a new view even 251 | private View getContentView() { 252 | View contentView = null; 253 | if (mContentResource != 0) { 254 | LayoutInflater lf = LayoutInflater.from(getContext()); 255 | contentView = lf.inflate(mContentResource, null); 256 | } 257 | return contentView; 258 | 259 | } 260 | 261 | private void loadLast() { 262 | ViewGroup parent = (ViewGroup) viewCollection.get(0); 263 | 264 | int lastIndex = (mNumVisible - 1) + mIndex; 265 | if (lastIndex > mAdapter.getCount() - 1) { 266 | parent.setVisibility(View.GONE); //hiding the top view and returning 267 | return; 268 | } 269 | 270 | View child = mAdapter.getView(lastIndex, getContentView(), parent); 271 | parent.removeAllViews();// remove all previous view 272 | parent.addView(child); // and then adding new 273 | } 274 | 275 | //return the size of stack 276 | public int getStackSize() { 277 | return mNumVisible; 278 | } 279 | 280 | public interface CardEventListener { 281 | //section 282 | // 0 | 1 283 | //-------- 284 | // 2 | 3 285 | // swipe distance, most likely be used with height and width of a view ; 286 | 287 | boolean swipeEnd(int section, float distance); 288 | 289 | boolean swipeStart(int section, float distance); 290 | 291 | boolean swipeContinue(int section, float distanceX, float distanceY); 292 | 293 | void discarded(int mIndex, int direction); 294 | 295 | void topCardTapped(); 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /mobile/src/main/java/com/tinderview/cardstatck/cardstack/CardAnimator.java: -------------------------------------------------------------------------------- 1 | package com.tinderview.cardstatck.cardstack; 2 | 3 | import android.animation.Animator; 4 | import android.animation.Animator.AnimatorListener; 5 | import android.animation.AnimatorListenerAdapter; 6 | import android.animation.AnimatorSet; 7 | import android.animation.ValueAnimator; 8 | import android.view.MotionEvent; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.RelativeLayout; 12 | import android.widget.RelativeLayout.LayoutParams; 13 | 14 | import com.tinderview.R; 15 | import com.tinderview.activities.MainScreenActivity; 16 | import com.tinderview.cardstatck.animation.RelativeLayoutParamsEvaluator; 17 | 18 | import java.util.ArrayList; 19 | import java.util.HashMap; 20 | 21 | 22 | /* 23 | * CardAnimator class is used to give animation on Card eg: dislike and like animation of card 24 | * dragging and dropping animation . 25 | * setting view of Card and arrange it in the form of stack. 26 | * shadow effect 27 | * curve effect of card 28 | * stack view 29 | * */ 30 | 31 | public class CardAnimator { 32 | private static final String DEBUG_TAG = "CardAnimator"; 33 | private static final int REMOTE_DISTANCE = 1000; 34 | public ArrayList mCardCollection; 35 | private float mRotation; //dislike rotation value 36 | private HashMap mLayoutsMap;//used to store the list of card's view 37 | private RelativeLayout.LayoutParams[] mRemoteLayouts = new RelativeLayout.LayoutParams[4];//creating the four list of stack 38 | private RelativeLayout.LayoutParams baseLayout; 39 | private int mStackMargin = 21;//set the margin of cardstack 40 | 41 | 42 | //passing list of cardStack view to mCardCollection. and jumping to setup method 43 | public CardAnimator(ArrayList viewCollection) { 44 | mCardCollection = viewCollection; 45 | setup(); 46 | 47 | } 48 | 49 | 50 | //calling to setup the each card based on view 51 | private void setup() { 52 | mLayoutsMap = new HashMap<>(); 53 | 54 | for (View v : mCardCollection) { 55 | //setup basic card layout 56 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams(); 57 | params.addRule(RelativeLayout.ALIGN_PARENT_TOP); 58 | params.width = LayoutParams.MATCH_PARENT; 59 | params.height = LayoutParams.MATCH_PARENT; 60 | 61 | v.setLayoutParams(params); 62 | 63 | } 64 | 65 | baseLayout = (RelativeLayout.LayoutParams) mCardCollection.get(0).getLayoutParams(); 66 | baseLayout = new RelativeLayout.LayoutParams(baseLayout); 67 | 68 | initLayout();//calling this method to arrange all the card based on StackView 69 | 70 | for (View v : mCardCollection) { 71 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams(); 72 | RelativeLayout.LayoutParams paramsCopy = new RelativeLayout.LayoutParams(params); 73 | mLayoutsMap.put(v, paramsCopy); 74 | } 75 | 76 | setupRemotes(); 77 | 78 | } 79 | 80 | /* finding the index of view and creating layoutParams using baseLayout object and those height and width setting to view 81 | * using method of v.setLayoutParams 82 | * and setting card scale size to give curve shape to card 83 | * and moving card toward top of others card, and gives look of stack. 84 | * */ 85 | public void initLayout() { 86 | int size = mCardCollection.size(); 87 | for (View v : mCardCollection) { 88 | int index = mCardCollection.indexOf(v); 89 | if (index != 0) { 90 | index -= 1; 91 | } 92 | LayoutParams params = new LayoutParams(baseLayout); 93 | v.setLayoutParams(params); 94 | 95 | //calling scale method of CardUtils class to set the margin and than put layout into v 96 | CardUtils.scale(v, -(size - index - 1) * 8); 97 | 98 | /*calling move method of CardUtils class which is going to move the card one by on based on the mStackMargin 99 | * first index would be 0 so it won't move card and the based on the index it will multiply with the given margin 100 | * and move card to down. 101 | */ 102 | CardUtils.move(v, index * mStackMargin, 0); 103 | 104 | v.setRotation(0);//setting the rotation of card as 0 105 | 106 | //here calling 3 different shadow layout for each Card 107 | //which will give shadow effect dynamically ... 108 | if (index == 0)// setting 0 used to add different layout shadow... 109 | v.setBackground(MainScreenActivity.context.getResources().getDrawable(R.drawable.card_stack_bg_shadow3)); 110 | else if (index == 1) 111 | v.setBackground(MainScreenActivity.context.getResources().getDrawable(R.drawable.card_stack_bg_shadow2)); 112 | else if (index == 2) 113 | v.setBackground(MainScreenActivity.context.getResources().getDrawable(R.drawable.card_stack_bg_shadow)); 114 | } 115 | } 116 | 117 | //setting the each card margins and putting view into array of mRemoteLayouts 118 | private void setupRemotes() { 119 | View topView = getTopView(); 120 | mRemoteLayouts[0] = CardUtils.getMoveParams(topView, REMOTE_DISTANCE, -REMOTE_DISTANCE); 121 | mRemoteLayouts[1] = CardUtils.getMoveParams(topView, REMOTE_DISTANCE, REMOTE_DISTANCE); 122 | mRemoteLayouts[2] = CardUtils.getMoveParams(topView, -REMOTE_DISTANCE, -REMOTE_DISTANCE); 123 | mRemoteLayouts[3] = CardUtils.getMoveParams(topView, -REMOTE_DISTANCE, REMOTE_DISTANCE); 124 | } 125 | 126 | 127 | //return the top view of stack. 128 | private View getTopView() { 129 | return mCardCollection.get(mCardCollection.size() - 1); 130 | } 131 | 132 | 133 | private void moveToBack(View child) { 134 | final ViewGroup parent = (ViewGroup) child.getParent(); 135 | if (null != parent) { 136 | parent.removeView(child); 137 | parent.addView(child, 0); 138 | } 139 | } 140 | 141 | //rearrange the mCardCollection list... 142 | // 143 | private void reorder() { 144 | View temp = getTopView(); 145 | moveToBack(temp); 146 | 147 | for (int i = (mCardCollection.size() - 1); i > 0; i--) { 148 | 149 | View current = mCardCollection.get(i - 1); 150 | //current replace next 151 | mCardCollection.set(i, current); 152 | 153 | 154 | } 155 | mCardCollection.set(0, temp); 156 | 157 | // temp = getTopView(); 158 | 159 | } 160 | 161 | //using to set the discard animation of CardStack into ArrayList 162 | public void discard(int direction, final AnimatorListener al) { 163 | AnimatorSet as = new AnimatorSet(); 164 | ArrayList aCollection = new ArrayList<>(); 165 | 166 | 167 | final View topView = getTopView(); 168 | RelativeLayout.LayoutParams topParams = (RelativeLayout.LayoutParams) topView.getLayoutParams(); 169 | RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(topParams); 170 | ValueAnimator discardAnim = ValueAnimator.ofObject(new RelativeLayoutParamsEvaluator(), layout, mRemoteLayouts[direction]); 171 | 172 | discardAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 173 | @Override 174 | public void onAnimationUpdate(ValueAnimator value) { 175 | topView.setLayoutParams((LayoutParams) value.getAnimatedValue()); 176 | } 177 | }); 178 | 179 | discardAnim.setDuration(100);//setting the discard removed animation time in ms. 180 | aCollection.add(discardAnim);//putting the discardAnimation to animation ArrayLIst 181 | 182 | for (int i = 0; i < mCardCollection.size(); i++) { 183 | final View v = mCardCollection.get(i); 184 | 185 | if (v == topView) continue; 186 | final View nv = mCardCollection.get(i + 1); 187 | RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v.getLayoutParams(); 188 | RelativeLayout.LayoutParams endLayout = new RelativeLayout.LayoutParams(layoutParams); 189 | ValueAnimator layoutAnim = ValueAnimator.ofObject(new RelativeLayoutParamsEvaluator(), endLayout, mLayoutsMap.get(nv)); 190 | layoutAnim.setDuration(100); 191 | layoutAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 192 | @Override 193 | public void onAnimationUpdate(ValueAnimator value) { 194 | v.setLayoutParams((LayoutParams) value.getAnimatedValue()); 195 | } 196 | }); 197 | aCollection.add(layoutAnim); 198 | } 199 | 200 | as.addListener(new AnimatorListenerAdapter() { 201 | 202 | 203 | @Override 204 | public void onAnimationEnd(Animator animation) { 205 | reorder(); 206 | if (al != null) { 207 | al.onAnimationEnd(animation); 208 | } 209 | mLayoutsMap = new HashMap(); 210 | for (View v : mCardCollection) { 211 | RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams(); 212 | RelativeLayout.LayoutParams paramsCopy = new RelativeLayout.LayoutParams(params); 213 | mLayoutsMap.put(v, paramsCopy); 214 | } 215 | 216 | } 217 | 218 | }); 219 | 220 | 221 | as.playTogether(aCollection); 222 | as.start(); 223 | 224 | 225 | } 226 | 227 | 228 | //even card is dragged and not discarded by the user then again this card will come on the top of the stack.. 229 | //this method will give the animation of reverse along with the reverse animation duration 230 | // time in ms... which is I defined as 250 231 | 232 | public void reverse(MotionEvent e1, MotionEvent e2) { 233 | final View topView = getTopView(); 234 | ValueAnimator rotationAnim = ValueAnimator.ofFloat(mRotation, 0f); 235 | rotationAnim.setDuration(250); 236 | rotationAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 237 | @Override 238 | public void onAnimationUpdate(ValueAnimator v) { 239 | topView.setRotation(((Float) (v.getAnimatedValue()))); 240 | } 241 | }); 242 | 243 | rotationAnim.start();//start the animation 244 | 245 | for (final View v : mCardCollection) { 246 | RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v.getLayoutParams(); 247 | RelativeLayout.LayoutParams endLayout = new RelativeLayout.LayoutParams(layoutParams); 248 | ValueAnimator layoutAnim = ValueAnimator.ofObject(new RelativeLayoutParamsEvaluator(), endLayout, mLayoutsMap.get(v)); 249 | layoutAnim.setDuration(250); 250 | layoutAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 251 | @Override 252 | public void onAnimationUpdate(ValueAnimator value) { 253 | v.setLayoutParams((LayoutParams) value.getAnimatedValue()); 254 | } 255 | }); 256 | layoutAnim.start(); 257 | } 258 | 259 | } 260 | 261 | 262 | //dragging method...it's gives the position of object and does the secondary animation of CardStack 263 | public void drag(MotionEvent e1, MotionEvent e2, float distanceX, 264 | float distanceY) { 265 | 266 | View topView = getTopView(); 267 | 268 | float rotation_coefficient = 20f;// 269 | 270 | RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) topView.getLayoutParams(); 271 | RelativeLayout.LayoutParams topViewLayouts = mLayoutsMap.get(topView); 272 | int x_diff = (int) ((e2.getRawX() - e1.getRawX())); 273 | int y_diff = (int) ((e2.getRawY() - e1.getRawY())); 274 | 275 | layoutParams.leftMargin = topViewLayouts.leftMargin + x_diff; 276 | layoutParams.rightMargin = topViewLayouts.rightMargin - x_diff; 277 | layoutParams.topMargin = topViewLayouts.topMargin + y_diff; 278 | layoutParams.bottomMargin = topViewLayouts.bottomMargin - y_diff; 279 | 280 | mRotation = (x_diff / rotation_coefficient); 281 | topView.setRotation(mRotation); 282 | topView.setLayoutParams(layoutParams); 283 | 284 | //animate secondary views. 285 | for (View v : mCardCollection) { 286 | int index = mCardCollection.indexOf(v); 287 | if (v != getTopView() && index != 0) { 288 | LayoutParams l = CardUtils.scaleFrom(v, mLayoutsMap.get(v), (int) (Math.abs(x_diff) * 0.05)); 289 | CardUtils.moveFrom(v, l, 0, (int) (Math.abs(x_diff) * 0.1)); 290 | } 291 | } 292 | } 293 | 294 | //using to set the margin into cardStack 295 | public void setStackMargin(int margin) { 296 | mStackMargin = margin;//passing the value to mStackMargin 297 | initLayout(); //and then calling this method to set the margin into view. 298 | } 299 | 300 | 301 | } 302 | --------------------------------------------------------------------------------