diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..9fbfb0a --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,40 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.yinuo.commonlibtest" + minSdkVersion 23 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + implementation project(path: ':commonLib') + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/yinuo/commonlibtest/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/yinuo/commonlibtest/ExampleInstrumentedTest.java new file mode 100644 index 0000000..82e98bd --- /dev/null +++ b/app/src/androidTest/java/com/yinuo/commonlibtest/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.yinuo.commonlibtest; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.yinuo.commonlibtest", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..321a4ca --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java b/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java new file mode 100644 index 0000000..f3ade52 --- /dev/null +++ b/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java @@ -0,0 +1,14 @@ +package com.yinuo.commonlibtest; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; + +public class MainActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4fc2444 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a571e60 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..61da551 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..c41dd28 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..db5080a Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6dba46d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..da31a87 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..15ac681 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b216f2d Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..f25a419 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..e96783c Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..be7ceb7 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..5c61ca5 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + CommonLibTest + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..b01a890 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/test/java/com/yinuo/commonlibtest/ExampleUnitTest.java b/app/src/test/java/com/yinuo/commonlibtest/ExampleUnitTest.java new file mode 100644 index 0000000..cf66f31 --- /dev/null +++ b/app/src/test/java/com/yinuo/commonlibtest/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.yinuo.commonlibtest; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..87611b4 --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply from: "commonLibConfig.gradle" +buildscript { + ext.kotlin_version = "1.5.21" + repositories { + google() + mavenCentral() + } + dependencies { + classpath "com.android.tools.build:gradle:4.2.2" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + mavenCentral() + jcenter() // Warning: this repository is going to shut down soon + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/commonLib/.gitignore b/commonLib/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/commonLib/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/commonLib/build.gradle b/commonLib/build.gradle new file mode 100644 index 0000000..07004a9 --- /dev/null +++ b/commonLib/build.gradle @@ -0,0 +1,53 @@ +plugins { + id 'com.android.library' + id 'kotlin-android' + id 'kotlin-android-extensions' + id 'kotlin-kapt' +} + +android { + compileSdkVersion rootProject.ext.android.compileSdkVersion + buildToolsVersion rootProject.ext.android.buildToolsVersion + + defaultConfig { + minSdkVersion rootProject.ext.android.minSdkVersion + targetSdkVersion rootProject.ext.android.targetSdkVersion + versionCode rootProject.ext.android.versionCode + versionName rootProject.ext.android.versionName + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + debug { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + + implementation 'androidx.navigation:navigation-fragment:2.3.0' + implementation 'androidx.navigation:navigation-ui:2.3.0' + + // 添加kotlin依赖 + implementation rootProject.ext.dependencies.kotlin + implementation rootProject.ext.dependencies.kotlin_android + + //luban图片压缩 + implementation rootProject.ext.dependencies.luban +} \ No newline at end of file diff --git a/commonLib/consumer-rules.pro b/commonLib/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/commonLib/proguard-rules.pro b/commonLib/proguard-rules.pro new file mode 100644 index 0000000..34cee7f --- /dev/null +++ b/commonLib/proguard-rules.pro @@ -0,0 +1,131 @@ +# 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 +# 有了verbose这句话,混淆后就会生成映射文件 +# 包含有类名->混淆后类名的映射关系 +# 然后使用printmapping指定映射文件的名称 +-verbose +-printmapping priguardMapping.txt + +# 保留所有的本地native方法不被混淆 +-keepclasseswithmembernames class * { + native ; +} + +# 保护代码中的Annotation不被混淆 +# 这在JSON实体映射时非常重要,比如fastJson +-keepattributes *Annotation* + +# 避免混淆泛型 +# 这在JSON实体映射时非常重要,比如fastJson +-keepattributes Signature + +# 抛出异常时保留代码行号 +-keepattributes SourceFile,LineNumberTable + +# 对R文件下的所有类及其方法,都不能被混淆 +-keepclassmembers class **.R$* { + *; +} + +# 保留了继承自Activity、Application这些类的子类 +# 因为这些子类有可能被外部调用 +# 比如第一行就保证了所有Activity的子类不要被混淆 +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class * extends android.view.View + +# 枚举类不能被混淆 +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# 保留自定义控件(继承自View)不能被混淆 +-keep public class * extends android.view.View { + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); + public void set*(***); + *** get* (); +} + +# 保留Parcelable序列化的类不能被混淆 +-keep class * implements android.os.Parcelable{ + public static final android.os.Parcelable$Creator *; +} + +# 保留Serializable 序列化的类不被混淆 +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + !static !transient ; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} + + +# AndroidX混淆 +-keep class com.google.android.material.** {*;} +-keep class androidx.** {*;} +-keep public class * extends androidx.** +-keep interface androidx.** {*;} +-dontwarn com.google.android.material.** +-dontnote com.google.android.material.** +-dontwarn androidx.** + +# 保留BaseFragment公共成员和方法不被混淆 +-keep class com.yinuo.commonlib.utils.*{*;} + +# 保留BaseFragment公共成员和方法不被混淆 +-keep class com.yinuo.commonlib.view.fragment.BaseFragment{ + public; + public; +} +# 保留BaseNavigationFragment公共成员和方法不被混淆 +-keep class com.yinuo.commonlib.view.fragment.BaseNavigationFragment{ + public; + public; +} +# 保留BaseActivity公共成员和方法不被混淆 +-keep class com.yinuo.commonlib.view.activity.BaseActivity{ + public; + public; +} + +# 保留CommonTitleView的内部类不被混淆 +-keep class com.yinuo.commonlib.view.CommonTitleView$*{ + *; +} + +# 保留BaseNavigationFragment公共成员和方法不被混淆 +-keep class com.yinuo.commonlib.view.SlideRecyclerView{ + public; + public; +} diff --git a/commonLib/src/main/AndroidManifest.xml b/commonLib/src/main/AndroidManifest.xml new file mode 100644 index 0000000..cac29a8 --- /dev/null +++ b/commonLib/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/utils/BaseUtils.kt b/commonLib/src/main/java/com/yinuo/commonlib/utils/BaseUtils.kt new file mode 100644 index 0000000..1084db8 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/utils/BaseUtils.kt @@ -0,0 +1,118 @@ +package com.yinuo.commonlib.utils + +import android.annotation.SuppressLint +import android.content.Context +import android.text.TextUtils +import java.text.SimpleDateFormat +import java.util.* +import kotlin.collections.ArrayList + +object BaseUtils { + private const val TAG: String = "BaseUtils" + + /** + * 如果使用大写HH标识使用24小时显示格式,如果使用小写hh就表示使用12小时制格式 + */ + const val DATE_TO_STRING_DETAIL_PATTERN = "yyyy-MM-dd HH:mm:ss" + + /** + * 年-月-日 显示格式 + * */ + const val DATE_TO_STRING_SHORT_PATTERN = "yyyy.MM.dd" + + /** + * 年-月-日 显示格式 + * */ + const val DATE_TO_STRING_LONG_PATTERN = "yyyy_MM_dd HH:mm:ss" + + /** + * 60秒 + */ + const val SECONDS = 60 + + /** + * 60分钟 + */ + const val MINUS = 60 + + fun isListEmpty(list: List?): Boolean { + return list == null || list.isEmpty() + } + + @SuppressLint("SimpleDateFormat") + fun getNowTimeFormat(format:String): String { + val formatter = SimpleDateFormat(format) + return formatter.format(getNow()) + } + + /** + * 得到现在时间 + * + * @return + */ + private fun getNow(): Date { + return Date() + } + + /** + * 将字符串List转化为用 | 分割的字符串 + */ + fun getStringSeparateByLine(list: List): String { + var result = "" + for (item in list.withIndex()) { + result = if (item.index == (list.size - 1)) { + "$result${item.value}" + } else { + "$result${item.value}|" + } + } + return result + } + + /** + * 将 | 分割符转化为list + */ + fun getListByString(source: String): List { + if (TextUtils.isEmpty(source)) { + return ArrayList() + } + return source.split("|") + } + + /** + * 将int型的数据转化成 XX:XX:XX" 形式的字符串 + */ + fun getDurationTimeByInt(source: Int): String { + var temp = source + var h = 0 + var m = 0 + var s = 0 + var result = "" + if (temp >= SECONDS * MINUS) { + h = temp / (SECONDS * MINUS) + temp -= h * (SECONDS * MINUS) + } + if (temp >= SECONDS) { + m = temp / SECONDS + temp -= m * SECONDS + } + s = temp + + result = when { + h > 0 -> { + "$h:$m:$s\"" + } + m > 0 -> { + "$m:$s\"" + } + else -> { + "$s\"" + } + } + return result + } + + fun getExternalStoragePath(context: Context): String? { + return context.getExternalFilesDir(null)?.path + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/utils/DisplayUtils.kt b/commonLib/src/main/java/com/yinuo/commonlib/utils/DisplayUtils.kt new file mode 100644 index 0000000..0a8e3a7 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/utils/DisplayUtils.kt @@ -0,0 +1,16 @@ +package com.yinuo.commonlib.utils + +import android.content.Context + +object DisplayUtils { + + fun dp2px(context: Context, dpVale: Float): Int { + val density = context.resources.displayMetrics.density + return ((dpVale * density + 0.5f).toInt()) + } + + fun px2dp(context: Context, pxVale: Float): Int { + val density = context.resources.displayMetrics.density + return ((pxVale / density + 0.5f).toInt()) + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/utils/PhotoUtils.kt b/commonLib/src/main/java/com/yinuo/commonlib/utils/PhotoUtils.kt new file mode 100644 index 0000000..c779db1 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/utils/PhotoUtils.kt @@ -0,0 +1,111 @@ +package com.yinuo.commonlib.utils + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.util.Log +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import top.zibin.luban.Luban +import top.zibin.luban.OnCompressListener +import java.io.File +import java.io.FileOutputStream +import java.text.SimpleDateFormat +import java.util.* + + +object PhotoUtils { + private const val TAG = "PhotoUtils"; + + /** + * 根据时间生成照片文件 + */ + fun generatePhotoFileByTime(context: Context, photoPath: String): File { + val rootPath: String = context.applicationContext.getExternalFilesDir(null)?.path ?: "" + val savePhotoFolderPath: String = rootPath + photoPath + val savePhotoFolder = File(savePhotoFolderPath) + if (!savePhotoFolder.exists()) { + //创建路径,需要权限 + savePhotoFolder.mkdirs() + } + val photoName = SimpleDateFormat("yyyy_MM_dd_hh_mm_ss_SSS").format(Date()) + ".png" + + return File(savePhotoFolder, photoName) + + } + + fun initPicPath(context: Context?, photoPath: String): String { + val rootPath: String = context?.getExternalFilesDir(null)?.path ?: "" + val savePhotoFilePath: String = rootPath + photoPath + val file = File(savePhotoFilePath) + if (!file.exists()) { + //创建路径,需要权限 + file.mkdirs() + } + val photoName = SimpleDateFormat("yyyy_MM_dd_hh_mm_ss_SSS").format(Date()) + ".png" + return "$savePhotoFilePath/$photoName" + } + + /** + * 得到保存图片的文件夹地址 + */ + fun getImageParentPath(context: Context, photoPath: String): String { + val rootPath: String = context.getExternalFilesDir(null)?.path ?: "" + val savePhotoFilePath: String = rootPath + photoPath + val file = File(savePhotoFilePath) + if (!file.exists()) { + //创建路径,需要权限 + file.mkdirs() + } + return savePhotoFilePath + } + + /** + * 压缩图片,使用Luban框架压缩处理 + */ + fun compressPicture( + context: Context, + file: File, + targetDir: String, + listener: OnCompressListener + ) { + Luban.with(context.applicationContext) + .load(file) + .ignoreBy(100) + .setTargetDir(targetDir) + .setCompressListener(listener).launch() + } + + /** + *把其他格式的图片转换成png格式的图片,耗时操作 + * originImageFile:原图片文件 + * imgSavePath:图片要保存的地址,如:/sdcard/0/emulator/data/xxx.xxx.xx/file/test.png + */ + fun tans2PNGSave(originImageFile: File?, imgSavePath: String?, callBack: TransformCallBack) { + GlobalScope.launch(Dispatchers.IO) { + val decodeFile = BitmapFactory.decodeFile(originImageFile?.absolutePath) + var out: FileOutputStream? = null + try { + out = FileOutputStream(File(imgSavePath)) + decodeFile.compress(Bitmap.CompressFormat.PNG, 90, out) + out.flush() + out.close() + } catch (e: Exception) { + Log.e(TAG, "tans2PNGSave error==" + e.message) + } finally { + out?.close() + } + + GlobalScope.launch(Dispatchers.Main) { + //通知主线程图片保存成功 + callBack.onSuccess() + } + } + } + + interface TransformCallBack { + fun onSuccess() + fun onError(); + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/utils/SpManager.kt b/commonLib/src/main/java/com/yinuo/commonlib/utils/SpManager.kt new file mode 100644 index 0000000..5ae93c5 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/utils/SpManager.kt @@ -0,0 +1,30 @@ +package com.yinuo.commonlib.utils + +import android.annotation.SuppressLint +import android.content.Context +import android.content.SharedPreferences + + +/** + * sharedPreference管理类 + */ +object SpManager { + const val HAS_INIT = "has_init" + private var sp: SharedPreferences? = null + private var editor: SharedPreferences.Editor? = null + + @SuppressLint("CommitPrefEdits") + fun init(context: Context, name: String, mod: Int) { + sp = context.getSharedPreferences(name, mod) + editor = sp!!.edit() + } + + fun putBoolean(key: String, boolean: Boolean) { + editor!!.putBoolean(key, boolean) + editor!!.apply() + } + + fun getBoolean(key: String): Boolean { + return sp!!.getBoolean(key, false) + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/CommonTitleView.java b/commonLib/src/main/java/com/yinuo/commonlib/view/CommonTitleView.java new file mode 100644 index 0000000..d7d90cc --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/CommonTitleView.java @@ -0,0 +1,233 @@ +package com.yinuo.commonlib.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.navigation.Navigation; + +import com.yinuo.commonlib.R; +import com.yinuo.commonlib.utils.DisplayUtils; + +public class CommonTitleView extends FrameLayout implements View.OnClickListener { + private Context mContext; + private ImageView ivBack; + private TextView tv_title; + private ImageView ivAdd; + private TextView tv_edit; + private int showStyle; + + private static final int STYLE_LEFT = 1; + private static final int STYLE_LEFT_MIDDLE = 2; + private static final int STYLE_LEFT_MIDDLE_RIGHT = 3; + private static final int STYLE_MIDDLE = 4; + private static final int STYLE_MIDDLE_RIGHT = 5; + private static final int STYLE_RIGHT = 6; + private static final int STYLE_EDIT = 7; + private String title; + //是否要固定高度的模式,不受match parent\warp content等影响 + private boolean isFixedHeight; + //设置固定的高度值,默认是48dp + private int fixedHeight; + + private static final int DEFAULT_HEIGHT = 48; + private View rlBackHotZone; + private View rlAddHotZone; + private View rlEditZone; + + public CommonTitleView(Context context) { + this(context, null); + } + + public CommonTitleView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CommonTitleView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + init(attrs); + } + + private void init(AttributeSet attrs) { + initAttrs(attrs); + LayoutInflater.from(mContext).inflate(R.layout.common_title_view, this, true); + ivBack = findViewById(R.id.iv_back); + ivAdd = findViewById(R.id.iv_add); + tv_title = findViewById(R.id.tv_title); + rlBackHotZone = findViewById(R.id.rl_back_hot_zone); + rlAddHotZone = findViewById(R.id.rl_add_hot_zone); + tv_edit = findViewById(R.id.tv_edit); + rlEditZone = findViewById(R.id.rl_edit_hot_zone); + initStyle(); + setTitle(title); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (isFixedHeight) { + int makeMeasureSpec = MeasureSpec.makeMeasureSpec(fixedHeight, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, makeMeasureSpec); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + private void initStyle() { + switch (showStyle) { + case STYLE_LEFT: + ivBack.setVisibility(VISIBLE); + rlBackHotZone.setOnClickListener(this); + tv_title.setVisibility(INVISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(INVISIBLE); + rlAddHotZone.setOnClickListener(null); + break; + case STYLE_LEFT_MIDDLE: + ivBack.setVisibility(VISIBLE); + rlBackHotZone.setOnClickListener(this); + tv_title.setVisibility(VISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(INVISIBLE); + rlAddHotZone.setOnClickListener(null); + break; + case STYLE_MIDDLE_RIGHT: + ivBack.setVisibility(INVISIBLE); + rlBackHotZone.setOnClickListener(null); + tv_title.setVisibility(VISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(VISIBLE); + rlAddHotZone.setOnClickListener(this); + break; + case STYLE_RIGHT: + ivBack.setVisibility(INVISIBLE); + rlBackHotZone.setOnClickListener(null); + tv_title.setVisibility(INVISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(VISIBLE); + rlAddHotZone.setOnClickListener(this); + break; + case STYLE_LEFT_MIDDLE_RIGHT: + ivBack.setVisibility(VISIBLE); + rlBackHotZone.setOnClickListener(this); + tv_title.setVisibility(VISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(VISIBLE); + rlAddHotZone.setOnClickListener(this); + break; + case STYLE_EDIT: + ivBack.setVisibility(VISIBLE); + rlBackHotZone.setOnClickListener(this); + tv_title.setVisibility(VISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(GONE); + rlAddHotZone.setVisibility(GONE); + rlAddHotZone.setOnClickListener(null); + tv_edit.setVisibility(VISIBLE); + rlEditZone.setVisibility(VISIBLE); + rlEditZone.setOnClickListener(this); + break; + case STYLE_MIDDLE: + default: + ivBack.setVisibility(INVISIBLE); + rlBackHotZone.setOnClickListener(null); + tv_title.setVisibility(VISIBLE); + tv_title.setText(""); + ivAdd.setVisibility(INVISIBLE); + rlAddHotZone.setOnClickListener(null); + break; + } + } + + private void initAttrs(AttributeSet attrs) { + TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.CommonTitleView); + showStyle = typedArray.getInt(R.styleable.CommonTitleView_show_style, STYLE_MIDDLE); + title = typedArray.getString(R.styleable.CommonTitleView_title); + isFixedHeight = typedArray.getBoolean(R.styleable.CommonTitleView_is_fixed_height, true); + fixedHeight = typedArray.getInteger(R.styleable.CommonTitleView_fixed_height, DisplayUtils.INSTANCE.dp2px(mContext, DEFAULT_HEIGHT)); + + typedArray.recycle(); + + } + + public void setTitle(String title) { + this.title = title; + tv_title.setText(title); + } + + + @Override + public void onClick(View v) { + int viewId = v.getId(); + if (viewId == R.id.rl_back_hot_zone) { + if (backButtonListener != null) { + backButtonListener.onClick(); + } else { + Navigation.findNavController(this).navigateUp(); + } + } else if (viewId == R.id.rl_add_hot_zone) { + if (addListener != null) { + addListener.onClick(); + } + } else if (viewId == R.id.rl_edit_hot_zone) { + if (editListener != null) { + editListener.onClick(); + } + } + } + + public interface BackButtonListener { + void onClick(); + } + + private BackButtonListener backButtonListener; + + public void setBackButtonListener(BackButtonListener backButtonListener) { + this.backButtonListener = backButtonListener; + } + + public interface AddListener { + void onClick(); + } + + private AddListener addListener; + + public void setAddListener(AddListener addListener) { + this.addListener = addListener; + } + + public interface EditListener { + void onClick(); + } + + private EditListener editListener; + + public void setEditListener(EditListener editListener) { + this.editListener = editListener; + } + + public int getEditState() { + if (tv_edit.getText().equals(mContext.getResources().getString(R.string.edit))) { + return 0; + } else if (tv_edit.getText().equals(mContext.getResources().getString(R.string.save))) { + return 1; + } else { + return -1; + } + } + + public void setEditText(int state) { + if (state == 0) { + tv_edit.setText(mContext.getResources().getString(R.string.edit)); + } else if (state == 1) { + tv_edit.setText(mContext.getResources().getString(R.string.save)); + } else { + tv_edit.setText(""); + } + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/MikeView.java b/commonLib/src/main/java/com/yinuo/commonlib/view/MikeView.java new file mode 100644 index 0000000..bbe6bc6 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/MikeView.java @@ -0,0 +1,155 @@ +package com.yinuo.commonlib.view; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.yinuo.commonlib.R; + +public class MikeView extends View { + //进度条格数 + private final int COUNT = 16; + //宽、高、间隔、进度条居上距离 + private int mVoiceRectW = 1; + private int mVoiceRectH = 10; + private int mInterval = 3; + private int mVoiceRectMarginTop = 83; + //mic 文字 进度条 背景 + private Paint mImagePaint; + private Paint mVoiceRectPaint; + private Paint mBackgroundPaint; + + private Bitmap mVoiceRecording;//mic图片 + + //屏幕宽高 + private int SCREEN_HEIGHT = 0; + private int SCREEN_WIDTH = 0; + + private int mVoiceRectStart = 0, mDescriptionW = 0;//进度条开始左边位置、文字长度 + + private int mCurrentPosition = 0;//当前位置 + private int mBackgroundRound = 3;//背景圆角 + + private int mImageW = 42;//新mic图片宽 + private int mImageH = 42;//新mic图片高 + + private int mMarginTop = 25, mTextMarginBottom = 11;//mic图片居上距离 文字居底部距离 + + public MikeView(Context context) { + this(context, null); + } + + public MikeView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public MikeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + DisplayMetrics dm = getResources().getDisplayMetrics(); + + mImageW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mImageW, dm); + mImageH = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mImageH, dm); + mMarginTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMarginTop, dm); + mTextMarginBottom = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mTextMarginBottom, dm); + mVoiceRectW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mVoiceRectW, dm); + mVoiceRectH = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mVoiceRectH, dm); + mInterval = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mInterval, dm); + mVoiceRectMarginTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mVoiceRectMarginTop, dm); + mBackgroundRound = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBackgroundRound, dm); + + mImagePaint = new Paint(); + + mVoiceRectPaint = new Paint(); + mVoiceRectPaint.setColor(Color.WHITE); + + mBackgroundPaint = new Paint(); + mBackgroundPaint.setColor(Color.TRANSPARENT);//背景颜色 + + mVoiceRecording = BitmapFactory.decodeResource(getResources(), R.drawable.mike); + mVoiceRecording = scaleBitmap(mVoiceRecording, mImageW, mImageH); + + setWillNotDraw(false); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (SCREEN_HEIGHT == 0 || SCREEN_WIDTH == 0) { + SCREEN_HEIGHT = getHeight(); + SCREEN_WIDTH = getWidth(); + } + if (mVoiceRectStart <= 0) { + mVoiceRectStart = SCREEN_WIDTH / 2 - (COUNT * mVoiceRectW + (COUNT - 1) * mInterval) / 2; + } + + canvas.drawRoundRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, mBackgroundRound, mBackgroundRound, mBackgroundPaint);//画灰色背景和圆角 + + canvas.drawBitmap(mVoiceRecording, SCREEN_WIDTH / 2 - mVoiceRecording.getWidth() / 2, mMarginTop, mImagePaint);//画mic图片 + + //画前几个是白色 后几个是灰色 + for (int i = 0; i < COUNT; i++) { + if (i < mCurrentPosition) { + mVoiceRectPaint.setColor(Color.WHITE); + } else { + mVoiceRectPaint.setColor(Color.parseColor("#73FFFFFF")); + } + canvas.drawRect(i * mVoiceRectW + (i * mInterval) + mVoiceRectStart, mVoiceRectMarginTop, i * mVoiceRectW + (i * mInterval) + mVoiceRectW + mVoiceRectStart, mVoiceRectMarginTop + mVoiceRectH, mVoiceRectPaint); + } + } + + public void setIndex(int p) { + if (p < 0) { + p = 0; + } + if (p >= COUNT) { + p = COUNT - 1; + } + + mCurrentPosition = p; + postInvalidate(); + } + + public void setIndex(double percent) { + int p = (int) (COUNT * percent); + setIndex(p); + } + + /** + * bitmap 缩放 + * + * @param origin 源 + * @param newWidth 宽 + * @param newHeight 高 + * @return bitmap + */ + private Bitmap scaleBitmap(Bitmap origin, int newWidth, int newHeight) { + if (origin == null) { + return null; + } + int height = origin.getHeight(); + int width = origin.getWidth(); + float scaleWidth = ((float) newWidth) / width; + float scaleHeight = ((float) newHeight) / height; + Matrix matrix = new Matrix(); + matrix.postScale(scaleWidth, scaleHeight);// 使用后乘 + Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false); + if (!origin.isRecycled()) { + origin.recycle(); + } + return newBM; + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/SlideRecyclerView.java b/commonLib/src/main/java/com/yinuo/commonlib/view/SlideRecyclerView.java new file mode 100644 index 0000000..47d875c --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/SlideRecyclerView.java @@ -0,0 +1,217 @@ +package com.yinuo.commonlib.view; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.Scroller; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * 支持侧滑删除的RecyclerView + *

+ * Created by DavidChen on 2018/5/29. + */ + +public class SlideRecyclerView extends RecyclerView { + private static final String TAG = "SlideRecyclerView"; + private static final int INVALID_POSITION = -1; // 触摸到的点不在子View范围内 + private static final int INVALID_CHILD_WIDTH = -1; // 子ItemView不含两个子View + private static final int SNAP_VELOCITY = 600; // 最小滑动速度 + + private VelocityTracker mVelocityTracker; // 速度追踪器 + private int mTouchSlop; // 认为是滑动的最小距离(一般由系统提供) + private Rect mTouchFrame; // 子View所在的矩形范围 + private Scroller mScroller; + private float mLastX; // 滑动过程中记录上次触碰点X + private float mFirstX, mFirstY; // 首次触碰范围 + private boolean mIsSlide; // 是否滑动子View + private ViewGroup mFlingView; // 触碰的子View + private int mPosition; // 触碰的view的位置 + private int mMenuViewWidth; // 菜单按钮宽度 + + public SlideRecyclerView(Context context) { + this(context, null); + } + + public SlideRecyclerView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlideRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + mScroller = new Scroller(context); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + int x = (int) e.getX(); + int y = (int) e.getY(); + obtainVelocity(e); + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: + if (!mScroller.isFinished()) { // 如果动画还没停止,则立即终止动画 + mScroller.abortAnimation(); + } + mFirstX = mLastX = x; + mFirstY = y; + mPosition = pointToPosition(x, y); // 获取触碰点所在的position + if (mPosition != INVALID_POSITION) { + View view = mFlingView; + // 获取触碰点所在的view + mFlingView = (ViewGroup) getChildAt(mPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition()); + // 这里判断一下如果之前触碰的view已经打开,而当前碰到的view不是那个view则立即关闭之前的view,此处并不需要担动画没完成冲突,因为之前已经abortAnimation + if (view != null && mFlingView != view && view.getScrollX() != 0) { + view.scrollTo(0, 0); + } + // 这里进行了强制的要求,RecyclerView的子ViewGroup必须要有2个子view,这样菜单按钮才会有值, + // 需要注意的是:如果不定制RecyclerView的子View,则要求子View必须要有固定的width。 + // 比如使用LinearLayout作为根布局,而content部分width已经是match_parent,此时如果菜单view用的是wrap_content,menu的宽度就会为0。 + if (mFlingView.getChildCount() == 2) { + mMenuViewWidth = mFlingView.getChildAt(1).getWidth(); + } else { + mMenuViewWidth = INVALID_CHILD_WIDTH; + } + } + break; + case MotionEvent.ACTION_MOVE: + mVelocityTracker.computeCurrentVelocity(1000); + // 此处有俩判断,满足其一则认为是侧滑: + // 1.如果x方向速度大于y方向速度,且大于最小速度限制; + // 2.如果x方向的侧滑距离大于y方向滑动距离,且x方向达到最小滑动距离; + float xVelocity = mVelocityTracker.getXVelocity(); + float yVelocity = mVelocityTracker.getYVelocity(); + if (Math.abs(xVelocity) > SNAP_VELOCITY && Math.abs(xVelocity) > Math.abs(yVelocity) + || Math.abs(x - mFirstX) >= mTouchSlop + && Math.abs(x - mFirstX) > Math.abs(y - mFirstY)) { + mIsSlide = true; + return true; + } + break; + case MotionEvent.ACTION_UP: + releaseVelocity(); + break; + } + return super.onInterceptTouchEvent(e); + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + if (mIsSlide && mPosition != INVALID_POSITION) { + float x = e.getX(); + obtainVelocity(e); + switch (e.getAction()) { + case MotionEvent.ACTION_DOWN: // 因为没有拦截,所以不会被调用到 + break; + case MotionEvent.ACTION_MOVE: + // 随手指滑动 + if (mMenuViewWidth != INVALID_CHILD_WIDTH) { + float dx = mLastX - x; + if (mFlingView.getScrollX() + dx <= mMenuViewWidth + && mFlingView.getScrollX() + dx > 0) { + mFlingView.scrollBy((int) dx, 0); + } + mLastX = x; + } + break; + case MotionEvent.ACTION_UP: + if (mMenuViewWidth != INVALID_CHILD_WIDTH) { + int scrollX = mFlingView.getScrollX(); + mVelocityTracker.computeCurrentVelocity(1000); + // 此处有两个原因决定是否打开菜单: + // 1.菜单被拉出宽度大于菜单宽度一半; + // 2.横向滑动速度大于最小滑动速度; + // 注意:之所以要小于负值,是因为向左滑则速度为负值 + if (mVelocityTracker.getXVelocity() < -SNAP_VELOCITY) { // 向左侧滑达到侧滑最低速度,则打开 + mScroller.startScroll(scrollX, 0, mMenuViewWidth - scrollX, 0, Math.abs(mMenuViewWidth - scrollX)); + } else if (mVelocityTracker.getXVelocity() >= SNAP_VELOCITY) { // 向右侧滑达到侧滑最低速度,则关闭 + mScroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX)); + } else if (scrollX >= mMenuViewWidth / 2) { // 如果超过删除按钮一半,则打开 + mScroller.startScroll(scrollX, 0, mMenuViewWidth - scrollX, 0, Math.abs(mMenuViewWidth - scrollX)); + } else { // 其他情况则关闭 + mScroller.startScroll(scrollX, 0, -scrollX, 0, Math.abs(scrollX)); + } + invalidate(); + } + mMenuViewWidth = INVALID_CHILD_WIDTH; + mIsSlide = false; + mPosition = INVALID_POSITION; + releaseVelocity(); // 这里之所以会调用,是因为如果前面拦截了,就不会执行ACTION_UP,需要在这里释放追踪 + break; + } + return true; + } else { + // 此处防止RecyclerView正常滑动时,还有菜单未关闭 + closeMenu(); + // Velocity,这里的释放是防止RecyclerView正常拦截了,但是在onTouchEvent中却没有被释放; + // 有三种情况:1.onInterceptTouchEvent并未拦截,在onInterceptTouchEvent方法中,DOWN和UP一对获取和释放; + // 2.onInterceptTouchEvent拦截,DOWN获取,但事件不是被侧滑处理,需要在这里进行释放; + // 3.onInterceptTouchEvent拦截,DOWN获取,事件被侧滑处理,则在onTouchEvent的UP中释放。 + releaseVelocity(); + } + return super.onTouchEvent(e); + } + + private void releaseVelocity() { + if (mVelocityTracker != null) { + mVelocityTracker.clear(); + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private void obtainVelocity(MotionEvent event) { + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(event); + } + + public int pointToPosition(int x, int y) { + if (null == getLayoutManager()) return INVALID_POSITION; + int firstPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition(); + Rect frame = mTouchFrame; + if (frame == null) { + mTouchFrame = new Rect(); + frame = mTouchFrame; + } + + final int count = getChildCount(); + for (int i = count - 1; i >= 0; i--) { + final View child = getChildAt(i); + if (child.getVisibility() == View.VISIBLE) { + child.getHitRect(frame); + if (frame.contains(x, y)) { + return firstPosition + i; + } + } + } + return INVALID_POSITION; + } + + @Override + public void computeScroll() { + if (mScroller.computeScrollOffset()) { + mFlingView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); + invalidate(); + } + } + + /** + * 将显示子菜单的子view关闭 + * 这里本身是要自己来实现的,但是由于不定制item,因此不好监听器点击事件,因此需要调用者手动的关闭 + */ + public void closeMenu() { + if (mFlingView != null && mFlingView.getScrollX() != 0) { + mFlingView.scrollTo(0, 0); + } + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/SpaceItemDecoration.java b/commonLib/src/main/java/com/yinuo/commonlib/view/SpaceItemDecoration.java new file mode 100644 index 0000000..7e92367 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/SpaceItemDecoration.java @@ -0,0 +1,32 @@ +package com.yinuo.commonlib.view; + +import android.graphics.Rect; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import org.jetbrains.annotations.NotNull; + +public class SpaceItemDecoration extends RecyclerView.ItemDecoration { + /** + * 默认图片展示单行数量 + */ + private static final int DEFAULT_MEDIA_SIZE = 3; + + /** + * 默认图片展示间距 + */ + private static final int DEFAULT_MEDIA_OFFSET = 30; + + @Override + public void getItemOffsets(@NotNull Rect outRect, @NotNull View view, RecyclerView parent, @NotNull RecyclerView.State state) { + int temp = parent.getChildAdapterPosition(view) % DEFAULT_MEDIA_SIZE; + outRect.left = DEFAULT_MEDIA_OFFSET * (temp); + + if (parent.getChildAdapterPosition(view) >= DEFAULT_MEDIA_SIZE) { + outRect.top = DEFAULT_MEDIA_OFFSET; + } else { + outRect.top = 0; + } + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/activity/BaseActivity.java b/commonLib/src/main/java/com/yinuo/commonlib/view/activity/BaseActivity.java new file mode 100644 index 0000000..d25a06c --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/activity/BaseActivity.java @@ -0,0 +1,28 @@ +package com.yinuo.commonlib.view.activity; + +import android.os.Bundle; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import com.yinuo.commonlib.R; + +public class BaseActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initStatusBar(); + } + + private void initStatusBar() { + Window window = getWindow(); + //After LOLLIPOP not translucent status bar + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + //Then call setStatusBarColor. + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(getResources().getColor(R.color.title_bar_bg_color)); + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/fragment/BaseFragment.java b/commonLib/src/main/java/com/yinuo/commonlib/view/fragment/BaseFragment.java new file mode 100644 index 0000000..2e2c6ca --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/fragment/BaseFragment.java @@ -0,0 +1,18 @@ +package com.yinuo.commonlib.view.fragment; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import org.jetbrains.annotations.NotNull; + +public class BaseFragment extends Fragment { + public Context mContext; + + @Override + public void onAttach(@NonNull @NotNull Context context) { + super.onAttach(context); + mContext = context; + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/view/fragment/BaseNavigationFragment.kt b/commonLib/src/main/java/com/yinuo/commonlib/view/fragment/BaseNavigationFragment.kt new file mode 100644 index 0000000..f0f7b44 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/view/fragment/BaseNavigationFragment.kt @@ -0,0 +1,59 @@ +package com.yinuo.commonlib.view.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup + +abstract class BaseNavigationFragment : BaseFragment() { + private var isNavigationViewInit = false//记录是否已经初始化过一次视图 + private var lastView: View? = null//记录上次创建的view + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + doPrepare() + //如果fragment的view已经创建则不再重新创建 + if (lastView == null) { + lastView = getRootView( + inflater, + container, + savedInstanceState + ) + } + return lastView + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + if (!isNavigationViewInit) {//初始化过视图则不再进行view和data初始化 + super.onViewCreated(view, savedInstanceState) + initView() + initData() + initOthers() + isNavigationViewInit = true + } + } + + abstract fun getRootView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? + + abstract fun initData() + + abstract fun initView() + + abstract fun initOthers() + + abstract fun doPrepare() + + fun getIsNavigationViewInit():Boolean{ + return isNavigationViewInit + } + + fun setIsNavigationViewInit(isNavigationViewInit:Boolean){ + this.isNavigationViewInit=isNavigationViewInit + } +} \ No newline at end of file diff --git a/commonLib/src/main/res/drawable-anydpi/ic_check_box_checked.xml b/commonLib/src/main/res/drawable-anydpi/ic_check_box_checked.xml new file mode 100644 index 0000000..f2e1d31 --- /dev/null +++ b/commonLib/src/main/res/drawable-anydpi/ic_check_box_checked.xml @@ -0,0 +1,11 @@ + + + diff --git a/commonLib/src/main/res/drawable-anydpi/ic_check_box_normal.xml b/commonLib/src/main/res/drawable-anydpi/ic_check_box_normal.xml new file mode 100644 index 0000000..57d07d4 --- /dev/null +++ b/commonLib/src/main/res/drawable-anydpi/ic_check_box_normal.xml @@ -0,0 +1,11 @@ + + + diff --git a/commonLib/src/main/res/drawable-hdpi/ic_add.png b/commonLib/src/main/res/drawable-hdpi/ic_add.png new file mode 100644 index 0000000..40768c0 Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_add.png differ diff --git a/commonLib/src/main/res/drawable-hdpi/ic_back.png b/commonLib/src/main/res/drawable-hdpi/ic_back.png new file mode 100644 index 0000000..b677fc1 Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_back.png differ diff --git a/commonLib/src/main/res/drawable-hdpi/ic_check_box_checked.png b/commonLib/src/main/res/drawable-hdpi/ic_check_box_checked.png new file mode 100644 index 0000000..9c9770f Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_check_box_checked.png differ diff --git a/commonLib/src/main/res/drawable-hdpi/ic_check_box_normal.png b/commonLib/src/main/res/drawable-hdpi/ic_check_box_normal.png new file mode 100644 index 0000000..cb5ca01 Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_check_box_normal.png differ diff --git a/commonLib/src/main/res/drawable-hdpi/ic_pic_delete.png b/commonLib/src/main/res/drawable-hdpi/ic_pic_delete.png new file mode 100644 index 0000000..47b9aca Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_pic_delete.png differ diff --git a/commonLib/src/main/res/drawable-hdpi/ic_record_delete.png b/commonLib/src/main/res/drawable-hdpi/ic_record_delete.png new file mode 100644 index 0000000..47b9aca Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_record_delete.png differ diff --git a/commonLib/src/main/res/drawable-hdpi/ic_right.png b/commonLib/src/main/res/drawable-hdpi/ic_right.png new file mode 100644 index 0000000..8a5244b Binary files /dev/null and b/commonLib/src/main/res/drawable-hdpi/ic_right.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_add.png b/commonLib/src/main/res/drawable-xhdpi/ic_add.png new file mode 100644 index 0000000..b9b15a3 Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_add.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_back.png b/commonLib/src/main/res/drawable-xhdpi/ic_back.png new file mode 100644 index 0000000..9980628 Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_back.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_check_box_checked.png b/commonLib/src/main/res/drawable-xhdpi/ic_check_box_checked.png new file mode 100644 index 0000000..2d6a04b Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_check_box_checked.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_check_box_normal.png b/commonLib/src/main/res/drawable-xhdpi/ic_check_box_normal.png new file mode 100644 index 0000000..81d9f74 Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_check_box_normal.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_pic_delete.png b/commonLib/src/main/res/drawable-xhdpi/ic_pic_delete.png new file mode 100644 index 0000000..0e560d0 Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_pic_delete.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_record_delete.png b/commonLib/src/main/res/drawable-xhdpi/ic_record_delete.png new file mode 100644 index 0000000..0e560d0 Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_record_delete.png differ diff --git a/commonLib/src/main/res/drawable-xhdpi/ic_right.png b/commonLib/src/main/res/drawable-xhdpi/ic_right.png new file mode 100644 index 0000000..fb61a0f Binary files /dev/null and b/commonLib/src/main/res/drawable-xhdpi/ic_right.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_add.png b/commonLib/src/main/res/drawable-xxhdpi/ic_add.png new file mode 100644 index 0000000..f7eb245 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_add.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_back.png b/commonLib/src/main/res/drawable-xxhdpi/ic_back.png new file mode 100644 index 0000000..e646cf2 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_back.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_check_box_checked.png b/commonLib/src/main/res/drawable-xxhdpi/ic_check_box_checked.png new file mode 100644 index 0000000..368a961 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_check_box_checked.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_check_box_normal.png b/commonLib/src/main/res/drawable-xxhdpi/ic_check_box_normal.png new file mode 100644 index 0000000..0764b18 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_check_box_normal.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_pic_delete.png b/commonLib/src/main/res/drawable-xxhdpi/ic_pic_delete.png new file mode 100644 index 0000000..13fb409 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_pic_delete.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_record_delete.png b/commonLib/src/main/res/drawable-xxhdpi/ic_record_delete.png new file mode 100644 index 0000000..13fb409 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_record_delete.png differ diff --git a/commonLib/src/main/res/drawable-xxhdpi/ic_right.png b/commonLib/src/main/res/drawable-xxhdpi/ic_right.png new file mode 100644 index 0000000..45fe9b3 Binary files /dev/null and b/commonLib/src/main/res/drawable-xxhdpi/ic_right.png differ diff --git a/commonLib/src/main/res/drawable/mike.png b/commonLib/src/main/res/drawable/mike.png new file mode 100644 index 0000000..30b74af Binary files /dev/null and b/commonLib/src/main/res/drawable/mike.png differ diff --git a/commonLib/src/main/res/layout/common_title_view.xml b/commonLib/src/main/res/layout/common_title_view.xml new file mode 100644 index 0000000..8552f71 --- /dev/null +++ b/commonLib/src/main/res/layout/common_title_view.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/commonLib/src/main/res/values/attrs.xml b/commonLib/src/main/res/values/attrs.xml new file mode 100644 index 0000000..4c24355 --- /dev/null +++ b/commonLib/src/main/res/values/attrs.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/commonLib/src/main/res/values/colors.xml b/commonLib/src/main/res/values/colors.xml new file mode 100644 index 0000000..e987809 --- /dev/null +++ b/commonLib/src/main/res/values/colors.xml @@ -0,0 +1,34 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + #FF0000 + + #FF5151 + #FFAA60 + + #666666 + #333333 + #999999 + #F5F5F5 + #E9E9E9 + + #0786F0 + #3BA6FF + #0786F0 + #FFAA61 + + #2E69FF + #FF973B + + #333333 + #F5F5F5 + #666666 + #999999 + + \ No newline at end of file diff --git a/commonLib/src/main/res/values/dimens.xml b/commonLib/src/main/res/values/dimens.xml new file mode 100644 index 0000000..e980670 --- /dev/null +++ b/commonLib/src/main/res/values/dimens.xml @@ -0,0 +1,50 @@ + + 0.5dp + 1dp + 2dp + 3dp + 4dp + 8dp + 5dp + 6dp + 7dp + 9dp + 10dp + 11dp + 12dp + 13dp + 14dp + 15dp + 16dp + 17dp + 18dp + 19dp + 20dp + 21dp + 22dp + 23dp + 24dp + 26dp + 27dp + 28dp + 30dp + 29dp + 40dp + 42dp + 46dp + 65dp + 70dp + 72dp + 74dp + 79dp + 80dp + 90dp + 84dp + 100dp + 115dp + 152dp + 160dp + 16dp + 48dp + 15dp + \ No newline at end of file diff --git a/commonLib/src/main/res/values/strings.xml b/commonLib/src/main/res/values/strings.xml new file mode 100644 index 0000000..5861c5e --- /dev/null +++ b/commonLib/src/main/res/values/strings.xml @@ -0,0 +1,5 @@ + + + 编辑 + 保存 + \ No newline at end of file diff --git a/commonLibConfig.gradle b/commonLibConfig.gradle new file mode 100644 index 0000000..1fb9e7c --- /dev/null +++ b/commonLibConfig.gradle @@ -0,0 +1,64 @@ +ext { + android = [ + compileSdkVersion: 30, + buildToolsVersion: "30.0.3", + minSdkVersion : 23, + targetSdkVersion : 28, + versionCode : 1, + versionName : "1.0" + ] + + sign = [ + keystore_path : "../yinuoapp.jks", + keystore_pwd : "123456", + keystore_alias: "yinuo" + ] + + compileOptions = [ + sourceCompatibility: JavaVersion.VERSION_1_8, + targetCompatibility: JavaVersion.VERSION_1_8, + ] + + versions = [ + appcompat : "1.2.0", + material : "1.2.1", + okhttp : "4.9.1", + retrofit : "2.4.0", + rxjava : "2.1.16", + rxandroid : "2.0.2", + kotlin : "1.5.10", + converter_gson : "2.4.0", + retrofit_rxjava : "2.9.0", + room : "2.3.0", + jxl : "2.6.12", + navigation_fragment_ktx: "2.3.0", + navigation_ui_ktx : "2.3.0", + glide : "4.11.0", + photo_view : "2.3.0", + luban : "1.1.8", + kotlin_android : "1.4.1" + ] + + dependencies = [ + okhttp : "com.squareup.okhttp3:okhttp:${versions.okhttp}", + retrofit : "com.squareup.retrofit2:retrofit:${versions.retrofit}", + rxjava : "io.reactivex.rxjava2:rxjava:${versions.rxjava}", + rxandroid : "io.reactivex.rxjava2:rxandroid:${versions.rxandroid}", + kotlin : "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}", + kotlin_android : "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.kotlin_android}", + converter_gson : "com.squareup.retrofit2:converter-gson:${versions.converter_gson}", + retrofit_rxjava : "com.squareup.retrofit2:adapter-rxjava2:${versions.retrofit_rxjava}", + room : "androidx.room:room-runtime:${versions.room}", + room_compiler : "androidx.room:room-compiler:${versions.room}", + room_ktx : "androidx.room:room-ktx:${versions.room}", + room_rxjava : "androidx.room:room-rxjava2:${versions.room}", + jxl : "net.sourceforge.jexcelapi:jxl:${versions.jxl}", + navigation_fragment_ktx: "androidx.navigation:navigation-fragment-ktx:${versions.navigation_fragment_ktx}", + navigation_ui_ktx : "androidx.navigation:navigation-ui-ktx:${versions.navigation_ui_ktx}", + navigation_arg : "androidx.navigation:navigation-safe-args-gradle-plugin:${versions.navigation_ui_ktx}", + glide : "com.github.bumptech.glide:glide:${versions.glide}", + annotationProcessor : "com.github.bumptech.glide:compiler:${versions.glide}", + photo_view : "com.github.chrisbanes:PhotoView:${versions.photo_view}", + luban : "top.zibin:Luban:${versions.luban}" + ] +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..6826e61 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,17 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..7978838 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Jul 15 16:06:54 CST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d5d5c7b --- /dev/null +++ b/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = "CommonLibTest" +include ':app' +include ':commonLib'