Browse Source

Initial commit

yanyi 7 years ago
commit
150fec3e0c
58 changed files with 3652 additions and 0 deletions
  1. 9 0
      .gitignore
  2. 19 0
      .idea/gradle.xml
  3. 36 0
      .idea/inspectionProfiles/Project_Default.xml
  4. 52 0
      .idea/misc.xml
  5. 10 0
      .idea/modules.xml
  6. 12 0
      .idea/runConfigurations.xml
  7. 1 0
      app/.gitignore
  8. 27 0
      app/build.gradle
  9. 21 0
      app/proguard-rules.pro
  10. 26 0
      app/src/androidTest/java/com/yanyi/dateselect/ExampleInstrumentedTest.java
  11. 11 0
      app/src/main/AndroidManifest.xml
  12. 34 0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  13. 170 0
      app/src/main/res/drawable/ic_launcher_background.xml
  14. 5 0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  15. 5 0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  16. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  17. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  18. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  19. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  20. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  21. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  22. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  23. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  24. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  25. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  26. 6 0
      app/src/main/res/values/colors.xml
  27. 3 0
      app/src/main/res/values/strings.xml
  28. 11 0
      app/src/main/res/values/styles.xml
  29. 17 0
      app/src/test/java/com/yanyi/dateselect/ExampleUnitTest.java
  30. 31 0
      build.gradle
  31. 1 0
      datelib/.gitignore
  32. 36 0
      datelib/build.gradle
  33. 21 0
      datelib/proguard-rules.pro
  34. 26 0
      datelib/src/androidTest/java/com/yanyi/datelib/ExampleInstrumentedTest.java
  35. 2 0
      datelib/src/main/AndroidManifest.xml
  36. 483 0
      datelib/src/main/java/com/yanyi/datelib/SelectData.java
  37. 75 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/AbstractWheelAdapter.java
  38. 330 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/AbstractWheelTextAdapter1.java
  39. 82 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/ItemsRange.java
  40. 34 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/OnWheelChangedListener.java
  41. 33 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/OnWheelClickedListener.java
  42. 35 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/OnWheelScrollListener.java
  43. 154 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/WheelRecycle.java
  44. 253 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/WheelScroller.java
  45. 964 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/WheelView.java
  46. 67 0
      datelib/src/main/java/com/yanyi/datelib/wheelview/WheelViewAdapter.java
  47. 23 0
      datelib/src/main/res/drawable/wheel_bg.xml
  48. 31 0
      datelib/src/main/res/drawable/wheel_val.xml
  49. 17 0
      datelib/src/main/res/layout/item_date.xml
  50. 185 0
      datelib/src/main/res/layout/select_date_pop_layout.xml
  51. 3 0
      datelib/src/main/res/values/strings.xml
  52. 17 0
      datelib/src/test/java/com/yanyi/datelib/ExampleUnitTest.java
  53. 17 0
      gradle.properties
  54. BIN
      gradle/wrapper/gradle-wrapper.jar
  55. 6 0
      gradle/wrapper/gradle-wrapper.properties
  56. 160 0
      gradlew
  57. 90 0
      gradlew.bat
  58. 1 0
      settings.gradle

+ 9 - 0
.gitignore

@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild

+ 19 - 0
.idea/gradle.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/datelib" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 36 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,36 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="TOP_LEVEL_CLASS_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="INNER_CLASS_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="METHOD_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+        </value>
+      </option>
+      <option name="FIELD_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="IGNORE_DEPRECATED" value="false" />
+      <option name="IGNORE_JAVADOC_PERIOD" value="true" />
+      <option name="IGNORE_DUPLICATED_THROWS" value="false" />
+      <option name="IGNORE_POINT_TO_ITSELF" value="false" />
+      <option name="myAdditionalJavadocTags" value="date" />
+    </inspection_tool>
+  </profile>
+</component>

+ 52 - 0
.idea/misc.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+  <component name="SvnConfiguration">
+    <configuration>C:\Users\Administrator\AppData\Roaming\Subversion</configuration>
+  </component>
+  <component name="masterDetails">
+    <states>
+      <state key="ProjectJDKs.UI">
+        <settings>
+          <last-edited>1.8</last-edited>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+    </states>
+  </component>
+</project>

+ 10 - 0
.idea/modules.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/DateSelect.iml" filepath="$PROJECT_DIR$/DateSelect.iml" />
+      <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
+      <module fileurl="file://$PROJECT_DIR$/datelib/datelib.iml" filepath="$PROJECT_DIR$/datelib/datelib.iml" />
+    </modules>
+  </component>
+</project>

+ 12 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 27 - 0
app/build.gradle

@@ -0,0 +1,27 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 26
+    defaultConfig {
+        applicationId "com.yanyi.dateselect"
+        minSdkVersion 15
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'com.android.support:appcompat-v7:26.1.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.1'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+}

+ 21 - 0
app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
app/src/androidTest/java/com/yanyi/dateselect/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.yanyi.dateselect;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.yanyi.dateselect", appContext.getPackageName());
+    }
+}

+ 11 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,11 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.yanyi.dateselect">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme" />
+</manifest>

+ 34 - 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml

@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="78.5885"
+                android:endY="90.9159"
+                android:startX="48.7653"
+                android:startY="61.0927"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1" />
+</vector>

+ 170 - 0
app/src/main/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillColor="#26A69A"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+</vector>

+ 5 - 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

+ 5 - 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png


+ 6 - 0
app/src/main/res/values/colors.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+</resources>

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">DateSelect</string>
+</resources>

+ 11 - 0
app/src/main/res/values/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+
+</resources>

+ 17 - 0
app/src/test/java/com/yanyi/dateselect/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.yanyi.dateselect;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 31 - 0
build.gradle

@@ -0,0 +1,31 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.0.1'
+        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
+        
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+        maven {
+            url 'https://jitpack.io'
+        }
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 1 - 0
datelib/.gitignore

@@ -0,0 +1 @@
+/build

+ 36 - 0
datelib/build.gradle

@@ -0,0 +1,36 @@
+apply plugin: 'com.android.library'
+apply plugin: 'com.github.dcendents.android-maven'
+group = 'com.github.BenYanYi'
+
+android {
+    compileSdkVersion 26
+
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'com.android.support:appcompat-v7:26.1.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.1'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+}

+ 21 - 0
datelib/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
datelib/src/androidTest/java/com/yanyi/datelib/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.yanyi.datelib;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.yanyi.datelib.test", appContext.getPackageName());
+    }
+}

+ 2 - 0
datelib/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.yanyi.datelib" />

+ 483 - 0
datelib/src/main/java/com/yanyi/datelib/SelectData.java

@@ -0,0 +1,483 @@
+package com.yanyi.datelib;
+
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import com.yanyi.datelib.wheelview.AbstractWheelTextAdapter1;
+import com.yanyi.datelib.wheelview.OnWheelChangedListener;
+import com.yanyi.datelib.wheelview.OnWheelScrollListener;
+import com.yanyi.datelib.wheelview.WheelView;
+
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+
+/**
+ * Created by wuguilin on 1/9/2017.
+ */
+
+
+public class SelectData extends PopupWindow implements View.OnClickListener {
+    private static final String TAG = "SelectData";
+
+    private WheelView wvYear;
+    private WheelView wvMonth;
+    private WheelView wvDay;
+    private WheelView wvHour;
+    private WheelView wvMinute;
+    private View lySelectDate;
+    private View lySelectDateChild;
+    private TextView btnSure;
+    private TextView btnCancel;
+
+    private LinearLayout hourContainer,minuteContainer;
+
+    private Context context;
+    private JSONObject mJsonObj;
+
+    private String[] mYearDatas, mMonthDatas, mDayDatas, mHourDatas, mMinuteDatas;
+
+
+    private DateTextAdapter yearAdapter;
+    private DateTextAdapter monthAdapter;
+    private DateTextAdapter dayAdapter;
+    private DateTextAdapter hourAdapter;
+    private DateTextAdapter minuteAdapter;
+
+    private String strYear;
+    private String strMonth;
+    private String strDay;
+    private String strHour;
+    private String strMinute;
+    private OnDateClickListener onDateClickListener;
+
+    private int maxSize = 14;
+    private int minSize = 12;
+    private Calendar calendar = Calendar.getInstance();
+    public SelectData(final Context context){
+        this(context,true);
+    }
+
+    public SelectData(final Context context, boolean showTime) {
+        super(context);
+        this.context = context;
+        View view = View.inflate(context, R.layout.select_date_pop_layout, null);
+
+        wvYear = (WheelView) view.findViewById(R.id.wv_date_year);
+        wvMonth = (WheelView) view.findViewById(R.id.wv_date_month);
+        wvDay = (WheelView) view.findViewById(R.id.wv_date_day);
+        wvHour = (WheelView) view.findViewById(R.id.wv_date_hour);
+        wvMinute = (WheelView) view.findViewById(R.id.wv_date_minute);
+        lySelectDate = view.findViewById(R.id.select_date);
+        lySelectDateChild = view.findViewById(R.id.select_date_child);
+        btnSure = (TextView) view.findViewById(R.id.btn_myinfo_sure);
+        btnCancel = (TextView) view.findViewById(R.id.btn_myinfo_cancel);
+
+        hourContainer = (LinearLayout) view.findViewById(R.id.hour_container);
+        minuteContainer = (LinearLayout) view.findViewById(R.id.minute_container);
+        if(showTime){
+            hourContainer.setVisibility(View.VISIBLE);
+            minuteContainer.setVisibility(View.VISIBLE);
+        }else {
+            hourContainer.setVisibility(View.GONE);
+            minuteContainer.setVisibility(View.GONE);
+        }
+
+
+        //设置SelectPicPopupWindow的View
+        this.setContentView(view);
+        //设置SelectPicPopupWindow弹出窗体的宽
+        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
+        //设置SelectPicPopupWindow弹出窗体的高
+        this.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
+        //设置SelectPicPopupWindow弹出窗体可点击
+        this.setFocusable(true);
+        //设置SelectPicPopupWindow弹出窗体动画效果
+//		this.setAnimationStyle(R.style.AnimBottom);
+        //实例化一个ColorDrawable颜色为半透明
+        ColorDrawable dw = new ColorDrawable(0xb0000000);
+        //设置SelectPicPopupWindow弹出窗体的背景
+        this.setBackgroundDrawable(dw);
+
+        lySelectDateChild.setOnClickListener(this);
+        btnSure.setOnClickListener(this);
+        btnCancel.setOnClickListener(this);
+
+        initDatas();
+
+        yearAdapter = new DateTextAdapter(context, mYearDatas, Integer.parseInt(strYear) - calendar.get(Calendar.YEAR) + 100, maxSize, minSize);
+        wvYear.setVisibleItems(5);
+        wvYear.setViewAdapter(yearAdapter);
+        wvYear.setCurrentItem(Integer.parseInt(strYear) - calendar.get(Calendar.YEAR) + 100);
+
+
+        monthAdapter = new DateTextAdapter(context, mMonthDatas, Integer.parseInt(strMonth) - 1, maxSize, minSize);
+        wvMonth.setVisibleItems(5);
+        wvMonth.setViewAdapter(monthAdapter);
+        wvMonth.setCurrentItem(Integer.parseInt(strMonth) - 1);
+
+        //initDays(mAreaDatasMap.get(strMonth));
+        dayAdapter = new DateTextAdapter(context, mDayDatas, Integer.parseInt(strDay) - 1, maxSize, minSize);
+        wvDay.setVisibleItems(5);
+        wvDay.setViewAdapter(dayAdapter);
+        wvDay.setCurrentItem(Integer.parseInt(strDay) - 1);
+
+        hourAdapter = new DateTextAdapter(context, mHourDatas, Integer.parseInt(strHour) , maxSize, minSize);
+        wvHour.setVisibleItems(5);
+        wvHour.setViewAdapter(hourAdapter);
+        wvHour.setCurrentItem(Integer.parseInt(strHour) );
+
+        minuteAdapter = new DateTextAdapter(context, mMinuteDatas, Integer.parseInt(strMinute), maxSize, minSize);
+        wvMinute.setVisibleItems(5);
+        wvMinute.setViewAdapter(minuteAdapter);
+        wvMinute.setCurrentItem(Integer.parseInt(strMinute));
+
+        wvYear.addChangingListener(new OnWheelChangedListener() {
+
+            @Override
+            public void onChanged(WheelView wheel, int oldValue, int newValue) {
+                // TODO Auto-generated method stub
+                String currentText = (String) yearAdapter.getItemText(wheel.getCurrentItem());
+                strYear = currentText;
+                setTextviewSize(currentText, yearAdapter);
+
+
+                mDayDatas = getDays(Integer.parseInt(strYear), Integer.parseInt(strMonth));
+                dayAdapter = new DateTextAdapter(context, mDayDatas, 0, maxSize, minSize);
+                wvDay.setVisibleItems(5);
+                wvDay.setViewAdapter(dayAdapter);
+                wvDay.setCurrentItem(0);
+                setTextviewSize("0", dayAdapter);
+            }
+        });
+
+        wvYear.addScrollingListener(new OnWheelScrollListener() {
+
+            @Override
+            public void onScrollingStarted(WheelView wheel) {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void onScrollingFinished(WheelView wheel) {
+                // TODO Auto-generated method stub
+                String currentText = (String) yearAdapter.getItemText(wheel.getCurrentItem());
+                setTextviewSize(currentText, yearAdapter);
+            }
+        });
+
+        wvMonth.addChangingListener(new OnWheelChangedListener() {
+
+            @Override
+            public void onChanged(WheelView wheel, int oldValue, int newValue) {
+                // TODO Auto-generated method stub
+                String currentText = (String) monthAdapter.getItemText(wheel.getCurrentItem());
+                strMonth = currentText;
+                setTextviewSize(currentText, monthAdapter);
+
+
+                mDayDatas = getDays(Integer.parseInt(strYear), Integer.parseInt(strMonth));
+                dayAdapter = new DateTextAdapter(context, mDayDatas, 0, maxSize, minSize);
+                wvDay.setVisibleItems(5);
+                wvDay.setViewAdapter(dayAdapter);
+                wvDay.setCurrentItem(0);
+                setTextviewSize("0", dayAdapter);
+
+
+            }
+        });
+
+        wvMonth.addScrollingListener(new OnWheelScrollListener() {
+
+            @Override
+            public void onScrollingStarted(WheelView wheel) {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void onScrollingFinished(WheelView wheel) {
+                // TODO Auto-generated method stub
+                String currentText = (String) monthAdapter.getItemText(wheel.getCurrentItem());
+                setTextviewSize(currentText, monthAdapter);
+            }
+        });
+
+        wvDay.addChangingListener(new OnWheelChangedListener() {
+
+            @Override
+            public void onChanged(WheelView wheel, int oldValue, int newValue) {
+                // TODO Auto-generated method stub
+                String currentText = (String) dayAdapter.getItemText(wheel.getCurrentItem());
+                strDay = currentText;
+                setTextviewSize(currentText, dayAdapter);
+            }
+        });
+
+        wvDay.addScrollingListener(new OnWheelScrollListener() {
+
+            @Override
+            public void onScrollingStarted(WheelView wheel) {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void onScrollingFinished(WheelView wheel) {
+                // TODO Auto-generated method stub
+                String currentText = (String) dayAdapter.getItemText(wheel.getCurrentItem());
+                setTextviewSize(currentText, dayAdapter);
+            }
+        });
+
+
+        wvHour.addChangingListener(new OnWheelChangedListener() {
+
+            @Override
+            public void onChanged(WheelView wheel, int oldValue, int newValue) {
+                // TODO Auto-generated method stub
+                String currentText = (String) hourAdapter.getItemText(wheel.getCurrentItem());
+                strMinute = currentText;
+                setTextviewSize(currentText, hourAdapter);
+            }
+        });
+
+        wvHour.addScrollingListener(new OnWheelScrollListener() {
+
+            @Override
+            public void onScrollingStarted(WheelView wheel) {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void onScrollingFinished(WheelView wheel) {
+                // TODO Auto-generated method stub
+                String currentText = (String) hourAdapter.getItemText(wheel.getCurrentItem());
+                setTextviewSize(currentText, hourAdapter);
+            }
+        });
+        wvMinute.addChangingListener(new OnWheelChangedListener() {
+
+            @Override
+            public void onChanged(WheelView wheel, int oldValue, int newValue) {
+                // TODO Auto-generated method stub
+                String currentText = (String) minuteAdapter.getItemText(wheel.getCurrentItem());
+                strMinute = currentText;
+                setTextviewSize(currentText, minuteAdapter);
+            }
+        });
+
+        wvMinute.addScrollingListener(new OnWheelScrollListener() {
+
+            @Override
+            public void onScrollingStarted(WheelView wheel) {
+                // TODO Auto-generated method stub
+
+            }
+
+            @Override
+            public void onScrollingFinished(WheelView wheel) {
+                // TODO Auto-generated method stub
+                String currentText = (String) minuteAdapter.getItemText(wheel.getCurrentItem());
+                setTextviewSize(currentText, minuteAdapter);
+            }
+        });
+
+    }
+
+
+    private class DateTextAdapter extends AbstractWheelTextAdapter1 {
+        String[] list;
+
+        protected DateTextAdapter(Context context, String[] list, int currentItem, int maxsize, int minsize) {
+            super(context, R.layout.item_date, NO_RESOURCE, currentItem, maxsize, minsize);
+            this.list = list;
+            setItemTextResource(R.id.tempValue);
+        }
+
+        @Override
+        public View getItem(int index, View cachedView, ViewGroup parent) {
+            View view = super.getItem(index, cachedView, parent);
+            return view;
+        }
+
+        @Override
+        public int getItemsCount() {
+            return list.length;
+        }
+
+        @Override
+        protected CharSequence getItemText(int index) {
+            // if (getItemsCount() == 0) return "";
+            return list[index];
+        }
+    }
+
+    /**
+     * 设置字体大小
+     *
+     * @param curriteItemText
+     * @param adapter
+     */
+    public void setTextviewSize(String curriteItemText, DateTextAdapter adapter) {
+        ArrayList<View> arrayList = adapter.getTestViews();
+        int size = arrayList.size();
+        String currentText;
+        for (int i = 0; i < size; i++) {
+            TextView textvew = (TextView) arrayList.get(i);
+            currentText = textvew.getText().toString();
+            if (curriteItemText.equals(currentText)) {
+                textvew.setTextSize(14);
+            } else {
+                textvew.setTextSize(12);
+            }
+        }
+    }
+
+    public void setDateClickListener(OnDateClickListener onDateClickListener) {
+
+        this.onDateClickListener = onDateClickListener;
+    }
+
+    @Override
+    public void onClick(View v) {
+        // TODO Auto-generated method stub
+        if (v == btnSure) {
+            if (onDateClickListener != null) {
+                onDateClickListener.onClick(strYear, strMonth, strDay, strHour, strMinute);
+            }
+        } else if (v == btnCancel) {
+
+        } else if (v == lySelectDateChild) {
+            return;
+        } else {
+//			dismiss();
+        }
+        dismiss();
+    }
+
+    /**
+     * 回调接口
+     *
+     * @author Administrator
+     */
+    public interface OnDateClickListener {
+        public void onClick(String year, String month, String day, String hour, String minute);
+    }
+
+    /**
+     * 从文件中读取地址数据
+     */
+/*    private void initJsonData() {
+        try {
+            StringBuffer sb = new StringBuffer();
+            InputStream is = context.getClass().getClassLoader().getResourceAsStream("assets/" + "city.json");
+            int len = -1;
+            byte[] buf = new byte[1024];
+            while ((len = is.read(buf)) != -1) {
+                sb.append(new String(buf, 0, len, "gbk"));
+            }
+            is.close();
+            mJsonObj = new JSONObject(sb.toString());
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+    }*/
+    private void initDatas() {
+        int year, month, day, hour, minute;
+
+        year = calendar.get(Calendar.YEAR);
+        month = calendar.get(Calendar.MONTH) + 1;
+        day = calendar.get(Calendar.DATE);
+        hour = calendar.get(Calendar.HOUR_OF_DAY);
+        minute = calendar.get(Calendar.MINUTE);
+        strYear = String.valueOf(year);
+        strMonth = (month<10?"0":"")+ String.valueOf(month);
+        strDay = (day<10?"0":"")+ String.valueOf(day);
+        strHour = (hour<10?"0":"")+ String.valueOf(hour);
+        strMinute = (minute<10?"0":"")+ String.valueOf(minute);
+
+        mYearDatas = new String[150];
+        //int year = calendar.get(Calendar.YEAR);
+        for (int i = year - 100, j = 0; i < year + 50; i++, j++) {
+            mYearDatas[j] = i + "";
+        }
+        mMonthDatas = new String[12];
+        for (int i = 0; i < 12; i++) {
+            if (i < 9) {
+                mMonthDatas[i] = "0" + (i + 1) + "";
+            } else {
+                mMonthDatas[i] = i + 1 + "";
+            }
+
+        }
+        int count = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
+        //Log.e(TAG, "initDatas: "+ strYear+":"+strMonth+":"+strDay+":"+count);
+
+
+        mDayDatas = new String[count];
+        for (int i = 0; i < count; i++) {
+            if (i < 9) {
+                mDayDatas[i] = "0" + (i + 1);
+            } else {
+                mDayDatas[i] = i + 1 + "";
+            }
+
+        }
+        mHourDatas = new String[24];
+        for (int i = 0; i < 24; i++) {
+            if (i < 10) {
+                mHourDatas[i] = "0" + i;
+            } else {
+                mHourDatas[i] = i + "";
+            }
+
+        }
+        mMinuteDatas = new String[60];
+        for (int i = 0; i < 60; i++) {
+            if (i < 10) {
+                mMinuteDatas[i] = "0" + i;
+            } else {
+                mMinuteDatas[i] = i + "";
+            }
+
+        }
+    }
+
+    private String[] getDays(int year, int month) {
+        String[] datas;
+        Calendar newCal = Calendar.getInstance();
+        // newCal.s
+        newCal.set(Calendar.YEAR, year);
+        newCal.set(Calendar.MONTH, month-1);
+        int count = newCal.getActualMaximum(Calendar.DAY_OF_MONTH);//new Date(year,month,0).getDate();
+
+         Log.e(TAG, "getDays: "+ year + ":" + month+":"+count );
+        datas = new String[count];
+        for (int i = 0; i < count; i++) {
+            if (i < 9) {
+                datas[i] = "0" + (i + 1);
+            } else {
+                datas[i] = i + 1 + "";
+            }
+
+
+        }
+        return datas;
+
+
+    }
+
+
+}

+ 75 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/AbstractWheelAdapter.java

@@ -0,0 +1,75 @@
+/*
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+import android.database.DataSetObserver;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Abstract Wheel adapter.
+ * @author myLove
+ */
+public abstract class AbstractWheelAdapter implements WheelViewAdapter {
+    // Observers
+    private List<DataSetObserver> datasetObservers;
+    
+    @Override
+    public View getEmptyItem(View convertView, ViewGroup parent) {
+        return null;
+    }
+
+    @Override
+    public void registerDataSetObserver(DataSetObserver observer) {
+        if (datasetObservers == null) {
+            datasetObservers = new LinkedList<DataSetObserver>();
+        }
+        datasetObservers.add(observer);
+    }
+
+    @Override
+    public void unregisterDataSetObserver(DataSetObserver observer) {
+        if (datasetObservers != null) {
+            datasetObservers.remove(observer);
+        }
+    }
+    
+    /**
+     * Notifies observers about data changing
+     */
+    protected void notifyDataChangedEvent() {
+        if (datasetObservers != null) {
+            for (DataSetObserver observer : datasetObservers) {
+                observer.onChanged();
+            }
+        }
+    }
+    
+    /**
+     * Notifies observers about invalidating data
+     */
+    protected void notifyDataInvalidatedEvent() {
+        if (datasetObservers != null) {
+            for (DataSetObserver observer : datasetObservers) {
+                observer.onInvalidated();
+            }
+        }
+    }
+}

+ 330 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/AbstractWheelTextAdapter1.java

@@ -0,0 +1,330 @@
+/*
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package com.yanyi.datelib.wheelview;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+/**
+ * Abstract wheel adapter provides common functionality for adapters.
+ * @author myLove
+ */
+public abstract class AbstractWheelTextAdapter1 extends AbstractWheelAdapter {
+
+	/** Text view resource. Used as a default view for adapter. */
+	public static final int TEXT_VIEW_ITEM_RESOURCE = -1;
+
+	/** No resource constant. */
+	protected static final int NO_RESOURCE = 0;
+
+	/** Default text color */
+	public static final int DEFAULT_TEXT_COLOR = 0xFF101010;
+
+	/** Default text color */
+	public static final int LABEL_COLOR = 0xFF700070;
+
+	/** Default text size */
+	public static final int DEFAULT_TEXT_SIZE = 24;
+
+	// Text settings
+	private int textColor = DEFAULT_TEXT_COLOR;
+	private int textSize = DEFAULT_TEXT_SIZE;
+
+	// Current context
+	protected Context context;
+	// Layout inflater
+	protected LayoutInflater inflater;
+
+	// Items resources
+	protected int itemResourceId;
+	protected int itemTextResourceId;
+
+	// Empty items resources
+	protected int emptyItemResourceId;
+
+	private int currentIndex = 0;
+	private static int maxsize = 14;
+	private static int minsize = 12;
+	private ArrayList<View> arrayList = new ArrayList<View>();
+
+	/**
+	 * Constructor
+	 * 
+	 * @param context
+	 *            the current context
+	 */
+	protected AbstractWheelTextAdapter1(Context context) {
+		this(context, TEXT_VIEW_ITEM_RESOURCE);
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param context
+	 *            the current context
+	 * @param itemResource
+	 *            the resource ID for a layout file containing a TextView to use
+	 *            when instantiating items views
+	 */
+	protected AbstractWheelTextAdapter1(Context context, int itemResource) {
+		this(context, itemResource, NO_RESOURCE, 0, maxsize, minsize);
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param context
+	 *            the current context
+	 * @param itemResource
+	 *            the resource ID for a layout file containing a TextView to use
+	 *            when instantiating items views
+	 * @param itemTextResource
+	 *            the resource ID for a text view in the item layout
+	 */
+	protected AbstractWheelTextAdapter1(Context context, int itemResource, int itemTextResource, int currentIndex,
+                                        int maxsize, int minsize) {
+		this.context = context;
+		itemResourceId = itemResource;
+		itemTextResourceId = itemTextResource;
+		this.currentIndex = currentIndex;
+		this.maxsize = maxsize;
+		this.minsize = minsize;
+
+		inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+	}
+
+	/**
+	 * get the list of show textview
+	 * 
+	 * @return the array of textview
+	 */
+	public ArrayList<View> getTestViews() {
+		return arrayList;
+	}
+
+	/**
+	 * Gets text color
+	 * 
+	 * @return the text color
+	 */
+	public int getTextColor() {
+		return textColor;
+	}
+
+	/**
+	 * Sets text color
+	 * 
+	 * @param textColor
+	 *            the text color to set
+	 */
+	public void setTextColor(int textColor) {
+		this.textColor = textColor;
+	}
+
+	/**
+	 * Gets text size
+	 * 
+	 * @return the text size
+	 */
+	public int getTextSize() {
+		return textSize;
+	}
+
+	/**
+	 * Sets text size
+	 * 
+	 * @param textSize
+	 *            the text size to set
+	 */
+	public void setTextSize(int textSize) {
+		this.textSize = textSize;
+	}
+
+	/**
+	 * Gets resource Id for items views
+	 * 
+	 * @return the item resource Id
+	 */
+	public int getItemResource() {
+		return itemResourceId;
+	}
+
+	/**
+	 * Sets resource Id for items views
+	 * 
+	 * @param itemResourceId
+	 *            the resource Id to set
+	 */
+	public void setItemResource(int itemResourceId) {
+		this.itemResourceId = itemResourceId;
+	}
+
+	/**
+	 * Gets resource Id for text view in item layout
+	 * 
+	 * @return the item text resource Id
+	 */
+	public int getItemTextResource() {
+		return itemTextResourceId;
+	}
+
+	/**
+	 * Sets resource Id for text view in item layout
+	 * 
+	 * @param itemTextResourceId
+	 *            the item text resource Id to set
+	 */
+	public void setItemTextResource(int itemTextResourceId) {
+		this.itemTextResourceId = itemTextResourceId;
+	}
+
+	/**
+	 * Gets resource Id for empty items views
+	 * 
+	 * @return the empty item resource Id
+	 */
+	public int getEmptyItemResource() {
+		return emptyItemResourceId;
+	}
+
+	/**
+	 * Sets resource Id for empty items views
+	 * 
+	 * @param emptyItemResourceId
+	 *            the empty item resource Id to set
+	 */
+	public void setEmptyItemResource(int emptyItemResourceId) {
+		this.emptyItemResourceId = emptyItemResourceId;
+	}
+
+	/**
+	 * Returns text for specified item
+	 * 
+	 * @param index
+	 *            the item index
+	 * @return the text of specified items
+	 */
+	protected abstract CharSequence getItemText(int index);
+
+	@Override
+	public View getItem(int index, View convertView, ViewGroup parent) {
+		if (index >= 0 && index < getItemsCount()) {
+			if (convertView == null) {
+				convertView = getView(itemResourceId, parent);
+			}
+			TextView textView = getTextView(convertView, itemTextResourceId);
+			if (!arrayList.contains(textView)) {
+				arrayList.add(textView);
+			}
+			if (textView != null) {
+				CharSequence text = getItemText(index);
+				if (text == null) {
+					text = "";
+				}
+				textView.setText(text);
+
+				if (index == currentIndex) {
+					textView.setTextSize(maxsize);
+				} else {
+					textView.setTextSize(minsize);
+				}
+
+				if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) {
+					configureTextView(textView);
+				}
+			}
+			return convertView;
+		}
+		return null;
+	}
+
+	@Override
+	public View getEmptyItem(View convertView, ViewGroup parent) {
+		if (convertView == null) {
+			convertView = getView(emptyItemResourceId, parent);
+		}
+		if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) {
+			configureTextView((TextView) convertView);
+		}
+
+		return convertView;
+	}
+
+	/**
+	 * Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views.
+	 * 
+	 * @param view
+	 *            the text view to be configured
+	 */
+	protected void configureTextView(TextView view) {
+		view.setTextColor(textColor);
+		view.setGravity(Gravity.CENTER);
+		view.setTextSize(textSize);
+		view.setLines(1);
+		view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
+	}
+
+	/**
+	 * Loads a text view from view
+	 * 
+	 * @param view
+	 *            the text view or layout containing it
+	 * @param textResource
+	 *            the text resource Id in layout
+	 * @return the loaded text view
+	 */
+	private TextView getTextView(View view, int textResource) {
+		TextView text = null;
+		try {
+			if (textResource == NO_RESOURCE && view instanceof TextView) {
+				text = (TextView) view;
+			} else if (textResource != NO_RESOURCE) {
+				text = (TextView) view.findViewById(textResource);
+			}
+		} catch (ClassCastException e) {
+			Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView");
+			throw new IllegalStateException("AbstractWheelAdapter requires the resource ID to be a TextView", e);
+		}
+
+		return text;
+	}
+
+	/**
+	 * Loads view from resources
+	 * 
+	 * @param resource
+	 *            the resource Id
+	 * @return the loaded view or null if resource is not set
+	 */
+	private View getView(int resource, ViewGroup parent) {
+		switch (resource) {
+		case NO_RESOURCE:
+			return null;
+		case TEXT_VIEW_ITEM_RESOURCE:
+			return new TextView(context);
+		default:
+			return inflater.inflate(resource, parent, false);
+		}
+	}
+}

+ 82 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/ItemsRange.java

@@ -0,0 +1,82 @@
+/*
+ *  Android Wheel Control.
+ *  https://code.google.com/p/android-wheel/
+ *  
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+/**
+ * Range for visible items.
+ * @author myLove
+ */
+public class ItemsRange {
+	// First item number
+	private int first;
+	
+	// Items count
+	private int count;
+
+	/**
+	 * Default constructor. Creates an empty range
+	 */
+    public ItemsRange() {
+        this(0, 0);
+    }
+    
+	/**
+	 * Constructor
+	 * @param first the number of first item
+	 * @param count the count of items
+	 */
+	public ItemsRange(int first, int count) {
+		this.first = first;
+		this.count = count;
+	}
+	
+	/**
+	 * Gets number of  first item
+	 * @return the number of the first item
+	 */
+	public int getFirst() {
+		return first;
+	}
+	
+	/**
+	 * Gets number of last item
+	 * @return the number of last item
+	 */
+	public int getLast() {
+		return getFirst() + getCount() - 1;
+	}
+	
+	/**
+	 * Get items count
+	 * @return the count of items
+	 */
+	public int getCount() {
+		return count;
+	}
+	
+	/**
+	 * Tests whether item is contained by range
+	 * @param index the item number
+	 * @return true if item is contained
+	 */
+	public boolean contains(int index) {
+		return index >= getFirst() && index <= getLast();
+	}
+}

+ 34 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/OnWheelChangedListener.java

@@ -0,0 +1,34 @@
+/*
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+/**
+ * Wheel changed listener interface.
+ * <p>The onChanged() method is called whenever current wheel positions is changed:
+ * <li> New Wheel position is set
+ * <li> Wheel view is scrolled
+ * @author myLove
+ */
+public interface OnWheelChangedListener {
+	/**
+	 * Callback method to be invoked when current item changed
+	 * @param wheel the wheel view whose state has changed
+	 * @param oldValue the old value of current item
+	 * @param newValue the new value of current item
+	 */
+	void onChanged(WheelView wheel, int oldValue, int newValue);
+}

+ 33 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/OnWheelClickedListener.java

@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+/**
+ * Wheel clicked listener interface.
+ * <p>The onItemClicked() method is called whenever a wheel item is clicked
+ * <li> New Wheel position is set
+ * <li> Wheel view is scrolled
+ * @author myLove
+ */
+public interface OnWheelClickedListener {
+    /**
+     * Callback method to be invoked when current item clicked
+     * @param wheel the wheel view
+     * @param itemIndex the index of clicked item
+     */
+    void onItemClicked(WheelView wheel, int itemIndex);
+}

+ 35 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/OnWheelScrollListener.java

@@ -0,0 +1,35 @@
+/*
+ *  Copyright 2010 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+/**
+ * Wheel scrolled listener interface.
+ * @author myLove
+ */
+public interface OnWheelScrollListener {
+	/**
+	 * Callback method to be invoked when scrolling started.
+	 * @param wheel the wheel view whose state has changed.
+	 */
+	void onScrollingStarted(WheelView wheel);
+	
+	/**
+	 * Callback method to be invoked when scrolling ended.
+	 * @param wheel the wheel view whose state has changed.
+	 */
+	void onScrollingFinished(WheelView wheel);
+}

+ 154 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/WheelRecycle.java

@@ -0,0 +1,154 @@
+/*
+ *  Android Wheel Control.
+ *  https://code.google.com/p/android-wheel/
+ *  
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+import android.view.View;
+import android.widget.LinearLayout;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Recycle stores wheel items to reuse.
+ * @author myLove
+ */
+public class WheelRecycle {
+	// Cached items
+	private List<View> items;
+	
+	// Cached empty items
+	private List<View> emptyItems;
+	
+	// Wheel view
+	private WheelView wheel;
+	
+	/**
+	 * Constructor
+	 * @param wheel the wheel view
+	 */
+	public WheelRecycle(WheelView wheel) {
+		this.wheel = wheel;
+	}
+
+	/**
+	 * Recycles items from specified layout.
+	 * There are saved only items not included to specified range.
+	 * All the cached items are removed from original layout.
+	 * 
+	 * @param layout the layout containing items to be cached
+	 * @param firstItem the number of first item in layout
+	 * @param range the range of current wheel items 
+	 * @return the new value of first item number
+	 */
+	public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) {
+		int index = firstItem;
+		for (int i = 0; i < layout.getChildCount();) {
+			if (!range.contains(index)) {
+				recycleView(layout.getChildAt(i), index);
+				layout.removeViewAt(i);
+				if (i == 0) { // first item
+					firstItem++;
+				}
+			} else {
+				i++; // go to next item
+			}
+			index++;
+		}
+		return firstItem;
+	}
+	
+	/**
+	 * Gets item view
+	 * @return the cached view
+	 */
+	public View getItem() {
+		return getCachedView(items);
+	}
+
+	/**
+	 * Gets empty item view
+	 * @return the cached empty view
+	 */
+	public View getEmptyItem() {
+		return getCachedView(emptyItems);
+	}
+	
+	/**
+	 * Clears all views 
+	 */
+	public void clearAll() {
+		if (items != null) {
+			items.clear();
+		}
+		if (emptyItems != null) {
+			emptyItems.clear();
+		}
+	}
+
+	/**
+	 * Adds view to specified cache. Creates a cache list if it is null.
+	 * @param view the view to be cached
+	 * @param cache the cache list
+	 * @return the cache list
+	 */
+	private List<View> addView(View view, List<View> cache) {
+		if (cache == null) {
+			cache = new LinkedList<View>();
+		}
+		
+		cache.add(view);
+		return cache;
+	}
+
+	/**
+	 * Adds view to cache. Determines view type (item view or empty one) by index.
+	 * @param view the view to be cached
+	 * @param index the index of view
+	 */
+	private void recycleView(View view, int index) {
+		int count = wheel.getViewAdapter().getItemsCount();
+
+		if ((index < 0 || index >= count) && !wheel.isCyclic()) {
+			// empty view
+			emptyItems = addView(view, emptyItems);
+		} else {
+			while (index < 0) {
+				index = count + index;
+			}
+			index %= count;
+			items = addView(view, items);
+		}
+	}
+	
+	/**
+	 * Gets view from specified cache.
+	 * @param cache the cache
+	 * @return the first view from cache.
+	 */
+	private View getCachedView(List<View> cache) {
+		if (cache != null && cache.size() > 0) {
+			View view = cache.get(0);
+			cache.remove(0);
+			return view;
+		}
+		return null;
+	}
+
+}

+ 253 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/WheelScroller.java

@@ -0,0 +1,253 @@
+/*
+ *  Android Wheel Control.
+ *  https://code.google.com/p/android-wheel/
+ *  
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.view.GestureDetector;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+/**
+ * Scroller class handles scrolling events and updates the
+ * @author myLove
+ */
+public class WheelScroller {
+    /**
+     * Scrolling listener interface
+     */
+    public interface ScrollingListener {
+        /**
+         * Scrolling callback called when scrolling is performed.
+         * @param distance the distance to scroll
+         */
+        void onScroll(int distance);
+
+        /**
+         * Starting callback called when scrolling is started
+         */
+        void onStarted();
+        
+        /**
+         * Finishing callback called after justifying
+         */
+        void onFinished();
+        
+        /**
+         * Justifying callback called to justify a view when scrolling is ended
+         */
+        void onJustify();
+    }
+    
+    /** Scrolling duration */
+    private static final int SCROLLING_DURATION = 400;
+
+    /** Minimum delta for scrolling */
+    public static final int MIN_DELTA_FOR_SCROLLING = 1;
+
+    // Listener
+    private ScrollingListener listener;
+    
+    // Context
+    private Context context;
+    
+    // Scrolling
+    private GestureDetector gestureDetector;
+    private Scroller scroller;
+    private int lastScrollY;
+    private float lastTouchedY;
+    private boolean isScrollingPerformed;
+
+    /**
+     * Constructor
+     * @param context the current context
+     * @param listener the scrolling listener
+     */
+    public WheelScroller(Context context, ScrollingListener listener) {
+        gestureDetector = new GestureDetector(context, gestureListener);
+        gestureDetector.setIsLongpressEnabled(false);
+        
+        scroller = new Scroller(context);
+
+        this.listener = listener;
+        this.context = context;
+    }
+    
+    /**
+     * Set the the specified scrolling interpolator
+     * @param interpolator the interpolator
+     */
+    public void setInterpolator(Interpolator interpolator) {
+        scroller.forceFinished(true);
+        scroller = new Scroller(context, interpolator);
+    }
+    
+    /**
+     * Scroll the wheel
+     * @param distance the scrolling distance
+     * @param time the scrolling duration
+     */
+    public void scroll(int distance, int time) {
+        scroller.forceFinished(true);
+
+        lastScrollY = 0;
+        
+        scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION);
+        setNextMessage(MESSAGE_SCROLL);
+        
+        startScrolling();
+    }
+   
+    /**
+     * Stops scrolling
+     */
+    public void stopScrolling() {
+        scroller.forceFinished(true);
+    }
+    
+    /**
+     * Handles Touch event 
+     * @param event the motion event
+     * @return
+     */
+    public boolean onTouchEvent(MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                lastTouchedY = event.getY();
+                scroller.forceFinished(true);
+                clearMessages();
+                break;
+    
+            case MotionEvent.ACTION_MOVE:
+                // perform scrolling
+                int distanceY = (int)(event.getY() - lastTouchedY);
+                if (distanceY != 0) {
+                    startScrolling();
+                    listener.onScroll(distanceY);
+                    lastTouchedY = event.getY();
+                }
+                break;
+        }
+        
+        if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {
+            justify();
+        }
+
+        return true;
+    }
+    
+    // gesture listener
+    private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
+        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+            // Do scrolling in onTouchEvent() since onScroll() are not call immediately
+            //  when user touch and move the wheel
+            return true;
+        }
+        
+        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+            lastScrollY = 0;
+            final int maxY = 0x7FFFFFFF;
+            final int minY = -maxY;
+            scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY);
+            setNextMessage(MESSAGE_SCROLL);
+            return true;
+        }
+    };
+
+    // Messages
+    private final int MESSAGE_SCROLL = 0;
+    private final int MESSAGE_JUSTIFY = 1;
+    
+    /**
+     * Set next message to queue. Clears queue before.
+     * 
+     * @param message the message to set
+     */
+    private void setNextMessage(int message) {
+        clearMessages();
+        animationHandler.sendEmptyMessage(message);
+    }
+
+    /**
+     * Clears messages from queue
+     */
+    private void clearMessages() {
+        animationHandler.removeMessages(MESSAGE_SCROLL);
+        animationHandler.removeMessages(MESSAGE_JUSTIFY);
+    }
+    
+    // animation handler
+    private Handler animationHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            scroller.computeScrollOffset();
+            int currY = scroller.getCurrY();
+            int delta = lastScrollY - currY;
+            lastScrollY = currY;
+            if (delta != 0) {
+                listener.onScroll(delta);
+            }
+            
+            // scrolling is not finished when it comes to final Y
+            // so, finish it manually 
+            if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
+                currY = scroller.getFinalY();
+                scroller.forceFinished(true);
+            }
+            if (!scroller.isFinished()) {
+                animationHandler.sendEmptyMessage(msg.what);
+            } else if (msg.what == MESSAGE_SCROLL) {
+                justify();
+            } else {
+                finishScrolling();
+            }
+        }
+    };
+    
+    /**
+     * Justifies wheel
+     */
+    private void justify() {
+        listener.onJustify();
+        setNextMessage(MESSAGE_JUSTIFY);
+    }
+
+    /**
+     * Starts scrolling
+     */
+    private void startScrolling() {
+        if (!isScrollingPerformed) {
+            isScrollingPerformed = true;
+            listener.onStarted();
+        }
+    }
+
+    /**
+     * Finishes scrolling
+     */
+    void finishScrolling() {
+        if (isScrollingPerformed) {
+            listener.onFinished();
+            isScrollingPerformed = false;
+        }
+    }
+}

+ 964 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/WheelView.java

@@ -0,0 +1,964 @@
+/*
+ *  Android Wheel Control.
+ *  https://code.google.com/p/android-wheel/
+ * 
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.GradientDrawable.Orientation;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
+
+import com.yanyi.datelib.R;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Numeric wheel view.
+ *
+ * @author myLove
+ */
+public class WheelView extends View {
+
+	/** Top and bottom shadows colors */
+	/*/ Modified by wulianghuan 2014-11-25
+	private int[] SHADOWS_COLORS = new int[] { 0xFF111111,
+			0x00AAAAAA, 0x00AAAAAA };
+	//*/
+	private int[] SHADOWS_COLORS = new int[] {0xFFFFFFFF, 0x00FFFFFF, 0x00FFFFFF };
+
+	/** Top and bottom items offset (to hide that) */
+	private static final int ITEM_OFFSET_PERCENT = 0;
+
+	/** Left and right padding value */
+	private static final int PADDING = 10;
+
+	/** Default count of visible items */
+	private static final int DEF_VISIBLE_ITEMS = 5;
+
+	// Wheel Values
+	private int currentItem = 0;
+
+	// Count of visible items
+	private int visibleItems = DEF_VISIBLE_ITEMS;
+
+	// Item height
+	private int itemHeight = 0;
+
+	// Center Line
+	private Drawable centerDrawable;
+
+	// Wheel drawables
+	private int wheelBackground = R.drawable.wheel_bg;
+	private int wheelForeground = R.drawable.wheel_val;
+
+	// Shadows drawables
+	private GradientDrawable topShadow;
+	private GradientDrawable bottomShadow;
+
+	// Draw Shadows
+	private boolean drawShadows = true;
+
+	// Scrolling
+	private WheelScroller scroller;
+	private boolean isScrollingPerformed;
+	private int scrollingOffset;
+
+	// Cyclic
+	boolean isCyclic = false;
+
+	// Items layout
+	private LinearLayout itemsLayout;
+
+	// The number of first item in layout
+	private int firstItem;
+
+	// View adapter
+	private WheelViewAdapter viewAdapter;
+
+	// Recycle
+	private WheelRecycle recycle = new WheelRecycle(this);
+
+	// Listeners
+	private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();
+	private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();
+	private List<OnWheelClickedListener> clickingListeners = new LinkedList<OnWheelClickedListener>();
+	
+	String label="";
+
+	/**
+	 * Constructor
+	 */
+	public WheelView(Context context, AttributeSet attrs, int defStyle) {
+		super(context, attrs, defStyle);
+		initData(context);
+	}
+
+	/**
+	 * Constructor
+	 */
+	public WheelView(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		initData(context);
+	}
+
+	/**
+	 * Constructor
+	 */
+	public WheelView(Context context) {
+		super(context);
+		initData(context);
+	}
+
+	/**
+	 * Initializes class data
+	 * @param context the context
+	 */
+	private void initData(Context context) {
+		scroller = new WheelScroller(getContext(), scrollingListener);
+	}
+
+	// Scrolling listener
+	WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() {
+		@Override
+		public void onStarted() {
+			isScrollingPerformed = true;
+			notifyScrollingListenersAboutStart();
+		}
+
+		@Override
+		public void onScroll(int distance) {
+			doScroll(distance);
+
+			int height = getHeight();
+			if (scrollingOffset > height) {
+				scrollingOffset = height;
+				scroller.stopScrolling();
+			} else if (scrollingOffset < -height) {
+				scrollingOffset = -height;
+				scroller.stopScrolling();
+			}
+		}
+
+		@Override
+		public void onFinished() {
+			if (isScrollingPerformed) {
+				notifyScrollingListenersAboutEnd();
+				isScrollingPerformed = false;
+			}
+
+			scrollingOffset = 0;
+			invalidate();
+		}
+
+		@Override
+		public void onJustify() {
+			if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) {
+				scroller.scroll(scrollingOffset, 0);
+			}
+		}
+	};
+
+	/**
+	 * Set the the specified scrolling interpolator
+	 * @param interpolator the interpolator
+	 */
+	public void setInterpolator(Interpolator interpolator) {
+		scroller.setInterpolator(interpolator);
+	}
+
+	/**
+	 * Gets count of visible items
+	 * 
+	 * @return the count of visible items
+	 */
+	public int getVisibleItems() {
+		return visibleItems;
+	}
+
+	/**
+	 * Sets the desired count of visible items.
+	 * Actual amount of visible items depends on wheel layout parameters.
+	 * To apply changes and rebuild view call measure().
+	 * 
+	 * @param count the desired count for visible items
+	 */
+	public void setVisibleItems(int count) {
+		visibleItems = count;
+	}
+
+	/**
+	 * Gets view adapter
+	 * @return the view adapter
+	 */
+	public WheelViewAdapter getViewAdapter() {
+		return viewAdapter;
+	}
+
+	// Adapter listener
+	private DataSetObserver dataObserver = new DataSetObserver() {
+		@Override
+		public void onChanged() {
+			invalidateWheel(false);
+		}
+
+		@Override
+		public void onInvalidated() {
+			invalidateWheel(true);
+		}
+	};
+
+	/**
+	 * Sets view adapter. Usually new adapters contain different views, so
+	 * it needs to rebuild view by calling measure().
+	 * 
+	 * @param viewAdapter the view adapter
+	 */
+	public void setViewAdapter(WheelViewAdapter viewAdapter) {
+		if (this.viewAdapter != null) {
+			this.viewAdapter.unregisterDataSetObserver(dataObserver);
+		}
+		this.viewAdapter = viewAdapter;
+		if (this.viewAdapter != null) {
+			this.viewAdapter.registerDataSetObserver(dataObserver);
+		}
+
+		invalidateWheel(true);
+	}
+
+	/**
+	 * Adds wheel changing listener
+	 * @param listener the listener
+	 */
+	public void addChangingListener(OnWheelChangedListener listener) {
+		changingListeners.add(listener);
+	}
+
+	/**
+	 * Removes wheel changing listener
+	 * @param listener the listener
+	 */
+	public void removeChangingListener(OnWheelChangedListener listener) {
+		changingListeners.remove(listener);
+	}
+
+	/**
+	 * Notifies changing listeners
+	 * @param oldValue the old wheel value
+	 * @param newValue the new wheel value
+	 */
+	protected void notifyChangingListeners(int oldValue, int newValue) {
+		for (OnWheelChangedListener listener : changingListeners) {
+			listener.onChanged(this, oldValue, newValue);
+		}
+	}
+
+	/**
+	 * Adds wheel scrolling listener
+	 * @param listener the listener
+	 */
+	public void addScrollingListener(OnWheelScrollListener listener) {
+		scrollingListeners.add(listener);
+	}
+
+	/**
+	 * Removes wheel scrolling listener
+	 * @param listener the listener
+	 */
+	public void removeScrollingListener(OnWheelScrollListener listener) {
+		scrollingListeners.remove(listener);
+	}
+
+	/**
+	 * Notifies listeners about starting scrolling
+	 */
+	protected void notifyScrollingListenersAboutStart() {
+		for (OnWheelScrollListener listener : scrollingListeners) {
+			listener.onScrollingStarted(this);
+		}
+	}
+
+	/**
+	 * Notifies listeners about ending scrolling
+	 */
+	protected void notifyScrollingListenersAboutEnd() {
+		for (OnWheelScrollListener listener : scrollingListeners) {
+			listener.onScrollingFinished(this);
+		}
+	}
+
+	/**
+	 * Adds wheel clicking listener
+	 * @param listener the listener
+	 */
+	public void addClickingListener(OnWheelClickedListener listener) {
+		clickingListeners.add(listener);
+	}
+
+	/**
+	 * Removes wheel clicking listener
+	 * @param listener the listener
+	 */
+	public void removeClickingListener(OnWheelClickedListener listener) {
+		clickingListeners.remove(listener);
+	}
+
+	/**
+	 * Notifies listeners about clicking
+	 */
+	protected void notifyClickListenersAboutClick(int item) {
+		for (OnWheelClickedListener listener : clickingListeners) {
+			listener.onItemClicked(this, item);
+		}
+	}
+
+	/**
+	 * Gets current value
+	 * 
+	 * @return the current value
+	 */
+	public int getCurrentItem() {
+		return currentItem;
+	}
+
+	/**
+	 * Sets the current item. Does nothing when index is wrong.
+	 * 
+	 * @param index the item index
+	 * @param animated the animation flag
+	 */
+	public void setCurrentItem(int index, boolean animated) {
+		if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
+			return; // throw?
+		}
+
+		int itemCount = viewAdapter.getItemsCount();
+		if (index < 0 || index >= itemCount) {
+			if (isCyclic) {
+				while (index < 0) {
+					index += itemCount;
+				}
+				index %= itemCount;
+			} else{
+				return; // throw?
+			}
+		}
+		if (index != currentItem) {
+			if (animated) {
+				int itemsToScroll = index - currentItem;
+				if (isCyclic) {
+					int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem);
+					if (scroll < Math.abs(itemsToScroll)) {
+						itemsToScroll = itemsToScroll < 0 ? scroll : -scroll;
+					}
+				}
+				scroll(itemsToScroll, 0);
+			} else {
+				scrollingOffset = 0;
+
+				int old = currentItem;
+				currentItem = index;
+
+				notifyChangingListeners(old, currentItem);
+
+				invalidate();
+			}
+		}
+	}
+
+	/**
+	 * Sets the current item w/o animation. Does nothing when index is wrong.
+	 * 
+	 * @param index the item index
+	 */
+	public void setCurrentItem(int index) {
+		setCurrentItem(index, false);
+	}
+
+	/**
+	 * Tests if wheel is cyclic. That means before the 1st item there is shown the last one
+	 * @return true if wheel is cyclic
+	 */
+	public boolean isCyclic() {
+		return isCyclic;
+	}
+
+	/**
+	 * Set wheel cyclic flag
+	 * @param isCyclic the flag to set
+	 */
+	public void setCyclic(boolean isCyclic) {
+		this.isCyclic = isCyclic;
+		invalidateWheel(false);
+	}
+
+	/**
+	 * Determine whether shadows are drawn
+	 * @return true is shadows are drawn
+	 */
+	public boolean drawShadows() {
+		return drawShadows;
+	}
+
+	/**
+	 * Set whether shadows should be drawn
+	 * @param drawShadows flag as true or false
+	 */
+	public void setDrawShadows(boolean drawShadows) {
+		this.drawShadows = drawShadows;
+	}
+
+	/**
+	 * Set the shadow gradient color
+	 * @param start
+	 * @param middle
+	 * @param end
+	 */
+	public void setShadowColor(int start, int middle, int end) {
+		SHADOWS_COLORS = new int[] {start, middle, end};
+	}
+
+	/**
+	 * Sets the drawable for the wheel background
+	 * @param resource
+	 */
+	public void setWheelBackground(int resource) {
+		wheelBackground = resource;
+		setBackgroundResource(wheelBackground);
+	}
+
+	/**
+	 * Sets the drawable for the wheel foreground
+	 * @param resource
+	 */
+	public void setWheelForeground(int resource) {
+		wheelForeground = resource;
+		centerDrawable = getContext().getResources().getDrawable(wheelForeground);
+	}
+
+	/**
+	 * Invalidates wheel
+	 * @param clearCaches if true then cached views will be clear
+	 */
+	public void invalidateWheel(boolean clearCaches) {
+		if (clearCaches) {
+			recycle.clearAll();
+			if (itemsLayout != null) {
+				itemsLayout.removeAllViews();
+			}
+			scrollingOffset = 0;
+		} else if (itemsLayout != null) {
+			// cache all items
+			recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
+		}
+
+		invalidate();
+	}
+
+	/**
+	 * Initializes resources
+	 */
+	private void initResourcesIfNecessary() {
+		if (centerDrawable == null) {
+			centerDrawable = getContext().getResources().getDrawable(wheelForeground);
+		}
+
+		if (topShadow == null) {
+			topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
+		}
+
+		if (bottomShadow == null) {
+			bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
+		}
+
+		setBackgroundResource(wheelBackground);
+	}
+
+	/**
+	 * Calculates desired height for layout
+	 * 
+	 * @param layout
+	 *            the source layout
+	 * @return the desired layout height
+	 */
+	private int getDesiredHeight(LinearLayout layout) {
+		if (layout != null && layout.getChildAt(0) != null) {
+			itemHeight = layout.getChildAt(0).getMeasuredHeight();
+		}
+
+		int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50;
+
+		return Math.max(desired, getSuggestedMinimumHeight());
+	}
+
+	/**
+	 * Returns height of wheel item
+	 * @return the item height
+	 */
+	private int getItemHeight() {
+		if (itemHeight != 0) {
+			return itemHeight;
+		}
+
+		if (itemsLayout != null && itemsLayout.getChildAt(0) != null) {
+			itemHeight = itemsLayout.getChildAt(0).getHeight();
+			return itemHeight;
+		}
+
+		return getHeight() / visibleItems;
+	}
+
+	/**
+	 * Calculates control width and creates text layouts
+	 * @param widthSize the input layout width
+	 * @param mode the layout mode
+	 * @return the calculated control width
+	 */
+	private int calculateLayoutWidth(int widthSize, int mode) {
+		initResourcesIfNecessary();
+
+		// TODO: make it static
+		itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+		itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED),
+				MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+		int width = itemsLayout.getMeasuredWidth();
+
+		if (mode == MeasureSpec.EXACTLY) {
+			width = widthSize;
+		} else {
+			width += 2 * PADDING;
+
+			// Check against our minimum width
+			width = Math.max(width, getSuggestedMinimumWidth());
+
+			if (mode == MeasureSpec.AT_MOST && widthSize < width) {
+				width = widthSize;
+			}
+		}
+
+		itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY),
+				MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+
+		return width;
+	}
+
+	@Override
+	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+		buildViewForMeasuring();
+
+		int width = calculateLayoutWidth(widthSize, widthMode);
+
+		int height;
+		if (heightMode == MeasureSpec.EXACTLY) {
+			height = heightSize;
+		} else {
+			height = getDesiredHeight(itemsLayout);
+
+			if (heightMode == MeasureSpec.AT_MOST) {
+				height = Math.min(height, heightSize);
+			}
+		}
+
+		setMeasuredDimension(width, height);
+	}
+
+	@Override
+	protected void onLayout(boolean changed, int l, int t, int r, int b) {
+		layout(r - l, b - t);
+	}
+
+	/**
+	 * Sets layouts width and height
+	 * @param width the layout width
+	 * @param height the layout height
+	 */
+	private void layout(int width, int height) {
+		int itemsWidth = width - 2 * PADDING;
+
+		itemsLayout.layout(0, 0, itemsWidth, height);
+	}
+
+	@Override
+	protected void onDraw(Canvas canvas) {
+		super.onDraw(canvas);
+
+		if (viewAdapter != null && viewAdapter.getItemsCount() > 0) {
+			updateView();
+
+			drawItems(canvas);
+			drawCenterRect(canvas);
+		}
+
+		if (drawShadows) {
+			drawShadows(canvas);
+		}
+	}
+
+	/**
+	 * Draws shadows on top and bottom of control
+	 * @param canvas the canvas for drawing
+	 */
+	private void drawShadows(Canvas canvas) {
+		/*/ Modified by wulianghuan 2014-11-25
+		int height = (int)(1.5 * getItemHeight());
+		//*/
+		int height = (int)(3 * getItemHeight());
+		//*/
+		//topShadow.setBounds(0, 0, getWidth(), height);
+		topShadow.setBounds(0, 0, getWidth(), getHeight());
+		topShadow.draw(canvas);
+
+		//bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());
+		bottomShadow.setBounds(0, 0, getWidth(), getHeight());
+		bottomShadow.draw(canvas);
+	}
+
+	/**
+	 * Draws items
+	 * @param canvas the canvas for drawing
+	 */
+	private void drawItems(Canvas canvas) {
+		canvas.save();
+
+		int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2;
+		canvas.translate(PADDING, - top + scrollingOffset);
+
+		itemsLayout.draw(canvas);
+
+		canvas.restore();
+	}
+
+	/**
+	 * Draws rect for current value
+	 * @param canvas the canvas for drawing
+	 */
+	private void drawCenterRect(Canvas canvas) {
+		int center = getHeight() / 2;
+		int offset = (int) (getItemHeight() / 2 * 1.2);
+//		int offset = 60;
+		/*/ Remarked by wulianghuan 2014-11-27  使用自己的画线,而不是描边
+		Rect rect = new Rect(left, top, right, bottom)
+		centerDrawable.setBounds(bounds)
+		centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);
+		centerDrawable.draw(canvas);
+		//*/
+		Paint paint = new Paint();
+		paint.setColor(Color.parseColor("#D0D0D0"));
+		// 设置线宽
+//		paint.setStrokeWidth((float) 3);
+		paint.setStrokeWidth((float) 2);
+		// 绘制上边直线
+		canvas.drawLine(0, center - offset, getWidth(), center - offset, paint);
+		// 绘制下边直线
+		canvas.drawLine(0, center + offset, getWidth(), center + offset, paint);
+		//*/
+	}
+
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+		if (!isEnabled() || getViewAdapter() == null) {
+			return true;
+		}
+
+		switch (event.getAction()) {
+			case MotionEvent.ACTION_MOVE:
+				if (getParent() != null) {
+					getParent().requestDisallowInterceptTouchEvent(true);
+				}
+				break;
+
+			case MotionEvent.ACTION_UP:
+				if (!isScrollingPerformed) {
+					int distance = (int) event.getY() - getHeight() / 2;
+					if (distance > 0) {
+						distance += getItemHeight() / 2;
+					} else {
+						distance -= getItemHeight() / 2;
+					}
+					int items = distance / getItemHeight();
+					if (items != 0 && isValidItemIndex(currentItem + items)) {
+						notifyClickListenersAboutClick(currentItem + items);
+					}
+				}
+				break;
+		}
+
+		return scroller.onTouchEvent(event);
+	}
+
+	/**
+	 * Scrolls the wheel
+	 * @param delta the scrolling value
+	 */
+	private void doScroll(int delta) {
+		scrollingOffset += delta;
+
+		int itemHeight = getItemHeight();
+		int count = scrollingOffset / itemHeight;
+
+		int pos = currentItem - count;
+		int itemCount = viewAdapter.getItemsCount();
+
+		int fixPos = scrollingOffset % itemHeight;
+		if (Math.abs(fixPos) <= itemHeight / 2) {
+			fixPos = 0;
+		}
+		if (isCyclic && itemCount > 0) {
+			if (fixPos > 0) {
+				pos--;
+				count++;
+			} else if (fixPos < 0) {
+				pos++;
+				count--;
+			}
+			// fix position by rotating
+			while (pos < 0) {
+				pos += itemCount;
+			}
+			pos %= itemCount;
+		} else {
+			//
+			if (pos < 0) {
+				count = currentItem;
+				pos = 0;
+			} else if (pos >= itemCount) {
+				count = currentItem - itemCount + 1;
+				pos = itemCount - 1;
+			} else if (pos > 0 && fixPos > 0) {
+				pos--;
+				count++;
+			} else if (pos < itemCount - 1 && fixPos < 0) {
+				pos++;
+				count--;
+			}
+		}
+
+		int offset = scrollingOffset;
+		if (pos != currentItem) {
+			setCurrentItem(pos, false);
+		} else {
+			invalidate();
+		}
+
+		// update offset
+		scrollingOffset = offset - count * itemHeight;
+		if (scrollingOffset > getHeight()) {
+			scrollingOffset = scrollingOffset % getHeight() + getHeight();
+		}
+	}
+
+	/**
+	 * Scroll the wheel
+	 * @param itemsToScroll items to scroll
+	 * @param time scrolling duration
+	 */
+	public void scroll(int itemsToScroll, int time) {
+		int distance = itemsToScroll * getItemHeight() - scrollingOffset;
+		scroller.scroll(distance, time);
+	}
+
+	/**
+	 * Calculates range for wheel items
+	 * @return the items range
+	 */
+	private ItemsRange getItemsRange() {
+		if (getItemHeight() == 0) {
+			return null;
+		}
+
+		int first = currentItem;
+		int count = 1;
+
+		while (count * getItemHeight() < getHeight()) {
+			first--;
+			count += 2; // top + bottom items
+		}
+
+		if (scrollingOffset != 0) {
+			if (scrollingOffset > 0) {
+				first--;
+			}
+			count++;
+
+			// process empty items above the first or below the second
+			int emptyItems = scrollingOffset / getItemHeight();
+			first -= emptyItems;
+			count += Math.asin(emptyItems);
+		}
+		return new ItemsRange(first, count);
+	}
+
+	/**
+	 * Rebuilds wheel items if necessary. Caches all unused items.
+	 * 
+	 * @return true if items are rebuilt
+	 */
+	private boolean rebuildItems() {
+		boolean updated = false;
+		ItemsRange range = getItemsRange();
+		if (itemsLayout != null) {
+			int first = recycle.recycleItems(itemsLayout, firstItem, range);
+			updated = firstItem != first;
+			firstItem = first;
+		} else {
+			createItemsLayout();
+			updated = true;
+		}
+
+		if (!updated) {
+			updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount();
+		}
+
+		if (firstItem > range.getFirst() && firstItem <= range.getLast()) {
+			for (int i = firstItem - 1; i >= range.getFirst(); i--) {
+				if (!addViewItem(i, true)) {
+					break;
+				}
+				firstItem = i;
+			}
+		} else {
+			firstItem = range.getFirst();
+		}
+
+		int first = firstItem;
+		for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) {
+			if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) {
+				first++;
+			}
+		}
+		firstItem = first;
+
+		return updated;
+	}
+
+	/**
+	 * Updates view. Rebuilds items and label if necessary, recalculate items sizes.
+	 */
+	private void updateView() {
+		if (rebuildItems()) {
+			calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);
+			layout(getWidth(), getHeight());
+		}
+	}
+
+	/**
+	 * Creates item layouts if necessary
+	 */
+	private void createItemsLayout() {
+		if (itemsLayout == null) {
+			itemsLayout = new LinearLayout(getContext());
+			itemsLayout.setOrientation(LinearLayout.VERTICAL);
+		}
+	}
+
+	/**
+	 * Builds view for measuring
+	 */
+	private void buildViewForMeasuring() {
+		// clear all items
+		if (itemsLayout != null) {
+			recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
+		} else {
+			createItemsLayout();
+		}
+
+		// add views
+		int addItems = visibleItems / 2;
+		for (int i = currentItem + addItems; i >= currentItem - addItems; i--) {
+			if (addViewItem(i, true)) {
+				firstItem = i;
+			}
+		}
+	}
+
+	/**
+	 * Adds view for item to items layout
+	 * @param index the item index
+	 * @param first the flag indicates if view should be first
+	 * @return true if corresponding item exists and is added
+	 */
+	private boolean addViewItem(int index, boolean first) {
+		View view = getItemView(index);
+		if (view != null) {
+			if (first) {
+				itemsLayout.addView(view, 0);
+			} else {
+				itemsLayout.addView(view);
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Checks whether intem index is valid
+	 * @param index the item index
+	 * @return true if item index is not out of bounds or the wheel is cyclic
+	 */
+	private boolean isValidItemIndex(int index) {
+		return viewAdapter != null && viewAdapter.getItemsCount() > 0 &&
+				(isCyclic || index >= 0 && index < viewAdapter.getItemsCount());
+	}
+
+	/**
+	 * Returns view for specified item
+	 * @param index the item index
+	 * @return item view or empty view if index is out of bounds
+	 */
+	private View getItemView(int index) {
+		if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
+			return null;
+		}
+		int count = viewAdapter.getItemsCount();
+		if (!isValidItemIndex(index)) {
+			return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout);
+		} else {
+			while (index < 0) {
+				index = count + index;
+			}
+		}
+
+		index %= count;
+		return viewAdapter.getItem(index, recycle.getItem(), itemsLayout);
+	}
+
+	/**
+	 * Stops scrolling
+	 */
+	public void stopScrolling() {
+		scroller.stopScrolling();
+	}
+}

+ 67 - 0
datelib/src/main/java/com/yanyi/datelib/wheelview/WheelViewAdapter.java

@@ -0,0 +1,67 @@
+/*
+ *  Copyright 2011 Yuri Kanivets
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.yanyi.datelib.wheelview;
+
+import android.database.DataSetObserver;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Wheel items adapter interface
+ * @author myLove
+ */
+public interface WheelViewAdapter {
+	
+	/**
+	 * Gets items count
+	 * @return the count of wheel items
+	 */
+	public int getItemsCount();
+	
+	/**
+	 * Get a View that displays the data at the specified position in the data set
+	 * 
+	 * @param index the item index
+	 * @param convertView the old view to reuse if possible
+	 * @param parent the parent that this view will eventually be attached to
+	 * @return the wheel item View
+	 */
+	public View getItem(int index, View convertView, ViewGroup parent);
+
+	/**
+	 * Get a View that displays an empty wheel item placed before the first or after
+	 * the last wheel item.
+	 * 
+	 * @param convertView the old view to reuse if possible
+     * @param parent the parent that this view will eventually be attached to
+	 * @return the empty item View
+	 */
+	public View getEmptyItem(View convertView, ViewGroup parent);
+	
+	/**
+	 * Register an observer that is called when changes happen to the data used by this adapter.
+	 * @param observer the observer to be registered
+	 */
+	public void registerDataSetObserver(DataSetObserver observer);
+	
+	/**
+	 * Unregister an observer that has previously been registered
+	 * @param observer the observer to be unregistered
+	 */
+	void unregisterDataSetObserver(DataSetObserver observer);
+	
+}

+ 23 - 0
datelib/src/main/res/drawable/wheel_bg.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 
+    Android Wheel Control.
+    http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
+   
+    Copyright 2010 Yuri Kanivets
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+	
+</layer-list>

+ 31 - 0
datelib/src/main/res/drawable/wheel_val.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 
+    Android Wheel Control.
+    http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
+   
+    Copyright 2010 Yuri Kanivets
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- 
+	<gradient
+		android:startColor="#70222222"
+		android:centerColor="#70222222"
+		android:endColor="#70EEEEEE"
+		android:angle="90" />
+		 -->
+
+	<stroke android:width="1dp" android:color="#C7C7C7" /> 
+</shape>

+ 17 - 0
datelib/src/main/res/layout/item_date.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="35dip"
+    android:orientation="horizontal"
+    android:gravity="center"
+    >
+    
+	<TextView 
+	    android:id="@+id/tempValue"
+	    android:layout_width="match_parent"
+	    android:layout_height="match_parent"
+	    android:gravity="center"
+	    android:textColor="#323232"
+	    />
+    
+</LinearLayout>

+ 185 - 0
datelib/src/main/res/layout/select_date_pop_layout.xml

@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/select_date"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#00000000"
+    android:gravity="bottom"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/select_date_child"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:background="#ffffff"
+        android:orientation="vertical">
+
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="44dp">
+
+            <TextView
+                android:id="@+id/btn_myinfo_cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentLeft="true"
+                android:layout_marginRight="15dip"
+                android:gravity="center"
+                android:paddingLeft="12dp"
+                android:text="取消"
+                android:textColor="#e84515"
+                android:textSize="13sp" />
+
+
+            <TextView
+                android:id="@+id/btn_myinfo_sure"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:gravity="center"
+                android:paddingRight="12dp"
+                android:text="完成"
+                android:textColor="#e84515"
+                android:textSize="12sp" />
+
+        </RelativeLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="#d8d8d8" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:paddingBottom="10dp"
+                    android:paddingTop="10dp"
+                    android:text="年"
+                    android:textColor="@android:color/black" />
+
+                <com.yanyi.datelib.wheelview.WheelView
+                    android:id="@+id/wv_date_year"
+                    android:layout_width="match_parent"
+                    android:layout_height="160dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="1" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:paddingBottom="10dp"
+                    android:paddingTop="10dp"
+                    android:text="月"
+                    android:textColor="@android:color/black" />
+
+                <com.yanyi.datelib.wheelview.WheelView
+                    android:id="@+id/wv_date_month"
+                    android:layout_width="match_parent"
+                    android:layout_height="160dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="1" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:paddingBottom="10dp"
+                    android:paddingTop="10dp"
+                    android:text="日"
+                    android:textColor="@android:color/black" />
+
+                <com.yanyi.datelib.wheelview.WheelView
+                    android:id="@+id/wv_date_day"
+                    android:layout_width="match_parent"
+                    android:layout_height="160dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="1" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/hour_container"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:paddingBottom="10dp"
+                    android:paddingTop="10dp"
+                    android:text="时"
+                    android:textColor="@android:color/black" />
+
+                <com.yanyi.datelib.wheelview.WheelView
+                    android:id="@+id/wv_date_hour"
+                    android:layout_width="match_parent"
+                    android:layout_height="160dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="1" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/minute_container"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:orientation="vertical">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:paddingBottom="10dp"
+                    android:paddingTop="10dp"
+                    android:text="分"
+                    android:textColor="@android:color/black" />
+
+                <com.yanyi.datelib.wheelview.WheelView
+                    android:id="@+id/wv_date_minute"
+                    android:layout_width="match_parent"
+                    android:layout_height="160dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="1" />
+            </LinearLayout>
+        </LinearLayout>
+
+    </LinearLayout>
+
+</LinearLayout>

+ 3 - 0
datelib/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">DateLib</string>
+</resources>

+ 17 - 0
datelib/src/test/java/com/yanyi/datelib/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.yanyi.datelib;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 17 - 0
gradle.properties

@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true

BIN
gradle/wrapper/gradle-wrapper.jar


+ 6 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Wed Mar 07 14:38:22 CST 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

+ 160 - 0
gradlew

@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

+ 90 - 0
gradlew.bat

@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
settings.gradle

@@ -0,0 +1 @@
+include ':app', ':datelib'