安卓 快速开发工具,封装了一些常用的基类、工具类、自定义控件,预装了一些常用的第三方库
- Android Studio Chipmunk | 2021.2.1
- Gradle 7.3.3
- Gradle plugin 7.2.0
- Kotlin 1.6.21
ViewBinding + MVP
-
在项目根目录创建 config.gradle 文件
ext { compile_sdk_version = 31 min_sdk_version = 21 target_sdk_version = 31 version_code = 6 version_name = '1.0.6' jvmTarget_version = '1.8' sourceCompatibility_version = JavaVersion.VERSION_1_8 targetCompatibility_version = JavaVersion.VERSION_1_8 }
-
在 settings.gradle 里面
dependencyResolutionManagement { repositories { // AndroidKit、CompressHelper 和 PhotoViewer 这几个第三方需要添加下面这行配置 maven { url 'https://jitpack.io' } } }
-
在项目 build.gradle 里面
// 添加这一行启用 config.gradle 公共配置 apply from: './config.gradle'
-
在 gradle.properties 里面
// 添加这两行使应用对support库的依赖自动转换为androidx的依赖 android.useAndroidX=true android.enableJetifier=true
-
在应用 build.gradle 里面
dependencies { // 最好把其余的删掉只保留这一行,因为 AndroidKit 已经使用 api 把需要的基础包添加进来了, // 依赖了 AndroidKit 相当于项目配置了那些基础包 implementation 'com.github.zhumj:AndroidKit:last-release' }
**在 Kotlin 项目上引用** 的基础上
-
在项目 build.gradle 里面
plugins { ... // 添加 Kotlin 插件 id 'org.jetbrains.kotlin.android' version '1.6.21' apply false }
-
在应用 build.gradle 里面
plugins { ... // 添加 Kotlin 插件 id 'org.jetbrains.kotlin.android' }
AppCompatActivity 基类
protected val mViewBinding: ViewBinding
protected var mPresenter: BasePresenter
initToolBar(toolbar: Toolbar?, isShowBack: Boolean/*是否显示返回键*/, isShowTitle: Boolean/*是否显示标题*/): 加载工具栏
protected abstract fun getViewBinding(): T //加载ViewBinding
protected abstract fun obtainPresenter(): P? //加载Presenter
/**
* 是否注册事件分发
* @return true 注册;false 不注册,默认不注册
*/
open fun isRegisteredEventBus(): Boolean = false
/**
* 是否启用点击空白区域隐藏软键盘
* @return true 启用;false 不启用
*/
open fun enableHideSoftKeyboardByClickBlank(): Boolean = false
/**
* 接收到Eventbus分发的事件
* @param event 事件
*/
@Subscribe(threadMode = ThreadMode.MAIN)
open fun onReceiveEvent(event: EventMessage<*>) {
}
/**
* 接收到Eventbus分发的粘性事件
* @param event 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
open fun onReceiveStickyEvent(event: EventMessage<*>) {
}
Fragment 基类
protected val mViewBinding: ViewBinding
protected var mPresenter: BasePresenter
initToolBar(toolbar: Toolbar?, isShowBack: Boolean/*是否显示返回键*/, isShowTitle: Boolean/*是否显示标题*/): 加载工具栏
protected abstract fun getViewBinding(): T //加载ViewBinding
protected abstract fun obtainPresenter(): P? //加载Presenter
/**
* 是否注册事件分发
* @return true 注册;false 不注册,默认不注册
*/
open fun isRegisteredEventBus(): Boolean = false
/**
* 接收到Eventbus分发的事件
* @param event 事件
*/
@Subscribe(threadMode = ThreadMode.MAIN)
open fun onReceiveEvent(event: EventMessage<*>) {
}
/**
* 接收到Eventbus分发的粘性事件
* @param event 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
open fun onReceiveStickyEvent(event: EventMessage<*>) {
}
MVP 中的 Presenter 基类
shape构造器,使用这个可以直接代码设置 shape 和 selector
setShapeType:设置 Shape 样式
enum class ShapeType { RECTANGLE, OVAL, LINE, RING }
setShapeSolidColor:设置底色
setShapeCornersRadius:设置四角倒圆角半径
setShapeCornersTopLeftRadius:设置左上角倒圆角半径
setShapeCornersTopRightRadius:设置右上角倒圆角半径
setShapeCornersBottomRightRadius:设置右下角倒圆角半径
setShapeCornersBottomLeftRadius:设置左下角倒圆角半径
setShapeStrokeWidth:设置边线宽
setShapeStrokeColor:设置边线颜色
setShapeStrokeDashWidth:设置虚线宽度
setShapeStrokeDashGap:设置虚线间隙
setShapeUseSelector:设置是否启用Selector
setShapeSelectorPressedColor:设置点击状态颜色
setShapeSelectorNormalColor:设置默认状态颜色
setShapeSelectorDisableColor:设置禁用状态颜色
setShapeSizeWidth:设置宽度
setShapeSizeHeight:设置高度
setShapeGradientAngle:设置渐变角度
setShapeGradientCenterX:设置渐变中心X
setShapeGradientCenterY:设置渐变中心Y
setShapeGradientRadius:设置渐变半径/范围
setShapeGradientStartColor:设置渐变开始颜色
setShapeGradientCenterColor:设置渐变中心颜色
setShapeGradientEndColor:设置渐变结束颜色
setShapeGradientType:设置渐变样式
enum class GradientType { LINEAR, RADIAL, SWEEP }
setShapeGradientUseLevel:设置渐变等级
into(view: View):对 view 启用以上设置
自定义Toast构造器,可设置类型(默认、成功、失败、消息、警告)、背景颜色、倒角、显示位置、文本颜色和大小 @Deprecated(message = "Android 11(API 30)之后 Toast 不能自定义了,请使用 SnackBarExt 里面的 Snackbar.showToast 方法代替")
setToastType:设置类型,可看 ToastType
enum class ToastType { NORMAL, SUCCESS, INFO, WARNING, ERROR }
setBgColor:设置背景颜色
setMessage:设置文本
setTextColor:设置文本颜色
setTextSize:设置文字大小
setIconId:设置图标资源ID
setIconWidth:设置图标宽度
setIconHeight:设置图标高度
setRadius:设置四角倒圆角半径
setGravity:设置显示位置
setDuration:设置显示时间
create():启用以上设置并生成Toast
EventBus 工具类
register:注册
unregister:解除注册
post:发送普通事件
postSticky:发送粘性事件
removeSticky:移除指定粘性事件
removeAllSticky:移除全部粘性事件
EventBus 数据实体
Preferences DataStore 扩展,对 Context 扩展了 DataStore 的 put、get 还有 clean 方法,在页面 context.对应方法 就可以直接调用
获取 Preferences DataStore 保存的数据:
fun <T> Context.getStoreValue(key: String, defaultValue: T): T
使用:
context.getStoreValue("key", defaultValue)
*Preferences DataStore 保存数据:*
fun <T> Context.putStoreValue(key: String, value: T)
使用:
context.putStoreValue("key", value)
获取 Preferences DataStore 保存的限制有效期的数据:
fun <T> Context.getStoreFiniteTimeValue(key: String): StoreFiniteTimeEntity<T>?
使用:
context.getStoreFiniteTimeValue("key")
Preferences DataStore 保存限制有效期的数据:
fun <T> Context.putStoreFiniteTimeValue(key: String, value: T, currentTime: Long = System.currentTimeMillis(), finiteTime: Long = 0)
使用:
context.putStoreFiniteTimeValue(key, value, currentTime, finiteTime)
方法:
fun Context.cleanPreferencesDataStore()
使用:
context.cleanPreferencesDataStore()
/**
* 存储的带有效期的数据实体,关于如何计算是否过期:
* currentTime = System.currentTimeMillis()
* currentTime - StoreFiniteTimeEntity.time > StoreFiniteTimeEntity.finiteTime: 已过有效期
* currentTime - StoreFiniteTimeEntity.time <= StoreFiniteTimeEntity.finiteTime: 未过有效期
*/
data class StoreFiniteTimeEntity<T>(
val time: Long,// 存储时间
val finiteTime: Long,// 有效时长
val data: T// 数据
)
SnackBar 扩展,新增显示 Toast 样式的 SnackBar 的方法
make:创建 SnackBar
showToast:显示 Toast 样式的 SnackBar,调用这个方法前最好是先调用 SnackBarExt 下面的 make 方法,因为正常的 SnackBar.make() 方法会有警告,强迫症者慎用
使用
SnackBarExt.make(view, "SnackBar Test", Snackbar.LENGTH_SHORT)
.showToast(
toastType = SnackBarExt.ToastType.SUCCESS,
gravity = Gravity.CENTER// 自定义位置:居中显示
)
ViewHolder 基类
继承 BaseViewHolder,方便 ViewBinding 使用
防止短时间内多次点击,默认 500 毫秒内重复点击无效
View.setOnClickClictener(onPreMultiClickClictener)
private val onPreMultiClickClictener = object: OnPreMultiClickClictener(1000) {
override fun onValidClick(view: View) {
// 有效的点击事件回调
}
override fun onInvalidClick(view: View) {
// 无效的点击事件回调
}
}
Kotlin 单例辅助类,T:需要实现单例的类,A:传递的参数,如 Context
class MyManager private constructor(context: Context) {
fun doSomething() {
...
}
companion object : SingletonHolder<MyManager, Context>(::MyManager)
}
MyManager.getInstance(context).doSomething()
Base64 编解码相关工具类,可对字符串、文件、Bitmap进行编解码
encodeToString:最原始的Base64编码
decode:最原始的Base64解码
stringEncode:对字符串进行Base64编码
stringDecode:对字符串进行Base64解码
fileEncode:对文件进行Base64编码
fileDecode:对文件进行Base64解码
bitmapEncode:对图片进行Base64编码
bitmapDecode:对图片进行Base64解码
App 相关工具类,可获取APP版本、名称等,可获取APK安装路径、可检查APK是否安装
getAppName:获取应用程序名称
getVersionName:取应用程序版本名称信息
getVersionCode:获取应用程序的版本Code信息
getSelfApkPath:获取APK安装路径
isPkgInstalled:检查APK是否安装
日期/时间 工具类
getNowLocalDateTime:获取当前日期和时间,如:12小时制 en: April 19, 2022, 1:30 PM zh: 2022年4月19日 下午1:30
getNowLocalDate:获取当前日期,如:en: April 19, 2022 zh: 2022年4月19日
getNowLocalTime:获取当前时间,如:12小时制 en: 1:30 PM zh: 下午 1:30
getDefaultTimeZone:获取默认时区
getDefaultTimeZoneName:获取默认时区名称,如:GMT+08:00 中国标准时间
getTimeZoneName:获取时区名称,如:GMT+08:00 中国标准时间
getTimeZoneShortName:获取时区短名称,如:GMT+08:00
getTimeZoneLongName:获取时区长名称,如:中国标准时间
isAM:判断是上午还是下午
is24HourFormat:判断系统使用的是24小时制还是12小时制
getNowDateFormat:根据指定格式,获取现在时间
getDateFormat:把String日期转成制定格式
getAgeByBirthday:根据生日计算年龄
设备相关工具类
getDeviceId:获取设备的唯一标识,deviceId
getPhoneBrand:获取手机品牌
getPhoneModel:获取手机型号
getBuildLevel:获取手机Android API等级(22、23 ...)
getBuildVersion:获取手机Android 版本(4.4、5.0、5.1 ...)
SharedPreferences工具类 @Deprecated(message = "狗哥建议使用 DataStore 替代 SharedPreferences,详情请看 PreferencesDataStoreExt")
put:保存数据的方法
get:得到保存的数据的方法
remove:移除某个key值对应的值
clear:清除所有数据
contains:查询某个key是否已经存在
getAll:获取所有已保存的键值对
正则验证工具类
isUserName:校验用户名,a-z、A-Z、0-9、"_",不包含中文和特殊字符,必须以字母开头,不能以“_”结尾,默认6-18位
isSimplePassword:校验简单的密码:不包含特殊字符, 至少需要一个 字母+数字,默认8-20位
isOrdinaryPassword:校验普通的密码:至少需要一个 字母+数字+特殊字符,默认8-20位
isComplexPassword:校验复杂的密码:至少需要一个 小写字母+大写字母+数字+特殊字符,默认8-20位
isMobile:校验手机号
isEmail:校验邮箱
isChinese:校验汉字
isNumber:校验数字,包含正负整数、浮点数
isInt:校验数字,包含正负整数
isDouble:校验数字,包含正负浮点数
屏幕相关工具类
getScreenWidth:获得屏幕宽度
getScreenHeight:获得屏幕高度
getStatusBarHeight、getStatusHeight:获取状态栏高度
分辨率相关
dp2px:dp转px
px2dp:px转dp
sp2px:sp转px
px2sp:px转sp
运算相关
add(v1: String, v2: String):提供精确的加法运算
add(v1: String, v2: String, scale: Int):提供精确的加法运算,scale 保留小数位数
sub(v1: String, v2: String):提供精确的减法运算
sub(v1: String, v2: String, scale: Int):提供精确的减法运算,scale 保留小数位数
mul(v1: String, v2: String):提供精确的乘法运算
mul(v1: String, v2: String, scale: Int):提供精确的乘法运算,scale 保留小数位数
p(v1: String, v2: String):提供精确的除法运算
p(v1: String, v2: String, scale: Int):提供精确的除法运算,scale 保留小数位数
remainder(v1: String, v2: String, scale: Int):取余数,scale 保留小数位数
round(b: BigDecimal, scale: Int):提供精确的小数位四舍五入处理,scale 保留小数位数
compare(v1: String, v2: String):比较大小,如果v1 大于v2 则 返回true 否则false
Text测量相关
// 获取Text宽度
getTextWidth(textPaint: Paint, text: String): Float
// 获取Text高度
getTextHeight(textPaint: Paint): Float
// 获取Text基线
getTextBaseLine(textPaint: Paint): Float
位置相关
interface OnGetLocationListener{
fun isLocationDisable() { }
fun onLocationCallBack(location: Location?) { }
fun onAddressCallBack(address: Address?) { }
}
isLocationEnabled:判断位置信息开关是否打开
getAddress:获取地址信息,协程使用回调OnGetLocationListener返回数据
address:获取地址信息
getLocation:获取位置信息,协程使用回调OnGetLocationListener返回数据
locale:获取位置信息,协程
gotoLocationSettings:进入“位置信息”设置界面
使用
val locationUtil = LocationUtil(this)
locationUtil.getAddress(lifecycleScope, object : LocationUtil.OnGetLocationListener {
// 位置信息开关处于禁用状态
override fun isLocationDisable() {
}
override fun onAddressCallBack(address: Address?) {
validPhone(address)
}
})
/*
locationUtil.getLocation(lifecycleScope, object : LocationUtil.OnGetLocationListener {
override fun isLocationDisable() {
}
override fun onLocationCallBack(location: Location?) {
}
})
*/
/*
lifecycleScope.launch {
locationUtil.isLocationEnabled().also {
if (it) {
locationUtil.locale().also { location: Location? ->
locationUtil.address(location).also { address: Address? ->
}
}
}
}
}
*/
剪切板相关工具类
copyText:复制字符串到剪切板
copyHtmlText:复制 Html 字符串到剪切板
copyUri:复制 Uri 到剪切板
copyRawUri:复制 RawUri 到剪切板
copyIntent:复制 Intent 到剪切板
getClipboardContent:获取剪切板上的第一条内容,不管什么类型都强制转成String
getClipType:获取第一条内容类型
enum class ClipType { UNKNOWN, TEXT, INTENT, URI, HTML, }
Gson解析工具类
parse:把数据转为Json字符串
from:把Json字符串转为特定数据
击空白处自动隐藏软键盘工具类
/**
* 点击空白隐藏键盘
* @param context
* @param event 点击事件
* @param view 当前拥有焦点的View
*/
touchToHideSoft(Context context, MotionEvent ev, View currentFocusView)
使用:
class MainActivity: AppCompatActivity() {
...
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
// 点击空白隐藏键盘
SoftKeyboardUtil.touchToHideSoft(this, ev, currentFocus)
return super.dispatchTouchEvent(ev)
}
}
文件操作相关
// 删除指定文件夹或文件
deleteFileOrDir(file: File): Boolean
// 获取文件夹/文件大小
getFolderSize(file: File): Float
// 格式化大小单位
getFormatSize(context: Context, fileSize: Long): String
自定义EditText,可设置DrawableRight图片添加一键清除功能,可开启文本抖动动画,可设置禁用/开启编辑状态
startShakeAnimation:晃动动画
setTextContent:设置文本,当 isEditable = false 时,则自动改为可编辑状态
getEditable:判断 EditText 是否处于可编辑状态
setEditable:设置 EditText 是否可编辑
自定义 AlertDialog,旨在统一 Dialog 风格
changeRootViewParam:修改最底层背景CardView参数
setTitleText:设置标题
changeTitleViewParam:修改标题TextView参数
setMessageText:设置默认内容文本
changeMessageViewParam:修改默认内容文本TextView参数
setCustomContentView:设置自定义内容,装在内容容器FrameLayout里面
changeButtonRootViewParam:修改按钮容器参数,LinearLayout
setClickCancelAutoDismiss:设置点击取消按钮是否 Dialog 自动消失
setOnCancelButtonClickListener:设置取消按钮点击事件监听
changeCancelButtonParam:修改取消按钮参数
setClickCompleteAutoDismiss:设置点击确认按钮是否 Dialog 自动消失
setOnCompleteButtonClickListener:设置确认按钮点击事件监听
changeCompleteButtonParam:修改取消按钮参数
interface OnZAlertDialogButtonClickListener {
fun onDialogButtonClick(dialog: ZAlertDialog, view: View)
}:按钮监听回调
使用
-
MainActivity
class MainActivity : BaseActivity<ActivityMainBinding, MainPresenter>(), MainContract.View { override fun getViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun obtainPresenter(): MainPresenter { return MainPresenter(this) } override fun onResume() { super.onResume() // MVP 获取数据 presenter?.queryDates() } override fun queryDatesSuccess(dates: List<Int>) { ToastBuilder(this) .setMessage("数据获取成功") .setToastType(ToastType.SUCCESS) .create() .show() } override fun queryDatesFailure(errCode: Int, errMsg: String) { ToastBuilder(this) .setMessage("数据获取失败") .setToastType(ToastType.ERROR) .create() .show() } }
-
MainPresenter
/** * 这里是 MVP 中对逻辑进行处理的地方,通过 View 回调告诉 Activity 如何更新 UI */ class MainPresenter(view: MainContract.View): BasePresenter<MainContract.View>(view), MainContract.Presenter { private val model = MainModel() var dates: List<Int> = ArrayList() override fun queryDates() { dates = model.queryDates().also { if (it.isEmpty()) { view?.queryDatesFailure(-1, "数据获取失败") } else { view?.queryDatesSuccess(dates) } } }
-
MainContract
/** * 这里是 MVP 定义接口的地方 */ interface MainContract { interface Model { fun queryDates(): List<Int> } interface View { fun queryDatesSuccess(dates: List<Int>) fun queryDatesFailure(errCode: Int, errMsg: String) } interface Presenter { fun queryDates() } }
-
MainModel
/** * 这里在 MVP 中是真正执行数据请求的地方 */ class MainModel: MainContract.Model { override fun queryDates(): List<Int> { return arrayListOf(0, 1, 2, 3, 4) } }
-
事件总线:Eventbus:3.3.1
-
比较好用的图片压缩:CompressHelper:1.0.5
-
微信朋友圈一样的图片查看器:PhotoViewer:0.50
-
图片加载:Coil:2.2.2
-
google 开源手机号码相关库:libphonenumber:8.13.12
-
下拉刷新、上拉加载库:SmartRefreshLayout:2.0.5
-
Preferences DataStore:Preferences DataStore:1.0.0
-
Gson:Gson:2.10.1
- 新增 Kotlin 单例辅助类: SingletonHolder
- 新增位置相关工具类: LocationUtil
- 新增运算相关工具类: ArithmeticUtil
- 新增分辨率工具类: DensityUtil
- 新增防止短时间内多次点击: OnPreMultiClickListener
- 新增自定义View: GridRadioGroup
- EventBusUtil: 新增 移除指定粘性事件 和 移除所有粘性事件 方法
- ValidatorUtil: 更新 密码验证 正则表达式
- 新增google 开源手机号码相关库:libphonenumber:8.12.47
- 新增剪切板相关工具类: ClipboardUtil
- ToastBuilder 添加过时标志: Android 11(API 30)之后 Toast.setView() 不能自定义了,请使用 SnackBarExt 里面的 Snackbar.showToast 方法代替
- 新增 SnackBar 扩展: SnackBarExt,自定义显示 Toast 样式的 SnackBar 的方法
- 升级第三方库 Coil 到 2.0.0-rc03 版本
- 新增 ViewHolder 基类 BaseViewHolder 和 继承于 BaseViewHolder 的方便 ViewBinding 使用的 BaseViewBindingHolder
- 新增下拉刷新、上拉加载库:SmartRefreshLayout:2.0.5 及相应的 header-classics:2.0.5、footer-classics:2.0.5'
- 新增自定义AlertDialog: ZAlertDialog,旨在统一 Dialog 风格
- 优化 ZAlertDialog 的方法
- BaseActivity、BaseFragment 中的字段修改:binding -> mViewBinding,presenter -> mPresenter
- 修复 BasePresenter 的 onDestroy 方法没有暴露给它的实现类的问题
- 新增 Text 测量相关工具类 TextUtil.kt,方便自定义View画文字
- 修复 BaseActivity 的 initToolBar(isShowBack: Boolean = false, isShowTitle: Boolean = false) 方法传递到下一层的问题
- 修改 OnPreMultiClickListener 的 onInvalidClick 方法为可选实现
- 删除 自定义View: GridRadioGroup,需要的话可以另行添加 RadioGridLayout
implementation 'com.github.zhumj:RadioGridLayout:1.0.1'
- SPUtil 添加过时标志: 狗哥建议使用 DataStore 替代 SharedPreferences,详情请看 PreferencesDataStoreExt
- 新增 Preferences DataStore 替代 SharedPreferences,使用更简单,详情请看 PreferencesDataStoreExt
- 新增 GsonUtil 工具类
- ZAlertDialog 按钮新增简体中文适配
- 修改 BasePresenter:继承 DefaultLifecycleObserver,使用 Lifecycle 自动感知生命周期
- 优化正则验证工具类:ValidatorUtil
- 新增 SoftKeyboardUtil 工具类,实现页面一句代码实现点击空白处隐藏软键盘
- BaseActivity 新增 点击空白区域隐藏软键盘 开关: enableHideSoftKeyboardByClickBlank
- 优化 DateTimeUtil
- 相关依赖库更新为最新的依赖库
- 新增 FileUtil: 文件操作相关工具类