├── settings.gradle
├── library
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── res
│ │ └── values
│ │ │ └── attrs.xml
│ │ └── java
│ │ └── com
│ │ └── jensdriller
│ │ └── libs
│ │ └── multistatelistview
│ │ └── MultiStateListView.java
├── gradle.properties
└── build.gradle
├── assets
├── Screenshot1.png
├── Screenshot2.png
├── Screenshot3.png
└── Screenshot4.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── sample
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable-hdpi
│ │ │ ├── empty.jpg
│ │ │ ├── error.jpg
│ │ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── values
│ │ │ ├── styles.xml
│ │ │ └── strings.xml
│ │ └── layout
│ │ │ ├── empty_view.xml
│ │ │ ├── error_view.xml
│ │ │ ├── loading_view.xml
│ │ │ └── activity_main.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── jensdriller
│ │ └── libs
│ │ └── multistatelistview
│ │ └── sample
│ │ └── MainActivity.java
└── build.gradle
├── gradle.properties
├── LICENSE
├── README.md
├── gradlew.bat
└── gradlew
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':sample', ':library'
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/Screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/assets/Screenshot1.png
--------------------------------------------------------------------------------
/assets/Screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/assets/Screenshot2.png
--------------------------------------------------------------------------------
/assets/Screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/assets/Screenshot3.png
--------------------------------------------------------------------------------
/assets/Screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/assets/Screenshot4.png
--------------------------------------------------------------------------------
/library/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Android-MultiStateListView
2 | POM_ARTIFACT_ID=library
3 | POM_PACKAGING=aar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gradle
2 | .gradle
3 | local.properties
4 | build
5 |
6 | # Android Studio
7 | .idea
8 | *.iml
9 |
10 | # Mac OSX
11 | .DS_Store
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/empty.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/sample/src/main/res/drawable-hdpi/empty.jpg
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/error.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/sample/src/main/res/drawable-hdpi/error.jpg
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/sample/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/sample/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/sample/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/HEAD/sample/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
7 |
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Android-MultiStateListView
5 | Load 0 items
6 | Load 10 items
7 | Load error
8 | Loading…
9 |
10 |
11 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/empty_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/error_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion Integer.parseInt(ANDROID_BUILD_COMPILE_SDK_VERSION)
5 | buildToolsVersion ANDROID_BUILD_TOOLS_VERSION
6 |
7 | defaultConfig {
8 | applicationId "com.jensdriller.libs.multistatelistview.sample"
9 | minSdkVersion 15
10 | targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION)
11 | versionCode Integer.parseInt(VERSION_CODE)
12 | versionName VERSION_NAME
13 | }
14 | }
15 |
16 | dependencies {
17 | compile project(":library")
18 | }
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion Integer.parseInt(ANDROID_BUILD_COMPILE_SDK_VERSION)
5 | buildToolsVersion ANDROID_BUILD_TOOLS_VERSION
6 |
7 | defaultConfig {
8 | applicationId "com.jensdriller.libs.multistatelistview"
9 | minSdkVersion 8
10 | targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION)
11 | versionCode Integer.parseInt(VERSION_CODE)
12 | versionName VERSION_NAME
13 | }
14 | }
15 |
16 | apply from: 'https://raw.githubusercontent.com/jenzz/gradle-mvn-push/master_jenzz/gradle-mvn-push.gradle'
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/loading_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | VERSION_NAME=1.0
2 | VERSION_CODE=1
3 | GROUP=com.github.jenzz.multistatelistview
4 |
5 | POM_DESCRIPTION=A simple Android ListView that lets you define three states: Loading, Empty & Error
6 | POM_URL=https://github.com/jenzz/Android-MultiStateListView
7 | POM_SCM_URL=https://github.com/jenzz/Android-MultiStateListView
8 | POM_SCM_CONNECTION=scm:git@github.com:jenzz/Android-MultiStateListView.git
9 | POM_SCM_DEV_CONNECTION=scm:git@github.com:jenzz/Android-MultiStateListView.git
10 | POM_LICENCE_NAME=The MIT License (MIT)
11 | POM_LICENCE_URL=http://opensource.org/licenses/MIT
12 | POM_LICENCE_DIST=repo
13 | POM_DEVELOPER_ID=jenzz
14 | POM_DEVELOPER_NAME=Jens Driller
15 | POM_DEVELOPER_EMAIL=jens@jensdriller.com
16 |
17 | ANDROID_BUILD_COMPILE_SDK_VERSION=20
18 | ANDROID_BUILD_TARGET_SDK_VERSION=20
19 | ANDROID_BUILD_TOOLS_VERSION=20.0.0
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Jens Driller
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
14 |
15 |
20 |
21 |
26 |
27 |
32 |
33 |
34 |
41 |
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Android - MultiStateListView
2 | ============================
3 |
4 | A simple Android `ListView` that lets you define **three states**:
5 |
6 | * Loading
7 | * Empty
8 | * Error
9 |
10 | Screenshots
11 | -----------
12 | 
13 | 
14 | 
15 | 
16 |
17 | Usage
18 | -----
19 | * Define the `MultiStateListView` via XML (use custom attributes to reference the state layouts):
20 |
21 | ```java
22 |
29 | ```
30 |
31 | * Or build it via Java:
32 |
33 | ```java
34 | MultiStateListView multiStateListView = new MultiStateListView.Builder(this)//
35 | .loadingView(R.layout.loading_view)//
36 | .emptyView(R.layout.empty_view)//
37 | .errorView(R.layout.error_view)//
38 | .build();
39 | ```
40 |
41 | * Show the desired state based on your logic:
42 |
43 | ```java
44 | multiStateListView.showLoadingView();
45 | ```
46 | ```java
47 | multiStateListView.showEmptyView();
48 | ```
49 | ```java
50 | multiStateListView.showErrorView();
51 | ```
52 |
53 | Example
54 | -------
55 | Check out the [sample project](https://github.com/jenzz/Android-MultiStateListView/tree/master/sample) for an example implementation.
56 |
57 | Download
58 | --------
59 |
60 | Grab it via Gradle:
61 | ```groovy
62 | compile 'com.github.jenzz.multistatelistview:library:1.0'
63 | ```
64 | or Maven:
65 | ```xml
66 |
67 | com.github.jenzz.multistatelistview
68 | library
69 | 1.0
70 |
71 | ```
72 |
73 | License
74 | -------
75 | This project is licensed under the [MIT License](https://raw.githubusercontent.com/jenzz/Android-MultiStateListView/master/LICENSE).
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/jensdriller/libs/multistatelistview/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.jensdriller.libs.multistatelistview.sample;
2 |
3 | import android.app.Activity;
4 | import android.os.AsyncTask;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.ArrayAdapter;
8 | import android.widget.Button;
9 |
10 | import com.jensdriller.libs.multistatelistview.MultiStateListView;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | public class MainActivity extends Activity implements View.OnClickListener {
16 |
17 | private Button mBtnLoad0;
18 | private Button mBtnLoad10;
19 | private Button mBtnError;
20 |
21 | private MultiStateListView mMultiStateListView;
22 | private ArrayAdapter mListAdapter;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 |
28 | setContentView(R.layout.activity_main);
29 |
30 | mBtnLoad0 = (Button) findViewById(R.id.btnLoad0);
31 | mBtnLoad10 = (Button) findViewById(R.id.btnLoad10);
32 | mBtnError = (Button) findViewById(R.id.btnError);
33 |
34 | mBtnLoad0.setOnClickListener(this);
35 | mBtnLoad10.setOnClickListener(this);
36 | mBtnError.setOnClickListener(this);
37 |
38 | mListAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, new ArrayList());
39 | mMultiStateListView = (MultiStateListView) findViewById(R.id.list);
40 | mMultiStateListView.setAdapter(mListAdapter);
41 | }
42 |
43 | @Override
44 | public void onClick(View v) {
45 | switch (v.getId()) {
46 | case R.id.btnLoad0:
47 | new LoadListDataTask().execute(0);
48 | break;
49 |
50 | case R.id.btnLoad10:
51 | new LoadListDataTask().execute(10);
52 | break;
53 |
54 | case R.id.btnError:
55 | new LoadListDataTask().execute(-1);
56 | break;
57 | }
58 | }
59 |
60 | private void setButtonsEnabled(boolean enabled) {
61 | mBtnLoad0.setEnabled(enabled);
62 | mBtnLoad10.setEnabled(enabled);
63 | mBtnError.setEnabled(enabled);
64 | }
65 |
66 | private class LoadListDataTask extends AsyncTask> {
67 |
68 | @Override
69 | protected void onPreExecute() {
70 | super.onPreExecute();
71 |
72 | mListAdapter.clear();
73 | mListAdapter.notifyDataSetChanged();
74 | mMultiStateListView.showLoadingView();
75 |
76 | setButtonsEnabled(false);
77 | }
78 |
79 | @Override
80 | protected List doInBackground(Integer... params) {
81 |
82 | try { // simulate loading task...
83 | Thread.sleep(2000);
84 | } catch (InterruptedException e) {
85 | e.printStackTrace();
86 | }
87 |
88 | int count = params[0];
89 | if (count == -1) {
90 | return null;
91 | }
92 |
93 | List dummyData = new ArrayList();
94 | for (int i = 1; i <= count; i++) {
95 | dummyData.add("#" + i);
96 | }
97 |
98 | return dummyData;
99 | }
100 |
101 | @Override
102 | protected void onPostExecute(List result) {
103 | super.onPostExecute(result);
104 |
105 | if (result == null) {
106 | mMultiStateListView.showErrorView();
107 | } else if (result.isEmpty()) {
108 | mMultiStateListView.showEmptyView();
109 | } else {
110 | mListAdapter.addAll(result);
111 | mListAdapter.notifyDataSetChanged();
112 | }
113 |
114 | setButtonsEnabled(true);
115 | }
116 |
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/library/src/main/java/com/jensdriller/libs/multistatelistview/MultiStateListView.java:
--------------------------------------------------------------------------------
1 | package com.jensdriller.libs.multistatelistview;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.FrameLayout;
10 | import android.widget.ListView;
11 |
12 | /**
13 | * A simple {@link ListView} that lets you define three states:
14 | *
15 | * - Loading
16 | * - Empty
17 | * - Error
18 | *
19 | *
20 | * @author Jens Driller
21 | */
22 | public class MultiStateListView extends ListView {
23 |
24 | //================================================================================
25 | // Fields
26 | //================================================================================
27 |
28 | private static final String TAG = MultiStateListView.class.getSimpleName();
29 |
30 | private View mLoadingView;
31 | private View mEmptyView;
32 | private View mErrorView;
33 |
34 | private LayoutInflater mLayoutInflater;
35 | private boolean mInitViews = true;
36 | private boolean mInvalidateView;
37 |
38 | //================================================================================
39 | // Constructors
40 | //================================================================================
41 |
42 | public MultiStateListView(Context context) {
43 | super(context);
44 | init(null);
45 | }
46 |
47 | public MultiStateListView(Context context, AttributeSet attrs) {
48 | super(context, attrs);
49 | init(attrs);
50 | }
51 |
52 | public MultiStateListView(Context context, AttributeSet attrs, int defStyle) {
53 | super(context, attrs, defStyle);
54 | init(attrs);
55 | }
56 |
57 | private void init(AttributeSet attrs) {
58 | mLayoutInflater = LayoutInflater.from(getContext());
59 |
60 | if (attrs != null) {
61 | TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MultiStateListView);
62 |
63 | int loadingViewResId = a.getResourceId(R.styleable.MultiStateListView_loadingView, 0);
64 | if (loadingViewResId > 0) {
65 | mLoadingView = mLayoutInflater.inflate(loadingViewResId, null);
66 | }
67 |
68 | int emptyViewResId = a.getResourceId(R.styleable.MultiStateListView_emptyView, 0);
69 | if (emptyViewResId > 0) {
70 | mEmptyView = mLayoutInflater.inflate(emptyViewResId, null);
71 | }
72 |
73 | int errorViewResId = a.getResourceId(R.styleable.MultiStateListView_errorView, 0);
74 | if (errorViewResId > 0) {
75 | mErrorView = mLayoutInflater.inflate(errorViewResId, null);
76 | }
77 |
78 | a.recycle();
79 | }
80 | }
81 |
82 | // Private constructor used for Builder pattern
83 | private MultiStateListView(Builder builder) {
84 | super(builder.mContext);
85 | mLoadingView = builder.mLoadingView;
86 | mEmptyView = builder.mEmptyView;
87 | mErrorView = builder.mErrorView;
88 | }
89 |
90 | //================================================================================
91 | // Builder
92 | //================================================================================
93 |
94 | public static class Builder {
95 |
96 | private Context mContext;
97 | private LayoutInflater mLayoutInflater;
98 |
99 | private View mLoadingView;
100 | private View mEmptyView;
101 | private View mErrorView;
102 |
103 | public Builder(Context context) {
104 | if (context == null) {
105 | throw new IllegalArgumentException("Context must not be null.");
106 | }
107 | mContext = context;
108 | mLayoutInflater = LayoutInflater.from(context);
109 | }
110 |
111 | public Builder loadingView(View view) {
112 | if (view == null) {
113 | throw new IllegalArgumentException("View must not be null.");
114 | }
115 | mLoadingView = view;
116 | return this;
117 | }
118 |
119 | public Builder loadingView(View view, OnClickListener clickListener) {
120 | if (view == null) {
121 | throw new IllegalArgumentException("View must not be null.");
122 | }
123 | mLoadingView = view;
124 | mLoadingView.setOnClickListener(clickListener);
125 | return this;
126 | }
127 |
128 | public Builder loadingView(int resId) {
129 | if (resId <= 0) {
130 | throw new IllegalArgumentException("View resource id must be greater than 0.");
131 | }
132 | mLoadingView = mLayoutInflater.inflate(resId, null);
133 | return this;
134 | }
135 |
136 | public Builder emptyView(View view) {
137 | if (view == null) {
138 | throw new IllegalArgumentException("View must not be null.");
139 | }
140 | mEmptyView = view;
141 | return this;
142 | }
143 |
144 | public Builder emptyView(View view, OnClickListener clickListener) {
145 | if (view == null) {
146 | throw new IllegalArgumentException("View must not be null.");
147 | }
148 | mEmptyView = view;
149 | mEmptyView.setOnClickListener(clickListener);
150 | return this;
151 | }
152 |
153 | public Builder emptyView(int resId) {
154 | if (resId <= 0) {
155 | throw new IllegalArgumentException("View resource id must be greater than 0.");
156 | }
157 | mEmptyView = mLayoutInflater.inflate(resId, null);
158 | return this;
159 | }
160 |
161 | public Builder errorView(View view) {
162 | if (view == null) {
163 | throw new IllegalArgumentException("View must not be null.");
164 | }
165 | mErrorView = view;
166 | return this;
167 | }
168 |
169 | public Builder errorView(View view, OnClickListener clickListener) {
170 | if (view == null) {
171 | throw new IllegalArgumentException("View must not be null.");
172 | }
173 | mErrorView = view;
174 | mErrorView.setOnClickListener(clickListener);
175 | return this;
176 | }
177 |
178 | public Builder errorView(int resId) {
179 | if (resId <= 0) {
180 | throw new IllegalArgumentException("View resource id must be greater than 0.");
181 | }
182 | mErrorView = mLayoutInflater.inflate(resId, null);
183 | return this;
184 | }
185 |
186 | public MultiStateListView build() {
187 | return new MultiStateListView(this);
188 | }
189 | }
190 |
191 | //================================================================================
192 | // Getters
193 | //================================================================================
194 |
195 | public View getLoadingView() {
196 | return mLoadingView;
197 | }
198 |
199 | @Override
200 | public View getEmptyView() {
201 | return mEmptyView;
202 | }
203 |
204 | public View getErrorView() {
205 | return mErrorView;
206 | }
207 |
208 | //================================================================================
209 | // Setters
210 | //================================================================================
211 |
212 | public void setLoadingView(View view) {
213 | setLoadingView(view, false);
214 | }
215 |
216 | public void setLoadingView(View view, boolean invalidateView) {
217 | if (view == null) {
218 | throw new IllegalArgumentException("View must not be null.");
219 | }
220 | mLoadingView = view;
221 | mInvalidateView = invalidateView;
222 | }
223 |
224 | public void setLoadingView(int resId) {
225 | setLoadingView(resId, false);
226 | }
227 |
228 | public void setLoadingView(int resId, boolean invalidateView) {
229 | if (resId <= 0) {
230 | throw new IllegalArgumentException("View resource id must be greater than 0.");
231 | }
232 | mLoadingView = mLayoutInflater.inflate(resId, null);
233 | mInvalidateView = invalidateView;
234 | }
235 |
236 | public void setLoadingView(View view, OnClickListener clickListener) {
237 | setLoadingView(view, clickListener, false);
238 | }
239 |
240 | public void setLoadingView(View view, OnClickListener clickListener, boolean invalidateView) {
241 | if (view == null) {
242 | throw new IllegalArgumentException("View must not be null.");
243 | }
244 | mLoadingView = view;
245 | mLoadingView.setOnClickListener(clickListener);
246 | mInvalidateView = invalidateView;
247 | }
248 |
249 | public void setLoadingView(int resId, OnClickListener clickListener) {
250 | setLoadingView(resId, clickListener, false);
251 | }
252 |
253 | public void setLoadingView(int resId, OnClickListener clickListener, boolean invalidateView) {
254 | if (resId <= 0) {
255 | throw new IllegalArgumentException("View resource id must be greater than 0.");
256 | }
257 | mLoadingView = mLayoutInflater.inflate(resId, null);
258 | mLoadingView.setOnClickListener(clickListener);
259 | mInvalidateView = invalidateView;
260 | }
261 |
262 | public void setLoadingViewClickListener(OnClickListener clickListener) {
263 | if (mLoadingView == null) {
264 | throw new IllegalStateException("Loading view is null. Cannot set click listener.");
265 | }
266 | mLoadingView.setOnClickListener(clickListener);
267 | }
268 |
269 | @Override
270 | public void setEmptyView(View view) {
271 | setEmptyView(view, false);
272 | }
273 |
274 | public void setEmptyView(View view, boolean invalidateView) {
275 | if (view == null) {
276 | throw new IllegalArgumentException("View must not be null.");
277 | }
278 | mEmptyView = view;
279 | mInvalidateView = invalidateView;
280 | }
281 |
282 | public void setEmptyView(int resId) {
283 | setEmptyView(resId, false);
284 | }
285 |
286 | public void setEmptyView(int resId, boolean invalidateView) {
287 | if (resId <= 0) {
288 | throw new IllegalArgumentException("View resource id must be greater than 0.");
289 | }
290 | mEmptyView = mLayoutInflater.inflate(resId, null);
291 | mInvalidateView = invalidateView;
292 | }
293 |
294 | public void setEmptyView(View view, OnClickListener clickListener) {
295 | setEmptyView(view, clickListener, false);
296 | }
297 |
298 | public void setEmptyView(View view, OnClickListener clickListener, boolean invalidateView) {
299 | if (view == null) {
300 | throw new IllegalArgumentException("View must not be null.");
301 | }
302 | mEmptyView = view;
303 | mEmptyView.setOnClickListener(clickListener);
304 | mInvalidateView = invalidateView;
305 | }
306 |
307 | public void setEmptyView(int resId, OnClickListener clickListener) {
308 | setEmptyView(resId, clickListener, false);
309 | }
310 |
311 | public void setEmptyView(int resId, OnClickListener clickListener, boolean invalidateView) {
312 | if (resId <= 0) {
313 | throw new IllegalArgumentException("View resource id must be greater than 0.");
314 | }
315 | mEmptyView = mLayoutInflater.inflate(resId, null);
316 | mEmptyView.setOnClickListener(clickListener);
317 | mInvalidateView = invalidateView;
318 | }
319 |
320 | public void setEmptyViewClickListener(OnClickListener clickListener) {
321 | if (mEmptyView == null) {
322 | throw new IllegalStateException("Empty view is null. Cannot set click listener.");
323 | }
324 | mEmptyView.setOnClickListener(clickListener);
325 | }
326 |
327 | public void setErrorView(View view) {
328 | setErrorView(view, false);
329 | }
330 |
331 | public void setErrorView(View view, boolean invalidateView) {
332 | if (view == null) {
333 | throw new IllegalArgumentException("View must not be null.");
334 | }
335 | mErrorView = view;
336 | mInvalidateView = invalidateView;
337 | }
338 |
339 | public void setErrorView(int resId) {
340 | setErrorView(resId, false);
341 | }
342 |
343 | public void setErrorView(int resId, boolean invalidateView) {
344 | if (resId <= 0) {
345 | throw new IllegalArgumentException("View resource id must be greater than 0.");
346 | }
347 | mErrorView = mLayoutInflater.inflate(resId, null);
348 | mInvalidateView = invalidateView;
349 | }
350 |
351 | public void setErrorView(View view, OnClickListener clickListener) {
352 | setErrorView(view, clickListener, false);
353 | }
354 |
355 | public void setErrorView(View view, OnClickListener clickListener, boolean invalidateView) {
356 | if (view == null) {
357 | throw new IllegalArgumentException("View must not be null.");
358 | }
359 | mErrorView = view;
360 | mErrorView.setOnClickListener(clickListener);
361 | mInvalidateView = invalidateView;
362 | }
363 |
364 | public void setErrorView(int resId, OnClickListener clickListener) {
365 | setErrorView(resId, clickListener, false);
366 | }
367 |
368 | public void setErrorView(int resId, OnClickListener clickListener, boolean invalidateView) {
369 | if (resId <= 0) {
370 | throw new IllegalArgumentException("View resource id must be greater than 0.");
371 | }
372 | mErrorView = mLayoutInflater.inflate(resId, null);
373 | mErrorView.setOnClickListener(clickListener);
374 | mInvalidateView = invalidateView;
375 | }
376 |
377 | public void setErrorViewClickListener(OnClickListener clickListener) {
378 | if (mErrorView == null) {
379 | throw new IllegalStateException("Error view is null. Cannot set click listener.");
380 | }
381 | mErrorView.setOnClickListener(clickListener);
382 | }
383 |
384 | //================================================================================
385 | // State Handling
386 | //================================================================================
387 |
388 | public static enum State {
389 | LOADING,
390 | EMPTY,
391 | ERROR
392 | }
393 |
394 | public void showLoadingView() {
395 | showView(State.LOADING);
396 | }
397 |
398 | public void showEmptyView() {
399 | showView(State.EMPTY);
400 | }
401 |
402 | public void showErrorView() {
403 | showView(State.ERROR);
404 | }
405 |
406 | public void showView(State state) {
407 | if (mInitViews || mInvalidateView) {
408 | initViews();
409 | mInitViews = mInvalidateView = false;
410 | }
411 |
412 | boolean showLoadingView = false;
413 | boolean showEmptyView = false;
414 | boolean showErrorView = false;
415 |
416 | switch (state) {
417 | case LOADING:
418 | showLoadingView = true;
419 | break;
420 | case EMPTY:
421 | showEmptyView = true;
422 | break;
423 | case ERROR:
424 | showErrorView = true;
425 | break;
426 | }
427 |
428 | if (mLoadingView != null) {
429 | mLoadingView.setVisibility(showLoadingView ? View.VISIBLE : View.GONE);
430 | }
431 |
432 | if (mEmptyView != null) {
433 | mEmptyView.setVisibility(showEmptyView ? View.VISIBLE : View.GONE);
434 | }
435 |
436 | if (mErrorView != null) {
437 | mErrorView.setVisibility(showErrorView ? View.VISIBLE : View.GONE);
438 | }
439 | }
440 |
441 | private void initViews() {
442 | ViewGroup parent = (ViewGroup) getParent();
443 | if (parent == null) {
444 | throw new IllegalStateException(getClass().getSimpleName() + " is not attached to parent view.");
445 | }
446 |
447 | ViewGroup container = getContainerView(parent);
448 | container.removeAllViews();
449 |
450 | parent.removeView(container);
451 | parent.addView(container);
452 |
453 | if (mLoadingView != null) {
454 | container.addView(mLoadingView);
455 | }
456 |
457 | if (mEmptyView != null) {
458 | container.addView(mEmptyView);
459 | }
460 |
461 | if (mErrorView != null) {
462 | container.addView(mErrorView);
463 | }
464 |
465 | super.setEmptyView(container);
466 | }
467 |
468 | private ViewGroup getContainerView(ViewGroup parent) {
469 | ViewGroup container = findContainerView(parent);
470 | if (container == null) {
471 | container = createContainerView();
472 | }
473 | return container;
474 | }
475 |
476 | private ViewGroup findContainerView(ViewGroup parent) {
477 | return (ViewGroup) parent.findViewWithTag(TAG);
478 | }
479 |
480 | private ViewGroup createContainerView() {
481 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
482 | FrameLayout container = new FrameLayout(getContext());
483 | container.setTag(TAG);
484 | container.setLayoutParams(lp);
485 | return container;
486 | }
487 | }
488 |
--------------------------------------------------------------------------------