1、BottomSheetDialog
1.1、创建一个xml布局,用于要展示的BottomSheetDialog样式
1.2、进行实例化,用.show(),将BottomSheetDialog展示出来
val mapBottomSheetDialog = MapBottomSheetDialog(ctx)
mapBottomSheetDialog.show()
1.3、设置BottomSheetDialog的圆角效果
在style.xml中设置圆角样式:
!--实现BottomSheetDialog圆角效果-->
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
</style>
在对应的代码中应用该布局样式:
class MapBottomSheetDialog(
context: Context,
) : BottomSheetDialog(context, R.style.BottomSheetDialog) {}
1.4、设置固定高度
override fun onStart() {
super.onStart()
//拿到系统的 bottom_sheet
val view: FrameLayout = dialog?.findViewById(R.id.design_bottom_sheet)!!
//获取behavior
val behavior = BottomSheetBehavior.from(view)
//设置弹出高度
behavior.peekHeight = 350
}
1.5、去掉背景阴影:
在style.xml中将backgroundDimEnabled设置为false
<!--实现BottomSheetDialog圆角效果-->
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
<!--去掉背景阴影-->
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
</style>
2、高德Android地图SDK使用
Android Studio 配置工程-创建工程-开发指南-Android 地图SDK | 高德地图API
3、权限框架
3.1.1、PermissionsDispatch权限框架
在build.gradle(:app)添加依赖:
apply plugin: 'kotlin-kapt'
dependencies {
implementation "com.github.permissions-dispatcher:permissionsdispatcher:${latest.version}"
kapt "com.github.permissions-dispatcher:permissionsdispatcher-processor:${latest.version}"
}
3.1.2、使用@RuntimePermissions 注册一个Activity
orFragment
来处理权限
使用@NeedsPermission 注释需要一个或者多个权限的操作方法
使用@OnPermissionDenied 注释,如果用户未授权权限则调用该方法
使用@OnNeverAskAgain 注释,如果用户选择让设备“不再询问”权限则调用该方法
使用@OnShowRationale 注释,解释为什么需要权限。
3.1.3、委托给生成的函数(第一次未编译前,编译器会报红,直接编译能通过,加注释的方法前不能用private修饰)
@RuntimePermissions
class MainActivity : AppCompatActivity(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById(R.id.button_camera).setOnClickListener {
showCameraWithPermissionCheck()
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// NOTE: delegate the permission handling to generated function
onRequestPermissionsResult(requestCode, grantResults)
}
@NeedsPermission(Manifest.permission.CAMERA)
fun showCamera() {
supportFragmentManager.beginTransaction()
.replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
.addToBackStack("camera")
.commitAllowingStateLoss()
}
@OnShowRationale(Manifest.permission.CAMERA)
fun showRationaleForCamera(request: PermissionRequest) {
showRationaleDialog(R.string.permission_camera_rationale, request)
}
@OnPermissionDenied(Manifest.permission.CAMERA)
fun onCameraDenied() {
Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show()
}
@OnNeverAskAgain(Manifest.permission.CAMERA)
fun onCameraNeverAskAgain() {
Toast.makeText(this, R.string.permission_camera_never_askagain, Toast.LENGTH_SHORT).show()
}
}
3.2.1、 ActivityResultLauncher请求权限
3.2.2、在 Activity 或 Fragment 中定义一个 ActivityResultLauncher
对象,并实现 ActivityResultCallback
接口
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// 权限已授予
// 执行相关操作
} else {
// 权限被拒绝
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.YOUR_PERMISSION)) {
onNeverAskAgain()
} else {
showPermissionRationaleDialog()
}
}
}
3.2.3、 在需要请求权限的地方,调用 requestPermissionLauncher.launch(permission)
来发起权限请求。其中permission
为请求的具体权限
3.2.4、当用户做出选择后,系统将调用 ActivityResultCallback
接口中的回调方法。在回调方法中,根据 isGranted
参数判断权限是否被授予。如果 isGranted
为 true
,表示权限已授予;如果为 false
,表示权限被拒绝
4、GSON解析
4.1、将对象转列表
private fun parseToList(json: String): List<String> {
val gson = ScaffoldConfig.getGson()
val a: List<String> = gson.fromJson(json, object : TypeToken<MutableList<String>>() {}.type)
return a
}
4.2、将字符串转换为对象
fun main() {
val jsonString = "{\"name\":\"John\",\"age\":30}"
val gson = Gson()
val person = gson.fromJson(jsonString, Person::class.java)
}
4.3、将对象转为字符串
data class Person(val name: String, val age: Int)
fun main() {
val person = Person("John", 30)
val gson = Gson()
// 将对象转换为 JSON 字符串
val jsonString = gson.toJson(person)
}
5、Retrofit使用
5.1、添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // 如果要使用 Gson 进行 JSON 数据的解析
5.2、创建API接口
interface MyApi {
@GET("users/{id}")
fun getUser(@Path("id") userId: String): Call<User>
}
5.3、创建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create()) // 使用Gson进行JSON数据解析
.build()
5.4、 创建API实例
val myApi = retrofit.create(MyApi::class.java)
5.5、发起网络请求
val call = myApi.getUser("123")
call.enqueue(object : Callback<User> {
override fun onResponse(call: Call<User>, response: Response<User>) {
if (response.isSuccessful) {
val user = response.body()
// 处理响应结果
} else {
// 处理错误情况
}
}
override fun onFailure(call: Call<User>, t: Throwable) {
// 处理请求失败情况
}
})
6、打开手机自带的选择器
val getContentIntent = Intent(Intent.ACTION_GET_CONTENT)
getContentIntent.type = "image/*" // 设置要获取的内容类型
startActivityForResult(getContentIntent, REQUEST_CODE_GET_CONTENT)
在onActivityResult回调中处理选择文件返回的结果
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FILE_SELECT_CODE && resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
selectedFileUri = uri
val fileName = getAudioFileName(uri)
binding.tvResult.text = "Selected File: $fileName"
}
}
}
7、协程
7.1、使用suspend标记支持协程的方法
interface VoiceToTextService {
@Headers(
"Domain-Name: $VOICE_TO_TEXT_KEY",
"Authorization: Bearer $VOICE_TO_TEXT_TOKEN",
"Content-Type: application/octet-stream"
)
@POST("models/XXX/XXXX")
suspend fun voiceConvertText(@Body requestBody: RequestBody): String
}
7.2、使用协程调用接口方法
private fun convertAudio() {
CoroutineScope(Dispatchers.IO).launch {
try {
val mediaTypeBinary = "application/octet-stream".toMediaTypeOrNull()
val file = File(uriToPath(mContext, selectedFileUri).toString())
if (file.exists()){
val requestBody: RequestBody =
RequestBody.create(mediaTypeBinary, file.readBytes())
withContext(Dispatchers.Main){
val result = voiceToService.voiceConvertText(requestBody)
val gson = Gson()
val apiResponse = gson.fromJson(result, VoiceToTextResponse::class.java)
if (apiResponse != null) {
val text = apiResponse.text
binding.tvResult.text = text
}
}
}
}catch (e: Throwable) {
e.printStackTrace()
}
}
}