├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── simmorsal
│ │ └── concealernestedscrollview
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── simmorsal
│ │ │ └── concealernestedscrollview
│ │ │ ├── AdapterRv.java
│ │ │ ├── ConcealerRecyclerViewTestActivity.java
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_concealer_recycler_view_test.xml
│ │ ├── activity_main.xml
│ │ └── rv_layout.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── simmorsal
│ └── concealernestedscrollview
│ └── ExampleUnitTest.java
├── build.gradle
├── concealer_nested_scroll_view
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── simmorsal
│ │ └── library
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── simmorsal
│ │ │ └── library
│ │ │ ├── ConcealerNestedScrollView.java
│ │ │ └── ConcealerRecyclerView.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── simmorsal
│ └── library
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
11 | \.idea/
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## ConcealerNestedScrollView & ConcealerRecyclerView
2 |
3 | A library to make views hide from top and bottom while scrolling
4 | a custom NestedScrollView and\or a custom RecyclerView.
5 |
6 | 
7 |
8 |
9 | ## Changelog
10 |
11 | > **V 2.0.0**
12 | >
13 | > * ConcealerNSV now has the ability to auto hide header and footer views
14 | >
15 | > ``` java
16 | > cnsv.setHeaderAutoHide(true); // true by default
17 | > ```
18 | >
19 | > * You can set how fast the views would auto hide
20 | >
21 | > ``` java
22 | > cnsv.setHeaderAutoHideSpeed(300); // in milliseconds
23 | > ```
24 | >
25 | > * You can set how much of the view would be hidden so it would auto hide
26 | > ``` java
27 | > cnsv.setHeaderPercentageToHide(50); // 40 by default
28 | > ```
29 | >
30 | > * You can make the views concealable or not, and also visible or not
31 | > ``` java
32 | > // parameters are (boolean viewConcealable, boolean shouldViewBeVisible)
33 | > cnsv.setHeaderConcealable(false, true);
34 | > ```
35 | >
36 | > * All methods above apply to `footerView` as well.
37 | >
38 | > * Added **`ConcealerRecyclerView`**
39 | >
40 | > * Usage is the same as `ConcealerNestedScrollView`
41 | >
42 | > * Every method that works on `CNSV`, also works on `CRV`
43 | >
44 | > * **KNOWN ISSUES**
45 | >
46 | > If the starting touch position is iniatiated on a clickable view inside `CNSV` and `CRV`,
47 | > both classes will be unable to detect the touch
48 | > (`MotionEvent.ACTION_DOWN` and `MotionEvent.ACTION_UP`), so they
49 | > wouldn't be able to do auto hiding the moment the finger is lifted
50 | > off the screen, and so they will do it 70 milliseconds after the last
51 | > call on `onScrollChanged`. Pull requests are welcome.
52 |
53 |
54 |
55 | ## Usage
56 |
57 | ### Gradle
58 |
59 | ``` gradle
60 | implementation 'com.simmorsal.library:concealer_nested_scroll_view:2.0.0'
61 | ```
62 |
63 | ### XML
64 | Starting with your XML layout, it should look like this:
65 |
66 | 
67 |
68 | A parent `RelativeLayout` or `FrameLayout` that inside it is the
69 | `ConcealerNestedScrollView` on top, and two views (or one) as
70 | header and footer below it.
71 |
72 | __IMPORTANT:__ DO NOT give `margin_top` to header view,
73 | or `margin_bottom` to footer view. We'll do that in Java.
74 |
75 | Click [here](https://github.com/SIMMORSAL/ConcealerNestedScrollView/blob/master/app/src/main/res/layout/activity_main.xml) to see a XML sample.
76 |
77 | ### JAVA
78 |
79 | In your java first get a reference to the `ConcealerNestedScrollView`
80 | widget. (also get a reference to the header and footer views as well).
81 |
82 | ``` JAVA
83 | ConcealerNestedScrollView cnsv = findViewById(R.id.cnsv);
84 | ```
85 |
86 | Then you should pass the `headerView` and `footerView` (and margin top
87 | for header and margin bottom for footer views) to the `cnsv` object.
88 |
89 | To pass these views, you should make sure that they are completely
90 | drawn on the screen, so the library would be able to get their sizes.
91 |
92 | In order to do so, in your `onCreate` call `.post()` on header and footer
93 | views:
94 |
95 | ``` JAVA
96 | headerView.post(new Runnable() {
97 | @Override
98 | public void run() {
99 | // parameters are (View headerView, int marginTop)
100 | cnsv.setHeaderView(headerView, 15);
101 | }
102 | });
103 | footerView.post(new Runnable() {
104 | @Override
105 | public void run() {
106 | // parameters are (View footerView, int marginBottom)
107 | cnsv.setFooterView(footerView, 0);
108 | }
109 | });
110 | ```
111 |
112 | __IMPORTANT NOTES:__
113 |
114 | * if you dont want to set header and footer views
115 | from inside the onCreate, or you are sure when you want to pass
116 | header or footer views, they are drawn on the screen, dont call
117 | `.post()` on the views, and directly pass the views.
118 |
119 | * if on runtime your `headerView` height size changes (either by
120 | directly changing it's size, or setting a view inside it to `VISIBLE`
121 | that causes the view's height size to change), make sure to call
122 | `cnsv.resetHeaderHeight();` immediately after the code for
123 | resizing has been run. Likewise for the `footerView`, call
124 | `cnsv.resetFooterHeight();`.
125 |
126 | * You can make the views hide twice as fast if the
127 | `cnsv` has been scrolled more than the view's heights, by calling
128 | `cnsv.setHeaderFastHide(true);` and/or `cnsv.setFooterFastHide(true);`.
129 |
130 |
131 |
132 | ## License
133 |
134 | None. Do with it what you will.
135 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 27
5 | defaultConfig {
6 | applicationId "com.simmorsal.concealernestedscrollview"
7 | minSdkVersion 14
8 | targetSdkVersion 27
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(dir: 'libs', include: ['*.jar'])
23 | implementation 'com.android.support:appcompat-v7:27.1.1'
24 | implementation 'com.android.support:cardview-v7:27.1.1'
25 | implementation 'com.android.support:design:27.1.1'
26 | testImplementation 'junit:junit:4.12'
27 | implementation project(path: ':concealer_nested_scroll_view')
28 | }
29 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/simmorsal/concealernestedscrollview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.concealernestedscrollview;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.simmorsal.concealernestedscrollview", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simmorsal/concealernestedscrollview/AdapterRv.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.concealernestedscrollview;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.simmorsal.library.ConcealerRecyclerView;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 |
16 |
17 | public class AdapterRv extends RecyclerView.Adapter {
18 |
19 | private List data = Arrays.asList("455A64", "90A4AE", "455A64", "90A4AE", "455A64", "90A4AE", "455A64", "90A4AE");
20 | private Activity context;
21 | private ConcealerRecyclerView rv;
22 |
23 |
24 | public AdapterRv(Activity context, ConcealerRecyclerView rv) {
25 | this.context = context;
26 | this.rv = rv;
27 | }
28 |
29 | @Override
30 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
31 | final View view = LayoutInflater.from(context).inflate(R.layout.rv_layout, parent, false);
32 | return new CellFeedViewHolder(view);
33 | }
34 |
35 | @Override
36 | public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
37 | final CellFeedViewHolder h = (CellFeedViewHolder) viewHolder;
38 |
39 | h.root.setBackgroundColor(Color.parseColor("#" + data.get(position)));
40 |
41 | h.root.setOnClickListener(new View.OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | switch (position) {
45 | case 0:
46 | rv.setHeaderConcealable(false, true);
47 | break;
48 |
49 | case 1:
50 | rv.setFooterConcealable(false, false);
51 | break;
52 |
53 | case 2:
54 | rv.setHeaderConcealable(true, false);
55 | break;
56 |
57 | case 3:
58 | rv.setFooterConcealable(true, true);
59 | }
60 | }
61 | });
62 | }
63 |
64 | @Override
65 | public int getItemCount() {
66 | return data.size();
67 | }
68 |
69 |
70 | private class CellFeedViewHolder extends RecyclerView.ViewHolder {
71 |
72 | View root;
73 |
74 | CellFeedViewHolder(View view) {
75 | super(view);
76 |
77 | root = view.findViewById(R.id.root);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simmorsal/concealernestedscrollview/ConcealerRecyclerViewTestActivity.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.concealernestedscrollview;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.view.View;
7 |
8 | import com.simmorsal.library.ConcealerRecyclerView;
9 |
10 | public class ConcealerRecyclerViewTestActivity extends AppCompatActivity {
11 |
12 | private ConcealerRecyclerView rv;
13 | private View viewHeader, viewFooter;
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_concealer_recycler_view_test);
19 |
20 | rv = findViewById(R.id.rv);
21 | viewHeader = findViewById(R.id.crdHeaderView);
22 | viewFooter = findViewById(R.id.linFooterView);
23 |
24 | setupConcealerRV();
25 | runRv();
26 | }
27 |
28 | private void setupConcealerRV() {
29 | viewHeader.post(new Runnable() {
30 | @Override
31 | public void run() {
32 | rv.setHeaderView(viewHeader, 16);
33 | }
34 | });
35 | viewFooter.post(new Runnable() {
36 | @Override
37 | public void run() {
38 | rv.setFooterView(viewFooter, 0);
39 | }
40 | });
41 |
42 | rv.setFooterPercentageToHide(80);
43 | }
44 |
45 | private void runRv() {
46 | rv.setAdapter(new AdapterRv(this, rv));
47 | rv.setLayoutManager(new LinearLayoutManager(this));
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simmorsal/concealernestedscrollview/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.concealernestedscrollview;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.support.v7.widget.CardView;
6 | import android.widget.LinearLayout;
7 |
8 | import com.simmorsal.library.ConcealerNestedScrollView;
9 |
10 | public class MainActivity extends AppCompatActivity {
11 |
12 | ConcealerNestedScrollView concealerNSV;
13 | CardView crdHeaderView;
14 | LinearLayout linFooterView;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_main);
20 |
21 | concealerNSV = findViewById(R.id.concealerNSV);
22 | crdHeaderView = findViewById(R.id.crdHeaderView);
23 | linFooterView = findViewById(R.id.linFooterView);
24 |
25 | setupConcealerNSV();
26 | }
27 |
28 | private void setupConcealerNSV() {
29 | // if you're setting header and footer views at the very start of the layout creation (onCreate),
30 | // as the views are not drawn yet, the library cant get their correct sizes, so you have to do this:
31 |
32 | crdHeaderView.post(new Runnable() {
33 | @Override
34 | public void run() {
35 | concealerNSV.setHeaderView(crdHeaderView, 15);
36 | }
37 | });
38 | linFooterView.post(new Runnable() {
39 | @Override
40 | public void run() {
41 | concealerNSV.setFooterView(linFooterView, 0);
42 | }
43 | });
44 |
45 |
46 | // pass a true to setHeaderFastHide to make views hide faster
47 | concealerNSV.setHeaderFastHide(true);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_concealer_recycler_view_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
15 |
22 |
23 |
30 |
31 |
32 |
38 |
39 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
22 |
26 |
30 |
34 |
38 |
42 |
43 |
44 |
45 |
52 |
53 |
60 |
61 |
62 |
68 |
69 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rv_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #455A64
4 | #263238
5 | #F4511E
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ConcealerNestedScrollView
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/simmorsal/concealernestedscrollview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.concealernestedscrollview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.1.2'
11 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.2'
12 | classpath "com.github.dcendents:android-maven-gradle-plugin:1.4.1"
13 |
14 |
15 | // NOTE: Do not place your application dependencies here; they belong
16 | // in the individual module build.gradle files
17 | }
18 | }
19 |
20 | allprojects {
21 | repositories {
22 | google()
23 | jcenter()
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 |
4 | final VERSION_NAME = "2.0.0"
5 | final VERSION_CODE = 2
6 |
7 | ext {
8 | bintrayRepo = 'maven'
9 | bintrayName = 'concealer-nested-scroll-view'
10 |
11 | publishedGroupId = 'com.simmorsal.library'
12 | libraryName = 'ConcealerNestedScrollView'
13 | artifact = 'concealer_nested_scroll_view'
14 |
15 | libraryDescription = 'A library to make views hide from top and bottom while scrolling a custom NestedScrollView (and RecyclerView)'
16 |
17 | siteUrl = 'https://github.com/SIMMORSAL/ConcealerNestedScrollView'
18 | gitUrl = 'https://github.com/SIMMORSAL/ConcealerNestedScrollView'
19 |
20 | libraryVersion = VERSION_NAME
21 |
22 | developerId = 'simmorsal'
23 | developerName = 'SIMMORSAL'
24 | developerEmail = 'simmorsal@gmail.com'
25 |
26 | licenseName = 'The Apache Software License, Version 2.0'
27 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
28 | allLicenses = ["Apache-2.0"]
29 | }
30 |
31 | android {
32 | compileSdkVersion 27
33 |
34 |
35 |
36 | defaultConfig {
37 | minSdkVersion 14
38 | targetSdkVersion 27
39 | versionCode VERSION_CODE
40 | versionName VERSION_NAME
41 |
42 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
43 |
44 | }
45 |
46 | buildTypes {
47 | release {
48 | minifyEnabled false
49 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
50 | }
51 | }
52 |
53 | }
54 |
55 | dependencies {
56 | implementation fileTree(dir: 'libs', include: ['*.jar'])
57 |
58 | implementation 'com.android.support:appcompat-v7:27.1.1'
59 | implementation "com.android.support:design:27.1.1"
60 | testImplementation 'junit:junit:4.12'
61 | }
62 |
63 |
64 | apply from: 'https://raw.githubusercontent.com/SIMMORSAL/JCenter/master/installv1.gradle'
65 | apply from: 'https://raw.githubusercontent.com/SIMMORSAL/JCenter/master/bintrayv1.gradle'
66 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/src/androidTest/java/com/simmorsal/library/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.library;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.simmorsal.library.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/src/main/java/com/simmorsal/library/ConcealerNestedScrollView.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.library;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.os.Build;
6 | import android.os.Handler;
7 | import android.support.v4.widget.NestedScrollView;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.ViewTreeObserver;
12 |
13 | public class ConcealerNestedScrollView extends NestedScrollView {
14 | public ConcealerNestedScrollView(Context context) {
15 | super(context);
16 | }
17 |
18 | public ConcealerNestedScrollView(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | }
21 |
22 | public ConcealerNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
23 | super(context, attrs, defStyleAttr);
24 | }
25 |
26 | @Override
27 | public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
28 | dispatchNestedPreScroll(dx, dy, consumed, null);
29 | }
30 |
31 |
32 | private View headerView, footerView;
33 | private boolean isThereTouch = false;
34 |
35 | private int deltaY;
36 | private int t = 0;
37 | private int headerViewHeight = 0;
38 | private int headerTranslateY = 0;
39 | private int headerMaxTranslate;
40 | private int headerMinTranslate;
41 | private int footerViewHeight = 0;
42 | private int footerTranslateY = 0;
43 | private int footerMaxTranslate;
44 | private int footerMinTranslate;
45 | private boolean isHeaderFastHide = false, isFooterFastHide = false;
46 |
47 | private boolean shouldHeaderAutoHide = true, shouldFooterAutoHide = true;
48 | private int headerAutoHideSpeed = 200, footerAutoHideSpeed = 200;
49 | private int headerPercentageToHide = 40, footerPercentageToHide = 40;
50 | private Handler handlerHeader = new Handler(), handlerFooter = new Handler();
51 | private boolean hasHeaderRunnableRun = false, hasFooterRunnableRun = false;
52 |
53 | private boolean isHeaderConcealable = true, isFooterConcealable = true;
54 |
55 |
56 | public void setFooterView(final View view, final int marginBottomInDp) {
57 | if (view.getHeight() == 0) {
58 | view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
59 | @Override
60 | public void onGlobalLayout() {
61 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
62 | view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
63 | }
64 | footerViewHeight = view.getHeight();
65 | footerMinTranslate = -footerViewHeight;
66 | }
67 | });
68 | } else {
69 | footerViewHeight = view.getHeight();
70 | footerMinTranslate = -footerViewHeight;
71 | }
72 | this.footerView = view;
73 |
74 | footerMaxTranslate = dpToPx(marginBottomInDp);
75 | footerTranslateY = footerMaxTranslate;
76 |
77 | view.setTranslationY(-footerMaxTranslate);
78 | }
79 |
80 | public void setHeaderView(final View view, final int marginTopInDp) {
81 | if (view.getHeight() == 0) {
82 | view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
83 | @Override
84 | public void onGlobalLayout() {
85 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
86 | view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
87 | }
88 | headerViewHeight = view.getHeight();
89 | headerMinTranslate = -headerViewHeight;
90 | }
91 | });
92 | } else {
93 | headerViewHeight = view.getHeight();
94 | headerMinTranslate = -headerViewHeight;
95 | }
96 | this.headerView = view;
97 |
98 | headerMaxTranslate = dpToPx(marginTopInDp);
99 | headerTranslateY = headerMaxTranslate;
100 |
101 | view.setTranslationY(headerMaxTranslate);
102 | }
103 |
104 |
105 | @Override
106 | protected void onScrollChanged(int l, int t, int oldl, int oldt) {
107 | super.onScrollChanged(l, t, oldl, oldt);
108 |
109 | this.t = t;
110 | deltaY = oldt - t;
111 | if (headerView != null && isHeaderConcealable)
112 | doHeaderTransition();
113 | if (footerView != null && isFooterConcealable)
114 | doFooterTransition();
115 | }
116 |
117 | private void doHeaderTransition() {
118 |
119 | if (shouldHeaderAutoHide)
120 | handlerHeader.removeCallbacks(headerAutoHideRunnable);
121 |
122 | int headerDelta = deltaY;
123 |
124 | // Going up
125 | if (headerDelta < 0 && headerTranslateY > headerMinTranslate) {
126 | if (isHeaderFastHide && t > headerMaxTranslate + headerViewHeight)
127 | headerDelta *= 2;
128 | headerTranslateY = headerTranslateY + headerDelta;
129 | if (headerTranslateY < headerMinTranslate)
130 | headerTranslateY = headerMinTranslate;
131 | headerView.setTranslationY(headerTranslateY);
132 | }
133 |
134 | // Going down
135 | else if (headerDelta > 0 && headerTranslateY < headerMaxTranslate) {
136 | if (t < headerMaxTranslate)
137 | headerDelta *= 3;
138 | headerTranslateY = headerTranslateY + headerDelta;
139 | if (t < 5)
140 | headerTranslateY = headerMaxTranslate;
141 | if (headerTranslateY > headerMaxTranslate)
142 | headerTranslateY = headerMaxTranslate;
143 | headerView.setTranslationY(headerTranslateY);
144 | }
145 |
146 | if (shouldHeaderAutoHide) {
147 | handlerHeader.postDelayed(headerAutoHideRunnable, 70);
148 | hasHeaderRunnableRun = false;
149 | }
150 | }
151 |
152 | private void doFooterTransition() {
153 | if (shouldFooterAutoHide)
154 | handlerFooter.removeCallbacks(footerAutoHideRunnable);
155 |
156 | int footerDelta = deltaY;
157 |
158 | // Going down
159 | if (footerDelta < 0 && footerTranslateY > footerMinTranslate) {
160 | if (isFooterFastHide && t > footerMaxTranslate + footerViewHeight)
161 | footerDelta *= 2;
162 | footerTranslateY = footerTranslateY + footerDelta;
163 | if (footerTranslateY < footerMinTranslate)
164 | footerTranslateY = footerMinTranslate;
165 | footerView.setTranslationY(-footerTranslateY);
166 | }
167 |
168 | // Going up
169 | else if (footerDelta > 0 && footerTranslateY < footerMaxTranslate) {
170 | if (t < footerMaxTranslate)
171 | footerDelta *= 3;
172 | footerTranslateY = footerTranslateY + footerDelta;
173 | if (t < 5)
174 | footerTranslateY = footerMaxTranslate;
175 | if (footerTranslateY > footerMaxTranslate)
176 | footerTranslateY = footerMaxTranslate;
177 | footerView.setTranslationY(-footerTranslateY);
178 | }
179 |
180 | if (shouldFooterAutoHide) {
181 | handlerFooter.postDelayed(footerAutoHideRunnable, 70);
182 | hasFooterRunnableRun = false;
183 | }
184 | }
185 |
186 | Runnable headerAutoHideRunnable = new Runnable() {
187 | @Override
188 | public void run() {
189 | hasHeaderRunnableRun = true;
190 | if (!isThereTouch) {
191 | if (headerTranslateY > (headerMinTranslate * (headerPercentageToHide / 100f))) {// should become visible
192 | headerTranslateY = headerMaxTranslate;
193 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
194 | headerView.animate().translationY(headerMaxTranslate).setDuration(headerAutoHideSpeed).withLayer();
195 | else
196 | headerView.setTranslationY(headerMaxTranslate);
197 | } else { // should hide
198 | if (t > headerMaxTranslate + headerViewHeight) {// can hide
199 | headerTranslateY = headerMinTranslate;
200 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
201 | headerView.animate().translationY(headerMinTranslate).setDuration(headerAutoHideSpeed).withLayer();
202 | else
203 | headerView.setTranslationY(headerMinTranslate);
204 | } else { // cant hide
205 | headerTranslateY = headerMaxTranslate;
206 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
207 | headerView.animate().translationY(headerMaxTranslate).setDuration(headerAutoHideSpeed).withLayer();
208 | else
209 | headerView.setTranslationY(headerMaxTranslate);
210 | }
211 | }
212 | }
213 | }
214 | };
215 |
216 | Runnable footerAutoHideRunnable = new Runnable() {
217 | @Override
218 | public void run() {
219 | hasFooterRunnableRun = true;
220 | if (!isThereTouch) {
221 | if (footerTranslateY > (footerMinTranslate * (footerPercentageToHide / 100f))) {// should become visible
222 | footerTranslateY = -footerMaxTranslate;
223 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
224 | footerView.animate().translationY(-footerMaxTranslate).setDuration(footerAutoHideSpeed).withLayer();
225 | else
226 | footerView.setTranslationY(-footerMaxTranslate);
227 | } else { // should hide
228 | if (t > headerMaxTranslate + headerViewHeight) {// can hide
229 | footerTranslateY = footerMinTranslate;
230 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
231 | footerView.animate().translationY(-footerMinTranslate).setDuration(footerAutoHideSpeed).withLayer();
232 | else
233 | footerView.setTranslationY(-footerMinTranslate);
234 | } else { // cant hide
235 | footerTranslateY = -footerMaxTranslate;
236 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
237 | footerView.animate().translationY(-footerMaxTranslate).setDuration(footerAutoHideSpeed).withLayer();
238 | else
239 | footerView.setTranslationY(-footerMaxTranslate);
240 | }
241 | }
242 | }
243 | }
244 | };
245 |
246 |
247 | @Override
248 | public boolean onTouchEvent(MotionEvent ev) {
249 |
250 | if (ev.getAction() == MotionEvent.ACTION_DOWN)
251 | isThereTouch = true;
252 | if (ev.getAction() == MotionEvent.ACTION_UP) {
253 | isThereTouch = false;
254 |
255 | if (shouldHeaderAutoHide && hasHeaderRunnableRun && isHeaderConcealable)
256 | handlerHeader.post(headerAutoHideRunnable);
257 |
258 | if (shouldFooterAutoHide && hasFooterRunnableRun && isFooterConcealable)
259 | handlerFooter.post(footerAutoHideRunnable);
260 | }
261 |
262 | return super.onTouchEvent(ev);
263 | }
264 |
265 | public void resetHeaderHeight() {
266 | if (headerView != null)
267 | headerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
268 | @Override
269 | public void onGlobalLayout() {
270 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
271 | headerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
272 | }
273 | headerViewHeight = headerView.getHeight();
274 | headerMinTranslate = -headerViewHeight;
275 | }
276 | });
277 | }
278 |
279 | public void resetFooterHeight() {
280 | if (footerView != null)
281 | footerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
282 | @Override
283 | public void onGlobalLayout() {
284 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
285 | footerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
286 | }
287 | footerViewHeight = footerView.getHeight();
288 | footerMinTranslate = -footerViewHeight;
289 | }
290 | });
291 | }
292 |
293 |
294 | public void setHeaderConcealable(boolean headerConcealable, boolean shouldHeaderBeVisible) {
295 | isHeaderConcealable = headerConcealable;
296 |
297 | if (shouldHeaderBeVisible) {
298 | headerTranslateY = headerMaxTranslate;
299 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
300 | headerView.animate().translationY(headerMaxTranslate).setDuration(headerAutoHideSpeed).withLayer();
301 | else
302 | headerView.setTranslationY(headerMaxTranslate);
303 | } else {
304 | headerTranslateY = headerMinTranslate;
305 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
306 | headerView.animate().translationY(headerMinTranslate).setDuration(headerAutoHideSpeed).withLayer();
307 | else
308 | headerView.setTranslationY(headerMinTranslate);
309 | }
310 | }
311 |
312 | public void setFooterConcealable(boolean footerConcealable, boolean shouldFooterBeVisible) {
313 | isFooterConcealable = footerConcealable;
314 |
315 | if (shouldFooterBeVisible) {
316 | footerTranslateY = -footerMaxTranslate;
317 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
318 | footerView.animate().translationY(-footerMaxTranslate).setDuration(footerAutoHideSpeed).withLayer();
319 | else
320 | footerView.setTranslationY(-footerMaxTranslate);
321 | } else {
322 | footerTranslateY = footerMinTranslate;
323 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
324 | footerView.animate().translationY(-footerMinTranslate).setDuration(footerAutoHideSpeed).withLayer();
325 | else
326 | footerView.setTranslationY(-footerMinTranslate);
327 | }
328 | }
329 |
330 | public void setHeaderFastHide(boolean isHeaderFastHide) {
331 | this.isHeaderFastHide = isHeaderFastHide;
332 | }
333 |
334 | public void setFooterFastHide(boolean isFooterFastHide) {
335 | this.isFooterFastHide = isFooterFastHide;
336 | }
337 |
338 | public void setHeaderAutoHide(boolean shouldHeaderAutoHide) {
339 | this.shouldHeaderAutoHide = shouldHeaderAutoHide;
340 | }
341 |
342 | public void setFooterAutoHide(boolean shouldFooterAutoHide) {
343 | this.shouldFooterAutoHide = shouldFooterAutoHide;
344 | }
345 |
346 | public void setHeaderAutoHideSpeed(int headerAutoHideSpeed) {
347 | this.headerAutoHideSpeed = headerAutoHideSpeed;
348 | }
349 |
350 | public void setFooterAutoHideSpeed(int footerAutoHideSpeed) {
351 | this.footerAutoHideSpeed = footerAutoHideSpeed;
352 | }
353 |
354 | public void setHeaderPercentageToHide(int headerPercentageToHide) {
355 | this.headerPercentageToHide = headerPercentageToHide;
356 | }
357 |
358 | public void setFooterPercentageToHide(int footerPercentageToHide) {
359 | this.footerPercentageToHide = footerPercentageToHide;
360 | }
361 |
362 | public static int dpToPx(int dp) {
363 | return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
364 | }
365 | }
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/src/main/java/com/simmorsal/library/ConcealerRecyclerView.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.library;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.os.Build;
6 | import android.os.Handler;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.util.AttributeSet;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.ViewTreeObserver;
13 |
14 | public class ConcealerRecyclerView extends RecyclerView {
15 | public ConcealerRecyclerView(Context context) { super(context); }
16 | public ConcealerRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); }
17 | public ConcealerRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }
18 |
19 |
20 | private int y = 0, oldy = 0;
21 |
22 | private View headerView, footerView;
23 | private boolean isThereTouch = false;
24 |
25 | private int deltaY;
26 | private int t = 0;
27 | private int headerViewHeight = 0;
28 | private int headerTranslateY = 0;
29 | private int headerMaxTranslate;
30 | private int headerMinTranslate;
31 | private int footerViewHeight = 0;
32 | private int footerTranslateY = 0;
33 | private int footerMaxTranslate;
34 | private int footerMinTranslate;
35 | private boolean isHeaderFastHide = false, isFooterFastHide = false;
36 |
37 | private boolean shouldHeaderAutoHide = true, shouldFooterAutoHide = true;
38 | private int headerAutoHideSpeed = 200, footerAutoHideSpeed = 200;
39 | private int headerPercentageToHide = 40, footerPercentageToHide = 40;
40 | private Handler handlerHeader = new Handler(), handlerFooter = new Handler();
41 | private boolean hasHeaderRunnableRun = false, hasFooterRunnableRun = false;
42 |
43 | private boolean isHeaderConcealable = true, isFooterConcealable = true;
44 |
45 |
46 | public void setFooterView(final View view, final int marginBottomInDp) {
47 | if (view.getHeight() == 0) {
48 | view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
49 | @Override
50 | public void onGlobalLayout() {
51 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
52 | view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
53 | }
54 | footerViewHeight = view.getHeight();
55 | footerMinTranslate = -footerViewHeight;
56 | }
57 | });
58 | } else {
59 | footerViewHeight = view.getHeight();
60 | footerMinTranslate = -footerViewHeight;
61 | }
62 | this.footerView = view;
63 |
64 | footerMaxTranslate = dpToPx(marginBottomInDp);
65 | footerTranslateY = footerMaxTranslate;
66 |
67 | view.setTranslationY(-footerMaxTranslate);
68 | }
69 |
70 | public void setHeaderView(final View view, final int marginTopInDp) {
71 | if (view.getHeight() == 0) {
72 | view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
73 | @Override
74 | public void onGlobalLayout() {
75 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
76 | view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
77 | }
78 | headerViewHeight = view.getHeight();
79 | headerMinTranslate = -headerViewHeight;
80 | }
81 | });
82 | } else {
83 | headerViewHeight = view.getHeight();
84 | headerMinTranslate = -headerViewHeight;
85 | }
86 | this.headerView = view;
87 |
88 | headerMaxTranslate = dpToPx(marginTopInDp);
89 | headerTranslateY = headerMaxTranslate;
90 |
91 | view.setTranslationY(headerMaxTranslate);
92 | }
93 |
94 |
95 | @Override
96 | protected void onScrollChanged(int l, int t, int oldl, int oldt) {
97 | super.onScrollChanged(l, t, oldl, oldt);
98 |
99 | y = computeVerticalScrollOffset();
100 |
101 | this.t = y;
102 | deltaY = oldy - y;
103 |
104 | if (headerView != null && isHeaderConcealable)
105 | doHeaderTransition();
106 | if (footerView != null && isFooterConcealable)
107 | doFooterTransition();
108 |
109 | oldy = y;
110 | }
111 | private void doHeaderTransition() {
112 |
113 | if (shouldHeaderAutoHide)
114 | handlerHeader.removeCallbacks(headerAutoHideRunnable);
115 |
116 | int headerDelta = deltaY;
117 |
118 | // Going up
119 | if (headerDelta < 0 && headerTranslateY > headerMinTranslate) {
120 | if (isHeaderFastHide && t > headerMaxTranslate + headerViewHeight)
121 | headerDelta *= 2;
122 | headerTranslateY = headerTranslateY + headerDelta;
123 | if (headerTranslateY < headerMinTranslate)
124 | headerTranslateY = headerMinTranslate;
125 | headerView.setTranslationY(headerTranslateY);
126 | }
127 |
128 | // Going down
129 | else if (headerDelta > 0 && headerTranslateY < headerMaxTranslate) {
130 | if (t < headerMaxTranslate)
131 | headerDelta *= 3;
132 | headerTranslateY = headerTranslateY + headerDelta;
133 | if (t < 5)
134 | headerTranslateY = headerMaxTranslate;
135 | if (headerTranslateY > headerMaxTranslate)
136 | headerTranslateY = headerMaxTranslate;
137 | headerView.setTranslationY(headerTranslateY);
138 | }
139 |
140 | if (shouldHeaderAutoHide) {
141 | handlerHeader.postDelayed(headerAutoHideRunnable, 70);
142 | hasHeaderRunnableRun = false;
143 | }
144 | }
145 |
146 | private void doFooterTransition() {
147 | if (shouldFooterAutoHide)
148 | handlerFooter.removeCallbacks(footerAutoHideRunnable);
149 |
150 | int footerDelta = deltaY;
151 |
152 | // Going down
153 | if (footerDelta < 0 && footerTranslateY > footerMinTranslate) {
154 | if (isFooterFastHide && t > footerMaxTranslate + footerViewHeight)
155 | footerDelta *= 2;
156 | footerTranslateY = footerTranslateY + footerDelta;
157 | if (footerTranslateY < footerMinTranslate)
158 | footerTranslateY = footerMinTranslate;
159 | footerView.setTranslationY(-footerTranslateY);
160 | }
161 |
162 | // Going up
163 | else if (footerDelta > 0 && footerTranslateY < footerMaxTranslate) {
164 | if (t < footerMaxTranslate)
165 | footerDelta *= 3;
166 | footerTranslateY = footerTranslateY + footerDelta;
167 | if (t < 5)
168 | footerTranslateY = footerMaxTranslate;
169 | if (footerTranslateY > footerMaxTranslate)
170 | footerTranslateY = footerMaxTranslate;
171 | footerView.setTranslationY(-footerTranslateY);
172 | }
173 |
174 | if (shouldFooterAutoHide) {
175 | handlerFooter.postDelayed(footerAutoHideRunnable, 70);
176 | hasFooterRunnableRun = false;
177 | }
178 | }
179 |
180 | Runnable headerAutoHideRunnable = new Runnable() {
181 | @Override
182 | public void run() {
183 | hasHeaderRunnableRun = true;
184 | if (!isThereTouch) {
185 | if (headerTranslateY > (headerMinTranslate * (headerPercentageToHide / 100f))) {// should become visible
186 | headerTranslateY = headerMaxTranslate;
187 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
188 | headerView.animate().translationY(headerMaxTranslate).setDuration(headerAutoHideSpeed).withLayer();
189 | else
190 | headerView.setTranslationY(headerMaxTranslate);
191 | } else { // should hide
192 | if (t > headerMaxTranslate + headerViewHeight) {// can hide
193 | headerTranslateY = headerMinTranslate;
194 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
195 | headerView.animate().translationY(headerMinTranslate).setDuration(headerAutoHideSpeed).withLayer();
196 | else
197 | headerView.setTranslationY(headerMinTranslate);
198 | } else { // cant hide
199 | headerTranslateY = headerMaxTranslate;
200 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
201 | headerView.animate().translationY(headerMaxTranslate).setDuration(headerAutoHideSpeed).withLayer();
202 | else
203 | headerView.setTranslationY(headerMaxTranslate);
204 | }
205 | }
206 | }
207 | }
208 | };
209 |
210 | Runnable footerAutoHideRunnable = new Runnable() {
211 | @Override
212 | public void run() {
213 | hasFooterRunnableRun = true;
214 | if (!isThereTouch) {
215 | if (footerTranslateY > (footerMinTranslate * (footerPercentageToHide / 100f))) {// should become visible
216 | footerTranslateY = -footerMaxTranslate;
217 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
218 | footerView.animate().translationY(-footerMaxTranslate).setDuration(footerAutoHideSpeed).withLayer();
219 | else
220 | footerView.setTranslationY(-footerMaxTranslate);
221 | } else { // should hide
222 | if (t > headerMaxTranslate + headerViewHeight) {// can hide
223 | footerTranslateY = footerMinTranslate;
224 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
225 | footerView.animate().translationY(-footerMinTranslate).setDuration(footerAutoHideSpeed).withLayer();
226 | else
227 | footerView.setTranslationY(-footerMinTranslate);
228 | } else { // cant hide
229 | footerTranslateY = -footerMaxTranslate;
230 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
231 | footerView.animate().translationY(-footerMaxTranslate).setDuration(footerAutoHideSpeed).withLayer();
232 | else
233 | footerView.setTranslationY(-footerMaxTranslate);
234 | }
235 | }
236 | }
237 | }
238 | };
239 |
240 |
241 | @Override
242 | public boolean onTouchEvent(MotionEvent ev) {
243 |
244 | if (ev.getAction() == MotionEvent.ACTION_DOWN)
245 | isThereTouch = true;
246 | if (ev.getAction() == MotionEvent.ACTION_UP) {
247 | isThereTouch = false;
248 |
249 | if (shouldHeaderAutoHide && hasHeaderRunnableRun && isHeaderConcealable)
250 | handlerHeader.post(headerAutoHideRunnable);
251 |
252 | if (shouldFooterAutoHide && hasFooterRunnableRun && isFooterConcealable)
253 | handlerFooter.post(footerAutoHideRunnable);
254 | }
255 |
256 | return super.onTouchEvent(ev);
257 | }
258 |
259 | public void resetHeaderHeight() {
260 | if (headerView != null)
261 | headerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
262 | @Override
263 | public void onGlobalLayout() {
264 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
265 | headerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
266 | }
267 | headerViewHeight = headerView.getHeight();
268 | headerMinTranslate = -headerViewHeight;
269 | }
270 | });
271 | }
272 |
273 | public void resetFooterHeight() {
274 | if (footerView != null)
275 | footerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
276 | @Override
277 | public void onGlobalLayout() {
278 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
279 | footerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
280 | }
281 | footerViewHeight = footerView.getHeight();
282 | footerMinTranslate = -footerViewHeight;
283 | }
284 | });
285 | }
286 |
287 |
288 | public void setHeaderConcealable(boolean headerConcealable, boolean shouldHeaderBeVisible) {
289 | isHeaderConcealable = headerConcealable;
290 |
291 | if (shouldHeaderBeVisible) {
292 | headerTranslateY = headerMaxTranslate;
293 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
294 | headerView.animate().translationY(headerMaxTranslate).setDuration(headerAutoHideSpeed).withLayer();
295 | else
296 | headerView.setTranslationY(headerMaxTranslate);
297 | } else {
298 | headerTranslateY = headerMinTranslate;
299 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
300 | headerView.animate().translationY(headerMinTranslate).setDuration(headerAutoHideSpeed).withLayer();
301 | else
302 | headerView.setTranslationY(headerMinTranslate);
303 | }
304 | }
305 |
306 | public void setFooterConcealable(boolean footerConcealable, boolean shouldFooterBeVisible) {
307 | isFooterConcealable = footerConcealable;
308 |
309 | if (shouldFooterBeVisible) {
310 | footerTranslateY = -footerMaxTranslate;
311 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
312 | footerView.animate().translationY(-footerMaxTranslate).setDuration(footerAutoHideSpeed).withLayer();
313 | else
314 | footerView.setTranslationY(-footerMaxTranslate);
315 | } else {
316 | footerTranslateY = footerMinTranslate;
317 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
318 | footerView.animate().translationY(-footerMinTranslate).setDuration(footerAutoHideSpeed).withLayer();
319 | else
320 | footerView.setTranslationY(-footerMinTranslate);
321 | }
322 | }
323 |
324 | public void setHeaderFastHide(boolean isHeaderFastHide) {
325 | this.isHeaderFastHide = isHeaderFastHide;
326 | }
327 |
328 | public void setFooterFastHide(boolean isFooterFastHide) {
329 | this.isFooterFastHide = isFooterFastHide;
330 | }
331 |
332 | public void setHeaderAutoHide(boolean shouldHeaderAutoHide) {
333 | this.shouldHeaderAutoHide = shouldHeaderAutoHide;
334 | }
335 |
336 | public void setFooterAutoHide(boolean shouldFooterAutoHide) {
337 | this.shouldFooterAutoHide = shouldFooterAutoHide;
338 | }
339 |
340 | public void setHeaderAutoHideSpeed(int headerAutoHideSpeed) {
341 | this.headerAutoHideSpeed = headerAutoHideSpeed;
342 | }
343 |
344 | public void setFooterAutoHideSpeed(int footerAutoHideSpeed) {
345 | this.footerAutoHideSpeed = footerAutoHideSpeed;
346 | }
347 |
348 | public void setHeaderPercentageToHide(int headerPercentageToHide) {
349 | this.headerPercentageToHide = headerPercentageToHide;
350 | }
351 |
352 | public void setFooterPercentageToHide(int footerPercentageToHide) {
353 | this.footerPercentageToHide = footerPercentageToHide;
354 | }
355 |
356 | public static int dpToPx(int dp) {
357 | return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
358 | }
359 |
360 | }
361 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | library
3 |
4 |
--------------------------------------------------------------------------------
/concealer_nested_scroll_view/src/test/java/com/simmorsal/library/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.simmorsal.library;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Mon Jan 15 20:53:38 PST 2018
16 |
17 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/simmorsal/ConcealerNestedScrollView-ConcealerRecyclerView/b0b26b512e52fe67d3d5d7ed89e77b46a9d1d376/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun May 13 19:17:36 IRDT 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':concealer_nested_scroll_view'
2 |
--------------------------------------------------------------------------------