├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── 1457534764216.gif
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── limxing
│ │ └── datepicker
│ │ └── MainActivity.java
│ └── res
│ ├── anim
│ ├── activity_tobottom.xml
│ └── activity_totop.xml
│ ├── drawable
│ ├── wheel_bg.xml
│ └── wheel_val.xml
│ ├── layout
│ ├── activity_main.xml
│ └── wheel_date_picker.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── themes.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── limxing
│ │ └── library
│ │ ├── AlertAnimateUtil.java
│ │ ├── AlertView.java
│ │ ├── AlertViewAdapter.java
│ │ ├── LoopView
│ │ ├── InertiaTimerTask.java
│ │ ├── LoopView.java
│ │ ├── LoopViewGestureListener.java
│ │ ├── MessageHandler.java
│ │ ├── OnItemSelectedListener.java
│ │ ├── OnItemSelectedRunnable.java
│ │ └── SmoothScrollTimerTask.java
│ │ ├── OnConfirmeListener.java
│ │ ├── OnDismissListener.java
│ │ └── OnItemClickListener.java
│ └── res
│ ├── anim
│ ├── alertview_bgin.xml
│ ├── alertview_bgout.xml
│ ├── fade_in_center.xml
│ ├── fade_out_center.xml
│ ├── slide_in_bottom.xml
│ └── slide_out_bottom.xml
│ ├── drawable
│ ├── bg_actionsheet_cancel.xml
│ ├── bg_actionsheet_header.xml
│ ├── bg_alertbutton_bottom.xml
│ ├── bg_alertbutton_left.xml
│ ├── bg_alertbutton_none.xml
│ ├── bg_alertbutton_right.xml
│ ├── bg_alertview_alert.xml
│ └── selector_pickerview_btn.xml
│ ├── layout
│ ├── alertview_data.xml
│ ├── include_alertheader.xml
│ ├── item_alertbutton.xml
│ ├── layout_alertview.xml
│ ├── layout_alertview_actionsheet.xml
│ ├── layout_alertview_alert.xml
│ ├── layout_alertview_alert_horizontal.xml
│ └── layout_alertview_alert_vertical.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── integers.xml
│ └── strings.xml
└── 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 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | DatePicker
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
26 |
27 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/1457534764216.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/1457534764216.gif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DatePicker
2 | 仿iOS的PickerView控件 从底部弹出的日期选择器,底部弹出的选择选择器
3 |
4 | 
5 |
6 | #### 第二版本更新
7 | 使用view呈现底部弹出的时间选择器,取代了之前用过的Dialog,Popwindow,学习了.
8 |
9 | 这次我使用了 Android-AlertView作为参考,
10 | 向AlertView中添加了从底部弹出的日期选择器;
11 |
12 | #### 使用
13 | git clone作为引用库,还能够自定义一些属性
14 |
15 |
16 | ####可参考原作者
17 | Android-AlertView
18 | androidWheelView
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.limxing.datepicker"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.2.0'
26 | compile project(':library')
27 | }
28 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/limxing/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/limxing/datepicker/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.limxing.datepicker;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import com.limxing.library.AlertView;
9 | import com.limxing.library.OnConfirmeListener;
10 |
11 |
12 | public class MainActivity extends AppCompatActivity implements OnConfirmeListener {
13 |
14 | private TextView text;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_main);
20 | text = (TextView) findViewById(R.id.text);
21 | }
22 |
23 | public void click(View view) {
24 | new AlertView("请选择日期",MainActivity.this,1991,2100,MainActivity.this).show();
25 |
26 | }
27 |
28 | @Override
29 | public void result(String s) {
30 | text.setText(s);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/activity_tobottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/activity_totop.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/wheel_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/wheel_val.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/wheel_date_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
25 |
26 |
31 |
32 |
36 |
37 |
42 |
43 |
48 |
49 |
54 |
55 |
56 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #D0D0D0
7 | #00000000
8 | #ffffff
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DatePicker
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.1.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/limxing/DatePicker/e5ccc48f917cb3e71c9c3b1f8d1502d1253dd827/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 24 09:14:46 CST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-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 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 23
10 | versionCode 2
11 | versionName "2.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:23.3.0'
25 | }
26 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/limxing/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/AlertAnimateUtil.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library;
2 |
3 | import android.view.Gravity;
4 |
5 | /**
6 | * Created by Sai on 15/8/9.
7 | */
8 | public class AlertAnimateUtil {
9 | private static final int INVALID = -1;
10 | /**
11 | * Get default animation resource when not defined by the user
12 | *
13 | * @param gravity the gravity of the dialog
14 | * @param isInAnimation determine if is in or out animation. true when is is
15 | * @return the id of the animation resource
16 | */
17 | static int getAnimationResource(int gravity, boolean isInAnimation) {
18 | switch (gravity) {
19 | case Gravity.BOTTOM:
20 | return isInAnimation ? R.anim.slide_in_bottom : R.anim.slide_out_bottom;
21 | case Gravity.CENTER:
22 | return isInAnimation ? R.anim.fade_in_center : R.anim.fade_out_center;
23 | }
24 | return INVALID;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/AlertView.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Typeface;
6 | import android.view.Gravity;
7 | import android.view.LayoutInflater;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.view.ViewStub;
12 | import android.view.animation.Animation;
13 | import android.view.animation.AnimationUtils;
14 | import android.widget.AdapterView;
15 | import android.widget.FrameLayout;
16 | import android.widget.LinearLayout;
17 | import android.widget.ListView;
18 | import android.widget.TextView;
19 |
20 | import com.limxing.library.LoopView.LoopView;
21 | import com.limxing.library.LoopView.OnItemSelectedListener;
22 |
23 | import java.util.ArrayList;
24 | import java.util.Arrays;
25 | import java.util.List;
26 |
27 | /**
28 | * Created by Sai on 15/8/9.
29 | * 精仿iOSAlertViewController控件
30 | * 点击取消按钮返回 -1,其他按钮从0开始算
31 | */
32 | public class AlertView implements OnItemSelectedListener {
33 | private OnConfirmeListener confirmeListener;
34 | private Animation bgAnim;
35 | private Animation bgAnimOut;
36 | private LoopView yearView;
37 | private LoopView monthView;
38 | private LoopView dayView;
39 | private ArrayList dayList;
40 |
41 | /**
42 | * 三个时间的监听
43 | *
44 | * @param view
45 | */
46 | @Override
47 | public void onItemSelected(LoopView view) {
48 | String year = yearView.getItems().get(yearView.getSelectedItem());
49 | year = year.substring(0, year.length() - 1);
50 | String month = monthView.getItems().get(monthView.getSelectedItem());
51 | month = month.substring(0, month.length() - 1);
52 | getDay(Integer.parseInt(year), Integer.parseInt(month));
53 | dayView.setInitPosition(0);
54 | dayView.setItems(dayList);
55 |
56 | }
57 |
58 | /**
59 | * @param year
60 | * @param month
61 | * @return
62 | */
63 |
64 | private int getDay(int year, int month) {
65 | int size = dayList.size();
66 | int day = 30;
67 | boolean flag = false;
68 | switch (year % 4) {
69 | case 0:
70 | flag = true;
71 | break;
72 | default:
73 | flag = false;
74 | break;
75 | }
76 | switch (month) {
77 | case 1:
78 | case 3:
79 | case 5:
80 | case 7:
81 | case 8:
82 | case 10:
83 | case 12:
84 | day = 31;
85 | for (int i = size; i < 31; i++) {
86 | dayList.add(i + 1 + "日");
87 | }
88 | break;
89 | case 2:
90 | day = flag ? 29 : 28;
91 | for (int i = day; i < size; i++) {
92 | dayList.remove(dayList.size() - 1);
93 | }
94 | if (size == 28 && flag) {
95 | dayList.add(29 + "日");
96 | }
97 |
98 | break;
99 | default:
100 | day = 30;
101 | for (int i = size; i < 30; i++) {
102 | dayList.add(i + 1 + "日");
103 | }
104 | if (size == 31) {
105 | dayList.remove(size - 1);
106 | }
107 | break;
108 | }
109 | return day;
110 | }
111 |
112 | public static enum Style {
113 | ActionSheet,
114 | Alert,
115 | Date
116 | }
117 |
118 | private final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
119 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM
120 | );
121 | public static final int HORIZONTAL_BUTTONS_MAXCOUNT = 2;
122 | public static final String OTHERS = "others";
123 | public static final String DESTRUCTIVE = "destructive";
124 | public static final String CANCEL = "cancel";
125 | public static final String TITLE = "title";
126 | public static final String MSG = "msg";
127 | public static final int CANCELPOSITION = -1;//点击取消按钮返回 -1,其他按钮从0开始算
128 |
129 | private String title;
130 | private String msg;
131 | private List mDestructive;
132 | private List mOthers;
133 | private String cancel;
134 | private ArrayList mDatas = new ArrayList();
135 |
136 | private Context context;
137 | private ViewGroup contentContainer;
138 | private ViewGroup decorView;//activity的根View
139 | private ViewGroup rootView;//AlertView 的 根View
140 | private ViewGroup loAlertHeader;//窗口headerView
141 |
142 | private Style style = Style.Alert;
143 |
144 | private OnDismissListener onDismissListener;
145 | private OnItemClickListener onItemClickListener;
146 | private boolean isDismissing;
147 |
148 | private Animation outAnim;
149 | private Animation inAnim;
150 | private int gravity = Gravity.CENTER;
151 |
152 | public AlertView(String title, String msg, String cancel, String[] destructive, String[] others, Context context, Style style, OnItemClickListener onItemClickListener) {
153 | this.context = context;
154 | if (style != null) this.style = style;
155 | this.onItemClickListener = onItemClickListener;
156 | initData(title, msg, cancel, destructive, others);
157 | initViews();
158 | init();
159 | initEvents();
160 | }
161 |
162 | public AlertView(String title, Context context, int startyear, int endyear, OnConfirmeListener confirmeListener) {
163 | this.title = title;
164 | this.context = context;
165 | this.confirmeListener = confirmeListener;
166 | this.style = Style.Date;
167 | initData(startyear, endyear);
168 | init();
169 | initEvents();
170 | }
171 |
172 | /**
173 | * 初始化时间
174 | *
175 | * @param startyear
176 | * @param endyear
177 | */
178 | private void initData(int startyear, int endyear) {
179 | List yearList = new ArrayList<>();
180 | List monthList = new ArrayList<>();
181 | dayList = new ArrayList<>();
182 | for (int i = startyear; i < endyear + 1; i++) {
183 | yearList.add(i + "年");
184 | }
185 | for (int i = 1; i < 13; i++) {
186 | monthList.add(i + "月");
187 | }
188 | for (int i = 1; i < 32; i++) {
189 | dayList.add(i + "日");
190 | }
191 | initViews(yearList, monthList, dayList);
192 | initLoopViewListener();
193 |
194 | }
195 |
196 | private void initLoopViewListener() {
197 | yearView.setListener(this);
198 | monthView.setListener(this);
199 | // dayView.setListener(this);
200 | }
201 |
202 | /**
203 | * 自定义的三级选择,联动需要自己设置下一个loopView的内容
204 | *
205 | * @param title
206 | * @param context
207 | * @param year
208 | * @param month
209 | * @param day
210 | * @param confirmeListener
211 | */
212 | public AlertView(String title, Context context, List year, List month, List day, OnConfirmeListener confirmeListener) {
213 | this.context = context;
214 | this.title = title;
215 | this.style = Style.Date;
216 | this.confirmeListener = confirmeListener;
217 | initViews(year, month, day);
218 | init();
219 | initEvents();
220 | }
221 |
222 | private void initViews(List year, List month, List day) {
223 | initViews();
224 | params.gravity = Gravity.BOTTOM;
225 | contentContainer.setLayoutParams(params);
226 | gravity = Gravity.BOTTOM;
227 | LayoutInflater layoutInflater = LayoutInflater.from(context);
228 | initDateViews(layoutInflater, year, month, day, title);
229 | }
230 |
231 | private void initDateViews(LayoutInflater layoutInflater, List year, final List month, final List day, String titlr) {
232 | ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(R.layout.alertview_data, contentContainer);
233 | yearView = (LoopView) viewGroup.findViewById(R.id.year);
234 | monthView = (LoopView) viewGroup.findViewById(R.id.month);
235 | TextView tvTitle = (TextView) viewGroup.findViewById(R.id.tvTitle);
236 | viewGroup.findViewById(R.id.btnSubmit).setOnClickListener(new View.OnClickListener() {
237 | @Override
238 | public void onClick(View view) {
239 | dismiss();
240 | String s = yearView.getItems().get(yearView.getSelectedItem());
241 | if (month != null) {
242 | s = s + monthView.getItems().get(monthView.getSelectedItem());
243 | }
244 | if (day != null) {
245 | s = s + dayView.getItems().get(dayView.getSelectedItem());
246 | }
247 | confirmeListener.result(s);
248 | }
249 | });
250 | viewGroup.findViewById(R.id.btnCancel).setOnClickListener(new View.OnClickListener() {
251 | @Override
252 | public void onClick(View view) {
253 | dismiss();
254 | }
255 | });
256 | tvTitle.setText(title);
257 | dayView = (LoopView) viewGroup.findViewById(R.id.day);
258 | yearView.setItems(year);
259 | if (month == null) {
260 | monthView.setVisibility(View.GONE);
261 | } else {
262 | monthView.setItems(month);
263 | }
264 | if (day == null) {
265 | dayView.setVisibility(View.GONE);
266 | } else {
267 | dayView.setItems(day);
268 | }
269 |
270 |
271 | }
272 |
273 | /**
274 | * 获取数据
275 | */
276 | protected void initData(String title, String msg, String cancel, String[] destructive, String[] others) {
277 |
278 | this.title = title;
279 | this.msg = msg;
280 | if (destructive != null) {
281 | this.mDestructive = Arrays.asList(destructive);
282 | this.mDatas.addAll(mDestructive);
283 | }
284 | if (others != null) {
285 | this.mOthers = Arrays.asList(others);
286 | this.mDatas.addAll(mOthers);
287 | }
288 | if (cancel != null) {
289 | this.cancel = cancel;
290 | if (style == Style.Alert && mDatas.size() < HORIZONTAL_BUTTONS_MAXCOUNT) {
291 | this.mDatas.add(0, cancel);
292 | }
293 | }
294 |
295 | }
296 |
297 | protected void initViews() {
298 | LayoutInflater layoutInflater = LayoutInflater.from(context);
299 | decorView = (ViewGroup) ((Activity) context).getWindow().getDecorView().findViewById(android.R.id.content);
300 | rootView = (ViewGroup) layoutInflater.inflate(R.layout.layout_alertview, decorView, false);
301 | rootView.setLayoutParams(new FrameLayout.LayoutParams(
302 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
303 | ));
304 | // rootView.setOnTouchListener(new View.OnTouchListener() {
305 | // @Override
306 | // public boolean onTouch(View view, MotionEvent motionEvent) {
307 | // if () {
308 | // dismiss();
309 | // }
310 | // return false;
311 | // }
312 | // });
313 | contentContainer = (ViewGroup) rootView.findViewById(R.id.content_container);
314 | contentContainer.setOnTouchListener(new View.OnTouchListener() {
315 | @Override
316 | public boolean onTouch(View view, MotionEvent motionEvent) {
317 | return true;
318 | }
319 | });
320 | int margin_alert_left_right = 0;
321 | switch (style) {
322 | case ActionSheet:
323 | params.gravity = Gravity.BOTTOM;
324 | margin_alert_left_right = context.getResources().getDimensionPixelSize(R.dimen.margin_actionsheet_left_right);
325 | params.setMargins(margin_alert_left_right, 0, margin_alert_left_right, margin_alert_left_right);
326 | contentContainer.setLayoutParams(params);
327 | gravity = Gravity.BOTTOM;
328 | initActionSheetViews(layoutInflater);
329 | break;
330 | case Alert:
331 | params.gravity = Gravity.CENTER;
332 | margin_alert_left_right = context.getResources().getDimensionPixelSize(R.dimen.margin_alert_left_right);
333 | params.setMargins(margin_alert_left_right, 0, margin_alert_left_right, 0);
334 | contentContainer.setLayoutParams(params);
335 | gravity = Gravity.CENTER;
336 | initAlertViews(layoutInflater);
337 | break;
338 | }
339 | }
340 |
341 | protected void initHeaderView(ViewGroup viewGroup) {
342 | loAlertHeader = (ViewGroup) viewGroup.findViewById(R.id.loAlertHeader);
343 | //标题和消息
344 | TextView tvAlertTitle = (TextView) viewGroup.findViewById(R.id.tvAlertTitle);
345 | TextView tvAlertMsg = (TextView) viewGroup.findViewById(R.id.tvAlertMsg);
346 | if (title != null) {
347 | tvAlertTitle.setText(title);
348 | } else {
349 | tvAlertTitle.setVisibility(View.GONE);
350 | }
351 | if (msg != null) {
352 | tvAlertMsg.setText(msg);
353 | } else {
354 | tvAlertMsg.setVisibility(View.GONE);
355 | }
356 | }
357 |
358 | protected void initListView() {
359 | ListView alertButtonListView = (ListView) contentContainer.findViewById(R.id.alertButtonListView);
360 | //把cancel作为footerView
361 | if (cancel != null && style == Style.Alert) {
362 | View itemView = LayoutInflater.from(context).inflate(R.layout.item_alertbutton, null);
363 | TextView tvAlert = (TextView) itemView.findViewById(R.id.tvAlert);
364 | tvAlert.setText(cancel);
365 | tvAlert.setClickable(true);
366 | tvAlert.setTypeface(Typeface.DEFAULT_BOLD);
367 | tvAlert.setTextColor(context.getResources().getColor(R.color.textColor_alert_button_cancel));
368 | tvAlert.setBackgroundResource(R.drawable.bg_alertbutton_bottom);
369 | tvAlert.setOnClickListener(new OnTextClickListener(CANCELPOSITION));
370 | alertButtonListView.addFooterView(itemView);
371 | }
372 | AlertViewAdapter adapter = new AlertViewAdapter(mDatas, mDestructive);
373 | alertButtonListView.setAdapter(adapter);
374 | alertButtonListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
375 | @Override
376 | public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
377 | if (onItemClickListener != null)
378 | onItemClickListener.onItemClick(AlertView.this, position);
379 | dismiss();
380 | }
381 | });
382 | }
383 |
384 | protected void initActionSheetViews(LayoutInflater layoutInflater) {
385 | ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(R.layout.layout_alertview_actionsheet, contentContainer);
386 | initHeaderView(viewGroup);
387 |
388 | initListView();
389 | TextView tvAlertCancel = (TextView) contentContainer.findViewById(R.id.tvAlertCancel);
390 | if (cancel != null) {
391 | tvAlertCancel.setVisibility(View.VISIBLE);
392 | tvAlertCancel.setText(cancel);
393 | }
394 | tvAlertCancel.setOnClickListener(new OnTextClickListener(CANCELPOSITION));
395 | }
396 |
397 | protected void initAlertViews(LayoutInflater layoutInflater) {
398 |
399 | ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(R.layout.layout_alertview_alert, contentContainer);
400 | initHeaderView(viewGroup);
401 |
402 | int position = 0;
403 | //如果总数据小于等于HORIZONTAL_BUTTONS_MAXCOUNT,则是横向button
404 | if (mDatas.size() <= HORIZONTAL_BUTTONS_MAXCOUNT) {
405 | ViewStub viewStub = (ViewStub) contentContainer.findViewById(R.id.viewStubHorizontal);
406 | viewStub.inflate();
407 | LinearLayout loAlertButtons = (LinearLayout) contentContainer.findViewById(R.id.loAlertButtons);
408 | for (int i = 0; i < mDatas.size(); i++) {
409 | //如果不是第一个按钮
410 | if (i != 0) {
411 | //添加上按钮之间的分割线
412 | View divier = new View(context);
413 | divier.setBackgroundColor(context.getResources().getColor(R.color.bgColor_divier));
414 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams((int) context.getResources().getDimension(R.dimen.size_divier), LinearLayout.LayoutParams.MATCH_PARENT);
415 | loAlertButtons.addView(divier, params);
416 | }
417 | View itemView = LayoutInflater.from(context).inflate(R.layout.item_alertbutton, null);
418 | TextView tvAlert = (TextView) itemView.findViewById(R.id.tvAlert);
419 | tvAlert.setClickable(true);
420 |
421 | //设置点击效果
422 | if (mDatas.size() == 1) {
423 | tvAlert.setBackgroundResource(R.drawable.bg_alertbutton_bottom);
424 | } else if (i == 0) {//设置最左边的按钮效果
425 | tvAlert.setBackgroundResource(R.drawable.bg_alertbutton_left);
426 | } else if (i == mDatas.size() - 1) {//设置最右边的按钮效果
427 | tvAlert.setBackgroundResource(R.drawable.bg_alertbutton_right);
428 | }
429 | String data = mDatas.get(i);
430 | tvAlert.setText(data);
431 |
432 | //取消按钮的样式
433 | if (data == cancel) {
434 | tvAlert.setTypeface(Typeface.DEFAULT_BOLD);
435 | tvAlert.setTextColor(context.getResources().getColor(R.color.textColor_alert_button_cancel));
436 | tvAlert.setOnClickListener(new OnTextClickListener(CANCELPOSITION));
437 | position = position - 1;
438 | }
439 | //高亮按钮的样式
440 | else if (mDestructive != null && mDestructive.contains(data)) {
441 | tvAlert.setTextColor(context.getResources().getColor(R.color.textColor_alert_button_destructive));
442 | }
443 |
444 | tvAlert.setOnClickListener(new OnTextClickListener(position));
445 | position++;
446 | loAlertButtons.addView(itemView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
447 | LinearLayout.LayoutParams.WRAP_CONTENT, 1));
448 | }
449 | } else {
450 | ViewStub viewStub = (ViewStub) contentContainer.findViewById(R.id.viewStubVertical);
451 | viewStub.inflate();
452 | initListView();
453 | }
454 | }
455 |
456 | protected void init() {
457 | inAnim = getInAnimation();
458 | outAnim = getOutAnimation();
459 | bgAnim = AnimationUtils.loadAnimation(context, R.anim.alertview_bgin);
460 | bgAnimOut = AnimationUtils.loadAnimation(context, R.anim.alertview_bgout);
461 | }
462 |
463 | protected void initEvents() {
464 | }
465 |
466 | public AlertView addExtView(View extView) {
467 | loAlertHeader.addView(extView);
468 | return this;
469 | }
470 |
471 | /**
472 | * show的时候调用
473 | *
474 | * @param view 这个View
475 | */
476 | private void onAttached(View view) {
477 | decorView.addView(view);
478 | rootView.startAnimation(bgAnim);
479 | contentContainer.startAnimation(inAnim);
480 | }
481 |
482 | /**
483 | * 添加这个View到Activity的根视图
484 | */
485 | public void show() {
486 | if (isShowing()) {
487 | return;
488 | }
489 | onAttached(rootView);
490 | }
491 |
492 | /**
493 | * 检测该View是不是已经添加到根视图
494 | *
495 | * @return 如果视图已经存在该View返回true
496 | */
497 | public boolean isShowing() {
498 | View view = decorView.findViewById(R.id.outmost_container);
499 | return view != null;
500 | }
501 |
502 | public void dismiss() {
503 | if (isDismissing) {
504 | return;
505 | }
506 |
507 | //消失动画
508 | outAnim.setAnimationListener(new Animation.AnimationListener() {
509 | @Override
510 | public void onAnimationStart(Animation animation) {
511 |
512 | }
513 |
514 | @Override
515 | public void onAnimationEnd(Animation animation) {
516 | decorView.post(new Runnable() {
517 | @Override
518 | public void run() {
519 | //从activity根视图移除
520 | decorView.removeView(rootView);
521 | isDismissing = false;
522 | if (onDismissListener != null) {
523 | onDismissListener.onDismiss(AlertView.this);
524 | }
525 | }
526 | });
527 | }
528 |
529 | @Override
530 | public void onAnimationRepeat(Animation animation) {
531 |
532 | }
533 | });
534 | contentContainer.startAnimation(outAnim);
535 | rootView.startAnimation(bgAnimOut);
536 | isDismissing = true;
537 | }
538 |
539 | public Animation getInAnimation() {
540 | int res = AlertAnimateUtil.getAnimationResource(this.gravity, true);
541 | return AnimationUtils.loadAnimation(context, res);
542 | }
543 |
544 | public Animation getOutAnimation() {
545 | int res = AlertAnimateUtil.getAnimationResource(this.gravity, false);
546 | return AnimationUtils.loadAnimation(context, res);
547 | }
548 |
549 | public AlertView setOnDismissListener(OnDismissListener onDismissListener) {
550 | this.onDismissListener = onDismissListener;
551 | return this;
552 | }
553 |
554 | class OnTextClickListener implements View.OnClickListener {
555 |
556 | private int position;
557 |
558 | public OnTextClickListener(int position) {
559 | this.position = position;
560 | }
561 |
562 | @Override
563 | public void onClick(View view) {
564 | if (onItemClickListener != null)
565 | onItemClickListener.onItemClick(AlertView.this, position);
566 | dismiss();
567 | }
568 | }
569 |
570 | /**
571 | * 主要用于拓展View的时候有输入框,键盘弹出则设置MarginBottom往上顶,避免输入法挡住界面
572 | */
573 | public void setMarginBottom(int marginBottom) {
574 | int margin_alert_left_right = context.getResources().getDimensionPixelSize(R.dimen.margin_alert_left_right);
575 | params.setMargins(margin_alert_left_right, 0, margin_alert_left_right, marginBottom);
576 | contentContainer.setLayoutParams(params);
577 | }
578 |
579 | /**
580 | * 设置点击返回键是否关闭对话框
581 | *
582 | * @param isCancelable
583 | * @return
584 | */
585 | public AlertView setCancelable(boolean isCancelable) {
586 | View view = rootView.findViewById(R.id.outmost_container);
587 |
588 | if (isCancelable) {
589 | view.setOnTouchListener(onCancelableTouchListener);
590 | } else {
591 | view.setOnTouchListener(null);
592 | }
593 | return this;
594 | }
595 |
596 | /**
597 | * Called when the user touch on black overlay in order to dismiss the dialog
598 | */
599 | private final View.OnTouchListener onCancelableTouchListener = new View.OnTouchListener() {
600 | @Override
601 | public boolean onTouch(View v, MotionEvent event) {
602 | if (event.getAction() == MotionEvent.ACTION_DOWN) {
603 | dismiss();
604 | }
605 | return false;
606 | }
607 | };
608 |
609 | /**
610 | * 向外爆喽三个联动View
611 | *
612 | * @return
613 | */
614 | public LoopView getYearView() {
615 | return yearView;
616 | }
617 |
618 | public LoopView getMonthView() {
619 | return monthView;
620 | }
621 |
622 | public LoopView getDayView() {
623 | return dayView;
624 | }
625 | }
626 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/AlertViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Created by Sai on 15/8/9.
14 | */
15 | public class AlertViewAdapter extends BaseAdapter{
16 | private List mDatas;
17 | private List mDestructive;
18 | public AlertViewAdapter(List datas,List destructive){
19 | this.mDatas =datas;
20 | this.mDestructive =destructive;
21 | }
22 | @Override
23 | public int getCount() {
24 | return mDatas.size();
25 | }
26 |
27 | @Override
28 | public Object getItem(int position) {
29 | return mDatas.get(position);
30 | }
31 |
32 | @Override
33 | public long getItemId(int position) {
34 | return position;
35 | }
36 |
37 | @Override
38 | public View getView(int position, View convertView, ViewGroup parent) {
39 | String data= mDatas.get(position);
40 | Holder holder=null;
41 | View view =convertView;
42 | if(view==null){
43 | LayoutInflater inflater = LayoutInflater.from(parent.getContext());
44 | view=inflater.inflate( R.layout.item_alertbutton, null);
45 | holder=creatHolder(view);
46 | view.setTag(holder);
47 | }
48 | else{
49 | holder=(Holder) view.getTag();
50 | }
51 | holder.UpdateUI(parent.getContext(),data,position);
52 | return view;
53 | }
54 | public Holder creatHolder(View view){
55 | return new Holder(view);
56 | }
57 | class Holder {
58 | private TextView tvAlert;
59 |
60 | public Holder(View view){
61 | tvAlert = (TextView) view.findViewById( R.id.tvAlert);
62 | }
63 | public void UpdateUI(Context context,String data,int position){
64 | tvAlert.setText(data);
65 | if (mDestructive!= null && mDestructive.contains(data)){
66 | tvAlert.setTextColor(context.getResources().getColor( R.color.textColor_alert_button_destructive));
67 | }
68 | else{
69 | tvAlert.setTextColor(context.getResources().getColor( R.color.textColor_alert_button_others));
70 | }
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/InertiaTimerTask.java:
--------------------------------------------------------------------------------
1 | // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
2 | // Jad home page: http://www.geocities.com/kpdus/jad.html
3 | // Decompiler options: braces fieldsfirst space lnc
4 |
5 | package com.limxing.library.LoopView;
6 |
7 | import java.util.TimerTask;
8 |
9 | // Referenced classes of package com.qingchifan.view:
10 | // LoopView
11 |
12 | final class InertiaTimerTask extends TimerTask {
13 |
14 | float a;
15 | final float velocityY;
16 | final LoopView loopView;
17 |
18 | InertiaTimerTask(LoopView loopview, float velocityY) {
19 | super();
20 | loopView = loopview;
21 | this.velocityY = velocityY;
22 | a = Integer.MAX_VALUE;
23 | }
24 |
25 | @Override
26 | public final void run() {
27 | if (a == Integer.MAX_VALUE) {
28 | if (Math.abs(velocityY) > 2000F) {
29 | if (velocityY > 0.0F) {
30 | a = 2000F;
31 | } else {
32 | a = -2000F;
33 | }
34 | } else {
35 | a = velocityY;
36 | }
37 | }
38 | if (Math.abs(a) >= 0.0F && Math.abs(a) <= 20F) {
39 | loopView.cancelFuture();
40 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_SMOOTH_SCROLL);
41 | return;
42 | }
43 | int i = (int) ((a * 10F) / 1000F);
44 | LoopView loopview = loopView;
45 | loopview.totalScrollY = loopview.totalScrollY - i;
46 | if (!loopView.isLoop) {
47 | float itemHeight = loopView.lineSpacingMultiplier * loopView.maxTextHeight;
48 | if (loopView.totalScrollY <= (int) ((float) (-loopView.initPosition) * itemHeight)) {
49 | a = 40F;
50 | loopView.totalScrollY = (int) ((float) (-loopView.initPosition) * itemHeight);
51 | } else if (loopView.totalScrollY >= (int) ((float) (loopView.items.size() - 1 - loopView.initPosition) * itemHeight)) {
52 | loopView.totalScrollY = (int) ((float) (loopView.items.size() - 1 - loopView.initPosition) * itemHeight);
53 | a = -40F;
54 | }
55 | }
56 | if (a < 0.0F) {
57 | a = a + 20F;
58 | } else {
59 | a = a - 20F;
60 | }
61 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/LoopView.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library.LoopView;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.graphics.Typeface;
8 | import android.os.Handler;
9 | import android.util.AttributeSet;
10 | import android.view.GestureDetector;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 |
14 | import java.util.List;
15 | import java.util.concurrent.Executors;
16 | import java.util.concurrent.ScheduledExecutorService;
17 | import java.util.concurrent.ScheduledFuture;
18 | import java.util.concurrent.TimeUnit;
19 |
20 | /**
21 | * 使用方法
22 | * LoopView loopView = (LoopView) findViewById(R.id.loopview);
23 | * ArrayList list = new ArrayList<>();
24 | * for (int i = 0; i < 15; i++) {
25 | * list.add(2000 + i+"年");
26 | * }
27 | * //设置是否循环播放
28 | * //loopView.setNotLoop();
29 | * //滚动监听
30 | * loopView.setListener(new OnItemSelectedListener() {
31 | *
32 | * @Override public void onItemSelected(int index) {
33 | * Log.d("debug", "Item " + index);
34 | * }
35 | * });
36 | * //设置原始数据
37 | * loopView.setItems(list);
38 | * //设置初始位置
39 | * loopView.setInitPosition(5);
40 | * //设置字体大小
41 | * //loopView.setTextSize(20);
42 | * Created by Weidongjian on 2015/8/18.
43 | */
44 | public class LoopView extends View {
45 |
46 | // private static final float CENTERCONTENTOFFSET = 6;
47 | private float scaleX = 1.05F;
48 | private int widthMeasureSpec;
49 | private float itemHeight;
50 | // private float centerY;
51 |
52 | public enum ACTION {
53 | // 点击,滑翔(滑到尽头),拖拽事件
54 | CLICK, FLING, DAGGLE
55 | }
56 |
57 | Context context;
58 |
59 | Handler handler;
60 | private GestureDetector gestureDetector;
61 | OnItemSelectedListener onItemSelectedListener;
62 |
63 | // Timer mTimer;
64 | ScheduledExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor();
65 | private ScheduledFuture> mFuture;
66 |
67 | Paint paintOuterText;
68 | Paint paintCenterText;
69 | Paint paintIndicator;
70 |
71 | List items;
72 |
73 | int textSize;
74 | int maxTextWidth;
75 | int maxTextHeight;
76 |
77 | int colorGray;
78 | int colorBlack;
79 | int colorLightGray;
80 |
81 | // 条目间距倍数
82 | float lineSpacingMultiplier;
83 | boolean isLoop;
84 |
85 | // 第一条线Y坐标值
86 | float firstLineY;
87 | float secondLineY;
88 |
89 | int totalScrollY;
90 | int initPosition;
91 | private int selectedItem;
92 | int preCurrentIndex;
93 | int change;
94 |
95 | // 显示几个条目
96 | int itemsVisible;
97 |
98 | int measuredHeight;
99 | int measuredWidth;
100 | int paddingLeft = 0;
101 | int paddingRight = 0;
102 |
103 | // 半圆周长
104 | int halfCircumference;
105 | // 半径
106 | int radius;
107 |
108 | private int mOffset = 0;
109 | private float previousY;
110 | long startTime = 0;
111 |
112 | private Rect tempRect = new Rect();
113 |
114 | public LoopView(Context context) {
115 | super(context);
116 | initLoopView(context);
117 | }
118 |
119 | public LoopView(Context context, AttributeSet attributeset) {
120 | super(context, attributeset);
121 | initLoopView(context);
122 | }
123 |
124 | public LoopView(Context context, AttributeSet attributeset, int defStyleAttr) {
125 | super(context, attributeset, defStyleAttr);
126 | initLoopView(context);
127 | }
128 |
129 | private void initLoopView(Context context) {
130 | this.context = context;
131 | handler = new MessageHandler(this);
132 | gestureDetector = new GestureDetector(context, new LoopViewGestureListener(this));
133 | gestureDetector.setIsLongpressEnabled(false);
134 |
135 | lineSpacingMultiplier = 1.6F;
136 | isLoop = false;
137 | itemsVisible = 9;
138 | textSize = 0;
139 | colorGray = 0xffafafaf;
140 | colorBlack = 0xff313131;
141 | colorLightGray = 0xffc5c5c5;
142 |
143 | totalScrollY = 0;
144 | initPosition = -1;
145 |
146 | initPaints();
147 |
148 | setTextSize(20F);
149 | }
150 |
151 | private void initPaints() {
152 | paintOuterText = new Paint();
153 | paintOuterText.setColor(colorGray);
154 | paintOuterText.setAntiAlias(true);
155 | paintOuterText.setTypeface(Typeface.MONOSPACE);
156 | paintOuterText.setTextSize(textSize);
157 |
158 | paintCenterText = new Paint();
159 | paintCenterText.setColor(colorBlack);
160 | paintCenterText.setAntiAlias(true);
161 | paintCenterText.setTextScaleX(scaleX);
162 | paintCenterText.setTypeface(Typeface.MONOSPACE);
163 | paintCenterText.setTextSize(textSize);
164 |
165 | paintIndicator = new Paint();
166 | paintIndicator.setColor(colorLightGray);
167 | paintIndicator.setAntiAlias(true);
168 |
169 | if (android.os.Build.VERSION.SDK_INT >= 11) {
170 | setLayerType(LAYER_TYPE_SOFTWARE, null);
171 | }
172 | }
173 |
174 | private void remeasure() {
175 | if (items == null) {
176 | return;
177 | }
178 |
179 | measureTextWidthHeight();
180 | //最大Text的高度乘间距倍数得到 可见文字实际的总高度,半圆的周长
181 | halfCircumference = (int) (itemHeight * (itemsVisible - 1));
182 | // halfCircumference = (int) (maxTextHeight * lineSpacingMultiplier * (itemsVisible - 1));
183 | measuredHeight = (int) ((halfCircumference * 2) / Math.PI);
184 | radius = (int) (halfCircumference / Math.PI);
185 | // measuredWidth = maxTextWidth + paddingLeft + paddingRight;
186 | measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
187 | //计算两条横线和控件中间点的Y位置
188 | firstLineY = (measuredHeight - itemHeight) / 2.0F;
189 | secondLineY = (measuredHeight + itemHeight) / 2.0F;
190 | // centerY = (measuredHeight + maxTextHeight) / 2.0F - CENTERCONTENTOFFSET;
191 |
192 | // firstLineY = (int) ((measuredHeight - lineSpacingMultiplier * maxTextHeight) / 2.0F);
193 | // secondLineY = (int) ((measuredHeight + lineSpacingMultiplier * maxTextHeight) / 2.0F);
194 | if (initPosition == -1) {
195 | if (isLoop) {
196 | initPosition = (items.size() + 1) / 2;
197 | } else {
198 | initPosition = 0;
199 | }
200 | }
201 |
202 | preCurrentIndex = initPosition;
203 | }
204 |
205 | private void measureTextWidthHeight() {
206 | for (int i = 0; i < items.size(); i++) {
207 | String s1 = items.get(i);
208 | paintCenterText.getTextBounds(s1, 0, s1.length(), tempRect);
209 | int textWidth = tempRect.width();
210 | if (textWidth > maxTextWidth) {
211 | maxTextWidth = (int) (textWidth * scaleX);
212 | }
213 | paintCenterText.getTextBounds("\u661F\u671F", 0, 2, tempRect); // 星期
214 | int textHeight = tempRect.height();
215 | if (textHeight > maxTextHeight) {
216 | maxTextHeight = textHeight;
217 | }
218 | }
219 | itemHeight = lineSpacingMultiplier * maxTextHeight;
220 |
221 | }
222 |
223 | void smoothScroll(ACTION action) {
224 | cancelFuture();
225 | if (action == ACTION.FLING || action == ACTION.DAGGLE) {
226 | // float itemHeight = lineSpacingMultiplier * maxTextHeight;
227 | mOffset = (int) ((totalScrollY % itemHeight + itemHeight) % itemHeight);
228 | if ((float) mOffset > itemHeight / 2.0F) {
229 | mOffset = (int) (itemHeight - (float) mOffset);
230 | } else {
231 | mOffset = -mOffset;
232 | }
233 | }
234 | mFuture = mExecutor.scheduleWithFixedDelay(new SmoothScrollTimerTask(this, mOffset), 0, 10, TimeUnit.MILLISECONDS);
235 | }
236 |
237 | // void smoothScroll() {
238 | // int offset = (int) (totalScrollY % (lineSpacingMultiplier * maxTextHeight));
239 | // cancelFuture();
240 | // mFuture = mExecutor.scheduleWithFixedDelay(new SmoothScrollTimerTask(this, offset), 0, 10, TimeUnit.MILLISECONDS);
241 | // }
242 |
243 | protected final void scrollBy(float velocityY) {
244 | cancelFuture();
245 | // 修改这个值可以改变滑行速度
246 | int velocityFling = 10;
247 | mFuture = mExecutor.scheduleWithFixedDelay(new InertiaTimerTask(this, velocityY), 0, velocityFling, TimeUnit.MILLISECONDS);
248 | }
249 |
250 | public void cancelFuture() {
251 | if (mFuture != null && !mFuture.isCancelled()) {
252 | mFuture.cancel(true);
253 | mFuture = null;
254 | }
255 | }
256 |
257 | public final void setNotLoop() {
258 | isLoop = false;
259 | }
260 |
261 | public final void setTextSize(float size) {
262 | if (size > 0.0F) {
263 | textSize = (int) (context.getResources().getDisplayMetrics().density * size);
264 | paintOuterText.setTextSize(textSize);
265 | paintCenterText.setTextSize(textSize);
266 | }
267 | }
268 |
269 | public final void setInitPosition(int initPosition) {
270 | if (initPosition < 0) {
271 | this.initPosition = 0;
272 | } else {
273 | if (items != null && (items.size() - 1) > initPosition) {
274 | this.initPosition = initPosition;
275 | }
276 | }
277 | }
278 |
279 | public final void setListener(OnItemSelectedListener OnItemSelectedListener) {
280 | onItemSelectedListener = OnItemSelectedListener;
281 | }
282 |
283 | public final void setItems(List items) {
284 | this.items = items;
285 | remeasure();
286 | invalidate();
287 | }
288 |
289 | public List getItems() {
290 | return items;
291 | }
292 |
293 | @Override
294 | public int getPaddingLeft() {
295 | return paddingLeft;
296 | }
297 |
298 | @Override
299 | public int getPaddingRight() {
300 | return paddingRight;
301 | }
302 |
303 | // 设置左右内边距
304 | public void setViewPadding(int left, int top, int right, int bottom) {
305 | paddingLeft = left;
306 | paddingRight = right;
307 | }
308 |
309 | public final int getSelectedItem() {
310 | return selectedItem;
311 | }
312 | //
313 | // protected final void scrollBy(float velocityY) {
314 | // Timer timer = new Timer();
315 | // mTimer = timer;
316 | // timer.schedule(new InertiaTimerTask(this, velocityY, timer), 0L, 20L);
317 | // }
318 |
319 | protected final void onItemSelected() {
320 | if (onItemSelectedListener != null) {
321 | postDelayed(new OnItemSelectedRunnable(this), 200L);
322 | }
323 | }
324 |
325 | @Override
326 | protected void onDraw(Canvas canvas) {
327 | if (items == null) {
328 | return;
329 | }
330 |
331 | String as[] = new String[itemsVisible];
332 | change = (int) (totalScrollY / (lineSpacingMultiplier * maxTextHeight));
333 | preCurrentIndex = initPosition + change % (items.size());
334 |
335 | if (!isLoop) {
336 | if (preCurrentIndex < 0) {
337 | preCurrentIndex = 0;
338 | }
339 | if (preCurrentIndex > items.size() - 1) {
340 | preCurrentIndex = items.size() - 1;
341 | }
342 | } else {
343 | if (preCurrentIndex < 0) {
344 | preCurrentIndex = items.size() + preCurrentIndex;
345 | }
346 | if (preCurrentIndex > items.size() - 1) {
347 | preCurrentIndex = preCurrentIndex - items.size();
348 | }
349 | }
350 |
351 | int j2 = (int) (totalScrollY % (lineSpacingMultiplier * maxTextHeight));
352 | // 设置as数组中每个元素的值
353 | int k1 = 0;
354 | while (k1 < itemsVisible) {
355 | int l1 = preCurrentIndex - (itemsVisible / 2 - k1);
356 | if (isLoop) {
357 | while (l1 < 0) {
358 | l1 = l1 + items.size();
359 | }
360 | while (l1 > items.size() - 1) {
361 | l1 = l1 - items.size();
362 | }
363 | as[k1] = items.get(l1);
364 | } else if (l1 < 0) {
365 | as[k1] = "";
366 | } else if (l1 > items.size() - 1) {
367 | as[k1] = "";
368 | } else {
369 | as[k1] = items.get(l1);
370 | }
371 | k1++;
372 | }
373 | canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator);
374 | canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator);
375 |
376 | int j1 = 0;
377 | while (j1 < itemsVisible) {
378 | canvas.save();
379 | // L(弧长)=α(弧度)* r(半径) (弧度制)
380 | // 求弧度--> (L * π ) / (π * r) (弧长X派/半圆周长)
381 | float itemHeight = maxTextHeight * lineSpacingMultiplier;
382 | double radian = ((itemHeight * j1 - j2) * Math.PI) / halfCircumference;
383 | // 弧度转换成角度(把半圆以Y轴为轴心向右转90度,使其处于第一象限及第四象限
384 | float angle = (float) (90D - (radian / Math.PI) * 180D);
385 | if (angle >= 90F || angle <= -90F) {
386 | canvas.restore();
387 | } else {
388 | int translateY = (int) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D);
389 | canvas.translate(0.0F, translateY);
390 | canvas.scale(1.0F, (float) Math.sin(radian));
391 | if (translateY <= firstLineY && maxTextHeight + translateY >= firstLineY) {
392 | // 条目经过第一条线
393 | canvas.save();
394 | canvas.clipRect(0, 0, measuredWidth, firstLineY - translateY);
395 | canvas.drawText(as[j1], getTextX(as[j1], paintOuterText, tempRect), maxTextHeight, paintOuterText);
396 | canvas.restore();
397 | canvas.save();
398 | canvas.clipRect(0, firstLineY - translateY, measuredWidth, (int) (itemHeight));
399 | canvas.drawText(as[j1], getTextX(as[j1], paintCenterText, tempRect), maxTextHeight, paintCenterText);
400 | canvas.restore();
401 | } else if (translateY <= secondLineY && maxTextHeight + translateY >= secondLineY) {
402 | // 条目经过第二条线
403 | canvas.save();
404 | canvas.clipRect(0, 0, measuredWidth, secondLineY - translateY);
405 | canvas.drawText(as[j1], getTextX(as[j1], paintCenterText, tempRect), maxTextHeight, paintCenterText);
406 | canvas.restore();
407 | canvas.save();
408 | canvas.clipRect(0, secondLineY - translateY, measuredWidth, (int) (itemHeight));
409 | canvas.drawText(as[j1], getTextX(as[j1], paintOuterText, tempRect), maxTextHeight, paintOuterText);
410 | canvas.restore();
411 | } else if (translateY >= firstLineY && maxTextHeight + translateY <= secondLineY) {
412 | // 中间条目
413 | canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
414 | canvas.drawText(as[j1], getTextX(as[j1], paintCenterText, tempRect), maxTextHeight, paintCenterText);
415 | selectedItem = items.indexOf(as[j1]);
416 | } else {
417 | // 其他条目
418 | canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
419 | canvas.drawText(as[j1], getTextX(as[j1], paintOuterText, tempRect), maxTextHeight, paintOuterText);
420 | }
421 | canvas.restore();
422 | }
423 | j1++;
424 | }
425 | }
426 |
427 | // 绘制文字起始位置
428 | private int getTextX(String a, Paint paint, Rect rect) {
429 | paint.getTextBounds(a, 0, a.length(), rect);
430 | // 获取到的是实际文字宽度
431 | int textWidth = rect.width();
432 | // 转换成绘制文字宽度
433 | textWidth *= scaleX;
434 | return (measuredWidth - textWidth) / 2;
435 | }
436 |
437 | @Override
438 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
439 | this.widthMeasureSpec = widthMeasureSpec;
440 | remeasure();
441 | setMeasuredDimension(measuredWidth, measuredHeight);
442 | }
443 |
444 | @Override
445 | public boolean onTouchEvent(MotionEvent event) {
446 | boolean eventConsumed = gestureDetector.onTouchEvent(event);
447 | float itemHeight = lineSpacingMultiplier * maxTextHeight;
448 |
449 | switch (event.getAction()) {
450 | case MotionEvent.ACTION_DOWN:
451 | startTime = System.currentTimeMillis();
452 | cancelFuture();
453 | previousY = event.getRawY();
454 | break;
455 |
456 | case MotionEvent.ACTION_MOVE:
457 | float dy = previousY - event.getRawY();
458 | previousY = event.getRawY();
459 |
460 | totalScrollY = (int) (totalScrollY + dy);
461 |
462 | // 边界处理。
463 | if (!isLoop) {
464 | float top = -initPosition * itemHeight;
465 | float bottom = (items.size() - 1 - initPosition) * itemHeight;
466 |
467 | if (totalScrollY < top) {
468 | totalScrollY = (int) top;
469 | } else if (totalScrollY > bottom) {
470 | totalScrollY = (int) bottom;
471 | }
472 | }
473 | break;
474 |
475 | case MotionEvent.ACTION_UP:
476 | default:
477 | if (!eventConsumed) {
478 | float y = event.getY();
479 | double l = Math.acos((radius - y) / radius) * radius;
480 | int circlePosition = (int) ((l + itemHeight / 2) / itemHeight);
481 |
482 | float extraOffset = (totalScrollY % itemHeight + itemHeight) % itemHeight;
483 | mOffset = (int) ((circlePosition - itemsVisible / 2) * itemHeight - extraOffset);
484 |
485 | if ((System.currentTimeMillis() - startTime) > 120) {
486 | // 处理拖拽事件
487 | smoothScroll(ACTION.DAGGLE);
488 | } else {
489 | // 处理条目点击事件
490 | // smoothScroll(ACTION.CLICK);
491 | }
492 | }
493 | break;
494 | }
495 |
496 | invalidate();
497 | return true;
498 | }
499 | }
500 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/LoopViewGestureListener.java:
--------------------------------------------------------------------------------
1 | // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
2 | // Jad home page: http://www.geocities.com/kpdus/jad.html
3 | // Decompiler options: braces fieldsfirst space lnc
4 |
5 | package com.limxing.library.LoopView;
6 |
7 | import android.view.MotionEvent;
8 |
9 | // Referenced classes of package com.qingchifan.view:
10 | // LoopView
11 |
12 | final class LoopViewGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
13 |
14 | final LoopView loopView;
15 |
16 | LoopViewGestureListener(LoopView loopview) {
17 | loopView = loopview;
18 | }
19 |
20 | @Override
21 | public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
22 | loopView.scrollBy(velocityY);
23 | return true;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/MessageHandler.java:
--------------------------------------------------------------------------------
1 | // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
2 | // Jad home page: http://www.geocities.com/kpdus/jad.html
3 | // Decompiler options: braces fieldsfirst space lnc
4 |
5 | package com.limxing.library.LoopView;
6 |
7 | import android.os.Handler;
8 | import android.os.Message;
9 |
10 | // Referenced classes of package com.qingchifan.view:
11 | // LoopView
12 |
13 | final class MessageHandler extends Handler {
14 | public static final int WHAT_INVALIDATE_LOOP_VIEW = 1000;
15 | public static final int WHAT_SMOOTH_SCROLL = 2000;
16 | public static final int WHAT_ITEM_SELECTED = 3000;
17 |
18 | final LoopView loopview;
19 |
20 | MessageHandler(LoopView loopview) {
21 | this.loopview = loopview;
22 | }
23 |
24 | @Override
25 | public final void handleMessage(Message msg) {
26 | switch (msg.what) {
27 | case WHAT_INVALIDATE_LOOP_VIEW:
28 | loopview.invalidate();
29 | break;
30 |
31 | case WHAT_SMOOTH_SCROLL:
32 | loopview.smoothScroll(LoopView.ACTION.FLING);
33 | break;
34 |
35 | case WHAT_ITEM_SELECTED:
36 | loopview.onItemSelected();
37 | break;
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/OnItemSelectedListener.java:
--------------------------------------------------------------------------------
1 | // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
2 | // Jad home page: http://www.geocities.com/kpdus/jad.html
3 | // Decompiler options: braces fieldsfirst space lnc
4 |
5 | package com.limxing.library.LoopView;
6 |
7 |
8 | public interface OnItemSelectedListener {
9 | void onItemSelected(LoopView view);
10 | }
11 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/OnItemSelectedRunnable.java:
--------------------------------------------------------------------------------
1 | // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
2 | // Jad home page: http://www.geocities.com/kpdus/jad.html
3 | // Decompiler options: braces fieldsfirst space lnc
4 |
5 | package com.limxing.library.LoopView;
6 |
7 | // Referenced classes of package com.qingchifan.view:
8 | // LoopView, OnItemSelectedListener
9 |
10 | final class OnItemSelectedRunnable implements Runnable {
11 | final LoopView loopView;
12 |
13 | OnItemSelectedRunnable(LoopView loopview) {
14 | loopView = loopview;
15 | }
16 |
17 | @Override
18 | public final void run() {
19 | loopView.onItemSelectedListener.onItemSelected(loopView);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/LoopView/SmoothScrollTimerTask.java:
--------------------------------------------------------------------------------
1 | // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
2 | // Jad home page: http://www.geocities.com/kpdus/jad.html
3 | // Decompiler options: braces fieldsfirst space lnc
4 |
5 | package com.limxing.library.LoopView;
6 |
7 | import java.util.TimerTask;
8 |
9 | final class SmoothScrollTimerTask extends TimerTask {
10 |
11 | int realTotalOffset;
12 | int realOffset;
13 | int offset;
14 | final LoopView loopView;
15 |
16 | SmoothScrollTimerTask(LoopView loopview, int offset) {
17 | this.loopView = loopview;
18 | this.offset = offset;
19 | realTotalOffset = Integer.MAX_VALUE;
20 | realOffset = 0;
21 | }
22 |
23 | @Override
24 | public final void run() {
25 | if (realTotalOffset == Integer.MAX_VALUE) {
26 | realTotalOffset = offset;
27 | }
28 | realOffset = (int) ((float) realTotalOffset * 0.1F);
29 |
30 | if (realOffset == 0) {
31 | if (realTotalOffset < 0) {
32 | realOffset = -1;
33 | } else {
34 | realOffset = 1;
35 | }
36 | }
37 | if (Math.abs(realTotalOffset) <= 0) {
38 | loopView.cancelFuture();
39 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED);
40 | } else {
41 | loopView.totalScrollY = loopView.totalScrollY + realOffset;
42 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
43 | realTotalOffset = realTotalOffset - realOffset;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/OnConfirmeListener.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library;
2 |
3 | /**
4 | * Created by limxing on 16/5/24.
5 | */
6 | public interface OnConfirmeListener {
7 | void result(String s);
8 | }
9 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/OnDismissListener.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library;
2 |
3 | /**
4 | * Created by Sai on 15/8/9.
5 | */
6 | public interface OnDismissListener {
7 | public void onDismiss(Object o);
8 | }
9 |
--------------------------------------------------------------------------------
/library/src/main/java/com/limxing/library/OnItemClickListener.java:
--------------------------------------------------------------------------------
1 | package com.limxing.library;
2 |
3 | /**
4 | * Created by Sai on 15/8/9.
5 | */
6 | public interface OnItemClickListener {
7 | public void onItemClick(Object o, int position);
8 | }
9 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/alertview_bgin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/alertview_bgout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/fade_in_center.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
17 |
18 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/fade_out_center.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
17 |
18 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/slide_in_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/slide_out_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_actionsheet_cancel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_actionsheet_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_alertbutton_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_alertbutton_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_alertbutton_none.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_alertbutton_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/bg_alertview_alert.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/selector_pickerview_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/alertview_data.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
23 |
24 |
34 |
35 |
47 |
48 |
49 |
60 |
61 |
66 |
67 |
72 |
73 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/include_alertheader.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
24 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/item_alertbutton.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
16 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_alertview.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_alertview_actionsheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
21 |
22 |
30 |
39 |
40 |
41 |
53 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_alertview_alert.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
15 |
20 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_alertview_alert_horizontal.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_alertview_alert_vertical.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #60000000
7 |
8 | #f8f8f8
9 | #f0f0f0
10 |
11 | #000000
12 | #8f8f8f
13 |
14 | #000000
15 | #8f8f8f
16 |
17 | #d7d7db
18 |
19 | #007aff
20 |
21 | #ff3b30
22 |
23 | #007aff
24 |
25 | #EAEAEA
26 |
27 | #ffffff
28 |
29 | #f5f5f5
30 | #000000
31 | #057dff
32 | #c2daf5
33 |
34 |
35 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 22sp
6 | 14sp
7 |
8 | 60dp
9 | 40dp
10 |
11 | 15sp
12 | 14sp
13 |
14 | 25dp
15 | 14dp
16 |
17 | 40dp
18 | 10dp
19 |
20 | 1dp
21 |
22 | 48dp
23 |
24 | 18sp
25 |
26 | 15px
27 |
28 |
29 | 44dp
30 |
31 | 10dp
32 |
33 | 30dp
34 |
35 | 16sp
36 | 18sp
37 |
38 |
--------------------------------------------------------------------------------
/library/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 300
5 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | library
3 | 取消
4 | 确定
5 |
6 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------