安卓 快速开发工具,封装了一些常用的基类、工具类、自定义控件,预装了一些常用的第三方库
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
implementation 'com.github.zhumj:RadioGridLayout:1.0.1'
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。