优化-待测试

This commit is contained in:
2025-12-01 12:05:39 +08:00
parent 46bfb3faac
commit 1c40491819
10 changed files with 448 additions and 162 deletions
@@ -1,13 +1,18 @@
package com.sw.inbound.activity
import android.annotation.SuppressLint
import android.app.Dialog
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
import androidx.camera.view.PreviewView
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.sw.inbound.R
@@ -17,6 +22,7 @@ import com.sw.inbound.databinding.ActivityFoodCollectionBinding
import com.sw.inbound.databinding.LayoutCameraPreviewBinding
import com.sw.inbound.databinding.LayoutEmptySearchBinding
import com.sw.inbound.dialog.CollectSearchDialog
import com.sw.inbound.dialog.CustomDialog
import com.sw.inbound.dialog.Loading
import com.sw.inbound.model.response.SearchGoodsInfo
import com.sw.inbound.objbox.Food
@@ -26,6 +32,7 @@ import com.sw.inbound.objbox.ObjectBox
import com.sw.inbound.utils.BitmapCropper
import com.sw.inbound.utils.BitmapSaver
import com.sw.inbound.utils.CameraUtils
import com.sw.inbound.utils.ImageUploader
import com.sw.inbound.utils.ImageUtil
import com.sw.inbound.utils.ext.addOnActionSearchListener
import com.sw.inbound.utils.ext.clickWithDebounce
@@ -41,7 +48,10 @@ import com.sw.inbound.viewmodel.ReceiptViewModel
import dagger.hilt.android.AndroidEntryPoint
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.io.File
@@ -77,8 +87,8 @@ class FoodCollectionActivity : ComponentActivity() {
it.uploadSuccess = false
}
collectionAdapter.notifyItemChanged(position)
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
binding.btnUploadImage.text = "待上传图片${count}"
val count = collectList.count { it.imageFile != null && it.uploadSuccess.not() }
// binding.btnUploadImage.text = "待上传图片${count}张"
}
}
}
@@ -135,14 +145,14 @@ class FoodCollectionActivity : ComponentActivity() {
searchGoods()
}
}
binding.btnUploadImage.setOnClickListener {
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
if (count == 0) {
toast("已全部上传成功")
return@setOnClickListener
}
uploadAllImage()
}
// binding.btnUploadImage.setOnClickListener {
// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
// if (count == 0) {
// toast("已全部上传成功")
// return@setOnClickListener
// }
// uploadAllImage()
// }
binding.btnSave.setOnClickListener { _ ->
if (clickIndex == -1) {
toast("请选择物品名称")
@@ -153,8 +163,10 @@ class FoodCollectionActivity : ComponentActivity() {
toast("请拍摄物品照片")
return@setOnClickListener
}
vectorThread()
uploadAllImage()
// vectorThread()
// uploadAllImage()
upload()
}
binding.btnTakePhoto.clickWithDebounce {
takePhoto()
@@ -261,14 +273,14 @@ class FoodCollectionActivity : ComponentActivity() {
searchAdapter.notifyDataSetChanged()
loadEmptyView()
binding.ivFinish.invisible()
binding.btnUploadImage.text = "待上传图片${0}"
// binding.btnUploadImage.text = "待上传图片${0}张"
}
private val cameraCallback: (Uri) -> Unit = { uri ->
val index = collectList.indexOfFirst { it.imageFile == null }
if (index == -1) {
toast("每次只允许保存6条数据")
rerurn@cameraCallback
rerurn@ cameraCallback
}
try {
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
@@ -286,7 +298,8 @@ class FoodCollectionActivity : ComponentActivity() {
return@let
}
val foodList = FoodModule.queryFoodNameScore(imageVector)
val filterList = foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子")}
val filterList =
foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子") }
if (filterList.isNotEmpty()) {
toast("当前物品可能被袋子遮挡,请检查后重试")
return@let
@@ -302,8 +315,8 @@ class FoodCollectionActivity : ComponentActivity() {
it.isShowCamera = false
}
collectionAdapter.notifyItemChanged(index)
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
binding.btnUploadImage.text = "待上传图片${count}"
val count = collectList.count { it.imageFile != null && it.uploadSuccess.not() }
// binding.btnUploadImage.text = "待上传图片${count}张"
if (cropBitmap.isRecycled.not()) {
cropBitmap.recycle()
}
@@ -337,9 +350,10 @@ class FoodCollectionActivity : ComponentActivity() {
}
private fun image2VectorTask(
bitmap: Bitmap?=null,
imageVector: FloatArray?=null,
position: Int) {
bitmap: Bitmap? = null,
imageVector: FloatArray? = null,
position: Int
) {
try {
initBox()
// val imageVector = try {
@@ -443,51 +457,77 @@ class FoodCollectionActivity : ComponentActivity() {
}
}
// private val failList = mutableListOf<File>()
// private var successCount = 0
private fun uploadAllImage() {
Loading.show(this)
val files = collectList.filter { it.imageFile!=null }.map { it.imageFile!! }
if (files.isEmpty()) {
return
}
// successCount = 0
// failList.clear()
val goods = searchGoodsList[clickIndex]
for (index in collectList.indices step 5) {
val end = if(index + 5 < collectList.size - 1) index + 5 else collectList.size - 1
val subList = collectList.subList(index, end)
val subFiles = subList.map { it.imageFile }
viewModel.uploadMultipleImages(goods.id!!, goods.goodsName!!, subFiles) {isSuccess->
Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
//{"code":"00000","data":null,"msg":"成功","total":0}
// val resp = result?.toObject<RespData>()
// val isSuccess = resp?.code == "00000"
subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
runOnUiThread {
binding.btnUploadImage.text = "待上传图片${count}"
if (count == 0) {
Loading.dismiss()
}
}
// binding.ivFinish.run {
// if (isSuccess) visible() else invisible()
// private fun uploadAllImage() {
// Loading.show(this)
// val files = collectList.filter { it.imageFile!=null }.map { it.imageFile!! }
// if (files.isEmpty()) {
// return
// }
// val goods = searchGoodsList[clickIndex]
// for (index in collectList.indices step 5) {
// val end = if(index + 5 < collectList.size - 1) index + 5 else collectList.size - 1
// val subList = collectList.subList(index, end)
// val subFiles = subList.map { it.imageFile }
// viewModel.uploadMultipleImages(goods.id!!, goods.goodsName!!, subFiles) {isSuccess->
// Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
// subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
//
// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
// runOnUiThread {
// binding.btnUploadImage.text = "待上传图片${count}张"
// if (count == 0) {
// Loading.dismiss()
// }
// }
// }
// }
// }
private fun upload() {
lifecycleScope.launch {
val totalFileCount = collectList.count { it.imageFile != null }
val goods = searchGoodsList[clickIndex]
val params = HashMap<String, RequestBody>()
//params["placeId"] = restId.toRequestBody()
params["foodId"] = goods.id!!.toRequestBody()
params["foodName"] = goods.goodsName!!.toRequestBody()
//params["foodVector"] = foodVector.toRequestBody()
ImageUploader(
totalList = collectList,
uploadImage = { batch ->
val files = batch.map { it.imageFile }
viewModel.uploadMultipleImages(files = files, params)
},
onProgress = { count, batch ->
runOnUiThread {
showWaitingDialog2("图片上传中$count/$totalFileCount")
batch.forEach {
it.uploadSuccess = true
}
}
},
onError = {
runOnUiThread {
hideWaitingDialog()
toast("上传失败,请稍后重试")
}
},
onComplete = {
hideWaitingDialog()
vectorThread()
}
).processUploads()
}
}
private val receiptViewModel: ReceiptViewModel by viewModels()
fun searchGoodsInfoList(goodsName: String, block:(List<SearchGoodsInfo.Record>)->Unit) {
fun searchGoodsInfoList(goodsName: String, block: (List<SearchGoodsInfo.Record>) -> Unit) {
runBlocking {
val list = searchGoodsInfoList2(goodsName)
block(list)
}
}
suspend fun searchGoodsInfoList2(
goodsName: String,
pageNo: Int = 1,
@@ -496,18 +536,53 @@ class FoodCollectionActivity : ComponentActivity() {
return receiptViewModel.searchGoodsInfoList2(goodsName, pageNo, pageSize)
}
private var mDialogWaiting: CustomDialog? = null
/**
* 显示等待提示框
*/
fun showWaitingDialog(tip: String?): Dialog? {
hideWaitingDialog()
val view = View.inflate(this, R.layout.dialog_waiting, null)
if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog)
mDialogWaiting!!.show()
mDialogWaiting!!.setCancelable(true)
return mDialogWaiting
}
/**
* 隐藏等待提示框
*/
fun hideWaitingDialog() {
mDialogWaiting?.dismiss()
mDialogWaiting = null
}
fun showWaitingDialog2(tip: String?) {
if (mDialogWaiting == null) {
hideWaitingDialog()
val view = View.inflate(this, R.layout.dialog_waiting, null)
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog)
mDialogWaiting!!.show()
mDialogWaiting!!.setCancelable(true)
}
val tvTip = findViewById<TextView>(R.id.tvTip)
tvTip.text = tip
}
data class RespData(
var code:String?=null,
var data:String?=null,
var msg:String?=null,
var code: String? = null,
var data: String? = null,
var msg: String? = null,
)
data class GoodsImage(
var goodsId:String,
var goodsName:String,
var startTime:Long,
var endTime:Long
var goodsId: String,
var goodsName: String,
var startTime: Long,
var endTime: Long
)
//
// val goodsImageList = mutableListOf<GoodsImage>().apply {
@@ -564,52 +639,52 @@ class FoodCollectionActivity : ComponentActivity() {
// ))
// }
private fun uploadImage(goodsImage: GoodsImage) {
Loading.show(this)
val cropFile = File(this.cacheDir, "crop")
val list = mutableListOf<File>()
val startTime = goodsImage.startTime
val endTime = goodsImage.endTime
cropFile.listFiles()?.forEach {
if (it.isDirectory) {
return@forEach
}
val start = "IMG_CROP_".length
val end = it.name.indexOf(".jpg")
val time = it.name.substring(start, end).toLong()
if (time in startTime..endTime) {
list.add(it)
}
if (list.size < 5) {
return@forEach
}
viewModel.uploadMultipleImages(
goodsId = goodsImage.goodsId,
goodsName = goodsImage.goodsName,
files = list
) { isSuccess ->
// val resp = data?.toObject<RespData>()
// val isSuccess = resp?.code == "00000"
binding.ivFinish.run {
if (isSuccess) visible() else invisible()
}
}
list.clear()
}
if (list.isNotEmpty()) {
viewModel.uploadMultipleImages(
goodsId = goodsImage.goodsId,
goodsName = goodsImage.goodsName,
files = list
) { isSuccess ->
// val resp = data?.toObject<RespData>()
// val isSuccess = resp?.code == "00000"
binding.ivFinish.run {
if (isSuccess) visible() else invisible()
}
}
}
Loading.dismiss()
}
// private fun uploadImage(goodsImage: GoodsImage) {
// Loading.show(this)
// val cropFile = File(this.cacheDir, "crop")
// val list = mutableListOf<File>()
// val startTime = goodsImage.startTime
// val endTime = goodsImage.endTime
// cropFile.listFiles()?.forEach {
// if (it.isDirectory) {
// return@forEach
// }
// val start = "IMG_CROP_".length
// val end = it.name.indexOf(".jpg")
// val time = it.name.substring(start, end).toLong()
// if (time in startTime..endTime) {
// list.add(it)
// }
// if (list.size < 5) {
// return@forEach
// }
// viewModel.uploadMultipleImages(
// goodsId = goodsImage.goodsId,
// goodsName = goodsImage.goodsName,
// files = list
// ) { isSuccess ->
//// val resp = data?.toObject<RespData>()
//// val isSuccess = resp?.code == "00000"
// binding.ivFinish.run {
// if (isSuccess) visible() else invisible()
// }
// }
// list.clear()
// }
// if (list.isNotEmpty()) {
// viewModel.uploadMultipleImages(
// goodsId = goodsImage.goodsId,
// goodsName = goodsImage.goodsName,
// files = list
// ) { isSuccess ->
//// val resp = data?.toObject<RespData>()
//// val isSuccess = resp?.code == "00000"
// binding.ivFinish.run {
// if (isSuccess) visible() else invisible()
// }
// }
// }
// Loading.dismiss()
// }
}
@@ -10,6 +10,7 @@ import androidx.activity.viewModels
import androidx.camera.view.PreviewView
import androidx.core.graphics.toColorInt
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import com.shuwei.intelligent.shelves.utils.ext.appendText
import com.shuwei.intelligent.shelves.utils.ext.buildSpannableString
@@ -45,7 +46,10 @@ import com.sw.inbound.utils.ext.toJsonString
import com.sw.inbound.utils.ext.toast
import com.sw.inbound.viewmodel.ReceiptViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.io.File
import kotlin.math.abs
@@ -180,7 +184,8 @@ abstract class GoodsListActivity : ComponentActivity() {
// Timber.tag(TAG).d(clazzName)
if (DialogManager.getDialogList().size == 1 &&
DialogManager.contains("GoodsRecognizeDialog") &&
goodsRecognizeDialog?.isShowing == true) {
goodsRecognizeDialog?.isShowing == true
) {
goodsRecognizeDialog?.dismiss()
}
}
@@ -313,7 +318,8 @@ abstract class GoodsListActivity : ComponentActivity() {
foodList.forEach {
it.name = it.name.split("WP")[0]
}
val filterList = foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子")}
val filterList =
foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子") }
if (filterList.isNotEmpty()) {
runOnUiThread {
toast("当前物品可能被袋子遮挡,请检查后重试")
@@ -622,14 +628,17 @@ abstract class GoodsListActivity : ComponentActivity() {
}
}
fun uploadImage(goodsId:String, goodsName:String, imageFile: File?) {
fun uploadImage(goodsId: String, goodsName: String, imageFile: File?) {
lifecycleScope.launch {
if (imageFile == null) {
return
return@launch
}
val list = mutableListOf<File>()
list.add(imageFile)
viewModel.uploadMultipleImages(goodsId, goodsName, list) {
Timber.tag(TAG).d("uploadMultipleImages: ${it}")
val map = hashMapOf<String, RequestBody>()
map["goodsId"] = goodsId.toRequestBody()
map["goodsName"] = goodsName.toRequestBody()
viewModel.uploadMultipleImages(files = list, params = map)
}
}
@@ -0,0 +1,95 @@
package com.sw.inbound.dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import com.sw.inbound.R;
/**
* 加载进度条弹窗
*/
public class CustomDialog extends Dialog {
/**
* 宽高由布局文件中指定(但是最底层的宽度无效,可以多嵌套一层解决)
*/
public CustomDialog(Context context, View layout, int style) {
super(context, style);
setContentView(layout);
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.CENTER;
window.setAttributes(params);
}
/**
* 宽高由该方法的参数设置
*/
public CustomDialog(Context context, int width, int height, View layout,
int style) {
super(context, style);
// 设置内容
setContentView(layout);
// 设置窗口属性
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
// 设置宽度、高度、密度、对齐方式
float density = getDensity(context);
params.width = (int) (width * density);
params.height = (int) (height * density);
params.gravity = Gravity.CENTER;
window.setAttributes(params);
}
/**
* 获取显示密度
*
* @param context
* @return
*/
public float getDensity(Context context) {
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
return dm.density;
}
private void fullScreenImmersive(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN;
view.setSystemUiVisibility(uiOptions);
}
}
@Override
public void show() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
super.show();
// fullScreenImmersive(getWindow().getDecorView());
// this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}
}
@@ -213,11 +213,11 @@ class RemoteRepository @Inject constructor(
}
}
suspend fun uploadMultipleImages(fileList: List<File>, param: Map<String, String>): ApiResponse<String> {
val paramsMap = hashMapOf<String, RequestBody>()
param.forEach { (key, value) ->
paramsMap[key] = value.toRequestBody("text/plain".toMediaTypeOrNull())
}
suspend fun uploadMultipleImages(fileList: List<File>, params: HashMap<String, RequestBody>): ApiResponse<String> {
// val paramsMap = hashMapOf<String, RequestBody>()
// param.forEach { (key, value) ->
// paramsMap[key] = value.toRequestBody("text/plain".toMediaTypeOrNull())
// }
// 准备文件参数
val fileParts = mutableListOf<MultipartBody.Part>()
@@ -232,7 +232,7 @@ class RemoteRepository @Inject constructor(
fileParts.add(filePart)
}
return safeApiCall {
apiService.uploadMultipleImages(params = paramsMap, goodsPics = fileParts)
apiService.uploadMultipleImages(params = params, goodsPics = fileParts)
}
}
}
@@ -0,0 +1,40 @@
package com.sw.inbound.utils
import com.sw.inbound.objbox.FoodCollectionBean
import java.util.concurrent.atomic.AtomicInteger
import kotlin.collections.chunked
import kotlin.collections.count
class ImageUploader(
private val totalList: List<FoodCollectionBean>,
private val uploadImage: suspend (List<FoodCollectionBean>)-> Boolean,
private val onProgress: (Int, List<FoodCollectionBean>) -> Unit,
private val onError:(List<FoodCollectionBean>) -> Unit,
private val onComplete:() -> Unit
) {
companion object {
private const val BATCH_SIZE = 5
}
private val uploadedCount = AtomicInteger(0)
suspend fun processUploads() {
val batches = totalList.chunked(BATCH_SIZE)
for (batch in batches) {
val success = uploadImage(batch)
if (!success) {
//println("上传失败,终止流程")
onError(batch)
return
}
val fileCount = batch.count { it.imageFile!=null }
uploadedCount.addAndGet(fileCount)
onProgress(uploadedCount.get(), batch)
//println("已上传 ${uploadedCount.get()}/$totalImages")
}
onComplete()
//println("流程完成,总计上传 ${uploadedCount.get()} 张图片")
}
}
@@ -9,6 +9,7 @@ import com.sw.inbound.model.response.SearchGoodsInfo
import com.sw.inbound.repository.RemoteRepository
import com.sw.inbound.utils.ext.toJsonString
import dagger.hilt.android.lifecycle.HiltViewModel
import okhttp3.RequestBody
import timber.log.Timber
import java.io.File
import javax.inject.Inject
@@ -347,7 +348,7 @@ class ReceiptViewModel @Inject constructor(
// }
// }
fun uploadImage(file:File, callback: (String?) -> Unit) {
fun uploadImage(file: File, callback: (String?) -> Unit) {
launchWithLoading {
val resp = repository.uploadImage(file)
if (!parseResponse(resp)) {
@@ -377,23 +378,42 @@ class ReceiptViewModel @Inject constructor(
callback(true)
}
}
fun uploadMultipleImages(goodsId:String, goodsName:String, files:List<File?>, callback: (Boolean) -> Unit) {
launchWithLoading {
val map = mutableMapOf<String, String>()
map["goodsId"] = goodsId
map["goodsName"] = goodsName
// fun uploadMultipleImages(goodsId:String, goodsName:String, files:List<File?>, callback: (Boolean) -> Unit) {
// launchWithLoading {
// val map = mutableMapOf<String, String>()
// map["goodsId"] = goodsId
// map["goodsName"] = goodsName
// val fileList = files.filterNotNull()
// if (fileList.isEmpty()) {
// callback(false)
// return@launchWithLoading
// }
// val resp = repository.uploadMultipleImages(fileList = fileList, param = map)
// if (!parseResponse(resp)) {
// callback(false)
// return@launchWithLoading
// }
// callback(resp.code == "00000")
// }
// }
suspend fun uploadMultipleImages(
files: List<File?>,
params: HashMap<String, RequestBody>
): Boolean {
// val map = mutableMapOf<String, String>()
// map["goodsId"] = goodsId
// map["goodsName"] = goodsName
val fileList = files.filterNotNull()
if (fileList.isEmpty()) {
callback(false)
return@launchWithLoading
}
val resp = repository.uploadMultipleImages(fileList = fileList, param = map)
if (!parseResponse(resp)) {
callback(false)
return@launchWithLoading
}
callback(resp.code == "00000")
return true
}
val resp = repository.uploadMultipleImages(fileList = fileList, params = params)
// if (!parseResponse(resp)) {
// callback(false)
// return@launchWithLoading
// }
return resp.code == "00000"
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
<solid android:color="@color/black" />
</shape>
@@ -353,18 +353,18 @@
android:layout_height="match_parent"
android:layout_weight="1" />
<TextView
android:id="@+id/btnUploadImage"
android:layout_width="270dp"
android:layout_height="90dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_blue_ripple"
android:gravity="center"
android:text="待上传图片"
android:textColor="@color/white"
android:textSize="26sp"
android:textStyle="bold" />
<!-- <TextView-->
<!-- android:id="@+id/btnUploadImage"-->
<!-- android:layout_width="270dp"-->
<!-- android:layout_height="90dp"-->
<!-- android:layout_gravity="center_vertical"-->
<!-- android:layout_marginEnd="20dp"-->
<!-- android:background="@drawable/bg_blue_ripple"-->
<!-- android:gravity="center"-->
<!-- android:text="待上传图片"-->
<!-- android:textColor="@color/white"-->
<!-- android:textSize="26sp"-->
<!-- android:textStyle="bold" />-->
<TextView
android:id="@+id/btnSave"
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/dialog_waiting"
android:paddingStart="20dp"
android:paddingTop="10dp"
android:paddingEnd="20dp"
android:paddingBottom="10dp">
<ProgressBar
android:layout_width="60dp"
android:layout_height="60dp"
android:indeterminateTint="@color/teal_200"
android:indeterminateTintMode="src_atop" />
<TextView
android:id="@+id/tvTip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请稍等"
android:layout_marginStart="10dp"
android:layout_gravity="center_vertical"
android:textColor="@color/white"
android:textSize="26sp" />
</LinearLayout>
+14
View File
@@ -27,4 +27,18 @@
<item name="android:windowIsFloating">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<!--圆角Dialog-->
<style name="MyDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:backgroundDimAmount">0.6</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
</resources>