1.优化代码将http通信通用模块放在baselibrary内
2.创建通用版本的library
7 文件已重命名
24个文件已修改
64个文件已添加
2个文件已删除
| | |
| | | |
| | | // implementation 'com.google.zxing:core:3.4.1' |
| | | implementation group: 'net.sourceforge.jexcelapi', name: 'jxl', version: '2.6.12' |
| | | implementation 'com.wang.avi:library:2.1.3' |
| | | // implementation 'com.wang.avi:library:2.1.3' |
| | | |
| | | implementation project(':henanlibrary') |
| | | implementation project(':baselibrary') |
| | |
| | | //权限申请 |
| | | implementation 'com.github.getActivity:XXPermissions:18.5' |
| | | //滚动选择框 |
| | | implementation 'com.contrarywind:Android-PickerView:4.1.9' |
| | | // implementation 'com.contrarywind:Android-PickerView:4.1.9' |
| | | |
| | | //列表 |
| | | implementation 'io.github.scwang90:refresh-layout-kernel:2.0.5' |
| | |
| | | |
| | | dependencies { |
| | | |
| | | implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs') |
| | | |
| | | compileOnly fileTree(include: ['*.jar'], dir: 'exlibs') |
| | | |
| | | implementation 'com.android.support:appcompat-v7:28.0.0' |
| | | implementation 'com.android.support.constraint:constraint-layout:1.1.3' |
| | | implementation 'androidx.core:core-ktx:1.8.0' |
| | |
| | | |
| | | compileOnly 'com.google.zxing:core:3.4.1' |
| | | compileOnly 'com.tencent.bugly:crashreport:4.1.9.3' |
| | | |
| | | implementation project(':pickerviewlibrary') |
| | | //loding |
| | | implementation 'com.wang.avi:library:2.1.3' |
| | | // implementation 'com.wang.avi:library:2.1.3' |
| | | |
| | | //滚动选择框 |
| | | compileOnly 'com.contrarywind:Android-PickerView:4.1.9' |
| | | // compileOnly 'com.contrarywind:Android-PickerView:4.1.9' |
| | | |
| | | implementation "androidx.room:room-runtime:2.3.0" |
| | | implementation "androidx.room:room-ktx:2.3.0" |
| | | runtimeOnly("androidx.room:room-common:2.3.0") |
| | | annotationProcessor "androidx.room:room-compiler:2.3.0" |
| | | |
| | | implementation 'com.pnikosis:materialish-progress:1.7' |
| | | //权限申请 |
| | | compileOnly 'com.github.getActivity:XXPermissions:18.5' |
| | | |
| | | //通信 |
| | | implementation 'com.squareup.retrofit2:retrofit:2.9.0' |
| | | implementation('com.squareup.retrofit2:converter-gson:2.9.0') { |
| | | exclude group: 'com.google.code.gson'; |
| | | } |
| | | implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' |
| | | implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' |
| | | implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0' |
| | | } |
| | |
| | | package com.dayu.baselibrary; |
| | | |
| | | import android.Manifest; |
| | | import android.app.Application; |
| | | import android.os.Build; |
| | | import android.util.Log; |
| | | |
| | | import com.android.newpos.printer.PrinterManager; |
| | | import com.dayu.baselibrary.tools.print.PrintAdater; |
| | | import com.dayu.baselibrary.tools.print.ShangMiAidlUtil; |
| | | import com.dayu.baselibrary.utils.ModelUtils; |
| | | import com.pos.device.SDKManager; |
| | | import com.pos.device.sys.SystemManager; |
| | | |
| | | /** |
| | | * author: zuo |
File was renamed from qiheonlinelibrary/src/main/java/com/dayu/qiheonlinelibrary/net/progress/NetLoadingDialog.java |
| | |
| | | package com.dayu.qiheonlinelibrary.net.progress; |
| | | package com.dayu.baselibrary.net.progress; |
| | | |
| | | import android.app.Dialog; |
| | | import android.content.Context; |
| | | import android.graphics.drawable.AnimationDrawable; |
| | | import android.view.Gravity; |
| | | |
| | | import com.dayu.qiheonlinelibrary.R; |
| | | import com.dayu.baselibrary.R; |
| | | import com.pnikosis.materialishprogress.ProgressWheel; |
| | | |
| | | |
File was renamed from qiheonlinelibrary/src/main/java/com/dayu/qiheonlinelibrary/net/progress/ProgressCancelListener.java |
| | |
| | | package com.dayu.qiheonlinelibrary.net.progress; |
| | | package com.dayu.baselibrary.net.progress; |
| | | |
| | | /** |
| | | * Created by qwy on 16/3/10. |
File was renamed from qiheonlinelibrary/src/main/java/com/dayu/qiheonlinelibrary/net/progress/ProgressDialogHandler.java |
| | |
| | | package com.dayu.qiheonlinelibrary.net.progress; |
| | | package com.dayu.baselibrary.net.progress; |
| | | |
| | | import android.content.Context; |
| | | import android.content.DialogInterface; |
| | |
| | | pd.setOnCancelListener(new DialogInterface.OnCancelListener() { |
| | | @Override |
| | | public void onCancel(DialogInterface dialogInterface) { |
| | | if (mProgressCancelListener != null) |
| | | mProgressCancelListener.onCancelProgress(); |
| | | if (mProgressCancelListener != null){ |
| | | mProgressCancelListener.onCancelProgress(); |
| | | } |
| | | } |
| | | }); |
| | | } |
File was renamed from qiheonlinelibrary/src/main/java/com/dayu/qiheonlinelibrary/net/subscribers/BaseProgressSubscriber.java |
| | |
| | | package com.dayu.qiheonlinelibrary.net.subscribers; |
| | | package com.dayu.baselibrary.net.subscribers; |
| | | |
| | | import android.content.Context; |
| | | |
File was renamed from qiheonlinelibrary/src/main/java/com/dayu/qiheonlinelibrary/net/subscribers/ProgressSubscriber.java |
| | |
| | | package com.dayu.qiheonlinelibrary.net.subscribers; |
| | | package com.dayu.baselibrary.net.subscribers; |
| | | |
| | | import android.content.Context; |
| | | |
| | | |
| | | import com.dayu.qiheonlinelibrary.net.progress.ProgressCancelListener; |
| | | import com.dayu.qiheonlinelibrary.net.progress.ProgressDialogHandler; |
| | | import com.dayu.baselibrary.net.progress.ProgressCancelListener; |
| | | import com.dayu.baselibrary.net.progress.ProgressDialogHandler; |
| | | |
| | | import io.reactivex.rxjava3.disposables.Disposable; |
| | | |
File was renamed from qiheonlinelibrary/src/main/java/com/dayu/qiheonlinelibrary/net/subscribers/SubscriberListener.java |
| | |
| | | package com.dayu.qiheonlinelibrary.net.subscribers; |
| | | package com.dayu.baselibrary.net.subscribers; |
| | | |
| | | /** |
| | | * Created by qwy on 16/3/10. |
| | |
| | | |
| | | import android.app.Application; |
| | | import android.content.Context; |
| | | import android.util.Log; |
| | | |
| | | import com.android.newpos.printer.PrinterManager; |
| | | import com.dayu.baselibrary.utils.ModelUtils; |
| | | import com.pos.device.SDKManager; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | case ModelUtils.ShangMiType: |
| | | ShangMiAidlUtil.getInstance().connectPrinterService(context); |
| | | break; |
| | | case ModelUtils.HuaZhiRongHaiType: |
| | | HuaZhiRongHaiPrint.getInstance().connectPrinterService(context); |
| | | break; |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | case ModelUtils.ShangMiType: |
| | | ShangMiAidlUtil.getInstance().printText(content, size, isBold, isUnderLine); |
| | | break; |
| | | case ModelUtils.HuaZhiRongHaiType: |
| | | HuaZhiRongHaiPrint.getInstance().printText(content, size, isBold, isUnderLine); |
| | | break; |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | plugins { |
| | | id 'com.android.application' version '7.2.2' apply false |
| | | id 'com.android.library' version '7.2.2' apply false |
| | | id 'org.jetbrains.kotlin.android' version '1.9.0' apply false |
| | | } |
New file |
| | |
| | | plugins { |
| | | id 'com.android.library' |
| | | id 'org.jetbrains.kotlin.android' |
| | | } |
| | | |
| | | android { |
| | | namespace 'com.dayu.general' |
| | | compileSdk 34 |
| | | |
| | | defaultConfig { |
| | | minSdk 24 |
| | | |
| | | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
| | | consumerProguardFiles "consumer-rules.pro" |
| | | } |
| | | |
| | | buildTypes { |
| | | release { |
| | | minifyEnabled false |
| | | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
| | | } |
| | | } |
| | | compileOptions { |
| | | sourceCompatibility JavaVersion.VERSION_1_8 |
| | | targetCompatibility JavaVersion.VERSION_1_8 |
| | | } |
| | | kotlinOptions { |
| | | jvmTarget = '1.8' |
| | | } |
| | | } |
| | | |
| | | dependencies { |
| | | |
| | | implementation project(":baselibrary") |
| | | implementation 'androidx.core:core-ktx:1.15.0' |
| | | implementation 'androidx.appcompat:appcompat:1.7.0' |
| | | implementation 'com.google.android.material:material:1.12.0' |
| | | testImplementation 'junit:junit:4.13.2' |
| | | androidTestImplementation 'androidx.test.ext:junit:1.2.1' |
| | | androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' |
| | | |
| | | |
| | | //数据库 |
| | | implementation "androidx.room:room-runtime:2.3.0" |
| | | implementation "androidx.room:room-ktx:2.3.0" |
| | | runtimeOnly("androidx.room:room-common:2.3.0") |
| | | annotationProcessor "androidx.room:room-compiler:2.3.0" |
| | | |
| | | //权限申请 |
| | | compileOnly 'com.github.getActivity:XXPermissions:18.5' |
| | | |
| | | //通信 |
| | | implementation 'com.squareup.retrofit2:retrofit:2.9.0' |
| | | implementation('com.squareup.retrofit2:converter-gson:2.9.0') { |
| | | exclude group: 'com.google.code.gson'; |
| | | } |
| | | implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' |
| | | implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' |
| | | implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0' |
| | | compileOnly 'com.google.code.gson:gson:2.10.1' |
| | | //loding |
| | | implementation 'com.pnikosis:materialish-progress:1.7' |
| | | |
| | | //列表 |
| | | compileOnly 'io.github.scwang90:refresh-layout-kernel:2.0.5' |
| | | compileOnly 'io.github.scwang90:refresh-header-classics:2.0.5' |
| | | compileOnly 'androidx.recyclerview:recyclerview:1.2.0'//经典刷新头 |
| | | } |
New file |
| | |
| | | # 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 |
New file |
| | |
| | | package com.dayu.general |
| | | |
| | | import androidx.test.platform.app.InstrumentationRegistry |
| | | import androidx.test.ext.junit.runners.AndroidJUnit4 |
| | | |
| | | import org.junit.Test |
| | | import org.junit.runner.RunWith |
| | | |
| | | import org.junit.Assert.* |
| | | |
| | | /** |
| | | * Instrumented test, which will execute on an Android device. |
| | | * |
| | | * See [testing documentation](http://d.android.com/tools/testing). |
| | | */ |
| | | @RunWith(AndroidJUnit4::class) |
| | | class ExampleInstrumentedTest { |
| | | @Test |
| | | fun useAppContext() { |
| | | // Context of the app under test. |
| | | val appContext = InstrumentationRegistry.getInstrumentation().targetContext |
| | | assertEquals("com.dayu.general.test", appContext.packageName) |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | |
| | | </manifest> |
New file |
| | |
| | | package com.dayu.general |
| | | |
| | | import android.app.Application |
| | | |
| | | public class BaseApplication : Application() { |
| | | |
| | | override fun onCreate() { |
| | | super.onCreate() |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.dayu.general.activity |
| | | |
| | | import androidx.fragment.app.Fragment |
| | | |
| | | class BSCardFragment :Fragment() { |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.dayu.general.activity |
| | | |
| | | import android.os.Bundle |
| | | import androidx.appcompat.app.AppCompatActivity |
| | | import com.dayu.general.dao.AppDataBase |
| | | import com.dayu.general.dao.BaseDaoSingleton |
| | | |
| | | open class BaseActivity : AppCompatActivity() { |
| | | |
| | | |
| | | var asynchBaseDao: AppDataBase? = null |
| | | |
| | | override fun onCreate(savedInstanceState: Bundle?) { |
| | | super.onCreate(savedInstanceState) |
| | | asynchBaseDao=BaseDaoSingleton.getAsynchInstance(this); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.dayu.general.activity |
| | | |
| | | import android.os.Bundle |
| | | import androidx.fragment.app.Fragment |
| | | |
| | | class MainActivity : BaseActivity(){ |
| | | |
| | | |
| | | private val fragments: ArrayList<Fragment> = ArrayList() |
| | | override fun onCreate(savedInstanceState: Bundle?) { |
| | | super.onCreate(savedInstanceState) |
| | | setupFragments(); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | private fun setupFragments() { |
| | | fragments.add(BSCardFragment()) |
| | | fragments.add(RechargeFragment()) |
| | | fragments.add(BSCardFragment()) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.dayu.general.activity |
| | | |
| | | import androidx.fragment.app.Fragment |
| | | |
| | | class MyFragment:Fragment() { |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.dayu.general.activity |
| | | |
| | | import androidx.fragment.app.Fragment |
| | | |
| | | class RechargeFragment:Fragment() { |
| | | } |
New file |
| | |
| | | package com.dayu.general.dao |
| | | |
| | | import androidx.room.RoomDatabase |
| | | |
| | | abstract class AppDataBase : RoomDatabase() { |
| | | } |
New file |
| | |
| | | package com.dayu.general.dao |
| | | |
| | | import android.content.Context |
| | | import android.os.Environment |
| | | import androidx.room.Room |
| | | import com.dayu.general.activity.BaseActivity |
| | | import java.io.File |
| | | |
| | | class BaseDaoSingleton { |
| | | |
| | | var baseDao: AppDataBase? = null |
| | | |
| | | var AsynchBaseDao: AppDataBase? = null |
| | | |
| | | var SqlitePath: String = |
| | | Environment.getExternalStorageDirectory().absolutePath + File.separator + ".dayu" + File.separator + "data" + File.separator |
| | | |
| | | //MyFileUtil.SqlitePath + |
| | | fun getInstance(context: Context?): AppDataBase? { |
| | | if (baseDao == null) { |
| | | baseDao = Room.databaseBuilder<AppDataBase>( |
| | | context!!, |
| | | AppDataBase::class.java, |
| | | SqlitePath + "ConfigurationData_generalV1" |
| | | ).allowMainThreadQueries().build() |
| | | } |
| | | return baseDao |
| | | } |
| | | |
| | | fun getAsynchInstance(context: Context?): AppDataBase? { |
| | | if (AsynchBaseDao == null) { |
| | | AsynchBaseDao = Room.databaseBuilder<AppDataBase>( |
| | | context!!, |
| | | AppDataBase::class.java, |
| | | SqlitePath + "ConfigurationData_generalV1" |
| | | ).build() |
| | | } |
| | | return AsynchBaseDao |
| | | } |
| | | |
| | | companion object { |
| | | fun getAsynchInstance(baseActivity: BaseActivity): AppDataBase? { |
| | | return getAsynchInstance(baseActivity) |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="24dp" |
| | | android:height="24dp" |
| | | android:viewportWidth="48" |
| | | android:viewportHeight="48"> |
| | | <path |
| | | android:pathData="M6,15L19.371,25.538C20.5,26.5 22.828,28 25,26C27.289,23.892 25.5,21.5 25,21L17,15" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M4,8H27L38,18" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M9,33L44,33.019" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M9,18V40H44V18H22" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | </vector> |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="24dp" |
| | | android:height="24dp" |
| | | android:viewportWidth="48" |
| | | android:viewportHeight="48"> |
| | | <path |
| | | android:pathData="M6,15L19.371,25.538C20.5,26.5 22.828,28 25,26C27.289,23.892 25.5,21.5 25,21L17,15" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M4,8H27L38,18" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M9,33L44,33.019" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M9,18V40H44V18H22" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | </vector> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <shape xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <solid android:color="@color/bottom_color" /> <!-- 按钮的背景色 --> |
| | | <corners android:radius="90dp" /> <!-- 让按钮的四个角变成圆形 --> |
| | | <size android:width="100dp" android:height="100dp" /> <!-- 设置按钮的宽高 --> |
| | | </shape> |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="24dp" |
| | | android:height="24dp" |
| | | android:viewportWidth="48" |
| | | android:viewportHeight="48"> |
| | | <path |
| | | android:pathData="M24,44C35.046,44 44,35.046 44,24C44,12.954 35.046,4 24,4C12.954,4 4,12.954 4,24C4,35.046 12.954,44 24,44Z" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:fillType="evenOdd" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M24,23C26.761,23 29,20.761 29,18C29,15.239 26.761,13 24,13C21.239,13 19,15.239 19,18C19,20.761 21.239,23 24,23Z" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333"/> |
| | | <path |
| | | android:pathData="M10.022,38.332C10.366,33.121 14.702,29 20,29H28C33.291,29 37.623,33.11 37.977,38.311" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | </vector> |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="24dp" |
| | | android:height="24dp" |
| | | android:viewportWidth="48" |
| | | android:viewportHeight="48"> |
| | | <path |
| | | android:pathData="M24,44C35.046,44 44,35.046 44,24C44,12.954 35.046,4 24,4C12.954,4 4,12.954 4,24C4,35.046 12.954,44 24,44Z" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:fillType="evenOdd" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M24,23C26.761,23 29,20.761 29,18C29,15.239 26.761,13 24,13C21.239,13 19,15.239 19,18C19,20.761 21.239,23 24,23Z" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff"/> |
| | | <path |
| | | android:pathData="M10.022,38.332C10.366,33.121 14.702,29 20,29H28C33.291,29 37.623,33.11 37.977,38.311" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | </vector> |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="24dp" |
| | | android:height="24dp" |
| | | android:viewportWidth="48" |
| | | android:viewportHeight="48"> |
| | | <path |
| | | android:pathData="M24,44C32.837,44 40,37.488 40,29.455C40,21.576 34.667,13.091 24,4C13.333,13.091 8,21.576 8,29.455C8,37.488 15.163,44 24,44Z" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333"/> |
| | | <path |
| | | android:pathData="M18.857,19L24,24.368L29.143,19" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M18,26.158H30" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M18,31.526H30" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M24,26.158V36" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#333" |
| | | android:strokeLineCap="round"/> |
| | | </vector> |
New file |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="24dp" |
| | | android:height="24dp" |
| | | android:viewportWidth="48" |
| | | android:viewportHeight="48"> |
| | | <path |
| | | android:pathData="M24,44C32.837,44 40,37.488 40,29.455C40,21.576 34.667,13.091 24,4C13.333,13.091 8,21.576 8,29.455C8,37.488 15.163,44 24,44Z" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff"/> |
| | | <path |
| | | android:pathData="M18.857,19L24,24.368L29.143,19" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M18,26.158H30" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M18,31.526H30" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | <path |
| | | android:pathData="M24,26.158V36" |
| | | android:strokeLineJoin="round" |
| | | android:strokeWidth="4" |
| | | android:fillColor="#00000000" |
| | | android:strokeColor="#fff" |
| | | android:strokeLineCap="round"/> |
| | | </vector> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | xmlns:tools="http://schemas.android.com/tools" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:background="#ffffff"> |
| | | |
| | | |
| | | <androidx.viewpager2.widget.ViewPager2 |
| | | android:id="@+id/viewPager" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:layout_above="@id/bottom_navigation" /> |
| | | |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/bottom_navigation" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="70dp" |
| | | android:layout_alignParentBottom="true" |
| | | android:layout_marginTop="-20dp" |
| | | android:background="#00ffffff" |
| | | android:gravity="bottom" |
| | | android:orientation="horizontal"> |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/orderLL" |
| | | android:layout_width="0dp" |
| | | android:layout_height="50dp" |
| | | android:layout_weight="1" |
| | | android:background="@color/bottom_color" |
| | | android:gravity="center" |
| | | android:orientation="vertical"> |
| | | |
| | | <RelativeLayout |
| | | android:layout_width="25dp" |
| | | android:layout_height="33dp"> |
| | | |
| | | <ImageView |
| | | android:id="@+id/orderImg" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="25dp" |
| | | android:layout_marginTop="8dp" |
| | | android:src="@drawable/bottom_card_black" /> |
| | | |
| | | |
| | | </RelativeLayout> |
| | | |
| | | <TextView |
| | | android:id="@+id/orderText" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginBottom="3dp" |
| | | android:text="制卡" |
| | | |
| | | android:textSize="12sp" /> |
| | | |
| | | </LinearLayout> |
| | | |
| | | <FrameLayout |
| | | android:id="@+id/mapLL" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" |
| | | android:gravity="bottom" |
| | | android:orientation="vertical"> |
| | | |
| | | <View |
| | | android:layout_width="match_parent" |
| | | android:layout_height="50dp" |
| | | android:layout_gravity="bottom" |
| | | android:background="@color/bottom_color" |
| | | android:orientation="vertical" /> |
| | | |
| | | <LinearLayout |
| | | android:layout_width="80dp" |
| | | android:layout_height="70dp" |
| | | android:layout_gravity="center" |
| | | android:background="@drawable/bottom_circle_bg" |
| | | android:gravity="center" |
| | | android:orientation="vertical"> |
| | | |
| | | <ImageView |
| | | android:id="@+id/mapImg" |
| | | android:layout_width="40dp" |
| | | android:layout_height="40dp" |
| | | android:layout_marginTop="8dp" |
| | | android:src="@drawable/bottom_recharge_white" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/mapText" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:text="充值" |
| | | android:textColor="@color/white" |
| | | android:textSize="15sp" /> |
| | | |
| | | </LinearLayout> |
| | | |
| | | </FrameLayout> |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/myLL" |
| | | android:layout_width="0dp" |
| | | android:layout_height="50dp" |
| | | android:layout_weight="1" |
| | | android:background="@color/bottom_color" |
| | | android:gravity="center" |
| | | android:orientation="vertical"> |
| | | |
| | | <ImageView |
| | | android:id="@+id/myImg" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="25dp" |
| | | android:layout_marginTop="8dp" |
| | | android:src="@drawable/bottom_my_black" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/myText" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginBottom="3dp" |
| | | android:text="我的" |
| | | android:textSize="12sp" /> |
| | | |
| | | </LinearLayout> |
| | | |
| | | </LinearLayout> |
| | | |
| | | |
| | | <!-- <!– BottomNavigationView 用于底部导航 –>--> |
| | | <!-- <com.google.android.material.bottomnavigation.BottomNavigationView--> |
| | | <!-- android:id="@+id/bottom_navigation"--> |
| | | <!-- android:layout_width="match_parent"--> |
| | | <!-- android:layout_height="wrap_content"--> |
| | | <!-- android:layout_alignParentBottom="true"--> |
| | | <!-- android:background="@color/bottom_color"--> |
| | | <!-- app:menu="@menu/main_bottom_nav_menu"--> |
| | | <!-- app:itemIconTint="@color/bottom_selector_nav_item"--> |
| | | <!-- app:itemTextColor="@color/bottom_selector_nav_item"--> |
| | | |
| | | <!-- />--> |
| | | |
| | | |
| | | </RelativeLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | <color name="bottom_color">#3D8BFF</color> |
| | | |
| | | </resources> |
New file |
| | |
| | | package com.dayu.general |
| | | |
| | | import org.junit.Test |
| | | |
| | | import org.junit.Assert.* |
| | | |
| | | /** |
| | | * Example local unit test, which will execute on the development machine (host). |
| | | * |
| | | * See [testing documentation](http://d.android.com/tools/testing). |
| | | */ |
| | | class ExampleUnitTest { |
| | | @Test |
| | | fun addition_isCorrect() { |
| | | assertEquals(4, 2 + 2) |
| | | } |
| | | } |
| | |
| | | path "CMakeLists.txt" |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | dependencies { |
| | |
| | | |
| | | |
| | | compileOnly group: 'net.sourceforge.jexcelapi', name: 'jxl', version: '2.6.12' |
| | | compileOnly 'com.wang.avi:library:2.1.3' |
| | | // compileOnly 'com.wang.avi:library:2.1.3' |
| | | implementation files('../baselibrary/libs/avi.library-2.1.3.aar') |
| | | //地址选择 |
| | | implementation project(':pickerviewlibrary') |
| | | compileOnly project(':pickerviewlibrary') |
| | | implementation project(':easysocket') |
| | | implementation project(':ocridcardlibrary') |
| | | implementation project(':baselibrary') |
| | |
| | | //权限申请 |
| | | compileOnly 'com.github.getActivity:XXPermissions:18.5' |
| | | //滚动选择框 |
| | | compileOnly 'com.contrarywind:Android-PickerView:4.1.9' |
| | | // compileOnly 'com.contrarywind:Android-PickerView:4.1.9' |
| | | |
| | | //列表 |
| | | compileOnly 'io.github.scwang90:refresh-layout-kernel:2.0.5' |
| | |
| | | dependencies { |
| | | // implementation fileTree(include: ['*.jar'], dir: 'libs') |
| | | implementation 'com.android.support:appcompat-v7:28.0.0' |
| | | implementation 'com.android.support:support-annotations:28.0.0' |
| | | testImplementation 'junit:junit:4.12' |
| | | androidTestImplementation 'com.android.support.test:runner:1.0.2' |
| | | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' |
| | |
| | | compileOnly "androidx.room:room-runtime:2.3.0" |
| | | runtimeOnly("androidx.room:room-common:2.3.0") |
| | | annotationProcessor "androidx.room:room-compiler:2.3.0" |
| | | |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.adapter; |
| | | |
| | | import com.contrarywind.adapter.WheelAdapter; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * The simple Array wheel adapter |
| | | * @param <T> the element type |
| | | */ |
| | | public class ArrayWheelAdapter<T> implements WheelAdapter { |
| | | |
| | | |
| | | // items |
| | | private List<T> items; |
| | | |
| | | /** |
| | | * Constructor |
| | | * @param items the items |
| | | */ |
| | | public ArrayWheelAdapter(List<T> items) { |
| | | this.items = items; |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public Object getItem(int index) { |
| | | if (index >= 0 && index < items.size()) { |
| | | return items.get(index); |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | @Override |
| | | public int getItemsCount() { |
| | | return items.size(); |
| | | } |
| | | |
| | | @Override |
| | | public int indexOf(Object o){ |
| | | return items.indexOf(o); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.adapter; |
| | | |
| | | |
| | | import com.contrarywind.adapter.WheelAdapter; |
| | | |
| | | /** |
| | | * Numeric Wheel adapter. |
| | | */ |
| | | public class NumericWheelAdapter implements WheelAdapter { |
| | | |
| | | private int minValue; |
| | | private int maxValue; |
| | | |
| | | /** |
| | | * Constructor |
| | | * @param minValue the wheel min value |
| | | * @param maxValue the wheel max value |
| | | */ |
| | | public NumericWheelAdapter(int minValue, int maxValue) { |
| | | this.minValue = minValue; |
| | | this.maxValue = maxValue; |
| | | } |
| | | |
| | | @Override |
| | | public Object getItem(int index) { |
| | | if (index >= 0 && index < getItemsCount()) { |
| | | int value = minValue + index; |
| | | return value; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public int getItemsCount() { |
| | | return maxValue - minValue + 1; |
| | | } |
| | | |
| | | @Override |
| | | public int indexOf(Object o){ |
| | | try { |
| | | return (int)o - minValue; |
| | | } catch (Exception e) { |
| | | return -1; |
| | | } |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.builder; |
| | | |
| | | import android.content.Context; |
| | | import android.graphics.Typeface; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | |
| | | import androidx.annotation.ColorInt; |
| | | |
| | | import com.bigkoo.pickerview.configure.PickerOptions; |
| | | import com.bigkoo.pickerview.listener.CustomListener; |
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener; |
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectListener; |
| | | import com.bigkoo.pickerview.view.OptionsPickerView; |
| | | import com.contrarywind.view.WheelView; |
| | | |
| | | /** |
| | | * Created by xiaosongzeem on 2018/3/20. |
| | | */ |
| | | |
| | | public class OptionsPickerBuilder { |
| | | |
| | | //配置类 |
| | | private PickerOptions mPickerOptions; |
| | | |
| | | |
| | | //Required |
| | | public OptionsPickerBuilder(Context context, OnOptionsSelectListener listener) { |
| | | mPickerOptions = new PickerOptions(PickerOptions.TYPE_PICKER_OPTIONS); |
| | | mPickerOptions.context = context; |
| | | mPickerOptions.optionsSelectListener = listener; |
| | | } |
| | | |
| | | //Option |
| | | public OptionsPickerBuilder setSubmitText(String textContentConfirm) { |
| | | mPickerOptions.textContentConfirm = textContentConfirm; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setCancelText(String textContentCancel) { |
| | | mPickerOptions.textContentCancel = textContentCancel; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setTitleText(String textContentTitle) { |
| | | mPickerOptions.textContentTitle = textContentTitle; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder isDialog(boolean isDialog) { |
| | | mPickerOptions.isDialog = isDialog; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder addOnCancelClickListener(View.OnClickListener cancelListener) { |
| | | mPickerOptions.cancelListener = cancelListener; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | public OptionsPickerBuilder setSubmitColor(int textColorConfirm) { |
| | | mPickerOptions.textColorConfirm = textColorConfirm; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setCancelColor(int textColorCancel) { |
| | | mPickerOptions.textColorCancel = textColorCancel; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * {@link #setOutSideColor} instead. |
| | | * |
| | | * @param backgroundId color resId. |
| | | */ |
| | | @Deprecated |
| | | public OptionsPickerBuilder setBackgroundId(int backgroundId) { |
| | | mPickerOptions.outSideColor = backgroundId; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 显示时的外部背景色颜色,默认是灰色 |
| | | * |
| | | * @param outSideColor color resId. |
| | | * @return |
| | | */ |
| | | public OptionsPickerBuilder setOutSideColor(int outSideColor) { |
| | | mPickerOptions.outSideColor = outSideColor; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * ViewGroup 类型 |
| | | * 设置PickerView的显示容器 |
| | | * |
| | | * @param decorView Parent View. |
| | | * @return |
| | | */ |
| | | public OptionsPickerBuilder setDecorView(ViewGroup decorView) { |
| | | mPickerOptions.decorView = decorView; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setLayoutRes(int res, CustomListener listener) { |
| | | mPickerOptions.layoutRes = res; |
| | | mPickerOptions.customListener = listener; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setBgColor(int bgColorWheel) { |
| | | mPickerOptions.bgColorWheel = bgColorWheel; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setTitleBgColor(int bgColorTitle) { |
| | | mPickerOptions.bgColorTitle = bgColorTitle; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setTitleColor(int textColorTitle) { |
| | | mPickerOptions.textColorTitle = textColorTitle; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setSubCalSize(int textSizeSubmitCancel) { |
| | | mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setTitleSize(int textSizeTitle) { |
| | | mPickerOptions.textSizeTitle = textSizeTitle; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setContentTextSize(int textSizeContent) { |
| | | mPickerOptions.textSizeContent = textSizeContent; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setOutSideCancelable(boolean cancelable) { |
| | | mPickerOptions.cancelable = cancelable; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | public OptionsPickerBuilder setLabels(String label1, String label2, String label3) { |
| | | mPickerOptions.label1 = label1; |
| | | mPickerOptions.label2 = label2; |
| | | mPickerOptions.label3 = label3; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置Item 的间距倍数,用于控制 Item 高度间隔 |
| | | * |
| | | * @param lineSpacingMultiplier 浮点型,1.0-4.0f 之间有效,超过则取极值。 |
| | | */ |
| | | public OptionsPickerBuilder setLineSpacingMultiplier(float lineSpacingMultiplier) { |
| | | mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Set item divider line type color. |
| | | * |
| | | * @param dividerColor color resId. |
| | | */ |
| | | public OptionsPickerBuilder setDividerColor(@ColorInt int dividerColor) { |
| | | mPickerOptions.dividerColor = dividerColor; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Set item divider line type. |
| | | * |
| | | * @param dividerType enum Type {@link WheelView.DividerType} |
| | | */ |
| | | public OptionsPickerBuilder setDividerType(WheelView.DividerType dividerType) { |
| | | mPickerOptions.dividerType = dividerType; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Set the textColor of selected item. |
| | | * |
| | | * @param textColorCenter color res. |
| | | */ |
| | | public OptionsPickerBuilder setTextColorCenter(int textColorCenter) { |
| | | mPickerOptions.textColorCenter = textColorCenter; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Set the textColor of outside item. |
| | | * |
| | | * @param textColorOut color resId. |
| | | */ |
| | | public OptionsPickerBuilder setTextColorOut(@ColorInt int textColorOut) { |
| | | mPickerOptions.textColorOut = textColorOut; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setTypeface(Typeface font) { |
| | | mPickerOptions.font = font; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) { |
| | | mPickerOptions.cyclic1 = cyclic1; |
| | | mPickerOptions.cyclic2 = cyclic2; |
| | | mPickerOptions.cyclic3 = cyclic3; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setSelectOptions(int option1) { |
| | | mPickerOptions.option1 = option1; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setSelectOptions(int option1, int option2) { |
| | | mPickerOptions.option1 = option1; |
| | | mPickerOptions.option2 = option2; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setSelectOptions(int option1, int option2, int option3) { |
| | | mPickerOptions.option1 = option1; |
| | | mPickerOptions.option2 = option2; |
| | | mPickerOptions.option3 = option3; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder setTextXOffset(int xoffset_one, int xoffset_two, int xoffset_three) { |
| | | mPickerOptions.x_offset_one = xoffset_one; |
| | | mPickerOptions.x_offset_two = xoffset_two; |
| | | mPickerOptions.x_offset_three = xoffset_three; |
| | | return this; |
| | | } |
| | | |
| | | public OptionsPickerBuilder isCenterLabel(boolean isCenterLabel) { |
| | | mPickerOptions.isCenterLabel = isCenterLabel; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置最大可见数目 |
| | | * |
| | | * @param count 建议设置为 3 ~ 9之间。 |
| | | */ |
| | | public OptionsPickerBuilder setItemVisibleCount(int count) { |
| | | mPickerOptions.itemsVisibleCount = count; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 透明度是否渐变 |
| | | * |
| | | * @param isAlphaGradient true of false |
| | | */ |
| | | public OptionsPickerBuilder isAlphaGradient(boolean isAlphaGradient) { |
| | | mPickerOptions.isAlphaGradient = isAlphaGradient; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 切换选项时,是否还原第一项 |
| | | * |
| | | * @param isRestoreItem true:还原; false: 保持上一个选项 |
| | | * @return TimePickerBuilder |
| | | */ |
| | | public OptionsPickerBuilder isRestoreItem(boolean isRestoreItem) { |
| | | mPickerOptions.isRestoreItem = isRestoreItem; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * @param listener 切换item项滚动停止时,实时回调监听。 |
| | | * @return |
| | | */ |
| | | public OptionsPickerBuilder setOptionsSelectChangeListener(OnOptionsSelectChangeListener listener) { |
| | | mPickerOptions.optionsSelectChangeListener = listener; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | public <T> OptionsPickerView<T> build() { |
| | | return new OptionsPickerView<>(mPickerOptions); |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.builder; |
| | | |
| | | import android.content.Context; |
| | | |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | |
| | | import androidx.annotation.ColorInt; |
| | | |
| | | import com.bigkoo.pickerview.configure.PickerOptions; |
| | | import com.bigkoo.pickerview.listener.CustomListener; |
| | | import com.bigkoo.pickerview.listener.OnTimeSelectChangeListener; |
| | | import com.bigkoo.pickerview.listener.OnTimeSelectListener; |
| | | import com.bigkoo.pickerview.view.TimePickerView; |
| | | import com.contrarywind.view.WheelView; |
| | | |
| | | import java.util.Calendar; |
| | | |
| | | /** |
| | | * Created by xiaosongzeem on 2018/3/20. |
| | | */ |
| | | |
| | | public class TimePickerBuilder { |
| | | |
| | | private PickerOptions mPickerOptions; |
| | | |
| | | //Required |
| | | public TimePickerBuilder(Context context, OnTimeSelectListener listener) { |
| | | mPickerOptions = new PickerOptions(PickerOptions.TYPE_PICKER_TIME); |
| | | mPickerOptions.context = context; |
| | | mPickerOptions.timeSelectListener = listener; |
| | | } |
| | | |
| | | //Option |
| | | public TimePickerBuilder setGravity(int gravity) { |
| | | mPickerOptions.textGravity = gravity; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder addOnCancelClickListener(View.OnClickListener cancelListener) { |
| | | mPickerOptions.cancelListener = cancelListener; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * new boolean[]{true, true, true, false, false, false} |
| | | * control the "year","month","day","hours","minutes","seconds " display or hide. |
| | | * 分别控制“年”“月”“日”“时”“分”“秒”的显示或隐藏。 |
| | | * |
| | | * @param type 布尔型数组,长度需要设置为6。 |
| | | * @return TimePickerBuilder |
| | | */ |
| | | public TimePickerBuilder setType(boolean[] type) { |
| | | mPickerOptions.type = type; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setSubmitText(String textContentConfirm) { |
| | | mPickerOptions.textContentConfirm = textContentConfirm; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder isDialog(boolean isDialog) { |
| | | mPickerOptions.isDialog = isDialog; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setCancelText(String textContentCancel) { |
| | | mPickerOptions.textContentCancel = textContentCancel; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setTitleText(String textContentTitle) { |
| | | mPickerOptions.textContentTitle = textContentTitle; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setSubmitColor(int textColorConfirm) { |
| | | mPickerOptions.textColorConfirm = textColorConfirm; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setCancelColor(int textColorCancel) { |
| | | mPickerOptions.textColorCancel = textColorCancel; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * ViewGroup 类型的容器 |
| | | * |
| | | * @param decorView 选择器会被添加到此容器中 |
| | | * @return TimePickerBuilder |
| | | */ |
| | | public TimePickerBuilder setDecorView(ViewGroup decorView) { |
| | | mPickerOptions.decorView = decorView; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setBgColor(int bgColorWheel) { |
| | | mPickerOptions.bgColorWheel = bgColorWheel; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setTitleBgColor(int bgColorTitle) { |
| | | mPickerOptions.bgColorTitle = bgColorTitle; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setTitleColor(int textColorTitle) { |
| | | mPickerOptions.textColorTitle = textColorTitle; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setSubCalSize(int textSizeSubmitCancel) { |
| | | mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setTitleSize(int textSizeTitle) { |
| | | mPickerOptions.textSizeTitle = textSizeTitle; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setContentTextSize(int textSizeContent) { |
| | | mPickerOptions.textSizeContent = textSizeContent; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置最大可见数目 |
| | | * |
| | | * @param count suggest value: 3, 5, 7, 9 |
| | | */ |
| | | public TimePickerBuilder setItemVisibleCount(int count) { |
| | | mPickerOptions.itemsVisibleCount = count; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 透明度是否渐变 |
| | | * |
| | | * @param isAlphaGradient true of false |
| | | */ |
| | | public TimePickerBuilder isAlphaGradient(boolean isAlphaGradient) { |
| | | mPickerOptions.isAlphaGradient = isAlphaGradient; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11 |
| | | * |
| | | * @param date |
| | | * @return TimePickerBuilder |
| | | */ |
| | | public TimePickerBuilder setDate(Calendar date) { |
| | | mPickerOptions.date = date; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setLayoutRes(int res, CustomListener customListener) { |
| | | mPickerOptions.layoutRes = res; |
| | | mPickerOptions.customListener = customListener; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置起始时间 |
| | | * 因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11 |
| | | */ |
| | | |
| | | public TimePickerBuilder setRangDate(Calendar startDate, Calendar endDate) { |
| | | mPickerOptions.startDate = startDate; |
| | | mPickerOptions.endDate = endDate; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置间距倍数,但是只能在1.0-4.0f之间 |
| | | * |
| | | * @param lineSpacingMultiplier |
| | | */ |
| | | public TimePickerBuilder setLineSpacingMultiplier(float lineSpacingMultiplier) { |
| | | mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线的颜色 |
| | | * |
| | | * @param dividerColor |
| | | */ |
| | | |
| | | public TimePickerBuilder setDividerColor(@ColorInt int dividerColor) { |
| | | mPickerOptions.dividerColor = dividerColor; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线的类型 |
| | | * |
| | | * @param dividerType |
| | | */ |
| | | public TimePickerBuilder setDividerType(WheelView.DividerType dividerType) { |
| | | mPickerOptions.dividerType = dividerType; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * {@link #setOutSideColor} instead. |
| | | * |
| | | * @param backgroundId color resId. |
| | | */ |
| | | @Deprecated |
| | | public TimePickerBuilder setBackgroundId(int backgroundId) { |
| | | mPickerOptions.outSideColor = backgroundId; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 显示时的外部背景色颜色,默认是灰色 |
| | | * |
| | | * @param outSideColor |
| | | */ |
| | | public TimePickerBuilder setOutSideColor(@ColorInt int outSideColor) { |
| | | mPickerOptions.outSideColor = outSideColor; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线之间的文字的颜色 |
| | | * |
| | | * @param textColorCenter |
| | | */ |
| | | public TimePickerBuilder setTextColorCenter(@ColorInt int textColorCenter) { |
| | | mPickerOptions.textColorCenter = textColorCenter; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线以外文字的颜色 |
| | | * |
| | | * @param textColorOut |
| | | */ |
| | | public TimePickerBuilder setTextColorOut(@ColorInt int textColorOut) { |
| | | mPickerOptions.textColorOut = textColorOut; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder isCyclic(boolean cyclic) { |
| | | mPickerOptions.cyclic = cyclic; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setOutSideCancelable(boolean cancelable) { |
| | | mPickerOptions.cancelable = cancelable; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder setLunarCalendar(boolean lunarCalendar) { |
| | | mPickerOptions.isLunarCalendar = lunarCalendar; |
| | | return this; |
| | | } |
| | | |
| | | |
| | | public TimePickerBuilder setLabel(String label_year, String label_month, String label_day, String label_hours, String label_mins, String label_seconds) { |
| | | mPickerOptions.label_year = label_year; |
| | | mPickerOptions.label_month = label_month; |
| | | mPickerOptions.label_day = label_day; |
| | | mPickerOptions.label_hours = label_hours; |
| | | mPickerOptions.label_minutes = label_mins; |
| | | mPickerOptions.label_seconds = label_seconds; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置X轴倾斜角度[ -90 , 90°] |
| | | * |
| | | * @param x_offset_year 年 |
| | | * @param x_offset_month 月 |
| | | * @param x_offset_day 日 |
| | | * @param x_offset_hours 时 |
| | | * @param x_offset_minutes 分 |
| | | * @param x_offset_seconds 秒 |
| | | * @return |
| | | */ |
| | | public TimePickerBuilder setTextXOffset(int x_offset_year, int x_offset_month, int x_offset_day, |
| | | int x_offset_hours, int x_offset_minutes, int x_offset_seconds) { |
| | | mPickerOptions.x_offset_year = x_offset_year; |
| | | mPickerOptions.x_offset_month = x_offset_month; |
| | | mPickerOptions.x_offset_day = x_offset_day; |
| | | mPickerOptions.x_offset_hours = x_offset_hours; |
| | | mPickerOptions.x_offset_minutes = x_offset_minutes; |
| | | mPickerOptions.x_offset_seconds = x_offset_seconds; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerBuilder isCenterLabel(boolean isCenterLabel) { |
| | | mPickerOptions.isCenterLabel = isCenterLabel; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * @param listener 切换item项滚动停止时,实时回调监听。 |
| | | * @return |
| | | */ |
| | | public TimePickerBuilder setTimeSelectChangeListener(OnTimeSelectChangeListener listener) { |
| | | mPickerOptions.timeSelectChangeListener = listener; |
| | | return this; |
| | | } |
| | | |
| | | public TimePickerView build() { |
| | | return new TimePickerView(mPickerOptions); |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.configure; |
| | | |
| | | import android.content.Context; |
| | | import android.graphics.Typeface; |
| | | import android.view.Gravity; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | |
| | | import com.bigkoo.pickerview.listener.CustomListener; |
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener; |
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectListener; |
| | | import com.bigkoo.pickerview.listener.OnTimeSelectChangeListener; |
| | | import com.bigkoo.pickerview.listener.OnTimeSelectListener; |
| | | import com.contrarywind.view.WheelView; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | import java.util.Calendar; |
| | | |
| | | /** |
| | | * Build Options |
| | | * Created by xiaosongzeem on 2018/3/8. |
| | | */ |
| | | |
| | | public class PickerOptions { |
| | | |
| | | //constant |
| | | private static final int PICKER_VIEW_BTN_COLOR_NORMAL = 0xFF057dff; |
| | | private static final int PICKER_VIEW_BG_COLOR_TITLE = 0xFFf5f5f5; |
| | | private static final int PICKER_VIEW_COLOR_TITLE = 0xFF000000; |
| | | private static final int PICKER_VIEW_BG_COLOR_DEFAULT = 0xFFFFFFFF; |
| | | |
| | | public static final int TYPE_PICKER_OPTIONS = 1; |
| | | public static final int TYPE_PICKER_TIME = 2; |
| | | |
| | | public OnOptionsSelectListener optionsSelectListener; |
| | | public OnTimeSelectListener timeSelectListener; |
| | | public View.OnClickListener cancelListener; |
| | | |
| | | public OnTimeSelectChangeListener timeSelectChangeListener; |
| | | public OnOptionsSelectChangeListener optionsSelectChangeListener; |
| | | public CustomListener customListener; |
| | | |
| | | //options picker |
| | | public String label1, label2, label3;//单位字符 |
| | | public int option1, option2, option3;//默认选中项 |
| | | public int x_offset_one, x_offset_two, x_offset_three;//x轴偏移量 |
| | | |
| | | public boolean cyclic1 = false;//是否循环,默认否 |
| | | public boolean cyclic2 = false; |
| | | public boolean cyclic3 = false; |
| | | |
| | | public boolean isRestoreItem = false; //切换时,还原第一项 |
| | | |
| | | |
| | | //time picker |
| | | public boolean[] type = new boolean[]{true, true, true, false, false, false};//显示类型,默认显示: 年月日 |
| | | |
| | | public Calendar date;//当前选中时间 |
| | | public Calendar startDate;//开始时间 |
| | | public Calendar endDate;//终止时间 |
| | | public int startYear;//开始年份 |
| | | public int endYear;//结尾年份 |
| | | |
| | | public boolean cyclic = false;//是否循环 |
| | | public boolean isLunarCalendar = false;//是否显示农历 |
| | | |
| | | public String label_year, label_month, label_day, label_hours, label_minutes, label_seconds;//单位 |
| | | public int x_offset_year, x_offset_month, x_offset_day, x_offset_hours, x_offset_minutes, x_offset_seconds;//单位 |
| | | |
| | | |
| | | public PickerOptions(int buildType) { |
| | | if (buildType == TYPE_PICKER_OPTIONS) { |
| | | layoutRes = R.layout.pickerview_options; |
| | | } else { |
| | | layoutRes = R.layout.pickerview_time; |
| | | } |
| | | } |
| | | |
| | | //******* general field ******// |
| | | public int layoutRes; |
| | | public ViewGroup decorView; |
| | | public int textGravity = Gravity.CENTER; |
| | | public Context context; |
| | | |
| | | public String textContentConfirm;//确定按钮文字 |
| | | public String textContentCancel;//取消按钮文字 |
| | | public String textContentTitle;//标题文字 |
| | | |
| | | public int textColorConfirm = PICKER_VIEW_BTN_COLOR_NORMAL;//确定按钮颜色 |
| | | public int textColorCancel = PICKER_VIEW_BTN_COLOR_NORMAL;//取消按钮颜色 |
| | | public int textColorTitle = PICKER_VIEW_COLOR_TITLE;//标题颜色 |
| | | |
| | | public int bgColorWheel = PICKER_VIEW_BG_COLOR_DEFAULT;//滚轮背景颜色 |
| | | public int bgColorTitle = PICKER_VIEW_BG_COLOR_TITLE;//标题背景颜色 |
| | | |
| | | public int textSizeSubmitCancel = 17;//确定取消按钮大小 |
| | | public int textSizeTitle = 18;//标题文字大小 |
| | | public int textSizeContent = 18;//内容文字大小 |
| | | |
| | | public int textColorOut = 0xFFa8a8a8; //分割线以外的文字颜色 |
| | | public int textColorCenter = 0xFF2a2a2a; //分割线之间的文字颜色 |
| | | public int dividerColor = 0xFFd5d5d5; //分割线的颜色 |
| | | public int outSideColor = -1; //显示时的外部背景色颜色,默认是灰色 |
| | | |
| | | public float lineSpacingMultiplier = 1.6f; // 条目间距倍数 默认1.6 |
| | | public boolean isDialog;//是否是对话框模式 |
| | | |
| | | public boolean cancelable = true;//是否能取消 |
| | | public boolean isCenterLabel = false;//是否只显示中间的label,默认每个item都显示 |
| | | public Typeface font = Typeface.MONOSPACE;//字体样式 |
| | | public WheelView.DividerType dividerType = WheelView.DividerType.FILL;//分隔线类型 |
| | | public int itemsVisibleCount = 9; //最大可见条目数 |
| | | public boolean isAlphaGradient = false; //透明度渐变 |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | import android.view.View; |
| | | |
| | | /** |
| | | * Created by KyuYi on 2017/3/2. |
| | | * E-Mail:kyu_yi@sina.com |
| | | * 功能: |
| | | */ |
| | | |
| | | public interface CustomListener { |
| | | void customLayout(View v); |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | /** |
| | | * Created by zengsong on 2018/3/21. |
| | | */ |
| | | |
| | | public interface ISelectTimeCallback { |
| | | |
| | | public void onTimeSelectChanged(); |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | /** |
| | | * Created by Sai on 15/8/9. |
| | | */ |
| | | public interface OnDismissListener { |
| | | public void onDismiss(Object o); |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | /** |
| | | * Created by xiaosong on 2018/3/20. |
| | | */ |
| | | |
| | | public interface OnOptionsSelectChangeListener { |
| | | |
| | | void onOptionsSelectChanged(int options1, int options2, int options3); |
| | | |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | import android.view.View; |
| | | |
| | | /** |
| | | * Created by xiaosong on 2018/3/20. |
| | | */ |
| | | |
| | | public interface OnOptionsSelectListener { |
| | | |
| | | void onOptionsSelect(int options1, int options2, int options3, View v); |
| | | |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * Created by xiaosong on 2018/3/20. |
| | | */ |
| | | |
| | | public interface OnTimeSelectChangeListener { |
| | | |
| | | void onTimeSelectChanged(Date date); |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.listener; |
| | | |
| | | import android.view.View; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * Created by xiaosong on 2018/3/20. |
| | | */ |
| | | |
| | | public interface OnTimeSelectListener { |
| | | |
| | | void onTimeSelect(Date date, View v); |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.utils; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | import java.util.GregorianCalendar; |
| | | import java.util.Locale; |
| | | |
| | | public class ChinaDate { |
| | | |
| | | /** |
| | | * <lunarInfo 数组值的计算原理> |
| | | * |
| | | * 0x代表十六进制,后面的五位数是十六进制数。 |
| | | * 举个例子: 1980年的数据是 0x095b0 |
| | | * 二进制: 0000 1001 0101 1011 0000 |
| | | * 1-4: 表示当年是否为闰年,是的话为1,否则为0。 |
| | | * 5-16: 为除了闰月外的正常月份是大月还是小月,1为30天,0为29天。 |
| | | * 注意: 从1月到12月对应的是第16位到第5位。 |
| | | * 17-20: 非闰年为0,大于0表示闰月月份,仅当存在闰月的情况下有意义。 |
| | | */ |
| | | final private static long[] lunarInfo = new long[]{ |
| | | 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,//1900-1909 |
| | | 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,//1910-1919 |
| | | 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,//1920-1929 |
| | | 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,//1930-1939 |
| | | 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,//1940-1949 |
| | | 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0,//1950-1959 |
| | | 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,//1960-1969 |
| | | 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6,//1970-1979 |
| | | 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,//1980-1989 |
| | | 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,//1990-1999 |
| | | 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,//2000-2009 |
| | | 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,//2010-2019 |
| | | 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,//2020-2029 |
| | | 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,//2030-2039 |
| | | 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0,//2040-2049 |
| | | 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0,//2050-2059 |
| | | 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4,//2060-2069 |
| | | 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0,//2070-2079 |
| | | 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160,//2080-2089 |
| | | 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252,//2090-2099 |
| | | 0x0d520};//2100 |
| | | |
| | | private final static String[] nStr1 = new String[]{"", "正", "二", "三", "四", |
| | | "五", "六", "七", "八", "九", "十", "冬", "腊"}; |
| | | private final static String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", |
| | | "己", "庚", "辛", "壬", "癸"}; |
| | | private final static String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", |
| | | "巳", "午", "未", "申", "酉", "戌", "亥"}; |
| | | private final static String[] Animals = new String[]{"鼠", "牛", "虎", "兔", |
| | | "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"}; |
| | | |
| | | /** |
| | | * 传回农历 |
| | | * |
| | | * @param y 年的总天数 |
| | | * @return 农历 |
| | | */ |
| | | final private static int lYearDays(int y) { |
| | | int i, sum = 348; |
| | | for (i = 0x8000; i > 0x8; i >>= 1) { |
| | | if ((lunarInfo[y - 1900] & i) != 0) |
| | | sum += 1; |
| | | } |
| | | return (sum + leapDays(y)); |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 |
| | | * |
| | | * @param y 年闰月的天数 |
| | | * @return 农历 |
| | | */ |
| | | final public static int leapDays(int y) { |
| | | if (leapMonth(y) != 0) { |
| | | if ((lunarInfo[y - 1900] & 0x10000) != 0) |
| | | return 30; |
| | | else |
| | | return 29; |
| | | } else |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 |
| | | * |
| | | * @param y 年闰哪个月 1-12 , 没闰传回 0 |
| | | * @return 农历 |
| | | */ |
| | | final public static int leapMonth(int y) { |
| | | return (int) (lunarInfo[y - 1900] & 0xf); |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 y |
| | | * |
| | | * @param y y年m月的总天数 |
| | | * @param m y年m月的总天数 |
| | | * @return 农历 |
| | | */ |
| | | final public static int monthDays(int y, int m) { |
| | | if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0) |
| | | return 29; |
| | | else |
| | | return 30; |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 |
| | | * |
| | | * @param y 年的生肖 |
| | | * @return |
| | | */ |
| | | final public static String AnimalsYear(int y) { |
| | | return Animals[(y - 4) % 12]; |
| | | } |
| | | |
| | | /** |
| | | * 传入 |
| | | * |
| | | * @param num 月日的offset 传回干支,0是甲子 |
| | | * @return 干支 |
| | | */ |
| | | final private static String cyclicalm(int num) { |
| | | return (Gan[num % 10] + Zhi[num % 12]); |
| | | } |
| | | |
| | | /** |
| | | * 传入 offset 传回干支 |
| | | * |
| | | * @param y 0是甲子 |
| | | * @return 干支 |
| | | */ |
| | | final public static String cyclical(int y) { |
| | | int num = y - 1900 + 36; |
| | | return (cyclicalm(num)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 传出y年m月d日对应的农历.year0 .month1 .day2 .yearCyl3 .monCyl4 .dayCyl5 .isLeap6 |
| | | * |
| | | * @param y 年 |
| | | * @param m 月 |
| | | * @param d 日 |
| | | * @return y年m月d日对应的农历 |
| | | */ |
| | | final public static long[] calElement(int y, int m, int d) { |
| | | long[] nongDate = new long[7]; |
| | | int i = 0, temp = 0, leap = 0; |
| | | Date baseDate = new GregorianCalendar(0 + 1900, 0, 31).getTime(); |
| | | Date objDate = new GregorianCalendar(y, m - 1, d).getTime(); |
| | | long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L; |
| | | nongDate[5] = offset + 40; |
| | | nongDate[4] = 14; |
| | | for (i = 1900; i < 2100 && offset > 0; i++) { |
| | | temp = lYearDays(i); |
| | | offset -= temp; |
| | | nongDate[4] += 12; |
| | | } |
| | | if (offset < 0) { |
| | | offset += temp; |
| | | i--; |
| | | nongDate[4] -= 12; |
| | | } |
| | | nongDate[0] = i; |
| | | nongDate[3] = i - 1864; |
| | | leap = leapMonth(i); // 闰哪个月 |
| | | nongDate[6] = 0; |
| | | for (i = 1; i < 13 && offset > 0; i++) { |
| | | // 闰月 |
| | | if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) { |
| | | --i; |
| | | nongDate[6] = 1; |
| | | temp = leapDays((int) nongDate[0]); |
| | | } else { |
| | | temp = monthDays((int) nongDate[0], i); |
| | | } |
| | | // 解除闰月 |
| | | if (nongDate[6] == 1 && i == (leap + 1)) |
| | | nongDate[6] = 0; |
| | | offset -= temp; |
| | | if (nongDate[6] == 0) |
| | | nongDate[4]++; |
| | | } |
| | | if (offset == 0 && leap > 0 && i == leap + 1) { |
| | | if (nongDate[6] == 1) { |
| | | nongDate[6] = 0; |
| | | } else { |
| | | nongDate[6] = 1; |
| | | --i; |
| | | --nongDate[4]; |
| | | } |
| | | } |
| | | if (offset < 0) { |
| | | offset += temp; |
| | | --i; |
| | | --nongDate[4]; |
| | | } |
| | | nongDate[1] = i; |
| | | nongDate[2] = offset + 1; |
| | | return nongDate; |
| | | } |
| | | |
| | | public final static String getChinaDate(int day) { |
| | | String a = ""; |
| | | if (day == 10) |
| | | return "初十"; |
| | | if (day == 20) |
| | | return "二十"; |
| | | if (day == 30) |
| | | return "三十"; |
| | | int two = (int) ((day) / 10); |
| | | if (two == 0) |
| | | a = "初"; |
| | | if (two == 1) |
| | | a = "十"; |
| | | if (two == 2) |
| | | a = "廿"; |
| | | if (two == 3) |
| | | a = "三"; |
| | | int one = (int) (day % 10); |
| | | switch (one) { |
| | | case 1: |
| | | a += "一"; |
| | | break; |
| | | case 2: |
| | | a += "二"; |
| | | break; |
| | | case 3: |
| | | a += "三"; |
| | | break; |
| | | case 4: |
| | | a += "四"; |
| | | break; |
| | | case 5: |
| | | a += "五"; |
| | | break; |
| | | case 6: |
| | | a += "六"; |
| | | break; |
| | | case 7: |
| | | a += "七"; |
| | | break; |
| | | case 8: |
| | | a += "八"; |
| | | break; |
| | | case 9: |
| | | a += "九"; |
| | | break; |
| | | } |
| | | return a; |
| | | } |
| | | |
| | | public static String getCurrentLunarDate() { |
| | | Calendar today = Calendar.getInstance(Locale.SIMPLIFIED_CHINESE); |
| | | int year = today.get(Calendar.YEAR); |
| | | int month = today.get(Calendar.MONTH) + 1; |
| | | int date = today.get(Calendar.DATE); |
| | | long[] l = calElement(year, month, date); |
| | | StringBuffer sToday = new StringBuffer(); |
| | | try { |
| | | sToday.append(sdf.format(today.getTime())); |
| | | sToday.append(" 农历"); |
| | | sToday.append(cyclical(year)); |
| | | sToday.append('('); |
| | | sToday.append(AnimalsYear(year)); |
| | | sToday.append(")年"); |
| | | sToday.append(nStr1[(int) l[1]]); |
| | | sToday.append("月"); |
| | | sToday.append(getChinaDate((int) (l[2]))); |
| | | return sToday.toString(); |
| | | } finally { |
| | | sToday = null; |
| | | } |
| | | } |
| | | |
| | | public static String oneDay(int year, int month, int day) { |
| | | // Calendar today = Calendar.getInstance(Locale.SIMPLIFIED_CHINESE); |
| | | long[] l = calElement(year, month, day); |
| | | StringBuffer sToday = new StringBuffer(); |
| | | try { |
| | | // sToday.append(sdf.format(today.getTime())); |
| | | sToday.append(" 农历"); |
| | | sToday.append(cyclical(year)); |
| | | sToday.append('('); |
| | | sToday.append(AnimalsYear(year)); |
| | | sToday.append(")年"); |
| | | sToday.append(nStr1[(int) l[1]]); |
| | | sToday.append("月"); |
| | | sToday.append(getChinaDate((int) (l[2]))); |
| | | return sToday.toString(); |
| | | } finally { |
| | | sToday = null; |
| | | } |
| | | } |
| | | |
| | | private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日 EEEEE"); |
| | | |
| | | |
| | | /** |
| | | * @param lunarYear 农历年份 |
| | | * @return String of Ganzhi: 甲子年 |
| | | * 甲乙丙丁戊己庚辛壬癸 |
| | | * 子丑寅卯辰巳无为申酉戌亥 |
| | | */ |
| | | public static String getLunarYearText(int lunarYear) { |
| | | return Gan[(lunarYear - 4) % 10] + Zhi[(lunarYear - 4) % 12] + "年"; |
| | | } |
| | | |
| | | |
| | | public static ArrayList<String> getYears(int startYear, int endYear) { |
| | | ArrayList<String> years = new ArrayList<>(); |
| | | for (int i = startYear; i < endYear; i++) { |
| | | years.add(String.format("%s(%d)", getLunarYearText(i), i)); |
| | | } |
| | | return years; |
| | | } |
| | | |
| | | /** |
| | | * 获取year年的所有月份 |
| | | * |
| | | * @param year 年 |
| | | * @return 月份列表 |
| | | */ |
| | | public static ArrayList<String> getMonths(int year) { |
| | | ArrayList<String> baseMonths = new ArrayList<>(); |
| | | for (int i = 1; i < nStr1.length; i++) { |
| | | baseMonths.add(nStr1[i] + "月"); |
| | | } |
| | | if (leapMonth(year) != 0) { |
| | | baseMonths.add(leapMonth(year), "闰" + nStr1[leapMonth(year)] + "月"); |
| | | } |
| | | return baseMonths; |
| | | } |
| | | |
| | | /** |
| | | * 获取每月农历显示名称 |
| | | * |
| | | * @param maxDay 天 |
| | | * @return 名称列表 |
| | | */ |
| | | public static ArrayList<String> getLunarDays(int maxDay) { |
| | | ArrayList<String> days = new ArrayList<>(); |
| | | for (int i = 1; i <= maxDay; i++) { |
| | | days.add(getChinaDate(i)); |
| | | } |
| | | return days; |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.utils; |
| | | |
| | | import android.util.Log; |
| | | |
| | | import java.util.Date; |
| | | import java.util.GregorianCalendar; |
| | | |
| | | /** |
| | | * author: Jerry on 2016/7/11 11:29. |
| | | * description:工具类,实现公农历互转 |
| | | */ |
| | | public class LunarCalendar { |
| | | |
| | | /** |
| | | * 支持转换的最小农历年份 |
| | | */ |
| | | public static final int MIN_YEAR = 1900; |
| | | /** |
| | | * 支持转换的最大农历年份 |
| | | */ |
| | | public static final int MAX_YEAR = 2099; |
| | | |
| | | /** |
| | | * 公历每月前的天数 |
| | | */ |
| | | private static final int DAYS_BEFORE_MONTH[] = {0, 31, 59, 90, 120, 151, 181, |
| | | 212, 243, 273, 304, 334, 365}; |
| | | |
| | | /** |
| | | * 用来表示1900年到2099年间农历年份的相关信息,共24位bit的16进制表示,其中: |
| | | * 1. 前4位表示该年闰哪个月; |
| | | * 2. 5-17位表示农历年份13个月的大小月分布,0表示小,1表示大; |
| | | * 3. 最后7位表示农历年首(正月初一)对应的公历日期。 |
| | | * <p> |
| | | * 以2014年的数据0x955ABF为例说明: |
| | | * 1001 0101 0101 1010 1011 1111 |
| | | * 闰九月 农历正月初一对应公历1月31号 |
| | | */ |
| | | private static final int LUNAR_INFO[] = { |
| | | 0x84B6BF,/*1900*/ |
| | | 0x04AE53, 0x0A5748, 0x5526BD, 0x0D2650, 0x0D9544, 0x46AAB9, 0x056A4D, 0x09AD42, 0x24AEB6, 0x04AE4A,/*1901-1910*/ |
| | | 0x6A4DBE, 0x0A4D52, 0x0D2546, 0x5D52BA, 0x0B544E, 0x0D6A43, 0x296D37, 0x095B4B, 0x749BC1, 0x049754,/*1911-1920*/ |
| | | 0x0A4B48, 0x5B25BC, 0x06A550, 0x06D445, 0x4ADAB8, 0x02B64D, 0x095742, 0x2497B7, 0x04974A, 0x664B3E,/*1921-1930*/ |
| | | 0x0D4A51, 0x0EA546, 0x56D4BA, 0x05AD4E, 0x02B644, 0x393738, 0x092E4B, 0x7C96BF, 0x0C9553, 0x0D4A48,/*1931-1940*/ |
| | | 0x6DA53B, 0x0B554F, 0x056A45, 0x4AADB9, 0x025D4D, 0x092D42, 0x2C95B6, 0x0A954A, 0x7B4ABD, 0x06CA51,/*1941-1950*/ |
| | | 0x0B5546, 0x555ABB, 0x04DA4E, 0x0A5B43, 0x352BB8, 0x052B4C, 0x8A953F, 0x0E9552, 0x06AA48, 0x6AD53C,/*1951-1960*/ |
| | | 0x0AB54F, 0x04B645, 0x4A5739, 0x0A574D, 0x052642, 0x3E9335, 0x0D9549, 0x75AABE, 0x056A51, 0x096D46,/*1961-1970*/ |
| | | 0x54AEBB, 0x04AD4F, 0x0A4D43, 0x4D26B7, 0x0D254B, 0x8D52BF, 0x0B5452, 0x0B6A47, 0x696D3C, 0x095B50,/*1971-1980*/ |
| | | 0x049B45, 0x4A4BB9, 0x0A4B4D, 0xAB25C2, 0x06A554, 0x06D449, 0x6ADA3D, 0x0AB651, 0x095746, 0x5497BB,/*1981-1990*/ |
| | | 0x04974F, 0x064B44, 0x36A537, 0x0EA54A, 0x86B2BF, 0x05AC53, 0x0AB647, 0x5936BC, 0x092E50, 0x0C9645,/*1991-2000*/ |
| | | 0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, 0x0A954E,/*2001-2010*/ |
| | | 0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, 0x474AB9,/*2011-2020*/ |
| | | 0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x6a573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, 0x05AA43,/*2021-2030*/ |
| | | 0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, 0x0B5A4C,/*2031-2040*/ |
| | | 0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, 0x355B37,/*2041-2050*/ |
| | | 0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06AA44, 0x4AB638, 0x0AAE4C, 0x092E42,/*2051-2060*/ |
| | | 0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, 0x052D4B,/*2061-2070*/ |
| | | 0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, 0x3A93B6,/*2071-2080*/ |
| | | 0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, 0x8E933E,/*2081-2090*/ |
| | | 0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5 /*2091-2099*/ |
| | | }; |
| | | private static int[] solar_1_1 = {1887, 0xec04c, 0xec23f, 0xec435, 0xec649, |
| | | 0xec83e, 0xeca51, 0xecc46, 0xece3a, 0xed04d, 0xed242, 0xed436, |
| | | 0xed64a, 0xed83f, 0xeda53, 0xedc48, 0xede3d, 0xee050, 0xee244, |
| | | 0xee439, 0xee64d, 0xee842, 0xeea36, 0xeec4a, 0xeee3e, 0xef052, |
| | | 0xef246, 0xef43a, 0xef64e, 0xef843, 0xefa37, 0xefc4b, 0xefe41, |
| | | 0xf0054, 0xf0248, 0xf043c, 0xf0650, 0xf0845, 0xf0a38, 0xf0c4d, |
| | | 0xf0e42, 0xf1037, 0xf124a, 0xf143e, 0xf1651, 0xf1846, 0xf1a3a, |
| | | 0xf1c4e, 0xf1e44, 0xf2038, 0xf224b, 0xf243f, 0xf2653, 0xf2848, |
| | | 0xf2a3b, 0xf2c4f, 0xf2e45, 0xf3039, 0xf324d, 0xf3442, 0xf3636, |
| | | 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46, 0xf403b, 0xf424e, 0xf4443, |
| | | 0xf4638, 0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48, 0xf503c, 0xf524f, |
| | | 0xf5445, 0xf5639, 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49, 0xf603e, |
| | | 0xf6251, 0xf6446, 0xf663b, 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b, |
| | | 0xf703f, 0xf7252, 0xf7447, 0xf763c, 0xf7850, 0xf7a45, 0xf7c39, |
| | | 0xf7e4d, 0xf8042, 0xf8254, 0xf8449, 0xf863d, 0xf8851, 0xf8a46, |
| | | 0xf8c3b, 0xf8e4f, 0xf9044, 0xf9237, 0xf944a, 0xf963f, 0xf9853, |
| | | 0xf9a47, 0xf9c3c, 0xf9e50, 0xfa045, 0xfa238, 0xfa44c, 0xfa641, |
| | | 0xfa836, 0xfaa49, 0xfac3d, 0xfae52, 0xfb047, 0xfb23a, 0xfb44e, |
| | | 0xfb643, 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53, 0xfc048, 0xfc23c, |
| | | 0xfc450, 0xfc645, 0xfc839, 0xfca4c, 0xfcc41, 0xfce36, 0xfd04a, |
| | | 0xfd23d, 0xfd451, 0xfd646, 0xfd83a, 0xfda4d, 0xfdc43, 0xfde37, |
| | | 0xfe04b, 0xfe23f, 0xfe453, 0xfe648, 0xfe83c, 0xfea4f, 0xfec44, |
| | | 0xfee38, 0xff04c, 0xff241, 0xff436, 0xff64a, 0xff83e, 0xffa51, |
| | | 0xffc46, 0xffe3a, 0x10004e, 0x100242, 0x100437, 0x10064b, 0x100841, |
| | | 0x100a53, 0x100c48, 0x100e3c, 0x10104f, 0x101244, 0x101438, |
| | | 0x10164c, 0x101842, 0x101a35, 0x101c49, 0x101e3d, 0x102051, |
| | | 0x102245, 0x10243a, 0x10264e, 0x102843, 0x102a37, 0x102c4b, |
| | | 0x102e3f, 0x103053, 0x103247, 0x10343b, 0x10364f, 0x103845, |
| | | 0x103a38, 0x103c4c, 0x103e42, 0x104036, 0x104249, 0x10443d, |
| | | 0x104651, 0x104846, 0x104a3a, 0x104c4e, 0x104e43, 0x105038, |
| | | 0x10524a, 0x10543e, 0x105652, 0x105847, 0x105a3b, 0x105c4f, |
| | | 0x105e45, 0x106039, 0x10624c, 0x106441, 0x106635, 0x106849, |
| | | 0x106a3d, 0x106c51, 0x106e47, 0x10703c, 0x10724f, 0x107444, |
| | | 0x107638, 0x10784c, 0x107a3f, 0x107c53, 0x107e48}; |
| | | private static int[] lunar_month_days = {1887, 0x1694, 0x16aa, 0x4ad5, |
| | | 0xab6, 0xc4b7, 0x4ae, 0xa56, 0xb52a, 0x1d2a, 0xd54, 0x75aa, 0x156a, |
| | | 0x1096d, 0x95c, 0x14ae, 0xaa4d, 0x1a4c, 0x1b2a, 0x8d55, 0xad4, |
| | | 0x135a, 0x495d, 0x95c, 0xd49b, 0x149a, 0x1a4a, 0xbaa5, 0x16a8, |
| | | 0x1ad4, 0x52da, 0x12b6, 0xe937, 0x92e, 0x1496, 0xb64b, 0xd4a, |
| | | 0xda8, 0x95b5, 0x56c, 0x12ae, 0x492f, 0x92e, 0xcc96, 0x1a94, |
| | | 0x1d4a, 0xada9, 0xb5a, 0x56c, 0x726e, 0x125c, 0xf92d, 0x192a, |
| | | 0x1a94, 0xdb4a, 0x16aa, 0xad4, 0x955b, 0x4ba, 0x125a, 0x592b, |
| | | 0x152a, 0xf695, 0xd94, 0x16aa, 0xaab5, 0x9b4, 0x14b6, 0x6a57, |
| | | 0xa56, 0x1152a, 0x1d2a, 0xd54, 0xd5aa, 0x156a, 0x96c, 0x94ae, |
| | | 0x14ae, 0xa4c, 0x7d26, 0x1b2a, 0xeb55, 0xad4, 0x12da, 0xa95d, |
| | | 0x95a, 0x149a, 0x9a4d, 0x1a4a, 0x11aa5, 0x16a8, 0x16d4, 0xd2da, |
| | | 0x12b6, 0x936, 0x9497, 0x1496, 0x1564b, 0xd4a, 0xda8, 0xd5b4, |
| | | 0x156c, 0x12ae, 0xa92f, 0x92e, 0xc96, 0x6d4a, 0x1d4a, 0x10d65, |
| | | 0xb58, 0x156c, 0xb26d, 0x125c, 0x192c, 0x9a95, 0x1a94, 0x1b4a, |
| | | 0x4b55, 0xad4, 0xf55b, 0x4ba, 0x125a, 0xb92b, 0x152a, 0x1694, |
| | | 0x96aa, 0x15aa, 0x12ab5, 0x974, 0x14b6, 0xca57, 0xa56, 0x1526, |
| | | 0x8e95, 0xd54, 0x15aa, 0x49b5, 0x96c, 0xd4ae, 0x149c, 0x1a4c, |
| | | 0xbd26, 0x1aa6, 0xb54, 0x6d6a, 0x12da, 0x1695d, 0x95a, 0x149a, |
| | | 0xda4b, 0x1a4a, 0x1aa4, 0xbb54, 0x16b4, 0xada, 0x495b, 0x936, |
| | | 0xf497, 0x1496, 0x154a, 0xb6a5, 0xda4, 0x15b4, 0x6ab6, 0x126e, |
| | | 0x1092f, 0x92e, 0xc96, 0xcd4a, 0x1d4a, 0xd64, 0x956c, 0x155c, |
| | | 0x125c, 0x792e, 0x192c, 0xfa95, 0x1a94, 0x1b4a, 0xab55, 0xad4, |
| | | 0x14da, 0x8a5d, 0xa5a, 0x1152b, 0x152a, 0x1694, 0xd6aa, 0x15aa, |
| | | 0xab4, 0x94ba, 0x14b6, 0xa56, 0x7527, 0xd26, 0xee53, 0xd54, 0x15aa, |
| | | 0xa9b5, 0x96c, 0x14ae, 0x8a4e, 0x1a4c, 0x11d26, 0x1aa4, 0x1b54, |
| | | 0xcd6a, 0xada, 0x95c, 0x949d, 0x149a, 0x1a2a, 0x5b25, 0x1aa4, |
| | | 0xfb52, 0x16b4, 0xaba, 0xa95b, 0x936, 0x1496, 0x9a4b, 0x154a, |
| | | 0x136a5, 0xda4, 0x15ac}; |
| | | |
| | | /** |
| | | * 将农历日期转换为公历日期 |
| | | * |
| | | * @param year 农历年份 |
| | | * @param month 农历月 |
| | | * @param monthDay 农历日 |
| | | * @param isLeapMonth 该月是否是闰月 |
| | | * @return 返回农历日期对应的公历日期,year0, month1, day2. |
| | | */ |
| | | public static final int[] lunarToSolar(int year, int month, int monthDay, |
| | | boolean isLeapMonth) { |
| | | int dayOffset; |
| | | int leapMonth; |
| | | int i; |
| | | |
| | | if (year < MIN_YEAR || year > MAX_YEAR || month < 1 || month > 12 |
| | | || monthDay < 1 || monthDay > 30) { |
| | | throw new IllegalArgumentException( |
| | | "Illegal lunar date, must be like that:\n\t" + |
| | | "year : 1900~2099\n\t" + |
| | | "month : 1~12\n\t" + |
| | | "day : 1~30"); |
| | | } |
| | | |
| | | dayOffset = (LUNAR_INFO[year - MIN_YEAR] & 0x001F) - 1; |
| | | |
| | | if (((LUNAR_INFO[year - MIN_YEAR] & 0x0060) >> 5) == 2) |
| | | dayOffset += 31; |
| | | |
| | | for (i = 1; i < month; i++) { |
| | | if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (i - 1))) == 0) |
| | | dayOffset += 29; |
| | | else |
| | | dayOffset += 30; |
| | | } |
| | | |
| | | dayOffset += monthDay; |
| | | leapMonth = (LUNAR_INFO[year - MIN_YEAR] & 0xf00000) >> 20; |
| | | |
| | | // 这一年有闰月 |
| | | if (leapMonth != 0) { |
| | | if (month > leapMonth || (month == leapMonth && isLeapMonth)) { |
| | | if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (month - 1))) == 0) |
| | | dayOffset += 29; |
| | | else |
| | | dayOffset += 30; |
| | | } |
| | | } |
| | | |
| | | if (dayOffset > 366 || (year % 4 != 0 && dayOffset > 365)) { |
| | | year += 1; |
| | | if (year % 4 == 1) |
| | | dayOffset -= 366; |
| | | else |
| | | dayOffset -= 365; |
| | | } |
| | | |
| | | int[] solarInfo = new int[3]; |
| | | for (i = 1; i < 13; i++) { |
| | | int iPos = DAYS_BEFORE_MONTH[i]; |
| | | if (year % 4 == 0 && i > 2) { |
| | | iPos += 1; |
| | | } |
| | | |
| | | if (year % 4 == 0 && i == 2 && iPos + 1 == dayOffset) { |
| | | solarInfo[1] = i; |
| | | solarInfo[2] = dayOffset - 31; |
| | | break; |
| | | } |
| | | |
| | | if (iPos >= dayOffset) { |
| | | solarInfo[1] = i; |
| | | iPos = DAYS_BEFORE_MONTH[i - 1]; |
| | | if (year % 4 == 0 && i > 2) { |
| | | iPos += 1; |
| | | } |
| | | if (dayOffset > iPos) |
| | | solarInfo[2] = dayOffset - iPos; |
| | | else if (dayOffset == iPos) { |
| | | if (year % 4 == 0 && i == 2) |
| | | solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1] + 1; |
| | | else |
| | | solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1]; |
| | | |
| | | } else |
| | | solarInfo[2] = dayOffset; |
| | | break; |
| | | } |
| | | } |
| | | solarInfo[0] = year; |
| | | |
| | | return solarInfo; |
| | | } |
| | | |
| | | public static final int[] solarToLunar(int year, int month, int monthDay) { |
| | | int[] lunarDate = new int[4]; |
| | | |
| | | int index = year - solar_1_1[0]; |
| | | int data = (year << 9) | (month << 5) |
| | | | (monthDay); |
| | | int solar11 = 0; |
| | | if (solar_1_1[index] > data) { |
| | | index--; |
| | | } |
| | | solar11 = solar_1_1[index]; |
| | | int y = getBitInt(solar11, 12, 9); |
| | | int m = getBitInt(solar11, 4, 5); |
| | | int d = getBitInt(solar11, 5, 0); |
| | | long offset = solarToInt(year, month, |
| | | monthDay) - solarToInt(y, m, d); |
| | | |
| | | int days = lunar_month_days[index]; |
| | | int leap = getBitInt(days, 4, 13); |
| | | |
| | | int lunarY = index + solar_1_1[0]; |
| | | int lunarM = 1; |
| | | int lunarD = 1; |
| | | offset += 1; |
| | | |
| | | for (int i = 0; i < 13; i++) { |
| | | int dm = getBitInt(days, 1, 12 - i) == 1 ? 30 : 29; |
| | | if (offset > dm) { |
| | | lunarM++; |
| | | offset -= dm; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | lunarD = (int) (offset); |
| | | lunarDate[0] = lunarY; |
| | | lunarDate[1] = lunarM; |
| | | boolean isLeap = false; |
| | | if (leap != 0 && lunarM > leap) { |
| | | lunarDate[1] = lunarM - 1; |
| | | if (lunarM == leap + 1) { |
| | | isLeap = true; |
| | | } |
| | | } |
| | | |
| | | lunarDate[2] = lunarD; |
| | | lunarDate[3] = isLeap ? 1 : 0; |
| | | //Log.i("----------->",year+"-"+month+"-"+monthDay+"====>"+lunarDate[0]+"-"+lunarDate[1]+"-"+lunarDate[2]+"-"+lunarDate[3]); |
| | | return lunarDate; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将公历日期转换为农历日期,且标识是否是闰月 |
| | | * |
| | | * @param year |
| | | * @param month |
| | | * @param monthDay |
| | | * @return 返回公历日期对应的农历日期,year0,month1,day2,leap3 |
| | | * @deprecated 不准确 |
| | | */ |
| | | @Deprecated |
| | | public static final int[] solarToLunarDeprecated(int year, int month, int monthDay) { |
| | | int[] lunarDate = new int[4]; |
| | | Date baseDate = new GregorianCalendar(1900, 0, 31).getTime(); |
| | | Date objDate = new GregorianCalendar(year, month - 1, monthDay).getTime(); |
| | | int offset = (int) ((objDate.getTime() - baseDate.getTime()) / 86400000L); |
| | | |
| | | // 用offset减去每农历年的天数计算当天是农历第几天 |
| | | // iYear最终结果是农历的年份, offset是当年的第几天 |
| | | int iYear, daysOfYear = 0; |
| | | for (iYear = MIN_YEAR; iYear <= MAX_YEAR && offset > 0; iYear++) { |
| | | daysOfYear = daysInLunarYear(iYear); |
| | | offset -= daysOfYear; |
| | | } |
| | | if (offset < 0) { |
| | | offset += daysOfYear; |
| | | iYear--; |
| | | } |
| | | |
| | | // 农历年份 |
| | | lunarDate[0] = iYear; |
| | | |
| | | int leapMonth = leapMonth(iYear); // 闰哪个月,1-12 |
| | | boolean isLeap = false; |
| | | // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天 |
| | | int iMonth, daysOfMonth = 0; |
| | | for (iMonth = 1; iMonth <= 13 && offset > 0; iMonth++) { |
| | | daysOfMonth = daysInLunarMonth(iYear, iMonth); |
| | | offset -= daysOfMonth; |
| | | } |
| | | // 当前月超过闰月,要校正 |
| | | if (leapMonth != 0 && iMonth > leapMonth) { |
| | | --iMonth; |
| | | Log.i("----------->", year + "-" + month + "-" + monthDay + "====>" + iMonth + "-" + leapMonth); |
| | | if (iMonth == leapMonth) { |
| | | isLeap = true; |
| | | } |
| | | } |
| | | // offset小于0时,也要校正 |
| | | if (offset < 0) { |
| | | offset += daysOfMonth; |
| | | --iMonth; |
| | | } |
| | | |
| | | lunarDate[1] = iMonth; |
| | | lunarDate[2] = offset + 1; |
| | | lunarDate[3] = isLeap ? 1 : 0; |
| | | |
| | | //Log.i("----------->",year+"-"+month+"-"+monthDay+"====>"+lunarDate[0]+"-"+lunarDate[1]+"-"+lunarDate[2]+"-"+lunarDate[3]); |
| | | return lunarDate; |
| | | } |
| | | |
| | | /** |
| | | * 传回农历year年month月的总天数 |
| | | * |
| | | * @param year 要计算的年份 |
| | | * @param month 要计算的月 |
| | | * @return 传回天数 |
| | | */ |
| | | final public static int daysInMonth(int year, int month) { |
| | | return daysInMonth(year, month, false); |
| | | } |
| | | |
| | | /** |
| | | * 传回农历year年month月的总天数 |
| | | * |
| | | * @param year 要计算的年份 |
| | | * @param month 要计算的月 |
| | | * @param leap 当月是否是闰月 |
| | | * @return 传回天数,如果闰月是错误的,返回0. |
| | | */ |
| | | public static final int daysInMonth(int year, int month, boolean leap) { |
| | | int leapMonth = leapMonth(year); |
| | | int offset = 0; |
| | | |
| | | // 如果本年有闰月且month大于闰月时,需要校正 |
| | | if (leapMonth != 0 && month > leapMonth) { |
| | | offset = 1; |
| | | } |
| | | |
| | | // 不考虑闰月 |
| | | if (!leap) { |
| | | return daysInLunarMonth(year, month + offset); |
| | | } else { |
| | | // 传入的闰月是正确的月份 |
| | | if (leapMonth != 0 && leapMonth == month) { |
| | | return daysInLunarMonth(year, month + 1); |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 year年的总天数 |
| | | * |
| | | * @param year 将要计算的年份 |
| | | * @return 返回传入年份的总天数 |
| | | */ |
| | | private static int daysInLunarYear(int year) { |
| | | int i, sum = 348; |
| | | if (leapMonth(year) != 0) { |
| | | sum = 377; |
| | | } |
| | | int monthInfo = LUNAR_INFO[year - MIN_YEAR] & 0x0FFF80; |
| | | for (i = 0x80000; i > 0x7; i >>= 1) { |
| | | if ((monthInfo & i) != 0) |
| | | sum += 1; |
| | | } |
| | | return sum; |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 year年month月的总天数,总共有13个月包括闰月 |
| | | * |
| | | * @param year 将要计算的年份 |
| | | * @param month 将要计算的月份 |
| | | * @return 传回农历 year年month月的总天数 |
| | | */ |
| | | private static int daysInLunarMonth(int year, int month) { |
| | | if ((LUNAR_INFO[year - MIN_YEAR] & (0x100000 >> month)) == 0) |
| | | return 29; |
| | | else |
| | | return 30; |
| | | } |
| | | |
| | | /** |
| | | * 传回农历 year年闰哪个月 1-12 , 没闰传回 0 |
| | | * |
| | | * @param year 将要计算的年份 |
| | | * @return 传回农历 year年闰哪个月1-12, 没闰传回 0 |
| | | */ |
| | | public static int leapMonth(int year) { |
| | | return (int) ((LUNAR_INFO[year - MIN_YEAR] & 0xF00000)) >> 20; |
| | | } |
| | | |
| | | |
| | | private static int getBitInt(int data, int length, int shift) { |
| | | return (data & (((1 << length) - 1) << shift)) >> shift; |
| | | } |
| | | |
| | | private static long solarToInt(int y, int m, int d) { |
| | | m = (m + 9) % 12; |
| | | y = y - m / 10; |
| | | return 365 * y + y / 4 - y / 100 + y / 400 + (m * 306 + 5) / 10 |
| | | + (d - 1); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.utils; |
| | | |
| | | import android.view.Gravity; |
| | | |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | |
| | | /** |
| | | * Created by Sai on 15/8/9. |
| | | */ |
| | | public class PickerViewAnimateUtil { |
| | | private static final int INVALID = -1; |
| | | /** |
| | | * Get default animation resource when not defined by the user |
| | | * |
| | | * @param gravity the animGravity of the dialog |
| | | * @param isInAnimation determine if is in or out animation. true when is is |
| | | * @return the id of the animation resource |
| | | */ |
| | | public static int getAnimationResource(int gravity, boolean isInAnimation) { |
| | | switch (gravity) { |
| | | case Gravity.BOTTOM: |
| | | return isInAnimation ? R.anim.pickerview_slide_in_bottom : R.anim.pickerview_slide_out_bottom; |
| | | } |
| | | return INVALID; |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.view; |
| | | |
| | | import android.app.Activity; |
| | | import android.app.Dialog; |
| | | import android.content.Context; |
| | | import android.content.DialogInterface; |
| | | import android.graphics.Color; |
| | | import android.view.Gravity; |
| | | import android.view.KeyEvent; |
| | | import android.view.LayoutInflater; |
| | | import android.view.MotionEvent; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | import android.view.Window; |
| | | import android.view.animation.Animation; |
| | | import android.view.animation.AnimationUtils; |
| | | import android.widget.FrameLayout; |
| | | |
| | | import com.bigkoo.pickerview.configure.PickerOptions; |
| | | import com.bigkoo.pickerview.listener.OnDismissListener; |
| | | import com.bigkoo.pickerview.utils.PickerViewAnimateUtil; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | /** |
| | | * Created by Sai on 15/11/22. |
| | | * 精仿iOSPickerViewController控件 |
| | | */ |
| | | public class BasePickerView { |
| | | |
| | | private Context context; |
| | | protected ViewGroup contentContainer; |
| | | private ViewGroup rootView;//附加View 的 根View |
| | | private ViewGroup dialogView;//附加Dialog 的 根View |
| | | |
| | | protected PickerOptions mPickerOptions; |
| | | private OnDismissListener onDismissListener; |
| | | private boolean dismissing; |
| | | |
| | | private Animation outAnim; |
| | | private Animation inAnim; |
| | | private boolean isShowing; |
| | | |
| | | protected int animGravity = Gravity.BOTTOM; |
| | | |
| | | private Dialog mDialog; |
| | | protected View clickView;//是通过哪个View弹出的 |
| | | private boolean isAnim = true; |
| | | |
| | | public BasePickerView(Context context) { |
| | | this.context = context; |
| | | } |
| | | |
| | | |
| | | protected void initViews() { |
| | | |
| | | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( |
| | | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM); |
| | | |
| | | LayoutInflater layoutInflater = LayoutInflater.from(context); |
| | | if (isDialog()) { |
| | | //如果是对话框模式 |
| | | dialogView = (ViewGroup) layoutInflater.inflate(R.layout.layout_basepickerview, null, false); |
| | | //设置界面的背景为透明 |
| | | dialogView.setBackgroundColor(Color.TRANSPARENT); |
| | | //这个是真正要加载选择器的父布局 |
| | | contentContainer = (ViewGroup) dialogView.findViewById(R.id.content_container); |
| | | //设置对话框 默认左右间距屏幕30 |
| | | params.leftMargin = 30; |
| | | params.rightMargin = 30; |
| | | contentContainer.setLayoutParams(params); |
| | | //创建对话框 |
| | | createDialog(); |
| | | //给背景设置点击事件,这样当点击内容以外的地方会关闭界面 |
| | | dialogView.setOnClickListener(new View.OnClickListener() { |
| | | @Override |
| | | public void onClick(View view) { |
| | | dismiss(); |
| | | } |
| | | }); |
| | | } else { |
| | | //如果只是要显示在屏幕的下方 |
| | | //decorView是activity的根View,包含 contentView 和 titleView |
| | | if (mPickerOptions.decorView == null) { |
| | | mPickerOptions.decorView = (ViewGroup) ((Activity) context).getWindow().getDecorView(); |
| | | } |
| | | //将控件添加到decorView中 |
| | | rootView = (ViewGroup) layoutInflater.inflate(R.layout.layout_basepickerview, mPickerOptions.decorView, false); |
| | | rootView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); |
| | | if (mPickerOptions.outSideColor != -1) { |
| | | rootView.setBackgroundColor(mPickerOptions.outSideColor); |
| | | } |
| | | //这个是真正要加载时间选取器的父布局 |
| | | contentContainer = (ViewGroup) rootView.findViewById(R.id.content_container); |
| | | contentContainer.setLayoutParams(params); |
| | | } |
| | | setKeyBackCancelable(true); |
| | | } |
| | | |
| | | protected void initAnim() { |
| | | inAnim = getInAnimation(); |
| | | outAnim = getOutAnimation(); |
| | | } |
| | | |
| | | protected void initEvents() { |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @param v (是通过哪个View弹出的) |
| | | * @param isAnim 是否显示动画效果 |
| | | */ |
| | | public void show(View v, boolean isAnim) { |
| | | this.clickView = v; |
| | | this.isAnim = isAnim; |
| | | show(); |
| | | } |
| | | |
| | | public void show(boolean isAnim) { |
| | | show(null, isAnim); |
| | | } |
| | | |
| | | public void show(View v) { |
| | | this.clickView = v; |
| | | show(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 添加View到根视图 |
| | | */ |
| | | public void show() { |
| | | if (isDialog()) { |
| | | showDialog(); |
| | | } else { |
| | | if (isShowing()) { |
| | | return; |
| | | } |
| | | isShowing = true; |
| | | onAttached(rootView); |
| | | rootView.requestFocus(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * show的时候调用 |
| | | * |
| | | * @param view 这个View |
| | | */ |
| | | private void onAttached(View view) { |
| | | mPickerOptions.decorView.addView(view); |
| | | if (isAnim) { |
| | | contentContainer.startAnimation(inAnim); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 检测该View是不是已经添加到根视图 |
| | | * |
| | | * @return 如果视图已经存在该View返回true |
| | | */ |
| | | public boolean isShowing() { |
| | | if (isDialog()) { |
| | | return false; |
| | | } else { |
| | | return rootView.getParent() != null || isShowing; |
| | | } |
| | | |
| | | } |
| | | |
| | | public void dismiss() { |
| | | if (isDialog()) { |
| | | dismissDialog(); |
| | | } else { |
| | | if (dismissing) { |
| | | return; |
| | | } |
| | | |
| | | if (isAnim) { |
| | | //消失动画 |
| | | outAnim.setAnimationListener(new Animation.AnimationListener() { |
| | | @Override |
| | | public void onAnimationStart(Animation animation) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void onAnimationEnd(Animation animation) { |
| | | dismissImmediately(); |
| | | } |
| | | |
| | | @Override |
| | | public void onAnimationRepeat(Animation animation) { |
| | | |
| | | } |
| | | }); |
| | | contentContainer.startAnimation(outAnim); |
| | | } else { |
| | | dismissImmediately(); |
| | | } |
| | | dismissing = true; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | public void dismissImmediately() { |
| | | |
| | | mPickerOptions.decorView.post(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | //从根视图移除 |
| | | mPickerOptions.decorView.removeView(rootView); |
| | | isShowing = false; |
| | | dismissing = false; |
| | | if (onDismissListener != null) { |
| | | onDismissListener.onDismiss(BasePickerView.this); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | |
| | | } |
| | | |
| | | private Animation getInAnimation() { |
| | | int res = PickerViewAnimateUtil.getAnimationResource(this.animGravity, true); |
| | | return AnimationUtils.loadAnimation(context, res); |
| | | } |
| | | |
| | | private Animation getOutAnimation() { |
| | | int res = PickerViewAnimateUtil.getAnimationResource(this.animGravity, false); |
| | | return AnimationUtils.loadAnimation(context, res); |
| | | } |
| | | |
| | | public BasePickerView setOnDismissListener(OnDismissListener onDismissListener) { |
| | | this.onDismissListener = onDismissListener; |
| | | return this; |
| | | } |
| | | |
| | | public void setKeyBackCancelable(boolean isCancelable) { |
| | | |
| | | ViewGroup View; |
| | | if (isDialog()) { |
| | | View = dialogView; |
| | | } else { |
| | | View = rootView; |
| | | } |
| | | |
| | | View.setFocusable(isCancelable); |
| | | View.setFocusableInTouchMode(isCancelable); |
| | | if (isCancelable) { |
| | | View.setOnKeyListener(onKeyBackListener); |
| | | } else { |
| | | View.setOnKeyListener(null); |
| | | } |
| | | } |
| | | |
| | | private View.OnKeyListener onKeyBackListener = new View.OnKeyListener() { |
| | | @Override |
| | | public boolean onKey(View v, int keyCode, KeyEvent event) { |
| | | if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == MotionEvent.ACTION_DOWN && isShowing()) { |
| | | dismiss(); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | protected BasePickerView setOutSideCancelable(boolean isCancelable) { |
| | | |
| | | if (rootView != null) { |
| | | View view = rootView.findViewById(R.id.outmost_container); |
| | | |
| | | if (isCancelable) { |
| | | view.setOnTouchListener(onCancelableTouchListener); |
| | | } else { |
| | | view.setOnTouchListener(null); |
| | | } |
| | | } |
| | | |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 设置对话框模式是否可以点击外部取消 |
| | | */ |
| | | public void setDialogOutSideCancelable() { |
| | | if (mDialog != null) { |
| | | mDialog.setCancelable(mPickerOptions.cancelable); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Called when the user touch on black overlay, in order to dismiss the dialog. |
| | | */ |
| | | private final View.OnTouchListener onCancelableTouchListener = new View.OnTouchListener() { |
| | | @Override |
| | | public boolean onTouch(View v, MotionEvent event) { |
| | | if (event.getAction() == MotionEvent.ACTION_DOWN) { |
| | | dismiss(); |
| | | } |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | public View findViewById(int id) { |
| | | return contentContainer.findViewById(id); |
| | | } |
| | | |
| | | public void createDialog() { |
| | | if (dialogView != null) { |
| | | mDialog = new Dialog(context, R.style.custom_dialog2); |
| | | mDialog.setCancelable(mPickerOptions.cancelable);//不能点外面取消,也不能点back取消 |
| | | mDialog.setContentView(dialogView); |
| | | |
| | | Window dialogWindow = mDialog.getWindow(); |
| | | if (dialogWindow != null) { |
| | | dialogWindow.setWindowAnimations(R.style.picker_view_scale_anim); |
| | | dialogWindow.setGravity(Gravity.CENTER);//可以改成Bottom |
| | | } |
| | | |
| | | mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { |
| | | @Override |
| | | public void onDismiss(DialogInterface dialog) { |
| | | if (onDismissListener != null) { |
| | | onDismissListener.onDismiss(BasePickerView.this); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | private void showDialog() { |
| | | if (mDialog != null) { |
| | | mDialog.show(); |
| | | } |
| | | } |
| | | |
| | | private void dismissDialog() { |
| | | if (mDialog != null) { |
| | | mDialog.dismiss(); |
| | | } |
| | | } |
| | | |
| | | public ViewGroup getDialogContainerLayout() { |
| | | return contentContainer; |
| | | } |
| | | |
| | | |
| | | public Dialog getDialog() { |
| | | return mDialog; |
| | | } |
| | | |
| | | |
| | | public boolean isDialog() { |
| | | return false; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.view; |
| | | |
| | | import android.content.Context; |
| | | import android.text.TextUtils; |
| | | import android.view.LayoutInflater; |
| | | import android.view.View; |
| | | import android.widget.Button; |
| | | import android.widget.LinearLayout; |
| | | import android.widget.RelativeLayout; |
| | | import android.widget.TextView; |
| | | |
| | | import com.bigkoo.pickerview.configure.PickerOptions; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 条件选择器 |
| | | * Created by Sai on 15/11/22. |
| | | */ |
| | | public class OptionsPickerView<T> extends BasePickerView implements View.OnClickListener { |
| | | |
| | | private WheelOptions<T> wheelOptions; |
| | | |
| | | private static final String TAG_SUBMIT = "submit"; |
| | | private static final String TAG_CANCEL = "cancel"; |
| | | |
| | | |
| | | public OptionsPickerView(PickerOptions pickerOptions) { |
| | | super(pickerOptions.context); |
| | | mPickerOptions = pickerOptions; |
| | | initView(pickerOptions.context); |
| | | } |
| | | |
| | | private void initView(Context context) { |
| | | setDialogOutSideCancelable(); |
| | | initViews(); |
| | | initAnim(); |
| | | initEvents(); |
| | | if (mPickerOptions.customListener == null) { |
| | | LayoutInflater.from(context).inflate(mPickerOptions.layoutRes, contentContainer); |
| | | |
| | | //顶部标题 |
| | | TextView tvTitle = (TextView) findViewById(R.id.tvTitle); |
| | | RelativeLayout rv_top_bar = (RelativeLayout) findViewById(R.id.rv_topbar); |
| | | |
| | | //确定和取消按钮 |
| | | Button btnSubmit = (Button) findViewById(R.id.btnSubmit); |
| | | Button btnCancel = (Button) findViewById(R.id.btnCancel); |
| | | |
| | | btnSubmit.setTag(TAG_SUBMIT); |
| | | btnCancel.setTag(TAG_CANCEL); |
| | | btnSubmit.setOnClickListener(this); |
| | | btnCancel.setOnClickListener(this); |
| | | |
| | | //设置文字 |
| | | btnSubmit.setText(TextUtils.isEmpty(mPickerOptions.textContentConfirm) ? context.getResources().getString(R.string.pickerview_submit) : mPickerOptions.textContentConfirm); |
| | | btnCancel.setText(TextUtils.isEmpty(mPickerOptions.textContentCancel) ? context.getResources().getString(R.string.pickerview_cancel) : mPickerOptions.textContentCancel); |
| | | tvTitle.setText(TextUtils.isEmpty(mPickerOptions.textContentTitle) ? "" : mPickerOptions.textContentTitle);//默认为空 |
| | | |
| | | //设置color |
| | | btnSubmit.setTextColor(mPickerOptions.textColorConfirm); |
| | | btnCancel.setTextColor(mPickerOptions.textColorCancel); |
| | | tvTitle.setTextColor(mPickerOptions.textColorTitle); |
| | | rv_top_bar.setBackgroundColor(mPickerOptions.bgColorTitle); |
| | | |
| | | //设置文字大小 |
| | | btnSubmit.setTextSize(mPickerOptions.textSizeSubmitCancel); |
| | | btnCancel.setTextSize(mPickerOptions.textSizeSubmitCancel); |
| | | tvTitle.setTextSize(mPickerOptions.textSizeTitle); |
| | | } else { |
| | | mPickerOptions.customListener.customLayout(LayoutInflater.from(context).inflate(mPickerOptions.layoutRes, contentContainer)); |
| | | } |
| | | |
| | | // ----滚轮布局 |
| | | final LinearLayout optionsPicker = (LinearLayout) findViewById(R.id.optionspicker); |
| | | optionsPicker.setBackgroundColor(mPickerOptions.bgColorWheel); |
| | | |
| | | wheelOptions = new WheelOptions<>(optionsPicker, mPickerOptions.isRestoreItem); |
| | | if (mPickerOptions.optionsSelectChangeListener != null) { |
| | | wheelOptions.setOptionsSelectChangeListener(mPickerOptions.optionsSelectChangeListener); |
| | | } |
| | | |
| | | wheelOptions.setTextContentSize(mPickerOptions.textSizeContent); |
| | | wheelOptions.setItemsVisible(mPickerOptions.itemsVisibleCount); |
| | | wheelOptions.setAlphaGradient(mPickerOptions.isAlphaGradient); |
| | | wheelOptions.setLabels(mPickerOptions.label1, mPickerOptions.label2, mPickerOptions.label3); |
| | | wheelOptions.setTextXOffset(mPickerOptions.x_offset_one, mPickerOptions.x_offset_two, mPickerOptions.x_offset_three); |
| | | wheelOptions.setCyclic(mPickerOptions.cyclic1, mPickerOptions.cyclic2, mPickerOptions.cyclic3); |
| | | wheelOptions.setTypeface(mPickerOptions.font); |
| | | |
| | | setOutSideCancelable(mPickerOptions.cancelable); |
| | | |
| | | wheelOptions.setDividerColor(mPickerOptions.dividerColor); |
| | | wheelOptions.setDividerType(mPickerOptions.dividerType); |
| | | wheelOptions.setLineSpacingMultiplier(mPickerOptions.lineSpacingMultiplier); |
| | | wheelOptions.setTextColorOut(mPickerOptions.textColorOut); |
| | | wheelOptions.setTextColorCenter(mPickerOptions.textColorCenter); |
| | | wheelOptions.isCenterLabel(mPickerOptions.isCenterLabel); |
| | | } |
| | | |
| | | /** |
| | | * 动态设置标题 |
| | | * |
| | | * @param text 标题文本内容 |
| | | */ |
| | | public void setTitleText(String text) { |
| | | TextView tvTitle = (TextView) findViewById(R.id.tvTitle); |
| | | if (tvTitle != null) { |
| | | tvTitle.setText(text); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置默认选中项 |
| | | * |
| | | * @param option1 |
| | | */ |
| | | public void setSelectOptions(int option1) { |
| | | mPickerOptions.option1 = option1; |
| | | reSetCurrentItems(); |
| | | } |
| | | |
| | | |
| | | public void setSelectOptions(int option1, int option2) { |
| | | mPickerOptions.option1 = option1; |
| | | mPickerOptions.option2 = option2; |
| | | reSetCurrentItems(); |
| | | } |
| | | |
| | | public void setSelectOptions(int option1, int option2, int option3) { |
| | | mPickerOptions.option1 = option1; |
| | | mPickerOptions.option2 = option2; |
| | | mPickerOptions.option3 = option3; |
| | | reSetCurrentItems(); |
| | | } |
| | | |
| | | private void reSetCurrentItems() { |
| | | if (wheelOptions != null) { |
| | | wheelOptions.setCurrentItems(mPickerOptions.option1, mPickerOptions.option2, mPickerOptions.option3); |
| | | } |
| | | } |
| | | |
| | | public void setPicker(List<T> optionsItems) { |
| | | this.setPicker(optionsItems, null, null); |
| | | } |
| | | |
| | | public void setPicker(List<T> options1Items, List<List<T>> options2Items) { |
| | | this.setPicker(options1Items, options2Items, null); |
| | | } |
| | | |
| | | public void setPicker(List<T> options1Items, |
| | | List<List<T>> options2Items, |
| | | List<List<List<T>>> options3Items) { |
| | | |
| | | wheelOptions.setPicker(options1Items, options2Items, options3Items); |
| | | reSetCurrentItems(); |
| | | } |
| | | |
| | | |
| | | //不联动情况下调用 |
| | | public void setNPicker(List<T> options1Items, |
| | | List<T> options2Items, |
| | | List<T> options3Items) { |
| | | |
| | | wheelOptions.setLinkage(false); |
| | | wheelOptions.setNPicker(options1Items, options2Items, options3Items); |
| | | reSetCurrentItems(); |
| | | } |
| | | |
| | | @Override |
| | | public void onClick(View v) { |
| | | String tag = (String) v.getTag(); |
| | | if (tag.equals(TAG_SUBMIT)) { |
| | | returnData(); |
| | | } else if (tag.equals(TAG_CANCEL)) { |
| | | if (mPickerOptions.cancelListener != null) { |
| | | mPickerOptions.cancelListener.onClick(v); |
| | | } |
| | | } |
| | | dismiss(); |
| | | } |
| | | |
| | | //抽离接口回调的方法 |
| | | public void returnData() { |
| | | if (mPickerOptions.optionsSelectListener != null) { |
| | | int[] optionsCurrentItems = wheelOptions.getCurrentItems(); |
| | | mPickerOptions.optionsSelectListener.onOptionsSelect(optionsCurrentItems[0], optionsCurrentItems[1], optionsCurrentItems[2], clickView); |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public boolean isDialog() { |
| | | return mPickerOptions.isDialog; |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.view; |
| | | |
| | | import android.content.Context; |
| | | import android.text.TextUtils; |
| | | import android.view.LayoutInflater; |
| | | import android.view.View; |
| | | import android.widget.Button; |
| | | import android.widget.LinearLayout; |
| | | import android.widget.RelativeLayout; |
| | | import android.widget.TextView; |
| | | |
| | | import com.bigkoo.pickerview.configure.PickerOptions; |
| | | import com.bigkoo.pickerview.listener.ISelectTimeCallback; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | import java.text.ParseException; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 时间选择器 |
| | | * Created by Sai on 15/11/22. |
| | | * Updated by XiaoSong on 2017-2-22. |
| | | */ |
| | | public class TimePickerView extends BasePickerView implements View.OnClickListener { |
| | | |
| | | private WheelTime wheelTime; //自定义控件 |
| | | private static final String TAG_SUBMIT = "submit"; |
| | | private static final String TAG_CANCEL = "cancel"; |
| | | |
| | | public TimePickerView(PickerOptions pickerOptions) { |
| | | super(pickerOptions.context); |
| | | mPickerOptions = pickerOptions; |
| | | initView(pickerOptions.context); |
| | | } |
| | | |
| | | private void initView(Context context) { |
| | | setDialogOutSideCancelable(); |
| | | initViews(); |
| | | initAnim(); |
| | | |
| | | if (mPickerOptions.customListener == null) { |
| | | LayoutInflater.from(context).inflate(R.layout.pickerview_time, contentContainer); |
| | | |
| | | //顶部标题 |
| | | TextView tvTitle = (TextView) findViewById(R.id.tvTitle); |
| | | RelativeLayout rv_top_bar = (RelativeLayout) findViewById(R.id.rv_topbar); |
| | | |
| | | //确定和取消按钮 |
| | | Button btnSubmit = (Button) findViewById(R.id.btnSubmit); |
| | | Button btnCancel = (Button) findViewById(R.id.btnCancel); |
| | | |
| | | btnSubmit.setTag(TAG_SUBMIT); |
| | | btnCancel.setTag(TAG_CANCEL); |
| | | |
| | | btnSubmit.setOnClickListener(this); |
| | | btnCancel.setOnClickListener(this); |
| | | |
| | | //设置文字 |
| | | btnSubmit.setText(TextUtils.isEmpty(mPickerOptions.textContentConfirm) ? context.getResources().getString(R.string.pickerview_submit) : mPickerOptions.textContentConfirm); |
| | | btnCancel.setText(TextUtils.isEmpty(mPickerOptions.textContentCancel) ? context.getResources().getString(R.string.pickerview_cancel) : mPickerOptions.textContentCancel); |
| | | tvTitle.setText(TextUtils.isEmpty(mPickerOptions.textContentTitle) ? "" : mPickerOptions.textContentTitle);//默认为空 |
| | | |
| | | //设置color |
| | | btnSubmit.setTextColor(mPickerOptions.textColorConfirm); |
| | | btnCancel.setTextColor(mPickerOptions.textColorCancel); |
| | | tvTitle.setTextColor(mPickerOptions.textColorTitle); |
| | | rv_top_bar.setBackgroundColor(mPickerOptions.bgColorTitle); |
| | | |
| | | //设置文字大小 |
| | | btnSubmit.setTextSize(mPickerOptions.textSizeSubmitCancel); |
| | | btnCancel.setTextSize(mPickerOptions.textSizeSubmitCancel); |
| | | tvTitle.setTextSize(mPickerOptions.textSizeTitle); |
| | | |
| | | } else { |
| | | mPickerOptions.customListener.customLayout(LayoutInflater.from(context).inflate(mPickerOptions.layoutRes, contentContainer)); |
| | | } |
| | | // 时间转轮 自定义控件 |
| | | LinearLayout timePickerView = (LinearLayout) findViewById(R.id.timepicker); |
| | | timePickerView.setBackgroundColor(mPickerOptions.bgColorWheel); |
| | | |
| | | initWheelTime(timePickerView); |
| | | } |
| | | |
| | | private void initWheelTime(LinearLayout timePickerView) { |
| | | wheelTime = new WheelTime(timePickerView, mPickerOptions.type, mPickerOptions.textGravity, mPickerOptions.textSizeContent); |
| | | if (mPickerOptions.timeSelectChangeListener != null) { |
| | | wheelTime.setSelectChangeCallback(new ISelectTimeCallback() { |
| | | @Override |
| | | public void onTimeSelectChanged() { |
| | | try { |
| | | Date date = WheelTime.dateFormat.parse(wheelTime.getTime()); |
| | | mPickerOptions.timeSelectChangeListener.onTimeSelectChanged(date); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | wheelTime.setLunarMode(mPickerOptions.isLunarCalendar); |
| | | |
| | | if (mPickerOptions.startYear != 0 && mPickerOptions.endYear != 0 |
| | | && mPickerOptions.startYear <= mPickerOptions.endYear) { |
| | | setRange(); |
| | | } |
| | | |
| | | //若手动设置了时间范围限制 |
| | | if (mPickerOptions.startDate != null && mPickerOptions.endDate != null) { |
| | | if (mPickerOptions.startDate.getTimeInMillis() > mPickerOptions.endDate.getTimeInMillis()) { |
| | | throw new IllegalArgumentException("startDate can't be later than endDate"); |
| | | } else { |
| | | setRangDate(); |
| | | } |
| | | } else if (mPickerOptions.startDate != null) { |
| | | if (mPickerOptions.startDate.get(Calendar.YEAR) < 1900) { |
| | | throw new IllegalArgumentException("The startDate can not as early as 1900"); |
| | | } else { |
| | | setRangDate(); |
| | | } |
| | | } else if (mPickerOptions.endDate != null) { |
| | | if (mPickerOptions.endDate.get(Calendar.YEAR) > 2100) { |
| | | throw new IllegalArgumentException("The endDate should not be later than 2100"); |
| | | } else { |
| | | setRangDate(); |
| | | } |
| | | } else {//没有设置时间范围限制,则会使用默认范围。 |
| | | setRangDate(); |
| | | } |
| | | |
| | | setTime(); |
| | | wheelTime.setLabels(mPickerOptions.label_year, mPickerOptions.label_month, mPickerOptions.label_day |
| | | , mPickerOptions.label_hours, mPickerOptions.label_minutes, mPickerOptions.label_seconds); |
| | | wheelTime.setTextXOffset(mPickerOptions.x_offset_year, mPickerOptions.x_offset_month, mPickerOptions.x_offset_day, |
| | | mPickerOptions.x_offset_hours, mPickerOptions.x_offset_minutes, mPickerOptions.x_offset_seconds); |
| | | wheelTime.setItemsVisible(mPickerOptions.itemsVisibleCount); |
| | | wheelTime.setAlphaGradient(mPickerOptions.isAlphaGradient); |
| | | setOutSideCancelable(mPickerOptions.cancelable); |
| | | wheelTime.setCyclic(mPickerOptions.cyclic); |
| | | wheelTime.setDividerColor(mPickerOptions.dividerColor); |
| | | wheelTime.setDividerType(mPickerOptions.dividerType); |
| | | wheelTime.setLineSpacingMultiplier(mPickerOptions.lineSpacingMultiplier); |
| | | wheelTime.setTextColorOut(mPickerOptions.textColorOut); |
| | | wheelTime.setTextColorCenter(mPickerOptions.textColorCenter); |
| | | wheelTime.isCenterLabel(mPickerOptions.isCenterLabel); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置默认时间 |
| | | */ |
| | | public void setDate(Calendar date) { |
| | | mPickerOptions.date = date; |
| | | setTime(); |
| | | } |
| | | |
| | | /** |
| | | * 设置可以选择的时间范围, 要在setTime之前调用才有效果 |
| | | */ |
| | | private void setRange() { |
| | | wheelTime.setStartYear(mPickerOptions.startYear); |
| | | wheelTime.setEndYear(mPickerOptions.endYear); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 设置可以选择的时间范围, 要在setTime之前调用才有效果 |
| | | */ |
| | | private void setRangDate() { |
| | | wheelTime.setRangDate(mPickerOptions.startDate, mPickerOptions.endDate); |
| | | initDefaultSelectedDate(); |
| | | } |
| | | |
| | | private void initDefaultSelectedDate() { |
| | | //如果手动设置了时间范围 |
| | | if (mPickerOptions.startDate != null && mPickerOptions.endDate != null) { |
| | | //若默认时间未设置,或者设置的默认时间越界了,则设置默认选中时间为开始时间。 |
| | | if (mPickerOptions.date == null || mPickerOptions.date.getTimeInMillis() < mPickerOptions.startDate.getTimeInMillis() |
| | | || mPickerOptions.date.getTimeInMillis() > mPickerOptions.endDate.getTimeInMillis()) { |
| | | mPickerOptions.date = mPickerOptions.startDate; |
| | | } |
| | | } else if (mPickerOptions.startDate != null) { |
| | | //没有设置默认选中时间,那就拿开始时间当默认时间 |
| | | mPickerOptions.date = mPickerOptions.startDate; |
| | | } else if (mPickerOptions.endDate != null) { |
| | | mPickerOptions.date = mPickerOptions.endDate; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置选中时间,默认选中当前时间 |
| | | */ |
| | | private void setTime() { |
| | | int year, month, day, hours, minute, seconds; |
| | | Calendar calendar = Calendar.getInstance(); |
| | | |
| | | if (mPickerOptions.date == null) { |
| | | calendar.setTimeInMillis(System.currentTimeMillis()); |
| | | year = calendar.get(Calendar.YEAR); |
| | | month = calendar.get(Calendar.MONTH); |
| | | day = calendar.get(Calendar.DAY_OF_MONTH); |
| | | hours = calendar.get(Calendar.HOUR_OF_DAY); |
| | | minute = calendar.get(Calendar.MINUTE); |
| | | seconds = calendar.get(Calendar.SECOND); |
| | | } else { |
| | | year = mPickerOptions.date.get(Calendar.YEAR); |
| | | month = mPickerOptions.date.get(Calendar.MONTH); |
| | | day = mPickerOptions.date.get(Calendar.DAY_OF_MONTH); |
| | | hours = mPickerOptions.date.get(Calendar.HOUR_OF_DAY); |
| | | minute = mPickerOptions.date.get(Calendar.MINUTE); |
| | | seconds = mPickerOptions.date.get(Calendar.SECOND); |
| | | } |
| | | |
| | | wheelTime.setPicker(year, month, day, hours, minute, seconds); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void onClick(View v) { |
| | | String tag = (String) v.getTag(); |
| | | if (tag.equals(TAG_SUBMIT)) { |
| | | returnData(); |
| | | } else if (tag.equals(TAG_CANCEL)) { |
| | | if (mPickerOptions.cancelListener != null) { |
| | | mPickerOptions.cancelListener.onClick(v); |
| | | } |
| | | } |
| | | dismiss(); |
| | | } |
| | | |
| | | public void returnData() { |
| | | if (mPickerOptions.timeSelectListener != null) { |
| | | try { |
| | | Date date = WheelTime.dateFormat.parse(wheelTime.getTime()); |
| | | mPickerOptions.timeSelectListener.onTimeSelect(date, clickView); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 动态设置标题 |
| | | * |
| | | * @param text 标题文本内容 |
| | | */ |
| | | public void setTitleText(String text) { |
| | | TextView tvTitle = (TextView) findViewById(R.id.tvTitle); |
| | | if (tvTitle != null) { |
| | | tvTitle.setText(text); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 目前暂时只支持设置1900 - 2100年 |
| | | * |
| | | * @param lunar 农历的开关 |
| | | */ |
| | | public void setLunarCalendar(boolean lunar) { |
| | | try { |
| | | int year, month, day, hours, minute, seconds; |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(WheelTime.dateFormat.parse(wheelTime.getTime())); |
| | | year = calendar.get(Calendar.YEAR); |
| | | month = calendar.get(Calendar.MONTH); |
| | | day = calendar.get(Calendar.DAY_OF_MONTH); |
| | | hours = calendar.get(Calendar.HOUR_OF_DAY); |
| | | minute = calendar.get(Calendar.MINUTE); |
| | | seconds = calendar.get(Calendar.SECOND); |
| | | |
| | | wheelTime.setLunarMode(lunar); |
| | | wheelTime.setLabels(mPickerOptions.label_year, mPickerOptions.label_month, mPickerOptions.label_day, |
| | | mPickerOptions.label_hours, mPickerOptions.label_minutes, mPickerOptions.label_seconds); |
| | | wheelTime.setPicker(year, month, day, hours, minute, seconds); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | public boolean isLunarCalendar() { |
| | | return wheelTime.isLunarMode(); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public boolean isDialog() { |
| | | return mPickerOptions.isDialog; |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.view; |
| | | |
| | | import android.graphics.Typeface; |
| | | import android.view.View; |
| | | |
| | | import com.bigkoo.pickerview.adapter.ArrayWheelAdapter; |
| | | import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener; |
| | | import com.contrarywind.listener.OnItemSelectedListener; |
| | | import com.contrarywind.view.WheelView; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | import java.util.List; |
| | | |
| | | public class WheelOptions<T> { |
| | | private View view; |
| | | private WheelView wv_option1; |
| | | private WheelView wv_option2; |
| | | private WheelView wv_option3; |
| | | |
| | | private List<T> mOptions1Items; |
| | | private List<List<T>> mOptions2Items; |
| | | private List<List<List<T>>> mOptions3Items; |
| | | |
| | | private boolean linkage = true;//默认联动 |
| | | private boolean isRestoreItem; //切换时,还原第一项 |
| | | private OnItemSelectedListener wheelListener_option1; |
| | | private OnItemSelectedListener wheelListener_option2; |
| | | |
| | | private OnOptionsSelectChangeListener optionsSelectChangeListener; |
| | | |
| | | public View getView() { |
| | | return view; |
| | | } |
| | | |
| | | public void setView(View view) { |
| | | this.view = view; |
| | | } |
| | | |
| | | public WheelOptions(View view, boolean isRestoreItem) { |
| | | super(); |
| | | this.isRestoreItem = isRestoreItem; |
| | | this.view = view; |
| | | wv_option1 = (WheelView) view.findViewById(R.id.options1);// 初始化时显示的数据 |
| | | wv_option2 = (WheelView) view.findViewById(R.id.options2); |
| | | wv_option3 = (WheelView) view.findViewById(R.id.options3); |
| | | } |
| | | |
| | | |
| | | public void setPicker(List<T> options1Items, |
| | | List<List<T>> options2Items, |
| | | List<List<List<T>>> options3Items) { |
| | | this.mOptions1Items = options1Items; |
| | | this.mOptions2Items = options2Items; |
| | | this.mOptions3Items = options3Items; |
| | | |
| | | // 选项1 |
| | | wv_option1.setAdapter(new ArrayWheelAdapter(mOptions1Items));// 设置显示数据 |
| | | wv_option1.setCurrentItem(0);// 初始化时显示的数据 |
| | | // 选项2 |
| | | if (mOptions2Items != null) { |
| | | wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(0)));// 设置显示数据 |
| | | } |
| | | wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 初始化时显示的数据 |
| | | // 选项3 |
| | | if (mOptions3Items != null) { |
| | | wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(0).get(0)));// 设置显示数据 |
| | | } |
| | | wv_option3.setCurrentItem(wv_option3.getCurrentItem()); |
| | | wv_option1.setIsOptions(true); |
| | | wv_option2.setIsOptions(true); |
| | | wv_option3.setIsOptions(true); |
| | | |
| | | if (this.mOptions2Items == null) { |
| | | wv_option2.setVisibility(View.GONE); |
| | | } else { |
| | | wv_option2.setVisibility(View.VISIBLE); |
| | | } |
| | | if (this.mOptions3Items == null) { |
| | | wv_option3.setVisibility(View.GONE); |
| | | } else { |
| | | wv_option3.setVisibility(View.VISIBLE); |
| | | } |
| | | |
| | | // 联动监听器 |
| | | wheelListener_option1 = new OnItemSelectedListener() { |
| | | |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | int opt2Select = 0; |
| | | if (mOptions2Items == null) {//只有1级联动数据 |
| | | if (optionsSelectChangeListener != null) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), 0, 0); |
| | | } |
| | | } else { |
| | | if (!isRestoreItem) { |
| | | opt2Select = wv_option2.getCurrentItem();//上一个opt2的选中位置 |
| | | //新opt2的位置,判断如果旧位置没有超过数据范围,则沿用旧位置,否则选中最后一项 |
| | | opt2Select = opt2Select >= mOptions2Items.get(index).size() - 1 ? mOptions2Items.get(index).size() - 1 : opt2Select; |
| | | } |
| | | wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(index))); |
| | | wv_option2.setCurrentItem(opt2Select); |
| | | |
| | | if (mOptions3Items != null) { |
| | | wheelListener_option2.onItemSelected(opt2Select); |
| | | } else {//只有2级联动数据,滑动第1项回调 |
| | | if (optionsSelectChangeListener != null) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(index, opt2Select, 0); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | wheelListener_option2 = new OnItemSelectedListener() { |
| | | |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | if (mOptions3Items != null) { |
| | | int opt1Select = wv_option1.getCurrentItem(); |
| | | opt1Select = opt1Select >= mOptions3Items.size() - 1 ? mOptions3Items.size() - 1 : opt1Select; |
| | | index = index >= mOptions2Items.get(opt1Select).size() - 1 ? mOptions2Items.get(opt1Select).size() - 1 : index; |
| | | int opt3 = 0; |
| | | if (!isRestoreItem) { |
| | | // wv_option3.getCurrentItem() 上一个opt3的选中位置 |
| | | //新opt3的位置,判断如果旧位置没有超过数据范围,则沿用旧位置,否则选中最后一项 |
| | | opt3 = wv_option3.getCurrentItem() >= mOptions3Items.get(opt1Select).get(index).size() - 1 ? |
| | | mOptions3Items.get(opt1Select).get(index).size() - 1 : wv_option3.getCurrentItem(); |
| | | } |
| | | wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(wv_option1.getCurrentItem()).get(index))); |
| | | wv_option3.setCurrentItem(opt3); |
| | | |
| | | //3级联动数据实时回调 |
| | | if (optionsSelectChangeListener != null) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, opt3); |
| | | } |
| | | } else {//只有2级联动数据,滑动第2项回调 |
| | | if (optionsSelectChangeListener != null) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, 0); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 添加联动监听 |
| | | if (options1Items != null && linkage) { |
| | | wv_option1.setOnItemSelectedListener(wheelListener_option1); |
| | | } |
| | | if (options2Items != null && linkage) { |
| | | wv_option2.setOnItemSelectedListener(wheelListener_option2); |
| | | } |
| | | if (options3Items != null && linkage && optionsSelectChangeListener != null) { |
| | | wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | |
| | | //不联动情况下 |
| | | public void setNPicker(List<T> options1Items, List<T> options2Items, List<T> options3Items) { |
| | | |
| | | // 选项1 |
| | | wv_option1.setAdapter(new ArrayWheelAdapter<>(options1Items));// 设置显示数据 |
| | | wv_option1.setCurrentItem(0);// 初始化时显示的数据 |
| | | // 选项2 |
| | | if (options2Items != null) { |
| | | wv_option2.setAdapter(new ArrayWheelAdapter<>(options2Items));// 设置显示数据 |
| | | } |
| | | wv_option2.setCurrentItem(wv_option2.getCurrentItem());// 初始化时显示的数据 |
| | | // 选项3 |
| | | if (options3Items != null) { |
| | | wv_option3.setAdapter(new ArrayWheelAdapter<>(options3Items));// 设置显示数据 |
| | | } |
| | | wv_option3.setCurrentItem(wv_option3.getCurrentItem()); |
| | | wv_option1.setIsOptions(true); |
| | | wv_option2.setIsOptions(true); |
| | | wv_option3.setIsOptions(true); |
| | | |
| | | if (optionsSelectChangeListener != null) { |
| | | wv_option1.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(index, wv_option2.getCurrentItem(), wv_option3.getCurrentItem()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | if (options2Items == null) { |
| | | wv_option2.setVisibility(View.GONE); |
| | | } else { |
| | | wv_option2.setVisibility(View.VISIBLE); |
| | | if (optionsSelectChangeListener != null) { |
| | | wv_option2.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), index, wv_option3.getCurrentItem()); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | if (options3Items == null) { |
| | | wv_option3.setVisibility(View.GONE); |
| | | } else { |
| | | wv_option3.setVisibility(View.VISIBLE); |
| | | if (optionsSelectChangeListener != null) { |
| | | wv_option3.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | optionsSelectChangeListener.onOptionsSelectChanged(wv_option1.getCurrentItem(), wv_option2.getCurrentItem(), index); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void setTextContentSize(int textSize) { |
| | | wv_option1.setTextSize(textSize); |
| | | wv_option2.setTextSize(textSize); |
| | | wv_option3.setTextSize(textSize); |
| | | } |
| | | |
| | | private void setLineSpacingMultiplier() { |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 设置选项的单位 |
| | | * |
| | | * @param label1 单位 |
| | | * @param label2 单位 |
| | | * @param label3 单位 |
| | | */ |
| | | public void setLabels(String label1, String label2, String label3) { |
| | | if (label1 != null) { |
| | | wv_option1.setLabel(label1); |
| | | } |
| | | if (label2 != null) { |
| | | wv_option2.setLabel(label2); |
| | | } |
| | | if (label3 != null) { |
| | | wv_option3.setLabel(label3); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置x轴偏移量 |
| | | */ |
| | | public void setTextXOffset(int x_offset_one, int x_offset_two, int x_offset_three) { |
| | | wv_option1.setTextXOffset(x_offset_one); |
| | | wv_option2.setTextXOffset(x_offset_two); |
| | | wv_option3.setTextXOffset(x_offset_three); |
| | | } |
| | | |
| | | /** |
| | | * 设置是否循环滚动 |
| | | * |
| | | * @param cyclic 是否循环 |
| | | */ |
| | | public void setCyclic(boolean cyclic) { |
| | | wv_option1.setCyclic(cyclic); |
| | | wv_option2.setCyclic(cyclic); |
| | | wv_option3.setCyclic(cyclic); |
| | | } |
| | | |
| | | /** |
| | | * 设置字体样式 |
| | | * |
| | | * @param font 系统提供的几种样式 |
| | | */ |
| | | public void setTypeface(Typeface font) { |
| | | wv_option1.setTypeface(font); |
| | | wv_option2.setTypeface(font); |
| | | wv_option3.setTypeface(font); |
| | | } |
| | | |
| | | /** |
| | | * 分别设置第一二三级是否循环滚动 |
| | | * |
| | | * @param cyclic1,cyclic2,cyclic3 是否循环 |
| | | */ |
| | | public void setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) { |
| | | wv_option1.setCyclic(cyclic1); |
| | | wv_option2.setCyclic(cyclic2); |
| | | wv_option3.setCyclic(cyclic3); |
| | | } |
| | | |
| | | /** |
| | | * 返回当前选中的结果对应的位置数组 因为支持三级联动效果,分三个级别索引,0,1,2。 |
| | | * 在快速滑动未停止时,点击确定按钮,会进行判断,如果匹配数据越界,则设为0,防止index出错导致崩溃。 |
| | | * |
| | | * @return 索引数组 |
| | | */ |
| | | public int[] getCurrentItems() { |
| | | int[] currentItems = new int[3]; |
| | | currentItems[0] = wv_option1.getCurrentItem(); |
| | | |
| | | if (mOptions2Items != null && mOptions2Items.size() > 0) {//非空判断 |
| | | currentItems[1] = wv_option2.getCurrentItem() > (mOptions2Items.get(currentItems[0]).size() - 1) ? 0 : wv_option2.getCurrentItem(); |
| | | } else { |
| | | currentItems[1] = wv_option2.getCurrentItem(); |
| | | } |
| | | |
| | | if (mOptions3Items != null && mOptions3Items.size() > 0) {//非空判断 |
| | | currentItems[2] = wv_option3.getCurrentItem() > (mOptions3Items.get(currentItems[0]).get(currentItems[1]).size() - 1) ? 0 : wv_option3.getCurrentItem(); |
| | | } else { |
| | | currentItems[2] = wv_option3.getCurrentItem(); |
| | | } |
| | | |
| | | return currentItems; |
| | | } |
| | | |
| | | public void setCurrentItems(int option1, int option2, int option3) { |
| | | if (linkage) { |
| | | itemSelected(option1, option2, option3); |
| | | } else { |
| | | wv_option1.setCurrentItem(option1); |
| | | wv_option2.setCurrentItem(option2); |
| | | wv_option3.setCurrentItem(option3); |
| | | } |
| | | } |
| | | |
| | | private void itemSelected(int opt1Select, int opt2Select, int opt3Select) { |
| | | if (mOptions1Items != null) { |
| | | wv_option1.setCurrentItem(opt1Select); |
| | | } |
| | | if (mOptions2Items != null) { |
| | | wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(opt1Select))); |
| | | wv_option2.setCurrentItem(opt2Select); |
| | | } |
| | | if (mOptions3Items != null) { |
| | | wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(opt1Select).get(opt2Select))); |
| | | wv_option3.setCurrentItem(opt3Select); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置间距倍数,但是只能在1.2-4.0f之间 |
| | | * |
| | | * @param lineSpacingMultiplier |
| | | */ |
| | | public void setLineSpacingMultiplier(float lineSpacingMultiplier) { |
| | | wv_option1.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_option2.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_option3.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线的颜色 |
| | | * |
| | | * @param dividerColor |
| | | */ |
| | | public void setDividerColor(int dividerColor) { |
| | | wv_option1.setDividerColor(dividerColor); |
| | | wv_option2.setDividerColor(dividerColor); |
| | | wv_option3.setDividerColor(dividerColor); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线的类型 |
| | | * |
| | | * @param dividerType |
| | | */ |
| | | public void setDividerType(WheelView.DividerType dividerType) { |
| | | wv_option1.setDividerType(dividerType); |
| | | wv_option2.setDividerType(dividerType); |
| | | wv_option3.setDividerType(dividerType); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线之间的文字的颜色 |
| | | * |
| | | * @param textColorCenter |
| | | */ |
| | | public void setTextColorCenter(int textColorCenter) { |
| | | wv_option1.setTextColorCenter(textColorCenter); |
| | | wv_option2.setTextColorCenter(textColorCenter); |
| | | wv_option3.setTextColorCenter(textColorCenter); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线以外文字的颜色 |
| | | * |
| | | * @param textColorOut |
| | | */ |
| | | public void setTextColorOut(int textColorOut) { |
| | | wv_option1.setTextColorOut(textColorOut); |
| | | wv_option2.setTextColorOut(textColorOut); |
| | | wv_option3.setTextColorOut(textColorOut); |
| | | } |
| | | |
| | | /** |
| | | * Label 是否只显示中间选中项的 |
| | | * |
| | | * @param isCenterLabel |
| | | */ |
| | | public void isCenterLabel(boolean isCenterLabel) { |
| | | wv_option1.isCenterLabel(isCenterLabel); |
| | | wv_option2.isCenterLabel(isCenterLabel); |
| | | wv_option3.isCenterLabel(isCenterLabel); |
| | | } |
| | | |
| | | public void setOptionsSelectChangeListener(OnOptionsSelectChangeListener optionsSelectChangeListener) { |
| | | this.optionsSelectChangeListener = optionsSelectChangeListener; |
| | | } |
| | | |
| | | public void setLinkage(boolean linkage) { |
| | | this.linkage = linkage; |
| | | } |
| | | |
| | | /** |
| | | * 设置最大可见数目 |
| | | * |
| | | * @param itemsVisible 建议设置为 3 ~ 9之间。 |
| | | */ |
| | | public void setItemsVisible(int itemsVisible) { |
| | | wv_option1.setItemsVisibleCount(itemsVisible); |
| | | wv_option2.setItemsVisibleCount(itemsVisible); |
| | | wv_option3.setItemsVisibleCount(itemsVisible); |
| | | } |
| | | |
| | | public void setAlphaGradient(boolean isAlphaGradient) { |
| | | wv_option1.setAlphaGradient(isAlphaGradient); |
| | | wv_option2.setAlphaGradient(isAlphaGradient); |
| | | wv_option3.setAlphaGradient(isAlphaGradient); |
| | | } |
| | | } |
New file |
| | |
| | | package com.bigkoo.pickerview.view; |
| | | |
| | | import android.view.View; |
| | | |
| | | import com.bigkoo.pickerview.adapter.ArrayWheelAdapter; |
| | | import com.bigkoo.pickerview.adapter.NumericWheelAdapter; |
| | | import com.bigkoo.pickerview.listener.ISelectTimeCallback; |
| | | import com.bigkoo.pickerview.utils.ChinaDate; |
| | | import com.bigkoo.pickerview.utils.LunarCalendar; |
| | | import com.contrarywind.listener.OnItemSelectedListener; |
| | | import com.contrarywind.view.WheelView; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | import java.text.DateFormat; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Arrays; |
| | | import java.util.Calendar; |
| | | import java.util.List; |
| | | |
| | | |
| | | public class WheelTime { |
| | | public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | private View view; |
| | | private WheelView wv_year; |
| | | private WheelView wv_month; |
| | | private WheelView wv_day; |
| | | private WheelView wv_hours; |
| | | private WheelView wv_minutes; |
| | | private WheelView wv_seconds; |
| | | private int gravity; |
| | | |
| | | private boolean[] type; |
| | | private static final int DEFAULT_START_YEAR = 1900; |
| | | private static final int DEFAULT_END_YEAR = 2100; |
| | | private static final int DEFAULT_START_MONTH = 1; |
| | | private static final int DEFAULT_END_MONTH = 12; |
| | | private static final int DEFAULT_START_DAY = 1; |
| | | private static final int DEFAULT_END_DAY = 31; |
| | | |
| | | private int startYear = DEFAULT_START_YEAR; |
| | | private int endYear = DEFAULT_END_YEAR; |
| | | private int startMonth = DEFAULT_START_MONTH; |
| | | private int endMonth = DEFAULT_END_MONTH; |
| | | private int startDay = DEFAULT_START_DAY; |
| | | private int endDay = DEFAULT_END_DAY; //表示31天的 |
| | | private int currentYear; |
| | | |
| | | private int textSize; |
| | | |
| | | private boolean isLunarCalendar = false; |
| | | private ISelectTimeCallback mSelectChangeCallback; |
| | | |
| | | public WheelTime(View view, boolean[] type, int gravity, int textSize) { |
| | | super(); |
| | | this.view = view; |
| | | this.type = type; |
| | | this.gravity = gravity; |
| | | this.textSize = textSize; |
| | | } |
| | | |
| | | public void setLunarMode(boolean isLunarCalendar) { |
| | | this.isLunarCalendar = isLunarCalendar; |
| | | } |
| | | |
| | | public boolean isLunarMode() { |
| | | return isLunarCalendar; |
| | | } |
| | | |
| | | public void setPicker(int year, int month, int day) { |
| | | this.setPicker(year, month, day, 0, 0, 0); |
| | | } |
| | | |
| | | public void setPicker(int year, final int month, int day, int h, int m, int s) { |
| | | if (isLunarCalendar) { |
| | | int[] lunar = LunarCalendar.solarToLunar(year, month + 1, day); |
| | | setLunar(lunar[0], lunar[1] - 1, lunar[2], lunar[3] == 1, h, m, s); |
| | | } else { |
| | | setSolar(year, month, day, h, m, s); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置农历 |
| | | * |
| | | * @param year |
| | | * @param month |
| | | * @param day |
| | | * @param h |
| | | * @param m |
| | | * @param s |
| | | */ |
| | | private void setLunar(int year, final int month, int day, boolean isLeap, int h, int m, int s) { |
| | | // 年 |
| | | wv_year = (WheelView) view.findViewById(R.id.year); |
| | | wv_year.setAdapter(new ArrayWheelAdapter(ChinaDate.getYears(startYear, endYear)));// 设置"年"的显示数据 |
| | | wv_year.setLabel("");// 添加文字 |
| | | wv_year.setCurrentItem(year - startYear);// 初始化时显示的数据 |
| | | wv_year.setGravity(gravity); |
| | | |
| | | // 月 |
| | | wv_month = (WheelView) view.findViewById(R.id.month); |
| | | wv_month.setAdapter(new ArrayWheelAdapter(ChinaDate.getMonths(year))); |
| | | wv_month.setLabel(""); |
| | | |
| | | int leapMonth = ChinaDate.leapMonth(year); |
| | | if (leapMonth != 0 && (month > leapMonth - 1 || isLeap)) { //选中月是闰月或大于闰月 |
| | | wv_month.setCurrentItem(month + 1); |
| | | } else { |
| | | wv_month.setCurrentItem(month); |
| | | } |
| | | |
| | | wv_month.setGravity(gravity); |
| | | |
| | | // 日 |
| | | wv_day = (WheelView) view.findViewById(R.id.day); |
| | | // 判断大小月及是否闰年,用来确定"日"的数据 |
| | | if (ChinaDate.leapMonth(year) == 0) { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year, month)))); |
| | | } else { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.leapDays(year)))); |
| | | } |
| | | wv_day.setLabel(""); |
| | | wv_day.setCurrentItem(day - 1); |
| | | wv_day.setGravity(gravity); |
| | | |
| | | wv_hours = (WheelView) view.findViewById(R.id.hour); |
| | | wv_hours.setAdapter(new NumericWheelAdapter(0, 23)); |
| | | //wv_hours.setLabel(context.getString(R.string.pickerview_hours));// 添加文字 |
| | | wv_hours.setCurrentItem(h); |
| | | wv_hours.setGravity(gravity); |
| | | |
| | | wv_minutes = (WheelView) view.findViewById(R.id.min); |
| | | wv_minutes.setAdapter(new NumericWheelAdapter(0, 59)); |
| | | //wv_minutes.setLabel(context.getString(R.string.pickerview_minutes));// 添加文字 |
| | | wv_minutes.setCurrentItem(m); |
| | | wv_minutes.setGravity(gravity); |
| | | |
| | | wv_seconds = (WheelView) view.findViewById(R.id.second); |
| | | wv_seconds.setAdapter(new NumericWheelAdapter(0, 59)); |
| | | //wv_seconds.setLabel(context.getString(R.string.pickerview_minutes));// 添加文字 |
| | | wv_seconds.setCurrentItem(m); |
| | | wv_seconds.setGravity(gravity); |
| | | |
| | | // 添加"年"监听 |
| | | wv_year.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | int year_num = index + startYear; |
| | | // 判断是不是闰年,来确定月和日的选择 |
| | | wv_month.setAdapter(new ArrayWheelAdapter(ChinaDate.getMonths(year_num))); |
| | | if (ChinaDate.leapMonth(year_num) != 0 && wv_month.getCurrentItem() > ChinaDate.leapMonth(year_num) - 1) { |
| | | wv_month.setCurrentItem(wv_month.getCurrentItem() + 1); |
| | | } else { |
| | | wv_month.setCurrentItem(wv_month.getCurrentItem()); |
| | | } |
| | | |
| | | int currentIndex = wv_day.getCurrentItem(); |
| | | int maxItem = 29; |
| | | if (ChinaDate.leapMonth(year_num) != 0 && wv_month.getCurrentItem() > ChinaDate.leapMonth(year_num) - 1) { |
| | | if (wv_month.getCurrentItem() == ChinaDate.leapMonth(year_num) + 1) { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.leapDays(year_num)))); |
| | | maxItem = ChinaDate.leapDays(year_num); |
| | | } else { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, wv_month.getCurrentItem())))); |
| | | maxItem = ChinaDate.monthDays(year_num, wv_month.getCurrentItem()); |
| | | } |
| | | } else { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, wv_month.getCurrentItem() + 1)))); |
| | | maxItem = ChinaDate.monthDays(year_num, wv_month.getCurrentItem() + 1); |
| | | } |
| | | |
| | | if (currentIndex > maxItem - 1) { |
| | | wv_day.setCurrentItem(maxItem - 1); |
| | | } |
| | | |
| | | if (mSelectChangeCallback != null) { |
| | | mSelectChangeCallback.onTimeSelectChanged(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 添加"月"监听 |
| | | wv_month.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | int month_num = index; |
| | | int year_num = wv_year.getCurrentItem() + startYear; |
| | | int currentIndex = wv_day.getCurrentItem(); |
| | | int maxItem = 29; |
| | | if (ChinaDate.leapMonth(year_num) != 0 && month_num > ChinaDate.leapMonth(year_num) - 1) { |
| | | if (wv_month.getCurrentItem() == ChinaDate.leapMonth(year_num) + 1) { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.leapDays(year_num)))); |
| | | maxItem = ChinaDate.leapDays(year_num); |
| | | } else { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, month_num)))); |
| | | maxItem = ChinaDate.monthDays(year_num, month_num); |
| | | } |
| | | } else { |
| | | wv_day.setAdapter(new ArrayWheelAdapter(ChinaDate.getLunarDays(ChinaDate.monthDays(year_num, month_num + 1)))); |
| | | maxItem = ChinaDate.monthDays(year_num, month_num + 1); |
| | | } |
| | | |
| | | if (currentIndex > maxItem - 1) { |
| | | wv_day.setCurrentItem(maxItem - 1); |
| | | } |
| | | |
| | | if (mSelectChangeCallback != null) { |
| | | mSelectChangeCallback.onTimeSelectChanged(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | setChangedListener(wv_day); |
| | | setChangedListener(wv_hours); |
| | | setChangedListener(wv_minutes); |
| | | setChangedListener(wv_seconds); |
| | | |
| | | if (type.length != 6) { |
| | | throw new RuntimeException("type[] length is not 6"); |
| | | } |
| | | wv_year.setVisibility(type[0] ? View.VISIBLE : View.GONE); |
| | | wv_month.setVisibility(type[1] ? View.VISIBLE : View.GONE); |
| | | wv_day.setVisibility(type[2] ? View.VISIBLE : View.GONE); |
| | | wv_hours.setVisibility(type[3] ? View.VISIBLE : View.GONE); |
| | | wv_minutes.setVisibility(type[4] ? View.VISIBLE : View.GONE); |
| | | wv_seconds.setVisibility(type[5] ? View.VISIBLE : View.GONE); |
| | | setContentTextSize(); |
| | | } |
| | | |
| | | /** |
| | | * 设置公历 |
| | | * |
| | | * @param year |
| | | * @param month |
| | | * @param day |
| | | * @param h |
| | | * @param m |
| | | * @param s |
| | | */ |
| | | private void setSolar(int year, final int month, int day, int h, int m, int s) { |
| | | // 添加大小月月份并将其转换为list,方便之后的判断 |
| | | String[] months_big = {"1", "3", "5", "7", "8", "10", "12"}; |
| | | String[] months_little = {"4", "6", "9", "11"}; |
| | | |
| | | final List<String> list_big = Arrays.asList(months_big); |
| | | final List<String> list_little = Arrays.asList(months_little); |
| | | |
| | | currentYear = year; |
| | | // 年 |
| | | wv_year = (WheelView) view.findViewById(R.id.year); |
| | | wv_year.setAdapter(new NumericWheelAdapter(startYear, endYear));// 设置"年"的显示数据 |
| | | |
| | | |
| | | wv_year.setCurrentItem(year - startYear);// 初始化时显示的数据 |
| | | wv_year.setGravity(gravity); |
| | | // 月 |
| | | wv_month = (WheelView) view.findViewById(R.id.month); |
| | | if (startYear == endYear) {//开始年等于终止年 |
| | | wv_month.setAdapter(new NumericWheelAdapter(startMonth, endMonth)); |
| | | wv_month.setCurrentItem(month + 1 - startMonth); |
| | | } else if (year == startYear) { |
| | | //起始日期的月份控制 |
| | | wv_month.setAdapter(new NumericWheelAdapter(startMonth, 12)); |
| | | wv_month.setCurrentItem(month + 1 - startMonth); |
| | | } else if (year == endYear) { |
| | | //终止日期的月份控制 |
| | | wv_month.setAdapter(new NumericWheelAdapter(1, endMonth)); |
| | | wv_month.setCurrentItem(month); |
| | | } else { |
| | | wv_month.setAdapter(new NumericWheelAdapter(1, 12)); |
| | | wv_month.setCurrentItem(month); |
| | | } |
| | | wv_month.setGravity(gravity); |
| | | // 日 |
| | | wv_day = (WheelView) view.findViewById(R.id.day); |
| | | |
| | | boolean leapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; |
| | | if (startYear == endYear && startMonth == endMonth) { |
| | | if (list_big.contains(String.valueOf(month + 1))) { |
| | | if (endDay > 31) { |
| | | endDay = 31; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay)); |
| | | } else if (list_little.contains(String.valueOf(month + 1))) { |
| | | if (endDay > 30) { |
| | | endDay = 30; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay)); |
| | | } else { |
| | | // 闰年 |
| | | if (leapYear) { |
| | | if (endDay > 29) { |
| | | endDay = 29; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay)); |
| | | } else { |
| | | if (endDay > 28) { |
| | | endDay = 28; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, endDay)); |
| | | } |
| | | } |
| | | wv_day.setCurrentItem(day - startDay); |
| | | } else if (year == startYear && month + 1 == startMonth) { |
| | | // 起始日期的天数控制 |
| | | if (list_big.contains(String.valueOf(month + 1))) { |
| | | |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, 31)); |
| | | } else if (list_little.contains(String.valueOf(month + 1))) { |
| | | |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, 30)); |
| | | } else { |
| | | // 闰年 29,平年 28 |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, leapYear ? 29 : 28)); |
| | | } |
| | | wv_day.setCurrentItem(day - startDay); |
| | | } else if (year == endYear && month + 1 == endMonth) { |
| | | // 终止日期的天数控制 |
| | | if (list_big.contains(String.valueOf(month + 1))) { |
| | | if (endDay > 31) { |
| | | endDay = 31; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(1, endDay)); |
| | | } else if (list_little.contains(String.valueOf(month + 1))) { |
| | | if (endDay > 30) { |
| | | endDay = 30; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(1, endDay)); |
| | | } else { |
| | | // 闰年 |
| | | if (leapYear) { |
| | | if (endDay > 29) { |
| | | endDay = 29; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(1, endDay)); |
| | | } else { |
| | | if (endDay > 28) { |
| | | endDay = 28; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(1, endDay)); |
| | | } |
| | | } |
| | | wv_day.setCurrentItem(day - 1); |
| | | } else { |
| | | // 判断大小月及是否闰年,用来确定"日"的数据 |
| | | if (list_big.contains(String.valueOf(month + 1))) { |
| | | wv_day.setAdapter(new NumericWheelAdapter(1, 31)); |
| | | } else if (list_little.contains(String.valueOf(month + 1))) { |
| | | wv_day.setAdapter(new NumericWheelAdapter(1, 30)); |
| | | } else { |
| | | // 闰年 29,平年 28 |
| | | wv_day.setAdapter(new NumericWheelAdapter(startDay, leapYear ? 29 : 28)); |
| | | } |
| | | wv_day.setCurrentItem(day - 1); |
| | | } |
| | | |
| | | wv_day.setGravity(gravity); |
| | | //时 |
| | | wv_hours = (WheelView) view.findViewById(R.id.hour); |
| | | wv_hours.setAdapter(new NumericWheelAdapter(0, 23)); |
| | | |
| | | wv_hours.setCurrentItem(h); |
| | | wv_hours.setGravity(gravity); |
| | | //分 |
| | | wv_minutes = (WheelView) view.findViewById(R.id.min); |
| | | wv_minutes.setAdapter(new NumericWheelAdapter(0, 59)); |
| | | |
| | | wv_minutes.setCurrentItem(m); |
| | | wv_minutes.setGravity(gravity); |
| | | //秒 |
| | | wv_seconds = (WheelView) view.findViewById(R.id.second); |
| | | wv_seconds.setAdapter(new NumericWheelAdapter(0, 59)); |
| | | |
| | | wv_seconds.setCurrentItem(s); |
| | | wv_seconds.setGravity(gravity); |
| | | |
| | | // 添加"年"监听 |
| | | wv_year.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | int year_num = index + startYear; |
| | | currentYear = year_num; |
| | | int currentMonthItem = wv_month.getCurrentItem();//记录上一次的item位置 |
| | | // 判断大小月及是否闰年,用来确定"日"的数据 |
| | | if (startYear == endYear) { |
| | | //重新设置月份 |
| | | wv_month.setAdapter(new NumericWheelAdapter(startMonth, endMonth)); |
| | | |
| | | if (currentMonthItem > wv_month.getAdapter().getItemsCount() - 1) { |
| | | currentMonthItem = wv_month.getAdapter().getItemsCount() - 1; |
| | | wv_month.setCurrentItem(currentMonthItem); |
| | | } |
| | | |
| | | int monthNum = currentMonthItem + startMonth; |
| | | |
| | | if (startMonth == endMonth) { |
| | | //重新设置日 |
| | | setReDay(year_num, monthNum, startDay, endDay, list_big, list_little); |
| | | } else if (monthNum == startMonth) { |
| | | //重新设置日 |
| | | setReDay(year_num, monthNum, startDay, 31, list_big, list_little); |
| | | } else if (monthNum == endMonth) { |
| | | setReDay(year_num, monthNum, 1, endDay, list_big, list_little); |
| | | } else {//重新设置日 |
| | | setReDay(year_num, monthNum, 1, 31, list_big, list_little); |
| | | } |
| | | } else if (year_num == startYear) {//等于开始的年 |
| | | //重新设置月份 |
| | | wv_month.setAdapter(new NumericWheelAdapter(startMonth, 12)); |
| | | |
| | | if (currentMonthItem > wv_month.getAdapter().getItemsCount() - 1) { |
| | | currentMonthItem = wv_month.getAdapter().getItemsCount() - 1; |
| | | wv_month.setCurrentItem(currentMonthItem); |
| | | } |
| | | |
| | | int month = currentMonthItem + startMonth; |
| | | if (month == startMonth) { |
| | | //重新设置日 |
| | | setReDay(year_num, month, startDay, 31, list_big, list_little); |
| | | } else { |
| | | //重新设置日 |
| | | setReDay(year_num, month, 1, 31, list_big, list_little); |
| | | } |
| | | |
| | | } else if (year_num == endYear) { |
| | | //重新设置月份 |
| | | wv_month.setAdapter(new NumericWheelAdapter(1, endMonth)); |
| | | if (currentMonthItem > wv_month.getAdapter().getItemsCount() - 1) { |
| | | currentMonthItem = wv_month.getAdapter().getItemsCount() - 1; |
| | | wv_month.setCurrentItem(currentMonthItem); |
| | | } |
| | | int monthNum = currentMonthItem + 1; |
| | | |
| | | if (monthNum == endMonth) { |
| | | //重新设置日 |
| | | setReDay(year_num, monthNum, 1, endDay, list_big, list_little); |
| | | } else { |
| | | //重新设置日 |
| | | setReDay(year_num, monthNum, 1, 31, list_big, list_little); |
| | | } |
| | | |
| | | } else { |
| | | //重新设置月份 |
| | | wv_month.setAdapter(new NumericWheelAdapter(1, 12)); |
| | | //重新设置日 |
| | | setReDay(year_num, wv_month.getCurrentItem() + 1, 1, 31, list_big, list_little); |
| | | } |
| | | |
| | | if (mSelectChangeCallback != null) { |
| | | mSelectChangeCallback.onTimeSelectChanged(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | |
| | | // 添加"月"监听 |
| | | wv_month.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | int month_num = index + 1; |
| | | |
| | | if (startYear == endYear) { |
| | | month_num = month_num + startMonth - 1; |
| | | if (startMonth == endMonth) { |
| | | //重新设置日 |
| | | setReDay(currentYear, month_num, startDay, endDay, list_big, list_little); |
| | | } else if (startMonth == month_num) { |
| | | |
| | | //重新设置日 |
| | | setReDay(currentYear, month_num, startDay, 31, list_big, list_little); |
| | | } else if (endMonth == month_num) { |
| | | setReDay(currentYear, month_num, 1, endDay, list_big, list_little); |
| | | } else { |
| | | setReDay(currentYear, month_num, 1, 31, list_big, list_little); |
| | | } |
| | | } else if (currentYear == startYear) { |
| | | month_num = month_num + startMonth - 1; |
| | | if (month_num == startMonth) { |
| | | //重新设置日 |
| | | setReDay(currentYear, month_num, startDay, 31, list_big, list_little); |
| | | } else { |
| | | //重新设置日 |
| | | setReDay(currentYear, month_num, 1, 31, list_big, list_little); |
| | | } |
| | | |
| | | } else if (currentYear == endYear) { |
| | | if (month_num == endMonth) { |
| | | //重新设置日 |
| | | setReDay(currentYear, wv_month.getCurrentItem() + 1, 1, endDay, list_big, list_little); |
| | | } else { |
| | | setReDay(currentYear, wv_month.getCurrentItem() + 1, 1, 31, list_big, list_little); |
| | | } |
| | | |
| | | } else { |
| | | //重新设置日 |
| | | setReDay(currentYear, month_num, 1, 31, list_big, list_little); |
| | | } |
| | | |
| | | if (mSelectChangeCallback != null) { |
| | | mSelectChangeCallback.onTimeSelectChanged(); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | setChangedListener(wv_day); |
| | | setChangedListener(wv_hours); |
| | | setChangedListener(wv_minutes); |
| | | setChangedListener(wv_seconds); |
| | | |
| | | if (type.length != 6) { |
| | | throw new IllegalArgumentException("type[] length is not 6"); |
| | | } |
| | | wv_year.setVisibility(type[0] ? View.VISIBLE : View.GONE); |
| | | wv_month.setVisibility(type[1] ? View.VISIBLE : View.GONE); |
| | | wv_day.setVisibility(type[2] ? View.VISIBLE : View.GONE); |
| | | wv_hours.setVisibility(type[3] ? View.VISIBLE : View.GONE); |
| | | wv_minutes.setVisibility(type[4] ? View.VISIBLE : View.GONE); |
| | | wv_seconds.setVisibility(type[5] ? View.VISIBLE : View.GONE); |
| | | setContentTextSize(); |
| | | } |
| | | |
| | | private void setChangedListener(WheelView wheelView) { |
| | | if (mSelectChangeCallback != null) { |
| | | wheelView.setOnItemSelectedListener(new OnItemSelectedListener() { |
| | | @Override |
| | | public void onItemSelected(int index) { |
| | | mSelectChangeCallback.onTimeSelectChanged(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | private void setReDay(int year_num, int monthNum, int startD, int endD, List<String> list_big, List<String> list_little) { |
| | | int currentItem = wv_day.getCurrentItem(); |
| | | |
| | | // int maxItem; |
| | | if (list_big.contains(String.valueOf(monthNum))) { |
| | | if (endD > 31) { |
| | | endD = 31; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startD, endD)); |
| | | // maxItem = endD; |
| | | } else if (list_little.contains(String.valueOf(monthNum))) { |
| | | if (endD > 30) { |
| | | endD = 30; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startD, endD)); |
| | | // maxItem = endD; |
| | | } else { |
| | | if ((year_num % 4 == 0 && year_num % 100 != 0) |
| | | || year_num % 400 == 0) { |
| | | if (endD > 29) { |
| | | endD = 29; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startD, endD)); |
| | | // maxItem = endD; |
| | | } else { |
| | | if (endD > 28) { |
| | | endD = 28; |
| | | } |
| | | wv_day.setAdapter(new NumericWheelAdapter(startD, endD)); |
| | | // maxItem = endD; |
| | | } |
| | | } |
| | | |
| | | if (currentItem > wv_day.getAdapter().getItemsCount() - 1) { |
| | | currentItem = wv_day.getAdapter().getItemsCount() - 1; |
| | | wv_day.setCurrentItem(currentItem); |
| | | } |
| | | } |
| | | |
| | | |
| | | private void setContentTextSize() { |
| | | wv_day.setTextSize(textSize); |
| | | wv_month.setTextSize(textSize); |
| | | wv_year.setTextSize(textSize); |
| | | wv_hours.setTextSize(textSize); |
| | | wv_minutes.setTextSize(textSize); |
| | | wv_seconds.setTextSize(textSize); |
| | | } |
| | | |
| | | |
| | | public void setLabels(String label_year, String label_month, String label_day, String label_hours, String label_mins, String label_seconds) { |
| | | if (isLunarCalendar) { |
| | | return; |
| | | } |
| | | |
| | | if (label_year != null) { |
| | | wv_year.setLabel(label_year); |
| | | } else { |
| | | wv_year.setLabel(view.getContext().getString(R.string.pickerview_year)); |
| | | } |
| | | if (label_month != null) { |
| | | wv_month.setLabel(label_month); |
| | | } else { |
| | | wv_month.setLabel(view.getContext().getString(R.string.pickerview_month)); |
| | | } |
| | | if (label_day != null) { |
| | | wv_day.setLabel(label_day); |
| | | } else { |
| | | wv_day.setLabel(view.getContext().getString(R.string.pickerview_day)); |
| | | } |
| | | if (label_hours != null) { |
| | | wv_hours.setLabel(label_hours); |
| | | } else { |
| | | wv_hours.setLabel(view.getContext().getString(R.string.pickerview_hours)); |
| | | } |
| | | if (label_mins != null) { |
| | | wv_minutes.setLabel(label_mins); |
| | | } else { |
| | | wv_minutes.setLabel(view.getContext().getString(R.string.pickerview_minutes)); |
| | | } |
| | | if (label_seconds != null) { |
| | | wv_seconds.setLabel(label_seconds); |
| | | } else { |
| | | wv_seconds.setLabel(view.getContext().getString(R.string.pickerview_seconds)); |
| | | } |
| | | |
| | | } |
| | | |
| | | public void setTextXOffset(int x_offset_year, int x_offset_month, int x_offset_day, |
| | | int x_offset_hours, int x_offset_minutes, int x_offset_seconds) { |
| | | wv_year.setTextXOffset(x_offset_year); |
| | | wv_month.setTextXOffset(x_offset_month); |
| | | wv_day.setTextXOffset(x_offset_day); |
| | | wv_hours.setTextXOffset(x_offset_hours); |
| | | wv_minutes.setTextXOffset(x_offset_minutes); |
| | | wv_seconds.setTextXOffset(x_offset_seconds); |
| | | } |
| | | |
| | | /** |
| | | * 设置是否循环滚动 |
| | | * |
| | | * @param cyclic |
| | | */ |
| | | public void setCyclic(boolean cyclic) { |
| | | wv_year.setCyclic(cyclic); |
| | | wv_month.setCyclic(cyclic); |
| | | wv_day.setCyclic(cyclic); |
| | | wv_hours.setCyclic(cyclic); |
| | | wv_minutes.setCyclic(cyclic); |
| | | wv_seconds.setCyclic(cyclic); |
| | | } |
| | | |
| | | public String getTime() { |
| | | if (isLunarCalendar) { |
| | | //如果是农历 返回对应的公历时间 |
| | | return getLunarTime(); |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | if (currentYear == startYear) { |
| | | /* int i = wv_month.getCurrentItem() + startMonth; |
| | | System.out.println("i:" + i);*/ |
| | | if ((wv_month.getCurrentItem() + startMonth) == startMonth) { |
| | | sb.append((wv_year.getCurrentItem() + startYear)).append("-") |
| | | .append((wv_month.getCurrentItem() + startMonth)).append("-") |
| | | .append((wv_day.getCurrentItem() + startDay)).append(" ") |
| | | .append(wv_hours.getCurrentItem()).append(":") |
| | | .append(wv_minutes.getCurrentItem()).append(":") |
| | | .append(wv_seconds.getCurrentItem()); |
| | | } else { |
| | | sb.append((wv_year.getCurrentItem() + startYear)).append("-") |
| | | .append((wv_month.getCurrentItem() + startMonth)).append("-") |
| | | .append((wv_day.getCurrentItem() + 1)).append(" ") |
| | | .append(wv_hours.getCurrentItem()).append(":") |
| | | .append(wv_minutes.getCurrentItem()).append(":") |
| | | .append(wv_seconds.getCurrentItem()); |
| | | } |
| | | |
| | | } else { |
| | | sb.append((wv_year.getCurrentItem() + startYear)).append("-") |
| | | .append((wv_month.getCurrentItem() + 1)).append("-") |
| | | .append((wv_day.getCurrentItem() + 1)).append(" ") |
| | | .append(wv_hours.getCurrentItem()).append(":") |
| | | .append(wv_minutes.getCurrentItem()).append(":") |
| | | .append(wv_seconds.getCurrentItem()); |
| | | } |
| | | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 农历返回对应的公历时间 |
| | | * |
| | | * @return |
| | | */ |
| | | private String getLunarTime() { |
| | | StringBuilder sb = new StringBuilder(); |
| | | int year = wv_year.getCurrentItem() + startYear; |
| | | int month = 1; |
| | | boolean isLeapMonth = false; |
| | | if (ChinaDate.leapMonth(year) == 0) { |
| | | month = wv_month.getCurrentItem() + 1; |
| | | } else { |
| | | if ((wv_month.getCurrentItem() + 1) - ChinaDate.leapMonth(year) <= 0) { |
| | | month = wv_month.getCurrentItem() + 1; |
| | | } else if ((wv_month.getCurrentItem() + 1) - ChinaDate.leapMonth(year) == 1) { |
| | | month = wv_month.getCurrentItem(); |
| | | isLeapMonth = true; |
| | | } else { |
| | | month = wv_month.getCurrentItem(); |
| | | } |
| | | } |
| | | int day = wv_day.getCurrentItem() + 1; |
| | | int[] solar = LunarCalendar.lunarToSolar(year, month, day, isLeapMonth); |
| | | |
| | | sb.append(solar[0]).append("-") |
| | | .append(solar[1]).append("-") |
| | | .append(solar[2]).append(" ") |
| | | .append(wv_hours.getCurrentItem()).append(":") |
| | | .append(wv_minutes.getCurrentItem()).append(":") |
| | | .append(wv_seconds.getCurrentItem()); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | public View getView() { |
| | | return view; |
| | | } |
| | | |
| | | public int getStartYear() { |
| | | return startYear; |
| | | } |
| | | |
| | | public void setStartYear(int startYear) { |
| | | this.startYear = startYear; |
| | | } |
| | | |
| | | public int getEndYear() { |
| | | return endYear; |
| | | } |
| | | |
| | | public void setEndYear(int endYear) { |
| | | this.endYear = endYear; |
| | | } |
| | | |
| | | |
| | | public void setRangDate(Calendar startDate, Calendar endDate) { |
| | | |
| | | if (startDate == null && endDate != null) { |
| | | int year = endDate.get(Calendar.YEAR); |
| | | int month = endDate.get(Calendar.MONTH) + 1; |
| | | int day = endDate.get(Calendar.DAY_OF_MONTH); |
| | | if (year > startYear) { |
| | | this.endYear = year; |
| | | this.endMonth = month; |
| | | this.endDay = day; |
| | | } else if (year == startYear) { |
| | | if (month > startMonth) { |
| | | this.endYear = year; |
| | | this.endMonth = month; |
| | | this.endDay = day; |
| | | } else if (month == startMonth) { |
| | | if (day > startDay) { |
| | | this.endYear = year; |
| | | this.endMonth = month; |
| | | this.endDay = day; |
| | | } |
| | | } |
| | | } |
| | | |
| | | } else if (startDate != null && endDate == null) { |
| | | int year = startDate.get(Calendar.YEAR); |
| | | int month = startDate.get(Calendar.MONTH) + 1; |
| | | int day = startDate.get(Calendar.DAY_OF_MONTH); |
| | | if (year < endYear) { |
| | | this.startMonth = month; |
| | | this.startDay = day; |
| | | this.startYear = year; |
| | | } else if (year == endYear) { |
| | | if (month < endMonth) { |
| | | this.startMonth = month; |
| | | this.startDay = day; |
| | | this.startYear = year; |
| | | } else if (month == endMonth) { |
| | | if (day < endDay) { |
| | | this.startMonth = month; |
| | | this.startDay = day; |
| | | this.startYear = year; |
| | | } |
| | | } |
| | | } |
| | | |
| | | } else if (startDate != null && endDate != null) { |
| | | this.startYear = startDate.get(Calendar.YEAR); |
| | | this.endYear = endDate.get(Calendar.YEAR); |
| | | this.startMonth = startDate.get(Calendar.MONTH) + 1; |
| | | this.endMonth = endDate.get(Calendar.MONTH) + 1; |
| | | this.startDay = startDate.get(Calendar.DAY_OF_MONTH); |
| | | this.endDay = endDate.get(Calendar.DAY_OF_MONTH); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 设置间距倍数,但是只能在1.0-4.0f之间 |
| | | * |
| | | * @param lineSpacingMultiplier |
| | | */ |
| | | public void setLineSpacingMultiplier(float lineSpacingMultiplier) { |
| | | wv_day.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_month.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_year.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_hours.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_minutes.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | wv_seconds.setLineSpacingMultiplier(lineSpacingMultiplier); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线的颜色 |
| | | * |
| | | * @param dividerColor |
| | | */ |
| | | public void setDividerColor(int dividerColor) { |
| | | wv_day.setDividerColor(dividerColor); |
| | | wv_month.setDividerColor(dividerColor); |
| | | wv_year.setDividerColor(dividerColor); |
| | | wv_hours.setDividerColor(dividerColor); |
| | | wv_minutes.setDividerColor(dividerColor); |
| | | wv_seconds.setDividerColor(dividerColor); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线的类型 |
| | | * |
| | | * @param dividerType |
| | | */ |
| | | public void setDividerType(WheelView.DividerType dividerType) { |
| | | wv_day.setDividerType(dividerType); |
| | | wv_month.setDividerType(dividerType); |
| | | wv_year.setDividerType(dividerType); |
| | | wv_hours.setDividerType(dividerType); |
| | | wv_minutes.setDividerType(dividerType); |
| | | wv_seconds.setDividerType(dividerType); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线之间的文字的颜色 |
| | | * |
| | | * @param textColorCenter |
| | | */ |
| | | public void setTextColorCenter(int textColorCenter) { |
| | | wv_day.setTextColorCenter(textColorCenter); |
| | | wv_month.setTextColorCenter(textColorCenter); |
| | | wv_year.setTextColorCenter(textColorCenter); |
| | | wv_hours.setTextColorCenter(textColorCenter); |
| | | wv_minutes.setTextColorCenter(textColorCenter); |
| | | wv_seconds.setTextColorCenter(textColorCenter); |
| | | } |
| | | |
| | | /** |
| | | * 设置分割线以外文字的颜色 |
| | | * |
| | | * @param textColorOut |
| | | */ |
| | | public void setTextColorOut(int textColorOut) { |
| | | wv_day.setTextColorOut(textColorOut); |
| | | wv_month.setTextColorOut(textColorOut); |
| | | wv_year.setTextColorOut(textColorOut); |
| | | wv_hours.setTextColorOut(textColorOut); |
| | | wv_minutes.setTextColorOut(textColorOut); |
| | | wv_seconds.setTextColorOut(textColorOut); |
| | | } |
| | | |
| | | /** |
| | | * @param isCenterLabel 是否只显示中间选中项的 |
| | | */ |
| | | public void isCenterLabel(boolean isCenterLabel) { |
| | | wv_day.isCenterLabel(isCenterLabel); |
| | | wv_month.isCenterLabel(isCenterLabel); |
| | | wv_year.isCenterLabel(isCenterLabel); |
| | | wv_hours.isCenterLabel(isCenterLabel); |
| | | wv_minutes.isCenterLabel(isCenterLabel); |
| | | wv_seconds.isCenterLabel(isCenterLabel); |
| | | } |
| | | |
| | | public void setSelectChangeCallback(ISelectTimeCallback mSelectChangeCallback) { |
| | | this.mSelectChangeCallback = mSelectChangeCallback; |
| | | } |
| | | |
| | | public void setItemsVisible(int itemsVisibleCount) { |
| | | wv_day.setItemsVisibleCount(itemsVisibleCount); |
| | | wv_month.setItemsVisibleCount(itemsVisibleCount); |
| | | wv_year.setItemsVisibleCount(itemsVisibleCount); |
| | | wv_hours.setItemsVisibleCount(itemsVisibleCount); |
| | | wv_minutes.setItemsVisibleCount(itemsVisibleCount); |
| | | wv_seconds.setItemsVisibleCount(itemsVisibleCount); |
| | | } |
| | | |
| | | public void setAlphaGradient(boolean isAlphaGradient) { |
| | | wv_day.setAlphaGradient(isAlphaGradient); |
| | | wv_month.setAlphaGradient(isAlphaGradient); |
| | | wv_year.setAlphaGradient(isAlphaGradient); |
| | | wv_hours.setAlphaGradient(isAlphaGradient); |
| | | wv_minutes.setAlphaGradient(isAlphaGradient); |
| | | wv_seconds.setAlphaGradient(isAlphaGradient); |
| | | } |
| | | } |
New file |
| | |
| | | package com.contrarywind.adapter; |
| | | |
| | | |
| | | public interface WheelAdapter<T> { |
| | | /** |
| | | * Gets items count |
| | | * @return the count of wheel items |
| | | */ |
| | | int getItemsCount(); |
| | | |
| | | /** |
| | | * Gets a wheel item by index. |
| | | * @param index the item index |
| | | * @return the wheel item text or null |
| | | */ |
| | | T getItem(int index); |
| | | |
| | | /** |
| | | * Gets maximum item length. It is used to determine the wheel width. |
| | | * If -1 is returned there will be used the default wheel width. |
| | | * @param o the item object |
| | | * @return the maximum item length or -1 |
| | | */ |
| | | int indexOf(T o); |
| | | } |
New file |
| | |
| | | package com.contrarywind.interfaces; |
| | | |
| | | /** |
| | | * Created by Sai on 2016/7/13. |
| | | */ |
| | | public interface IPickerViewData { |
| | | String getPickerViewText(); |
| | | } |
New file |
| | |
| | | package com.contrarywind.listener; |
| | | |
| | | import android.view.MotionEvent; |
| | | |
| | | import com.contrarywind.view.WheelView; |
| | | |
| | | |
| | | /** |
| | | * 手势监听 |
| | | */ |
| | | public final class LoopViewGestureListener extends android.view.GestureDetector.SimpleOnGestureListener { |
| | | |
| | | private final WheelView wheelView; |
| | | |
| | | |
| | | public LoopViewGestureListener(WheelView wheelView) { |
| | | this.wheelView = wheelView; |
| | | } |
| | | |
| | | @Override |
| | | public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { |
| | | wheelView.scrollBy(velocityY); |
| | | return true; |
| | | } |
| | | } |
New file |
| | |
| | | package com.contrarywind.listener; |
| | | |
| | | |
| | | public interface OnItemSelectedListener { |
| | | void onItemSelected(int index); |
| | | } |
New file |
| | |
| | | package com.contrarywind.timer; |
| | | |
| | | import com.contrarywind.view.WheelView; |
| | | |
| | | import java.util.TimerTask; |
| | | |
| | | /** |
| | | * 滚动惯性的实现 |
| | | * |
| | | * @author 小嵩 |
| | | * date: 2017-12-23 23:20:44 |
| | | */ |
| | | public final class InertiaTimerTask extends TimerTask { |
| | | |
| | | private float mCurrentVelocityY; //当前滑动速度 |
| | | private final float mFirstVelocityY;//手指离开屏幕时的初始速度 |
| | | private final WheelView mWheelView; |
| | | |
| | | /** |
| | | * @param wheelView 滚轮对象 |
| | | * @param velocityY Y轴滑行速度 |
| | | */ |
| | | public InertiaTimerTask(WheelView wheelView, float velocityY) { |
| | | super(); |
| | | this.mWheelView = wheelView; |
| | | this.mFirstVelocityY = velocityY; |
| | | mCurrentVelocityY = Integer.MAX_VALUE; |
| | | } |
| | | |
| | | @Override |
| | | public final void run() { |
| | | |
| | | //防止闪动,对速度做一个限制。 |
| | | if (mCurrentVelocityY == Integer.MAX_VALUE) { |
| | | if (Math.abs(mFirstVelocityY) > 2000F) { |
| | | mCurrentVelocityY = mFirstVelocityY > 0 ? 2000F : -2000F; |
| | | } else { |
| | | mCurrentVelocityY = mFirstVelocityY; |
| | | } |
| | | } |
| | | |
| | | //发送handler消息 处理平顺停止滚动逻辑 |
| | | if (Math.abs(mCurrentVelocityY) >= 0.0F && Math.abs(mCurrentVelocityY) <= 20F) { |
| | | mWheelView.cancelFuture(); |
| | | mWheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_SMOOTH_SCROLL); |
| | | return; |
| | | } |
| | | |
| | | int dy = (int) (mCurrentVelocityY / 100F); |
| | | mWheelView.setTotalScrollY(mWheelView.getTotalScrollY() - dy); |
| | | if (!mWheelView.isLoop()) { |
| | | float itemHeight = mWheelView.getItemHeight(); |
| | | float top = (-mWheelView.getInitPosition()) * itemHeight; |
| | | float bottom = (mWheelView.getItemsCount() - 1 - mWheelView.getInitPosition()) * itemHeight; |
| | | if (mWheelView.getTotalScrollY() - itemHeight * 0.25 < top) { |
| | | top = mWheelView.getTotalScrollY() + dy; |
| | | } else if (mWheelView.getTotalScrollY() + itemHeight * 0.25 > bottom) { |
| | | bottom = mWheelView.getTotalScrollY() + dy; |
| | | } |
| | | |
| | | if (mWheelView.getTotalScrollY() <= top) { |
| | | mCurrentVelocityY = 40F; |
| | | mWheelView.setTotalScrollY((int) top); |
| | | } else if (mWheelView.getTotalScrollY() >= bottom) { |
| | | mWheelView.setTotalScrollY((int) bottom); |
| | | mCurrentVelocityY = -40F; |
| | | } |
| | | } |
| | | |
| | | if (mCurrentVelocityY < 0.0F) { |
| | | mCurrentVelocityY = mCurrentVelocityY + 20F; |
| | | } else { |
| | | mCurrentVelocityY = mCurrentVelocityY - 20F; |
| | | } |
| | | |
| | | //刷新UI |
| | | mWheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW); |
| | | } |
| | | } |
New file |
| | |
| | | package com.contrarywind.timer; |
| | | |
| | | import android.os.Handler; |
| | | import android.os.Message; |
| | | |
| | | import com.contrarywind.view.WheelView; |
| | | |
| | | /** |
| | | * Handler 消息类 |
| | | * |
| | | * @author 小嵩 |
| | | * date: 2017-12-23 23:20:44 |
| | | */ |
| | | public final class MessageHandler extends Handler { |
| | | public static final int WHAT_INVALIDATE_LOOP_VIEW = 1000; |
| | | public static final int WHAT_SMOOTH_SCROLL = 2000; |
| | | public static final int WHAT_ITEM_SELECTED = 3000; |
| | | |
| | | private final WheelView wheelView; |
| | | |
| | | public MessageHandler(WheelView wheelView) { |
| | | this.wheelView = wheelView; |
| | | } |
| | | |
| | | @Override |
| | | public final void handleMessage(Message msg) { |
| | | switch (msg.what) { |
| | | case WHAT_INVALIDATE_LOOP_VIEW: |
| | | wheelView.invalidate(); |
| | | break; |
| | | |
| | | case WHAT_SMOOTH_SCROLL: |
| | | wheelView.smoothScroll(WheelView.ACTION.FLING); |
| | | break; |
| | | |
| | | case WHAT_ITEM_SELECTED: |
| | | wheelView.onItemSelected(); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.contrarywind.timer; |
| | | |
| | | import com.contrarywind.view.WheelView; |
| | | |
| | | import java.util.TimerTask; |
| | | |
| | | /** |
| | | * 平滑滚动的实现 |
| | | * |
| | | * @author 小嵩 |
| | | */ |
| | | public final class SmoothScrollTimerTask extends TimerTask { |
| | | |
| | | private int realTotalOffset; |
| | | private int realOffset; |
| | | private int offset; |
| | | private final WheelView wheelView; |
| | | |
| | | public SmoothScrollTimerTask(WheelView wheelView, int offset) { |
| | | this.wheelView = wheelView; |
| | | this.offset = offset; |
| | | realTotalOffset = Integer.MAX_VALUE; |
| | | realOffset = 0; |
| | | } |
| | | |
| | | @Override |
| | | public final void run() { |
| | | if (realTotalOffset == Integer.MAX_VALUE) { |
| | | realTotalOffset = offset; |
| | | } |
| | | //把要滚动的范围细分成10小份,按10小份单位来重绘 |
| | | realOffset = (int) ((float) realTotalOffset * 0.1F); |
| | | |
| | | if (realOffset == 0) { |
| | | if (realTotalOffset < 0) { |
| | | realOffset = -1; |
| | | } else { |
| | | realOffset = 1; |
| | | } |
| | | } |
| | | |
| | | if (Math.abs(realTotalOffset) <= 1) { |
| | | wheelView.cancelFuture(); |
| | | wheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED); |
| | | } else { |
| | | wheelView.setTotalScrollY(wheelView.getTotalScrollY() + realOffset); |
| | | |
| | | //这里如果不是循环模式,则点击空白位置需要回滚,不然就会出现选到-1 item的 情况 |
| | | if (!wheelView.isLoop()) { |
| | | float itemHeight = wheelView.getItemHeight(); |
| | | float top = (float) (-wheelView.getInitPosition()) * itemHeight; |
| | | float bottom = (float) (wheelView.getItemsCount() - 1 - wheelView.getInitPosition()) * itemHeight; |
| | | if (wheelView.getTotalScrollY() <= top || wheelView.getTotalScrollY() >= bottom) { |
| | | wheelView.setTotalScrollY(wheelView.getTotalScrollY() - realOffset); |
| | | wheelView.cancelFuture(); |
| | | wheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED); |
| | | return; |
| | | } |
| | | } |
| | | wheelView.getHandler().sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW); |
| | | realTotalOffset = realTotalOffset - realOffset; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.contrarywind.view; |
| | | |
| | | import android.content.Context; |
| | | import android.content.res.TypedArray; |
| | | import android.graphics.Canvas; |
| | | import android.graphics.Paint; |
| | | import android.graphics.Rect; |
| | | import android.graphics.Typeface; |
| | | import android.os.Handler; |
| | | import android.text.TextUtils; |
| | | import android.util.AttributeSet; |
| | | import android.util.DisplayMetrics; |
| | | import android.util.Log; |
| | | import android.view.GestureDetector; |
| | | import android.view.Gravity; |
| | | import android.view.MotionEvent; |
| | | import android.view.View; |
| | | |
| | | import com.contrarywind.adapter.WheelAdapter; |
| | | import com.contrarywind.interfaces.IPickerViewData; |
| | | import com.contrarywind.listener.LoopViewGestureListener; |
| | | import com.contrarywind.listener.OnItemSelectedListener; |
| | | import com.contrarywind.timer.InertiaTimerTask; |
| | | import com.contrarywind.timer.MessageHandler; |
| | | import com.contrarywind.timer.SmoothScrollTimerTask; |
| | | import com.example.pickerviewlibrary.R; |
| | | |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.ScheduledFuture; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * 3d滚轮控件 |
| | | */ |
| | | public class WheelView extends View { |
| | | |
| | | public enum ACTION { // 点击,滑翔(滑到尽头),拖拽事件 |
| | | CLICK, FLING, DAGGLE |
| | | } |
| | | |
| | | public enum DividerType { // 分隔线类型 |
| | | FILL, WRAP, CIRCLE |
| | | } |
| | | |
| | | private static final String[] TIME_NUM = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09"}; |
| | | |
| | | private DividerType dividerType;//分隔线类型 |
| | | |
| | | private Context context; |
| | | private Handler handler; |
| | | private GestureDetector gestureDetector; |
| | | private OnItemSelectedListener onItemSelectedListener; |
| | | |
| | | private boolean isOptions = false; |
| | | private boolean isCenterLabel = true; |
| | | |
| | | // Timer mTimer; |
| | | private ScheduledExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor(); |
| | | private ScheduledFuture<?> mFuture; |
| | | |
| | | private Paint paintOuterText; |
| | | private Paint paintCenterText; |
| | | private Paint paintIndicator; |
| | | |
| | | private WheelAdapter adapter; |
| | | |
| | | private String label;//附加单位 |
| | | private int textSize;//选项的文字大小 |
| | | private int maxTextWidth; |
| | | private int maxTextHeight; |
| | | private int textXOffset; |
| | | private float itemHeight;//每行高度 |
| | | |
| | | |
| | | private Typeface typeface = Typeface.MONOSPACE;//字体样式,默认是等宽字体 |
| | | private int textColorOut; |
| | | private int textColorCenter; |
| | | private int dividerColor; |
| | | private int dividerWidth; |
| | | |
| | | // 条目间距倍数 |
| | | private float lineSpacingMultiplier = 1.6F; |
| | | private boolean isLoop; |
| | | |
| | | // 第一条线Y坐标值 |
| | | private float firstLineY; |
| | | //第二条线Y坐标 |
| | | private float secondLineY; |
| | | //中间label绘制的Y坐标 |
| | | private float centerY; |
| | | |
| | | //当前滚动总高度y值 |
| | | private float totalScrollY; |
| | | |
| | | //初始化默认选中项 |
| | | private int initPosition; |
| | | |
| | | //选中的Item是第几个 |
| | | private int selectedItem; |
| | | private int preCurrentIndex; |
| | | |
| | | // 绘制几个条目,实际上第一项和最后一项Y轴压缩成0%了,所以可见的数目实际为9 |
| | | private int itemsVisible = 11; |
| | | |
| | | private int measuredHeight;// WheelView 控件高度 |
| | | private int measuredWidth;// WheelView 控件宽度 |
| | | |
| | | // 半径 |
| | | private int radius; |
| | | |
| | | private int mOffset = 0; |
| | | private float previousY = 0; |
| | | private long startTime = 0; |
| | | |
| | | // 修改这个值可以改变滑行速度 |
| | | private static final int VELOCITY_FLING = 5; |
| | | private int widthMeasureSpec; |
| | | |
| | | private int mGravity = Gravity.CENTER; |
| | | private int drawCenterContentStart = 0;//中间选中文字开始绘制位置 |
| | | private int drawOutContentStart = 0;//非中间文字开始绘制位置 |
| | | private static final float SCALE_CONTENT = 0.8F;//非中间文字则用此控制高度,压扁形成3d错觉 |
| | | private float CENTER_CONTENT_OFFSET;//偏移量 |
| | | |
| | | private boolean isAlphaGradient = false; //透明度渐变 |
| | | |
| | | public WheelView(Context context) { |
| | | this(context, null); |
| | | } |
| | | |
| | | public WheelView(Context context, AttributeSet attrs) { |
| | | super(context, attrs); |
| | | |
| | | textSize = getResources().getDimensionPixelSize(R.dimen.pickerview_textsize);//默认大小 |
| | | |
| | | DisplayMetrics dm = getResources().getDisplayMetrics(); |
| | | float density = dm.density; // 屏幕密度比(0.75/1.0/1.5/2.0/3.0) |
| | | |
| | | if (density < 1) {//根据密度不同进行适配 |
| | | CENTER_CONTENT_OFFSET = 2.4F; |
| | | } else if (1 <= density && density < 2) { |
| | | CENTER_CONTENT_OFFSET = 4.0F; |
| | | } else if (2 <= density && density < 3) { |
| | | CENTER_CONTENT_OFFSET = 6.0F; |
| | | } else if (density >= 3) { |
| | | CENTER_CONTENT_OFFSET = density * 2.5F; |
| | | } |
| | | |
| | | if (attrs != null) { |
| | | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.pickerview, 0, 0); |
| | | mGravity = a.getInt(R.styleable.pickerview_wheelview_gravity, Gravity.CENTER); |
| | | textColorOut = a.getColor(R.styleable.pickerview_wheelview_textColorOut, 0xFFa8a8a8); |
| | | textColorCenter = a.getColor(R.styleable.pickerview_wheelview_textColorCenter, 0xFF2a2a2a); |
| | | dividerColor = a.getColor(R.styleable.pickerview_wheelview_dividerColor, 0xFFd5d5d5); |
| | | dividerWidth = a.getDimensionPixelSize(R.styleable.pickerview_wheelview_dividerWidth, 2); |
| | | textSize = a.getDimensionPixelOffset(R.styleable.pickerview_wheelview_textSize, textSize); |
| | | lineSpacingMultiplier = a.getFloat(R.styleable.pickerview_wheelview_lineSpacingMultiplier, lineSpacingMultiplier); |
| | | a.recycle();//回收内存 |
| | | } |
| | | |
| | | judgeLineSpace(); |
| | | initLoopView(context); |
| | | } |
| | | |
| | | /** |
| | | * 判断间距是否在1.0-4.0之间 |
| | | */ |
| | | private void judgeLineSpace() { |
| | | if (lineSpacingMultiplier < 1.0f) { |
| | | lineSpacingMultiplier = 1.0f; |
| | | } else if (lineSpacingMultiplier > 4.0f) { |
| | | lineSpacingMultiplier = 4.0f; |
| | | } |
| | | } |
| | | |
| | | private void initLoopView(Context context) { |
| | | this.context = context; |
| | | handler = new MessageHandler(this); |
| | | gestureDetector = new GestureDetector(context, new LoopViewGestureListener(this)); |
| | | gestureDetector.setIsLongpressEnabled(false); |
| | | isLoop = true; |
| | | |
| | | totalScrollY = 0; |
| | | initPosition = -1; |
| | | initPaints(); |
| | | } |
| | | |
| | | private void initPaints() { |
| | | paintOuterText = new Paint(); |
| | | paintOuterText.setColor(textColorOut); |
| | | paintOuterText.setAntiAlias(true); |
| | | paintOuterText.setTypeface(typeface); |
| | | paintOuterText.setTextSize(textSize); |
| | | |
| | | paintCenterText = new Paint(); |
| | | paintCenterText.setColor(textColorCenter); |
| | | paintCenterText.setAntiAlias(true); |
| | | paintCenterText.setTextScaleX(1.1F); |
| | | paintCenterText.setTypeface(typeface); |
| | | paintCenterText.setTextSize(textSize); |
| | | |
| | | paintIndicator = new Paint(); |
| | | paintIndicator.setColor(dividerColor); |
| | | paintIndicator.setAntiAlias(true); |
| | | |
| | | setLayerType(LAYER_TYPE_SOFTWARE, null); |
| | | } |
| | | |
| | | private void reMeasure() {//重新测量 |
| | | if (adapter == null) { |
| | | return; |
| | | } |
| | | |
| | | measureTextWidthHeight(); |
| | | |
| | | //半圆的周长 = item高度乘以item数目-1 |
| | | int halfCircumference = (int) (itemHeight * (itemsVisible - 1)); |
| | | //整个圆的周长除以PI得到直径,这个直径用作控件的总高度 |
| | | measuredHeight = (int) ((halfCircumference * 2) / Math.PI); |
| | | //求出半径 |
| | | radius = (int) (halfCircumference / Math.PI); |
| | | //控件宽度,这里支持weight |
| | | measuredWidth = MeasureSpec.getSize(widthMeasureSpec); |
| | | //计算两条横线 和 选中项画笔的基线Y位置 |
| | | firstLineY = (measuredHeight - itemHeight) / 2.0F; |
| | | secondLineY = (measuredHeight + itemHeight) / 2.0F; |
| | | centerY = secondLineY - (itemHeight - maxTextHeight) / 2.0f - CENTER_CONTENT_OFFSET; |
| | | |
| | | //初始化显示的item的position |
| | | if (initPosition == -1) { |
| | | if (isLoop) { |
| | | initPosition = (adapter.getItemsCount() + 1) / 2; |
| | | } else { |
| | | initPosition = 0; |
| | | } |
| | | } |
| | | preCurrentIndex = initPosition; |
| | | } |
| | | |
| | | /** |
| | | * 计算最大length的Text的宽高度 |
| | | */ |
| | | private void measureTextWidthHeight() { |
| | | Rect rect = new Rect(); |
| | | for (int i = 0; i < adapter.getItemsCount(); i++) { |
| | | String s1 = getContentText(adapter.getItem(i)); |
| | | paintCenterText.getTextBounds(s1, 0, s1.length(), rect); |
| | | |
| | | int textWidth = rect.width(); |
| | | if (textWidth > maxTextWidth) { |
| | | maxTextWidth = textWidth; |
| | | } |
| | | } |
| | | paintCenterText.getTextBounds("\u661F\u671F", 0, 2, rect); // 星期的字符编码(以它为标准高度) |
| | | maxTextHeight = rect.height() + 2; |
| | | itemHeight = lineSpacingMultiplier * maxTextHeight; |
| | | } |
| | | |
| | | public void smoothScroll(ACTION action) {//平滑滚动的实现 |
| | | cancelFuture(); |
| | | if (action == ACTION.FLING || action == ACTION.DAGGLE) { |
| | | mOffset = (int) ((totalScrollY % itemHeight + itemHeight) % itemHeight); |
| | | if ((float) mOffset > itemHeight / 2.0F) {//如果超过Item高度的一半,滚动到下一个Item去 |
| | | mOffset = (int) (itemHeight - (float) mOffset); |
| | | } else { |
| | | mOffset = -mOffset; |
| | | } |
| | | } |
| | | //停止的时候,位置有偏移,不是全部都能正确停止到中间位置的,这里把文字位置挪回中间去 |
| | | mFuture = mExecutor.scheduleWithFixedDelay(new SmoothScrollTimerTask(this, mOffset), 0, 10, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | public final void scrollBy(float velocityY) {//滚动惯性的实现 |
| | | cancelFuture(); |
| | | mFuture = mExecutor.scheduleWithFixedDelay(new InertiaTimerTask(this, velocityY), 0, VELOCITY_FLING, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | public void cancelFuture() { |
| | | if (mFuture != null && !mFuture.isCancelled()) { |
| | | mFuture.cancel(true); |
| | | mFuture = null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置是否循环滚动 |
| | | * |
| | | * @param cyclic 是否循环 |
| | | */ |
| | | public final void setCyclic(boolean cyclic) { |
| | | isLoop = cyclic; |
| | | } |
| | | |
| | | public final void setTypeface(Typeface font) { |
| | | typeface = font; |
| | | paintOuterText.setTypeface(typeface); |
| | | paintCenterText.setTypeface(typeface); |
| | | } |
| | | |
| | | public final void setTextSize(float size) { |
| | | if (size > 0.0F) { |
| | | textSize = (int) (context.getResources().getDisplayMetrics().density * size); |
| | | paintOuterText.setTextSize(textSize); |
| | | paintCenterText.setTextSize(textSize); |
| | | } |
| | | } |
| | | |
| | | public final void setCurrentItem(int currentItem) { |
| | | //不添加这句,当这个wheelView不可见时,默认都是0,会导致获取到的时间错误 |
| | | this.selectedItem = currentItem; |
| | | this.initPosition = currentItem; |
| | | totalScrollY = 0;//回归顶部,不然重设setCurrentItem的话位置会偏移的,就会显示出不对位置的数据 |
| | | invalidate(); |
| | | } |
| | | |
| | | public final void setOnItemSelectedListener(OnItemSelectedListener OnItemSelectedListener) { |
| | | this.onItemSelectedListener = OnItemSelectedListener; |
| | | } |
| | | |
| | | public final void setAdapter(WheelAdapter adapter) { |
| | | this.adapter = adapter; |
| | | reMeasure(); |
| | | invalidate(); |
| | | } |
| | | |
| | | public void setItemsVisibleCount(int visibleCount) { |
| | | if (visibleCount % 2 == 0) { |
| | | visibleCount += 1; |
| | | } |
| | | this.itemsVisible = visibleCount + 2; //第一条和最后一条 |
| | | } |
| | | |
| | | public void setAlphaGradient(boolean alphaGradient) { |
| | | isAlphaGradient = alphaGradient; |
| | | } |
| | | |
| | | public final WheelAdapter getAdapter() { |
| | | return adapter; |
| | | } |
| | | |
| | | public final int getCurrentItem() { |
| | | // return selectedItem; |
| | | if (adapter == null) { |
| | | return 0; |
| | | } |
| | | if (isLoop && (selectedItem < 0 || selectedItem >= adapter.getItemsCount())) { |
| | | return Math.max(0, Math.min(Math.abs(Math.abs(selectedItem) - adapter.getItemsCount()), adapter.getItemsCount() - 1)); |
| | | } |
| | | return Math.max(0, Math.min(selectedItem, adapter.getItemsCount() - 1)); |
| | | } |
| | | |
| | | public final void onItemSelected() { |
| | | if (onItemSelectedListener != null) { |
| | | postDelayed(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | onItemSelectedListener.onItemSelected(getCurrentItem()); |
| | | } |
| | | }, 200L); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onDraw(Canvas canvas) { |
| | | if (adapter == null) { |
| | | return; |
| | | } |
| | | //initPosition越界会造成preCurrentIndex的值不正确 |
| | | initPosition = Math.min(Math.max(0, initPosition), adapter.getItemsCount() - 1); |
| | | |
| | | //滚动的Y值高度除去每行Item的高度,得到滚动了多少个item,即change数 |
| | | //滚动偏移值,用于记录滚动了多少个item |
| | | int change = (int) (totalScrollY / itemHeight); |
| | | // Log.d("change", "" + change); |
| | | |
| | | try { |
| | | //滚动中实际的预选中的item(即经过了中间位置的item) = 滑动前的位置 + 滑动相对位置 |
| | | preCurrentIndex = initPosition + change % adapter.getItemsCount(); |
| | | |
| | | } catch (ArithmeticException e) { |
| | | Log.e("WheelView", "出错了!adapter.getItemsCount() == 0,联动数据不匹配"); |
| | | } |
| | | if (!isLoop) {//不循环的情况 |
| | | if (preCurrentIndex < 0) { |
| | | preCurrentIndex = 0; |
| | | } |
| | | if (preCurrentIndex > adapter.getItemsCount() - 1) { |
| | | preCurrentIndex = adapter.getItemsCount() - 1; |
| | | } |
| | | } else {//循环 |
| | | if (preCurrentIndex < 0) {//举个例子:如果总数是5,preCurrentIndex = -1,那么preCurrentIndex按循环来说,其实是0的上面,也就是4的位置 |
| | | preCurrentIndex = adapter.getItemsCount() + preCurrentIndex; |
| | | } |
| | | if (preCurrentIndex > adapter.getItemsCount() - 1) {//同理上面,自己脑补一下 |
| | | preCurrentIndex = preCurrentIndex - adapter.getItemsCount(); |
| | | } |
| | | } |
| | | //跟滚动流畅度有关,总滑动距离与每个item高度取余,即并不是一格格的滚动,每个item不一定滚到对应Rect里的,这个item对应格子的偏移值 |
| | | float itemHeightOffset = (totalScrollY % itemHeight); |
| | | |
| | | |
| | | //绘制中间两条横线 |
| | | if (dividerType == DividerType.WRAP) {//横线长度仅包裹内容 |
| | | float startX; |
| | | float endX; |
| | | |
| | | if (TextUtils.isEmpty(label)) {//隐藏Label的情况 |
| | | startX = (measuredWidth - maxTextWidth) / 2 - 12; |
| | | } else { |
| | | startX = (measuredWidth - maxTextWidth) / 4 - 12; |
| | | } |
| | | |
| | | if (startX <= 0) {//如果超过了WheelView的边缘 |
| | | startX = 10; |
| | | } |
| | | endX = measuredWidth - startX; |
| | | canvas.drawLine(startX, firstLineY, endX, firstLineY, paintIndicator); |
| | | canvas.drawLine(startX, secondLineY, endX, secondLineY, paintIndicator); |
| | | } else if (dividerType == DividerType.CIRCLE) { |
| | | //分割线为圆圈形状 |
| | | paintIndicator.setStyle(Paint.Style.STROKE); |
| | | paintIndicator.setStrokeWidth(dividerWidth); |
| | | float startX; |
| | | float endX; |
| | | if (TextUtils.isEmpty(label)) {//隐藏Label的情况 |
| | | startX = (measuredWidth - maxTextWidth) / 2f - 12; |
| | | } else { |
| | | startX = (measuredWidth - maxTextWidth) / 4f - 12; |
| | | } |
| | | if (startX <= 0) {//如果超过了WheelView的边缘 |
| | | startX = 10; |
| | | } |
| | | endX = measuredWidth - startX; |
| | | //半径始终以宽高中最大的来算 |
| | | float radius = Math.max((endX - startX), itemHeight) / 1.8f; |
| | | canvas.drawCircle(measuredWidth / 2f, measuredHeight / 2f, radius, paintIndicator); |
| | | } else { |
| | | canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator); |
| | | canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator); |
| | | } |
| | | |
| | | //只显示选中项Label文字的模式,并且Label文字不为空,则进行绘制 |
| | | if (!TextUtils.isEmpty(label) && isCenterLabel) { |
| | | //绘制文字,靠右并留出空隙 |
| | | int drawRightContentStart = measuredWidth - getTextWidth(paintCenterText, label); |
| | | canvas.drawText(label, drawRightContentStart - CENTER_CONTENT_OFFSET, centerY, paintCenterText); |
| | | } |
| | | |
| | | // 设置数组中每个元素的值 |
| | | int counter = 0; |
| | | while (counter < itemsVisible) { |
| | | Object showText; |
| | | int index = preCurrentIndex - (itemsVisible / 2 - counter);//索引值,即当前在控件中间的item看作数据源的中间,计算出相对源数据源的index值 |
| | | |
| | | //判断是否循环,如果是循环数据源也使用相对循环的position获取对应的item值,如果不是循环则超出数据源范围使用""空白字符串填充,在界面上形成空白无数据的item项 |
| | | if (isLoop) { |
| | | index = getLoopMappingIndex(index); |
| | | showText = adapter.getItem(index); |
| | | } else if (index < 0) { |
| | | showText = ""; |
| | | } else if (index > adapter.getItemsCount() - 1) { |
| | | showText = ""; |
| | | } else { |
| | | showText = adapter.getItem(index); |
| | | } |
| | | |
| | | canvas.save(); |
| | | // 弧长 L = itemHeight * counter - itemHeightOffset |
| | | // 求弧度 α = L / r (弧长/半径) [0,π] |
| | | double radian = ((itemHeight * counter - itemHeightOffset)) / radius; |
| | | // 弧度转换成角度(把半圆以Y轴为轴心向右转90度,使其处于第一象限及第四象限 |
| | | // angle [-90°,90°] |
| | | float angle = (float) (90D - (radian / Math.PI) * 180D);//item第一项,从90度开始,逐渐递减到 -90度 |
| | | |
| | | // 计算取值可能有细微偏差,保证负90°到90°以外的不绘制 |
| | | if (angle > 90F || angle < -90F) { |
| | | canvas.restore(); |
| | | } else { |
| | | //获取内容文字 |
| | | String contentText; |
| | | |
| | | //如果是label每项都显示的模式,并且item内容不为空、label 也不为空 |
| | | if (!isCenterLabel && !TextUtils.isEmpty(label) && !TextUtils.isEmpty(getContentText(showText))) { |
| | | contentText = getContentText(showText) + label; |
| | | } else { |
| | | contentText = getContentText(showText); |
| | | } |
| | | // 根据当前角度计算出偏差系数,用以在绘制时控制文字的 水平移动 透明度 倾斜程度. |
| | | float offsetCoefficient = (float) Math.pow(Math.abs(angle) / 90f, 2.2); |
| | | |
| | | reMeasureTextSize(contentText); |
| | | //计算开始绘制的位置 |
| | | measuredCenterContentStart(contentText); |
| | | measuredOutContentStart(contentText); |
| | | float translateY = (float) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D); |
| | | //根据Math.sin(radian)来更改canvas坐标系原点,然后缩放画布,使得文字高度进行缩放,形成弧形3d视觉差 |
| | | canvas.translate(0.0F, translateY); |
| | | if (translateY <= firstLineY && maxTextHeight + translateY >= firstLineY) { |
| | | // 条目经过第一条线 |
| | | canvas.save(); |
| | | canvas.clipRect(0, 0, measuredWidth, firstLineY - translateY); |
| | | canvas.scale(1.0F, (float) Math.sin(radian) * SCALE_CONTENT); |
| | | setOutPaintStyle(offsetCoefficient, angle); |
| | | canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText); |
| | | canvas.restore(); |
| | | canvas.save(); |
| | | canvas.clipRect(0, firstLineY - translateY, measuredWidth, (int) (itemHeight)); |
| | | canvas.scale(1.0F, (float) Math.sin(radian) * 1.0F); |
| | | canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTER_CONTENT_OFFSET, paintCenterText); |
| | | canvas.restore(); |
| | | } else if (translateY <= secondLineY && maxTextHeight + translateY >= secondLineY) { |
| | | // 条目经过第二条线 |
| | | canvas.save(); |
| | | canvas.clipRect(0, 0, measuredWidth, secondLineY - translateY); |
| | | canvas.scale(1.0F, (float) Math.sin(radian) * 1.0F); |
| | | canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTER_CONTENT_OFFSET, paintCenterText); |
| | | canvas.restore(); |
| | | canvas.save(); |
| | | canvas.clipRect(0, secondLineY - translateY, measuredWidth, (int) (itemHeight)); |
| | | canvas.scale(1.0F, (float) Math.sin(radian) * SCALE_CONTENT); |
| | | setOutPaintStyle(offsetCoefficient, angle); |
| | | canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText); |
| | | canvas.restore(); |
| | | } else if (translateY >= firstLineY && maxTextHeight + translateY <= secondLineY) { |
| | | // 中间条目 |
| | | // canvas.clipRect(0, 0, measuredWidth, maxTextHeight); |
| | | //让文字居中 |
| | | float Y = maxTextHeight - CENTER_CONTENT_OFFSET;//因为圆弧角换算的向下取值,导致角度稍微有点偏差,加上画笔的基线会偏上,因此需要偏移量修正一下 |
| | | canvas.drawText(contentText, drawCenterContentStart, Y, paintCenterText); |
| | | //设置选中项 |
| | | selectedItem = preCurrentIndex - (itemsVisible / 2 - counter); |
| | | } else { |
| | | // 其他条目 |
| | | canvas.save(); |
| | | canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight)); |
| | | canvas.scale(1.0F, (float) Math.sin(radian) * SCALE_CONTENT); |
| | | setOutPaintStyle(offsetCoefficient, angle); |
| | | // 控制文字水平偏移距离 |
| | | canvas.drawText(contentText, drawOutContentStart + textXOffset * offsetCoefficient, maxTextHeight, paintOuterText); |
| | | canvas.restore(); |
| | | } |
| | | canvas.restore(); |
| | | paintCenterText.setTextSize(textSize); |
| | | } |
| | | counter++; |
| | | } |
| | | } |
| | | |
| | | //设置文字倾斜角度,透明度 |
| | | private void setOutPaintStyle(float offsetCoefficient, float angle) { |
| | | // 控制文字倾斜角度 |
| | | float DEFAULT_TEXT_TARGET_SKEW_X = 0.5f; |
| | | int multiplier = 0; |
| | | if (textXOffset > 0) { |
| | | multiplier = 1; |
| | | } else if (textXOffset < 0) { |
| | | multiplier = -1; |
| | | } |
| | | paintOuterText.setTextSkewX(multiplier * (angle > 0 ? -1 : 1) * DEFAULT_TEXT_TARGET_SKEW_X * offsetCoefficient); |
| | | |
| | | // 控制透明度 |
| | | int alpha = isAlphaGradient ? (int) ((90F - Math.abs(angle)) / 90f * 255) : 255; |
| | | // Log.d("WheelView", "alpha:" + alpha); |
| | | paintOuterText.setAlpha(alpha); |
| | | } |
| | | |
| | | /** |
| | | * reset the size of the text Let it can fully display |
| | | * |
| | | * @param contentText item text content. |
| | | */ |
| | | private void reMeasureTextSize(String contentText) { |
| | | Rect rect = new Rect(); |
| | | paintCenterText.getTextBounds(contentText, 0, contentText.length(), rect); |
| | | int width = rect.width(); |
| | | int size = textSize; |
| | | while (width > measuredWidth) { |
| | | size--; |
| | | //设置2条横线中间的文字大小 |
| | | paintCenterText.setTextSize(size); |
| | | paintCenterText.getTextBounds(contentText, 0, contentText.length(), rect); |
| | | width = rect.width(); |
| | | } |
| | | //设置2条横线外面的文字大小 |
| | | paintOuterText.setTextSize(size); |
| | | } |
| | | |
| | | |
| | | //递归计算出对应的index |
| | | private int getLoopMappingIndex(int index) { |
| | | if (index < 0) { |
| | | index = index + adapter.getItemsCount(); |
| | | index = getLoopMappingIndex(index); |
| | | } else if (index > adapter.getItemsCount() - 1) { |
| | | index = index - adapter.getItemsCount(); |
| | | index = getLoopMappingIndex(index); |
| | | } |
| | | return index; |
| | | } |
| | | |
| | | /** |
| | | * 获取所显示的数据源 |
| | | * |
| | | * @param item data resource |
| | | * @return 对应显示的字符串 |
| | | */ |
| | | private String getContentText(Object item) { |
| | | if (item == null) { |
| | | return ""; |
| | | } else if (item instanceof IPickerViewData) { |
| | | return ((IPickerViewData) item).getPickerViewText(); |
| | | } else if (item instanceof Integer) { |
| | | //如果为整形则最少保留两位数. |
| | | return getFixNum((int) item); |
| | | } |
| | | return item.toString(); |
| | | } |
| | | |
| | | private String getFixNum(int timeNum) { |
| | | return timeNum >= 0 && timeNum < 10 ? TIME_NUM[timeNum] : String.valueOf(timeNum); |
| | | } |
| | | |
| | | private void measuredCenterContentStart(String content) { |
| | | Rect rect = new Rect(); |
| | | paintCenterText.getTextBounds(content, 0, content.length(), rect); |
| | | switch (mGravity) { |
| | | case Gravity.CENTER://显示内容居中 |
| | | if (isOptions || label == null || label.equals("") || !isCenterLabel) { |
| | | drawCenterContentStart = (int) ((measuredWidth - rect.width()) * 0.5); |
| | | } else {//只显示中间label时,时间选择器内容偏左一点,留出空间绘制单位标签 |
| | | drawCenterContentStart = (int) ((measuredWidth - rect.width()) * 0.25); |
| | | } |
| | | break; |
| | | case Gravity.LEFT: |
| | | drawCenterContentStart = 0; |
| | | break; |
| | | case Gravity.RIGHT://添加偏移量 |
| | | drawCenterContentStart = measuredWidth - rect.width() - (int) CENTER_CONTENT_OFFSET; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void measuredOutContentStart(String content) { |
| | | Rect rect = new Rect(); |
| | | paintOuterText.getTextBounds(content, 0, content.length(), rect); |
| | | switch (mGravity) { |
| | | case Gravity.CENTER: |
| | | if (isOptions || label == null || label.equals("") || !isCenterLabel) { |
| | | drawOutContentStart = (int) ((measuredWidth - rect.width()) * 0.5); |
| | | } else {//只显示中间label时,时间选择器内容偏左一点,留出空间绘制单位标签 |
| | | drawOutContentStart = (int) ((measuredWidth - rect.width()) * 0.25); |
| | | } |
| | | break; |
| | | case Gravity.LEFT: |
| | | drawOutContentStart = 0; |
| | | break; |
| | | case Gravity.RIGHT: |
| | | drawOutContentStart = measuredWidth - rect.width() - (int) CENTER_CONTENT_OFFSET; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| | | this.widthMeasureSpec = widthMeasureSpec; |
| | | reMeasure(); |
| | | setMeasuredDimension(measuredWidth, measuredHeight); |
| | | } |
| | | |
| | | @Override |
| | | public boolean onTouchEvent(MotionEvent event) { |
| | | boolean eventConsumed = gestureDetector.onTouchEvent(event); |
| | | boolean isIgnore = false;//超过边界滑动时,不再绘制UI。 |
| | | |
| | | float top = -initPosition * itemHeight; |
| | | float bottom = (adapter.getItemsCount() - 1 - initPosition) * itemHeight; |
| | | float ratio = 0.25f; |
| | | |
| | | switch (event.getAction()) { |
| | | case MotionEvent.ACTION_DOWN: |
| | | startTime = System.currentTimeMillis(); |
| | | cancelFuture(); |
| | | previousY = event.getRawY(); |
| | | break; |
| | | |
| | | case MotionEvent.ACTION_MOVE: |
| | | float dy = previousY - event.getRawY(); |
| | | previousY = event.getRawY(); |
| | | totalScrollY = totalScrollY + dy; |
| | | |
| | | // normal mode。 |
| | | if (!isLoop) { |
| | | if ((totalScrollY - itemHeight * ratio < top && dy < 0) |
| | | || (totalScrollY + itemHeight * ratio > bottom && dy > 0)) { |
| | | //快滑动到边界了,设置已滑动到边界的标志 |
| | | totalScrollY -= dy; |
| | | isIgnore = true; |
| | | } else { |
| | | isIgnore = false; |
| | | } |
| | | } |
| | | break; |
| | | |
| | | case MotionEvent.ACTION_UP: |
| | | default: |
| | | if (!eventConsumed) {//未消费掉事件 |
| | | |
| | | /** |
| | | *@describe <关于弧长的计算> |
| | | * |
| | | * 弧长公式: L = α*R |
| | | * 反余弦公式:arccos(cosα) = α |
| | | * 由于之前是有顺时针偏移90度, |
| | | * 所以实际弧度范围α2的值 :α2 = π/2-α (α=[0,π] α2 = [-π/2,π/2]) |
| | | * 根据正弦余弦转换公式 cosα = sin(π/2-α) |
| | | * 代入,得: cosα = sin(π/2-α) = sinα2 = (R - y) / R |
| | | * 所以弧长 L = arccos(cosα)*R = arccos((R - y) / R)*R |
| | | */ |
| | | |
| | | float y = event.getY(); |
| | | double L = Math.acos((radius - y) / radius) * radius; |
| | | //item0 有一半是在不可见区域,所以需要加上 itemHeight / 2 |
| | | int circlePosition = (int) ((L + itemHeight / 2) / itemHeight); |
| | | float extraOffset = (totalScrollY % itemHeight + itemHeight) % itemHeight; |
| | | //已滑动的弧长值 |
| | | mOffset = (int) ((circlePosition - itemsVisible / 2) * itemHeight - extraOffset); |
| | | |
| | | if ((System.currentTimeMillis() - startTime) > 120) { |
| | | // 处理拖拽事件 |
| | | smoothScroll(ACTION.DAGGLE); |
| | | } else { |
| | | // 处理条目点击事件 |
| | | smoothScroll(ACTION.CLICK); |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | if (!isIgnore && event.getAction() != MotionEvent.ACTION_DOWN) { |
| | | invalidate(); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public int getItemsCount() { |
| | | return adapter != null ? adapter.getItemsCount() : 0; |
| | | } |
| | | |
| | | public void setLabel(String label) { |
| | | this.label = label; |
| | | } |
| | | |
| | | public void isCenterLabel(boolean isCenterLabel) { |
| | | this.isCenterLabel = isCenterLabel; |
| | | } |
| | | |
| | | public void setGravity(int gravity) { |
| | | this.mGravity = gravity; |
| | | } |
| | | |
| | | public int getTextWidth(Paint paint, String str) { //calculate text width |
| | | int iRet = 0; |
| | | if (str != null && str.length() > 0) { |
| | | int len = str.length(); |
| | | float[] widths = new float[len]; |
| | | paint.getTextWidths(str, widths); |
| | | for (int j = 0; j < len; j++) { |
| | | iRet += (int) Math.ceil(widths[j]); |
| | | } |
| | | } |
| | | return iRet; |
| | | } |
| | | |
| | | public void setIsOptions(boolean options) { |
| | | isOptions = options; |
| | | } |
| | | |
| | | public void setTextColorOut(int textColorOut) { |
| | | |
| | | this.textColorOut = textColorOut; |
| | | paintOuterText.setColor(this.textColorOut); |
| | | } |
| | | |
| | | public void setTextColorCenter(int textColorCenter) { |
| | | this.textColorCenter = textColorCenter; |
| | | paintCenterText.setColor(this.textColorCenter); |
| | | } |
| | | |
| | | public void setTextXOffset(int textXOffset) { |
| | | this.textXOffset = textXOffset; |
| | | if (textXOffset != 0) { |
| | | paintCenterText.setTextScaleX(1.0f); |
| | | } |
| | | } |
| | | |
| | | public void setDividerWidth(int dividerWidth) { |
| | | this.dividerWidth = dividerWidth; |
| | | paintIndicator.setStrokeWidth(dividerWidth); |
| | | } |
| | | |
| | | public void setDividerColor(int dividerColor) { |
| | | this.dividerColor = dividerColor; |
| | | paintIndicator.setColor(dividerColor); |
| | | } |
| | | |
| | | public void setDividerType(DividerType dividerType) { |
| | | this.dividerType = dividerType; |
| | | } |
| | | |
| | | public void setLineSpacingMultiplier(float lineSpacingMultiplier) { |
| | | if (lineSpacingMultiplier != 0) { |
| | | this.lineSpacingMultiplier = lineSpacingMultiplier; |
| | | judgeLineSpace(); |
| | | } |
| | | } |
| | | |
| | | public boolean isLoop() { |
| | | return isLoop; |
| | | } |
| | | |
| | | public float getTotalScrollY() { |
| | | return totalScrollY; |
| | | } |
| | | |
| | | public void setTotalScrollY(float totalScrollY) { |
| | | this.totalScrollY = totalScrollY; |
| | | } |
| | | |
| | | public float getItemHeight() { |
| | | return itemHeight; |
| | | } |
| | | |
| | | public int getInitPosition() { |
| | | return initPosition; |
| | | } |
| | | |
| | | @Override |
| | | public Handler getHandler() { |
| | | return handler; |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <set xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | |
| | | |
| | | <alpha |
| | | android:duration="@integer/animation_default_duration" |
| | | android:fromAlpha="0.0" |
| | | android:toAlpha="1.0" /> |
| | | |
| | | <scale |
| | | android:duration="@integer/animation_default_duration" |
| | | android:fromXScale="0.0" |
| | | android:toXScale="1.0" |
| | | android:fromYScale="0.0" |
| | | android:toYScale="1.0" |
| | | android:pivotX="50%" |
| | | android:pivotY="50%"/> |
| | | |
| | | </set> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <set xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | |
| | | |
| | | <alpha |
| | | android:duration="@integer/animation_default_duration" |
| | | android:fromAlpha="1.0" |
| | | android:toAlpha="0.3" /> |
| | | |
| | | <scale |
| | | android:duration="@integer/animation_default_duration" |
| | | android:fromXScale="1.0" |
| | | android:toXScale="0.0" |
| | | android:fromYScale="1.0" |
| | | android:toYScale="0.0" |
| | | android:pivotX="50%" |
| | | android:pivotY="50%"/> |
| | | </set> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <set xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:shareInterpolator="false"> |
| | | |
| | | <translate |
| | | android:duration="@integer/animation_default_duration" |
| | | android:fromXDelta="0%" |
| | | android:toXDelta="0%" |
| | | android:fromYDelta="100%" |
| | | android:toYDelta="0%"/> |
| | | </set> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <set xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:shareInterpolator="false"> |
| | | |
| | | <translate |
| | | android:duration="@integer/animation_default_duration" |
| | | android:fromXDelta="0%" |
| | | android:toXDelta="0%" |
| | | android:fromYDelta="0%" |
| | | android:toYDelta="100%"/> |
| | | </set> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <selector |
| | | xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <item android:state_pressed="true" android:color="@color/pickerview_timebtn_pre" /> |
| | | <item android:color="@color/pickerview_timebtn_nor" /> |
| | | </selector> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:id="@+id/rv_topbar" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:background="@color/pickerview_bg_topbar"> |
| | | |
| | | <Button |
| | | android:id="@+id/btnCancel" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="match_parent" |
| | | android:background="@android:color/transparent" |
| | | android:gravity="left|center_vertical" |
| | | android:paddingLeft="@dimen/pickerview_topbar_padding" |
| | | android:text="@string/pickerview_cancel" |
| | | android:textAllCaps="false" |
| | | android:textColor="@drawable/selector_pickerview_btn" |
| | | android:textSize="@dimen/pickerview_topbar_btn_textsize" /> |
| | | |
| | | <TextView |
| | | android:id="@+id/tvTitle" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_centerVertical="true" |
| | | android:layout_toLeftOf="@+id/btnSubmit" |
| | | android:layout_toRightOf="@+id/btnCancel" |
| | | android:gravity="center" |
| | | android:textColor="@color/pickerview_topbar_title" |
| | | android:textSize="@dimen/pickerview_topbar_title_textsize" /> |
| | | |
| | | <Button |
| | | android:id="@id/btnSubmit" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="match_parent" |
| | | android:layout_alignParentRight="true" |
| | | android:background="@android:color/transparent" |
| | | android:gravity="right|center_vertical" |
| | | android:paddingRight="@dimen/pickerview_topbar_padding" |
| | | android:text="@string/pickerview_submit" |
| | | android:textAllCaps="false" |
| | | android:textColor="@drawable/selector_pickerview_btn" |
| | | android:textSize="@dimen/pickerview_topbar_btn_textsize" /> |
| | | </RelativeLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <FrameLayout |
| | | android:id="@+id/outmost_container" |
| | | xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:clickable="true" |
| | | android:background="@color/pickerview_bgColor_overlay"> |
| | | |
| | | <FrameLayout |
| | | android:id="@+id/content_container" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content"> |
| | | </FrameLayout> |
| | | |
| | | </FrameLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:orientation="vertical"> |
| | | |
| | | <include |
| | | layout="@layout/include_pickerview_topbar" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="@dimen/pickerview_topbar_height" /> |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/optionspicker" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:background="@android:color/white" |
| | | android:gravity="center" |
| | | android:minHeight="180dp" |
| | | android:orientation="horizontal"> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/options1" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/options2" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/options3" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | </LinearLayout> |
| | | |
| | | |
| | | </LinearLayout> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:orientation="vertical"> |
| | | |
| | | <include |
| | | layout="@layout/include_pickerview_topbar" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="@dimen/pickerview_topbar_height" /> |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/timepicker" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:background="@android:color/white" |
| | | android:gravity="center" |
| | | android:minHeight="150dp" |
| | | android:orientation="horizontal"> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/year" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="0.96" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/month" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/day" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/hour" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/min" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | |
| | | <com.contrarywind.view.WheelView |
| | | android:id="@+id/second" |
| | | android:layout_width="0dp" |
| | | android:layout_height="match_parent" |
| | | android:layout_weight="1" /> |
| | | </LinearLayout> |
| | | |
| | | |
| | | </LinearLayout> |
| | |
| | | <attr name="background_fillet" format="integer"/> |
| | | |
| | | </declare-styleable> |
| | | |
| | | <declare-styleable name="pickerview"> |
| | | <attr name="wheelview_gravity"> |
| | | <enum name="center" value="17"/> |
| | | <enum name="left" value="3"/> |
| | | <enum name="right" value="5"/> |
| | | </attr> |
| | | <attr name="wheelview_textSize" format="dimension"/> |
| | | <attr name="wheelview_textColorOut" format="color"/> |
| | | <attr name="wheelview_textColorCenter" format="color"/> |
| | | <attr name="wheelview_dividerColor" format="color"/> |
| | | <attr name="wheelview_dividerWidth" format="dimension"/> |
| | | <attr name="wheelview_lineSpacingMultiplier" format="float"/> |
| | | </declare-styleable> |
| | | </resources> |
| | |
| | | <color name="picker_border_color">#e5e5e5</color> |
| | | |
| | | <color name="transparent_background">#00000000</color> |
| | | <color name="pickerview_timebtn_nor">#057dff</color> |
| | | <color name="pickerview_timebtn_pre">#c2daf5</color> |
| | | <color name="pickerview_bg_topbar">#f5f5f5</color> |
| | | |
| | | <color name="pickerview_topbar_title">#000000</color> |
| | | <color name="pickerview_wheelview_textcolor_out">#a8a8a8</color> |
| | | <color name="pickerview_wheelview_textcolor_center">#2a2a2a</color> |
| | | <color name="pickerview_wheelview_textcolor_divider">#d5d5d5</color> |
| | | <color name="pickerview_bgColor_overlay">#60000000</color> |
| | | <color name="pickerview_bgColor_default">#FFFFFFFF</color> |
| | | </resources> |
New file |
| | |
| | | <resources> |
| | | <!-- 顶部按钮栏高度 --> |
| | | <dimen name="pickerview_topbar_height">44dp</dimen> |
| | | |
| | | <!-- 顶部按钮padding --> |
| | | <dimen name="pickerview_topbar_padding">20dp</dimen> |
| | | |
| | | <!-- 顶部按钮文字大小 --> |
| | | <dimen name="pickerview_topbar_btn_textsize">17sp</dimen> |
| | | <dimen name="pickerview_topbar_title_textsize">18sp</dimen> |
| | | <!-- 选项文字大小 --> |
| | | <dimen name="pickerview_textsize">20sp</dimen> |
| | | |
| | | </resources> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | |
| | | <integer name="animation_default_duration">300</integer> |
| | | </resources> |
| | |
| | | <resources> |
| | | <string name="app_name">TeaPickerView</string> |
| | | <string name="pickerview_cancel">取消</string> |
| | | <string name="pickerview_submit">确定</string> |
| | | <string name="pickerview_year">年</string> |
| | | <string name="pickerview_month">月</string> |
| | | <string name="pickerview_day">日</string> |
| | | <string name="pickerview_hours">时</string> |
| | | <string name="pickerview_minutes">分</string> |
| | | <string name="pickerview_seconds">秒</string> |
| | | </resources> |
| | |
| | | <item name="android:windowExitAnimation">@anim/slide_out_to_bottom</item> |
| | | </style> |
| | | |
| | | <style name="custom_dialog2" parent="@android:style/Theme.Dialog"> |
| | | <item name="android:windowFrame">@null</item> |
| | | <!-- Dialog的windowFrame框为无 --> |
| | | <item name="android:windowIsFloating">true</item> |
| | | <!-- 是否漂现在activity上 --> |
| | | <item name="android:windowIsTranslucent">true</item> |
| | | <!-- 是否半透明 --> |
| | | <item name="android:windowNoTitle">true</item> |
| | | <item name="android:background">@null</item> |
| | | <item name="android:windowBackground">@android:color/transparent</item> |
| | | <item name="android:windowContentOverlay">@null</item> |
| | | <!-- 去除黑色边框的关键设置项 --> |
| | | <item name="android:backgroundDimEnabled">true</item> |
| | | <!-- 屏幕背景是否变暗 --> |
| | | <item name="android:backgroundDimAmount">0.3</item> |
| | | </style> |
| | | |
| | | <style name="picker_view_scale_anim" mce_bogus="1" parent="android:Animation"> |
| | | <item name="android:windowEnterAnimation">@anim/pickerview_dialog_scale_in</item> |
| | | <item name="android:windowExitAnimation">@anim/pickerview_dialog_scale_out</item> |
| | | </style> |
| | | |
| | | |
| | | <style name="picker_view_slide_anim" mce_bogus="1" parent="android:Animation"> |
| | | <item name="android:windowEnterAnimation">@anim/pickerview_slide_in_bottom</item> |
| | | <item name="android:windowExitAnimation">@anim/pickerview_slide_out_bottom</item> |
| | | </style> |
| | | </resources> |
| | |
| | | |
| | | |
| | | compileOnly group: 'net.sourceforge.jexcelapi', name: 'jxl', version: '2.6.12' |
| | | compileOnly 'com.wang.avi:library:2.1.3' |
| | | |
| | | //地址选择 |
| | | implementation project(':pickerviewlibrary') |
| | | compileOnly project(':pickerviewlibrary') |
| | | implementation project(':ocridcardlibrary') |
| | | implementation project(':baselibrary') |
| | | |
| | | compileOnly 'com.tencent.bugly:crashreport:4.1.9.3' |
| | | // 处理图片 |
| | | // implementation (name: 'ocr-library', ext: 'aar') |
| | | //权限申请 |
| | | compileOnly 'com.github.getActivity:XXPermissions:18.5' |
| | | //滚动选择框 |
| | | compileOnly 'com.contrarywind:Android-PickerView:4.1.9' |
| | | |
| | | // compileOnly 'com.contrarywind:Android-PickerView:4.1.9' |
| | | implementation files('../baselibrary/libs/avi.library-2.1.3.aar') |
| | | //列表 |
| | | compileOnly 'io.github.scwang90:refresh-layout-kernel:2.0.5' |
| | | compileOnly 'io.github.scwang90:refresh-header-classics:2.0.5' |
| | |
| | | path "CMakeLists.txt" |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | dependencies { |
| | |
| | | |
| | | implementation project(':ocridcardlibrary') |
| | | implementation project(':baselibrary') |
| | | compileOnly project(':pickerviewlibrary') |
| | | //数据库 |
| | | implementation "androidx.room:room-runtime:2.3.0" |
| | | implementation "androidx.room:room-ktx:2.3.0" |
| | |
| | | compileOnly 'io.github.scwang90:refresh-header-classics:2.0.5' |
| | | compileOnly 'androidx.recyclerview:recyclerview:1.2.0'//经典刷新头 |
| | | |
| | | compileOnly 'com.wang.avi:library:2.1.3' |
| | | //将注释掉的远程依赖改为本地aar引用 |
| | | implementation files('../baselibrary/libs/avi.library-2.1.3.aar') |
| | | |
| | | compileOnly group: 'net.sourceforge.jexcelapi', name: 'jxl', version: '2.6.12' |
| | | } |
| | | |
| | |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.utils.TipUtil; |
| | | import com.dayu.baselibrary.utils.ToastUtil; |
| | | import com.dayu.qiheonlinelibrary.activity.HomeActivityQHOline; |
| | |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.RSAUtile; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | |
| | | |
| | | import androidx.recyclerview.widget.LinearLayoutManager; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.utils.BaseCommon; |
| | | import com.dayu.baselibrary.utils.DeviceUtils; |
| | | import com.dayu.baselibrary.utils.TipUtil; |
| | |
| | | import com.dayu.qiheonlinelibrary.dbBean.UserCardBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | |
| | | import com.scwang.smart.refresh.footer.ClassicsFooter; |
| | | import com.scwang.smart.refresh.header.ClassicsHeader; |
| | | import com.scwang.smart.refresh.layout.api.RefreshLayout; |
| | |
| | | import android.os.Bundle; |
| | | import android.view.LayoutInflater; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.tools.HexUtil; |
| | | import com.dayu.baselibrary.utils.BaseCommon; |
| | | import com.dayu.baselibrary.utils.TipUtil; |
| | |
| | | import com.dayu.qiheonlinelibrary.dbBean.UserCardBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.tools.NfcReadHelper; |
| | | import com.dayu.qiheonlinelibrary.utils.CardCommon; |
| | | import com.dayu.qiheonlinelibrary.view.ProgressDialog; |
| | |
| | | import android.view.LayoutInflater; |
| | | import android.view.View; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.tools.HexUtil; |
| | | import com.dayu.baselibrary.utils.BaseCommon; |
| | | import com.dayu.baselibrary.utils.DeviceUtils; |
| | |
| | | import com.dayu.qiheonlinelibrary.dbBean.UserCardBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.tools.NfcReadHelper; |
| | | import com.dayu.qiheonlinelibrary.tools.WriteCardUtils; |
| | | import com.dayu.qiheonlinelibrary.utils.CardCommon; |
| | |
| | | NFCWreatActivityQHOline.nfcWreatActivity.finish(); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | super.onDestroy(); |
| | | nfcWreatActivity = null; |
| | |
| | | |
| | | import androidx.annotation.NonNull; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.tools.Utils; |
| | | import com.dayu.baselibrary.utils.DeviceUtils; |
| | | import com.dayu.baselibrary.utils.TipUtil; |
| | |
| | | import com.dayu.qiheonlinelibrary.dbBean.UserCardBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | import com.hjq.permissions.OnPermissionCallback; |
| | | import com.hjq.permissions.Permission; |
| | | import com.hjq.permissions.XXPermissions; |
| | |
| | | import android.view.LayoutInflater; |
| | | import android.view.View; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.utils.MornyUtil; |
| | | import com.dayu.baselibrary.utils.TipUtil; |
| | | import com.dayu.baselibrary.view.ConfirmDialog; |
| | |
| | | import com.dayu.qiheonlinelibrary.dbBean.AdminDataBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.tools.NfcReadHelper; |
| | | import com.dayu.qiheonlinelibrary.utils.CardCommon; |
| | | import com.dayu.qiheonlinelibrary.view.ProgressDialog; |
| | |
| | | import android.view.View; |
| | | import android.widget.EditText; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.baselibrary.utils.DeviceUtils; |
| | | import com.dayu.baselibrary.utils.MornyUtil; |
| | | import com.dayu.baselibrary.utils.TipUtil; |
| | |
| | | import com.dayu.qiheonlinelibrary.dbBean.RechargeBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.tools.NfcReadHelper; |
| | | import com.dayu.qiheonlinelibrary.utils.CardCommon; |
| | | import com.tencent.bugly.crashreport.CrashReport; |
| | |
| | | CardInfoResult cardInfoResult; |
| | | |
| | | |
| | | |
| | | @Override |
| | | protected void onCreate(Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | |
| | | CrashReport.postCatchedException(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | | super.onDestroy(); |
| | | rechargeActivity = null; |
| | |
| | | |
| | | import androidx.recyclerview.widget.LinearLayoutManager; |
| | | |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.adapter.UserSearchAdapter; |
| | | import com.dayu.qiheonlinelibrary.bean.UserListResult; |
| | | import com.dayu.qiheonlinelibrary.databinding.ActivityUserSearchQhlBinding; |
| | | import com.dayu.qiheonlinelibrary.dbBean.UserCardBean; |
| | | import com.dayu.qiheonlinelibrary.net.ApiManager; |
| | | import com.dayu.qiheonlinelibrary.net.BaseResponse; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.view.UserSearchDialog; |
| | | import com.scwang.smart.refresh.footer.ClassicsFooter; |
| | | import com.scwang.smart.refresh.layout.api.RefreshLayout; |
| | |
| | | import android.text.TextUtils; |
| | | |
| | | import com.dayu.baselibrary.business.BusinessProvider; |
| | | import com.dayu.baselibrary.net.subscribers.BaseProgressSubscriber; |
| | | import com.dayu.baselibrary.net.subscribers.ProgressSubscriber; |
| | | import com.dayu.baselibrary.net.subscribers.SubscriberListener; |
| | | import com.dayu.qiheonlinelibrary.bean.BaseResult; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.BaseProgressSubscriber; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.ProgressSubscriber; |
| | | import com.dayu.qiheonlinelibrary.net.subscribers.SubscriberListener; |
| | | |
| | | import com.dayu.qiheonlinelibrary.utils.MyJsonParser; |
| | | |
| | | import java.util.List; |
| | |
| | | public class ApiManager { |
| | | |
| | | static ApiManager apiManager; |
| | | //文件上传失败重复次数 |
| | | int uplodFilerepeatSize = 3; |
| | | |
| | | ApiService apiService; |
| | | |
| | |
| | | if (BusinessProvider.getBusinessProvider() != null) { |
| | | BusinessProvider.getBusinessProvider().startLoginNavigotor.navigateToLogin(context); |
| | | } |
| | | |
| | | } |
| | | |
| | | response.setCode(tem.getCode()); |
| | | response.setMsg(tem.getMsg()); |
| | | if (tClass != null) { |
| | |
| | | include ':henanlibrary' |
| | | include ':qihealonelibrary' |
| | | include ':qiheonlinelibrary' |
| | | include ':generallibrary' |