app/src/main/java/com/xw/yunwei/model/SiteModel.kt
@@ -1,10 +1,13 @@ package com.xw.yunwei.model import android.os.Parcelable import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** * 点位管理数据类 */ @Parcelize data class SiteModel( /** @@ -151,4 +154,4 @@ */ @SerializedName("distance") val distance: Double? = null ) ) : Parcelable app/src/main/java/com/xw/yunwei/net/CommonApi.kt
@@ -10,6 +10,6 @@ interface CommonApi { /*文件上传*/ @POST("operation/base/v1/oss/upload") @POST("operation/maintenance-app/base/v1/oss/upload") fun uploadFile(@Body body: MultipartBody): Call<HttpResponse<UploadModel>> } app/src/main/java/com/xw/yunwei/net/WorkApi.kt
@@ -135,5 +135,7 @@ @GET("map/maintenance-app/api/v1/fence/listByCityCode") fun getFenceByCode(@Query("cityCode") cityCode: String): Call<HttpResponse<List<FenceInfoModel>>> /* 现场情况上报 */ @POST("operation/maintenance-app/api/v1/pointSituationReport/addPointSituationReport") fun addPointSituationReport(@Body params: Map<String, Any>): Call<HttpResponse<Any>> } app/src/main/java/com/xw/yunwei/net/WorkRepository.kt
@@ -1,9 +1,11 @@ package com.xw.yunwei.net import com.blankj.utilcode.util.GsonUtils import com.xw.common.net.BaseHttpManager.Companion.getBody import com.xw.common.net.interceptAwait import com.xw.yunwei.model.CheckRecordModel import com.xw.yunwei.model.MaintainRecordModel import com.xw.yunwei.model.SiteModel class WorkRepository(private val api: WorkApi) { @@ -55,4 +57,19 @@ suspend fun getFenceByCode(cityCode: String) = api.getFenceByCode(cityCode).interceptAwait() suspend fun queryArea() = api.queryArea().interceptAwait() /* 现场情况上报 */ suspend fun addPointSituationReport( work: Boolean, model: SiteModel, sceneDescription: String, scenePhoto: List<String>,//现场照片JSON数组 ): Any? { val map = mapOf<String, Any>( "fieldSituation" to if (work) 1 else 2,//现场情况(1=正常,2=异常) "pointId" to model.id.toString(),//点位id "sceneDescription" to sceneDescription,//现场情况说明 "scenePhoto" to GsonUtils.toJson(scenePhoto), ) return api.addPointSituationReport(map).interceptAwait() } } app/src/main/java/com/xw/yunwei/ui/work/site/SiteErrorUploadActivity.kt
@@ -1,26 +1,117 @@ package com.xw.yunwei.ui.work.site import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import android.view.View import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.widget.addTextChangedListener import androidx.recyclerview.widget.GridLayoutManager import com.xw.common.base.BaseActivity import com.xw.common.utils.GlideEngine import com.xw.yunwei.BR import com.xw.yunwei.R import com.xw.yunwei.databinding.ActivitySiteErrorUploadBinding import com.xw.yunwei.model.SiteModel import com.xw.yunwei.ui.work.site.adapter.PictureOperationAdapter import com.xw.yunwei.ui.work.site.viewmodel.SiteErrorUploadVM class SiteErrorUploadActivity : AppCompatActivity() { companion object{ fun getParams(params:List<Pair<String,Any>>): Bundle{ class SiteErrorUploadActivity : BaseActivity<ActivitySiteErrorUploadBinding, SiteErrorUploadVM>() { companion object { //获取跳转该页面参数 fun getParams(model: SiteModel): Bundle { return bundleOf("model" to model) } } val adapter by lazy { PictureOperationAdapter().apply { addChildClickViewIds(R.id.iv_delete) } } override fun getBindingVariable() = BR.viewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(R.layout.activity_site_error_upload) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets viewModel.model.postValue(intent.getParcelableExtra("model")) } override fun setListener() { super.setListener() binding.tvWork.setOnClickListener { viewModel.working.postValue(true) } binding.tvError.setOnClickListener { viewModel.working.postValue(false) } binding.etInput.addTextChangedListener { binding.tvNotice.visibility = if ((it?.toString()?.length ?: 0) > viewModel.maxLength.value!!) { View.VISIBLE } else { View.GONE } viewModel.countNotice.postValue("${it?.toString()?.length ?: 0}/${viewModel.maxLength.value!!}") } adapter.setOnItemClickListener { _, _, i -> viewModel.operatePicture(this, i) } adapter.setOnItemChildClickListener { _, _, i -> viewModel.removePicture(i) } } //设置运行状态 private fun setWorkState() { binding.tvWork.setTextColor( ContextCompat.getColor( this, if (viewModel.working.value == true) { com.xw.common.R.color.green_5 } else { com.xw.common.R.color.gray_9 } ) ) binding.tvWork.setBackgroundResource( if (viewModel.working.value == true) { R.drawable.shape_green_1_bg_4 } else { R.drawable.shape_gray11_bg_4 } ) binding.tvWork.setTextColor( ContextCompat.getColor( this, if (viewModel.working.value == false) { com.xw.common.R.color.orange_5 } else { com.xw.common.R.color.gray_9 } ) ) binding.tvError.setBackgroundResource( if (viewModel.working.value == false) { R.drawable.shape_orange_1_bg_4 } else { R.drawable.shape_gray11_bg_4 } ) } override fun setObservable() { super.setObservable() viewModel.model.observe(this) { GlideEngine.createGlideEngine().load(binding.ivPicture, it.pointPictures, 0, 0, 4f) binding.tvTitle.text = it.pointName binding.tvDetail.text = it.pointAddress } viewModel.operationPictures.observe(this) { adapter.setNewInstance(it) } viewModel.working.observe(this) { setWorkState() } } override fun init() { super.init() binding.rvList.adapter = adapter binding.rvList.layoutManager = GridLayoutManager(this, 5) } } app/src/main/java/com/xw/yunwei/ui/work/site/SiteNavActivity.kt
@@ -1,6 +1,5 @@ package com.xw.yunwei.ui.work.site import com.xw.common.utils.LogUtils import android.view.Gravity import android.view.KeyEvent import android.view.View @@ -10,7 +9,6 @@ import android.widget.LinearLayout import androidx.core.view.isVisible import androidx.databinding.DataBindingUtil import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.customview.customView @@ -20,12 +18,10 @@ import com.xw.common.CommonDialog import com.xw.common.R import com.xw.common.base.BaseActivity import com.xw.common.base.OnItemClickListener import com.xw.common.base.OneItemElementClickListener import com.xw.common.utils.BindUtils import com.xw.common.utils.BindUtils.getUrl import com.xw.common.utils.GpsHelper.Companion.navigate import com.xw.common.utils.ToastUtilCommon import com.xw.common.viewAdapter.ImageDefault import com.xw.common.viewAdapter.ViewAdapter import com.xw.common.viewAdapter.ViewAdapter.Companion.showAnim @@ -34,7 +30,6 @@ import com.xw.yunwei.databinding.DialogSiteFilterBinding import com.xw.yunwei.model.SiteModel import com.xw.yunwei.ui.work.AMapFragment import kotlinx.coroutines.launch import org.json.JSONArray class SiteNavActivity : BaseActivity<ActivitySiteNavBinding, SiteNavVM>(), @@ -104,7 +99,7 @@ areas.add(area) } } if(areas.isNotEmpty()){ if (areas.isNotEmpty()) { mapFrag.drawPolygon(areas) } } @@ -119,7 +114,7 @@ // if (viewModel.search.value.isNullOrEmpty()) { // ToastUtilCommon.show("请输入搜索内容") // } else { viewModel.query() viewModel.query() // } } false @@ -139,7 +134,8 @@ CommonDialog.showTipsDialog( this@SiteNavActivity, "您未开启gps权限,无法获取当前定位,请打开后重新操作", null) null ) } else { if (viewModel.fences.value.isNullOrEmpty()) { viewModel.cityCode = location.adCode.substring(0, 4) + "00" @@ -157,7 +153,10 @@ } binding.btnErrorUpload.setOnClickListener { viewModel.siteItem.value?.let { startActivity( SiteErrorUploadActivity::class.java, SiteErrorUploadActivity.getParams(it) ) } } } app/src/main/java/com/xw/yunwei/ui/work/site/adapter/PictureOperationAdapter.kt
New file @@ -0,0 +1,29 @@ package com.xw.yunwei.ui.work.site.adapter import android.widget.ImageView import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.viewholder.BaseViewHolder import com.xw.common.utils.GlideEngine import com.xw.yunwei.R //图片操作适配器 class PictureOperationAdapter() : BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_picture_operation) { override fun convert( holder: BaseViewHolder, item: String ) { val imageView = holder.getView<ImageView>(R.id.iv_picture) if (item.isEmpty()) { imageView.setImageResource(R.mipmap.ic_add_picture) } else { GlideEngine.createGlideEngine().load( imageView, item, 0, 0, 4f ) } holder.setGone(R.id.iv_delete, item.isEmpty()) } } app/src/main/java/com/xw/yunwei/ui/work/site/viewmodel/SiteErrorUploadVM.kt
New file @@ -0,0 +1,194 @@ package com.xw.yunwei.ui.work.site.viewmodel import android.annotation.SuppressLint import android.app.Application import android.content.Context import android.view.View import androidx.core.net.toUri import androidx.lifecycle.MutableLiveData import com.blankj.utilcode.util.UriUtils import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.PictureMimeType import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.xw.common.CommonDialog import com.xw.common.base.BaseViewModel import com.xw.common.utils.GlideEngine import com.xw.common.utils.PictureCompressEngine import com.xw.common.utils.ToastUtilCommon import com.xw.yunwei.R import com.xw.yunwei.model.SiteModel import com.xw.yunwei.net.CommonRepository import com.xw.yunwei.net.WorkRepository import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.RequestBody.Companion.asRequestBody import org.koin.core.component.inject import java.io.File class SiteErrorUploadVM(application: Application) : BaseViewModel(application), OnResultCallbackListener<LocalMedia> { val commonRepository: CommonRepository by inject() val workRepository: WorkRepository by inject() val model = MutableLiveData<SiteModel>() var working = MutableLiveData<Boolean>() val maxLength = MutableLiveData(200) val desc = MutableLiveData("") val countNotice: MutableLiveData<String> = MutableLiveData("${desc.value?.length ?: 0}/${maxLength.value}") val noticeLabel: MutableLiveData<String> = MutableLiveData("最多输入${maxLength.value}字") val pictureMax = MutableLiveData(9) //操作图片 val operationPictures: MutableLiveData<MutableList<String>> = MutableLiveData(mutableListOf("")) //是否正在上传中 var isUploading = false val onClick = View.OnClickListener { when (it.id) { R.id.btn_error_upload -> submit() } } //添加图片 fun addPicture(url: String) { val list = operationPictures.value ?: mutableListOf() list.add(url) refreshPictures(list) operationPictures.postValue(list) } //移除图片 fun removePicture(position: Int) { val list = operationPictures.value ?: mutableListOf() list.removeAt(position) refreshPictures(list) operationPictures.postValue(list) } //刷新图片 fun refreshPictures(list: MutableList<String>) { list.removeIf { it.isEmpty() } if (list.size == pictureMax.value) { return } list.add("") } //操作图片 fun operatePicture(context: Context, position: Int) { val list = operationPictures.value ?: mutableListOf() val element = list.elementAtOrNull(position) ?: return if (element.isEmpty()) { operatePictureFromDevice(context) } } //从设备操作图片 fun operatePictureFromDevice(context: Context) { CommonDialog.showTypeDialog(context) { if (it == 0) takeAPhotograph(context) else if (it == 1) enterGallery(context) } } // 进入图库 @SuppressLint("SourceLockedOrientationActivity") private fun enterGallery(context: Context) { PictureSelector.create(context) .openGallery(SelectMimeType.ofImage()) .setImageEngine(GlideEngine.createGlideEngine()) .setMaxSelectNum(1) .setImageSpanCount(4) .isPreviewImage(true) .isDisplayCamera(false) .setCompressEngine(PictureCompressEngine()) .forResult(this) } // 拍照 private fun takeAPhotograph(context: Context) { PictureSelector.create(context) .openCamera(SelectMimeType.ofImage()) .setCompressEngine(PictureCompressEngine()) .forResultActivity(this) } override fun onResult(result: ArrayList<LocalMedia>?) { result?.let { selectList -> for (item in selectList) { val path: String = item.availablePath val imgPath = if (PictureMimeType.isContent(path) && !item.isCut && !item.isCompressed) { UriUtils.uri2File(path.toUri()).absolutePath } else { path } addPicture(imgPath) } } } override fun onCancel() { } private fun uploadFile(files: MutableList<String>, succ: () -> Unit) { files.removeIf { it.isEmpty() } val result = files.find { !it.startsWith("http") } if (result == null) { succ() } else { launchRequest(showLoading = false, error = { _, errMsg -> ToastUtilCommon.showError(errMsg) dismissDialog() isUploading = false }) { val file = File(result) val fileRequestBody = file.asRequestBody("image/jpg".toMediaType()) val mBuilder = MultipartBody.Builder() mBuilder.addFormDataPart("file", file.name, fileRequestBody) mBuilder.setType(MultipartBody.FORM) val data = commonRepository.uploadFile(mBuilder.build()) files[files.indexOf(result)] = data?.url ?: "" uploadFile(files, succ) } } } //提交 fun submit() { if (working.value == null) { ToastUtilCommon.showSuc("请选择现场情况") return } if ((desc.value?.length ?: 0) > maxLength.value!!) { ToastUtilCommon.showSuc(noticeLabel.value) return } val list = operationPictures.value ?: mutableListOf() list.removeIf { it.isEmpty() } if (list.count { !it.startsWith("http") } > 0) { uploadFile(list) { submit(list) } return } submit(list) } //提交 private fun submit(urls: MutableList<String>) { launchRequest { workRepository.addPointSituationReport( working.value!!, model.value!!, desc.value ?: "", urls ) ?.let { ToastUtilCommon.showSuc("提交成功") finish() } } } } app/src/main/res/drawable/shape_gray11_bg_4.xml
New file @@ -0,0 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="@dimen/dp_4" /> <solid android:color="@color/gray_11" /> </shape> app/src/main/res/layout/activity_site_error_upload.xml
@@ -1,10 +1,213 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.work.site.SiteErrorUploadActivity"> xmlns:tools="http://schemas.android.com/tools"> </androidx.constraintlayout.widget.ConstraintLayout> <data> <variable name="viewModel" type="com.xw.yunwei.ui.work.site.viewmodel.SiteErrorUploadVM" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white"> <androidx.appcompat.widget.AppCompatImageView android:id="@+id/back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_marginTop="@dimen/dp_56" android:onClick="@{viewModel::onBack}" android:src="@drawable/svg_back" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.appcompat.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="现场情况上报" android:textColor="@color/gray_10" android:textSize="@dimen/sp_16" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="@+id/back" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="@+id/back" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="@dimen/dp_88" android:fillViewport="true" android:orientation="vertical"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="@dimen/dp_12" android:layout_weight="1"> <ImageView android:id="@+id/iv_picture" android:layout_width="@dimen/dp_68" android:layout_height="@dimen/dp_92" android:layout_marginStart="@dimen/dp_20" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv_title" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_8" android:layout_marginEnd="@dimen/dp_20" android:textColor="@color/gray_9" android:textSize="@dimen/sp_14" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/iv_picture" app:layout_constraintTop_toTopOf="@id/iv_picture" /> <TextView android:id="@+id/tv_detail" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_8" android:layout_marginTop="@dimen/dp_4" android:layout_marginEnd="@dimen/dp_20" android:textColor="@color/color_838fa6" android:textSize="@dimen/sp_14" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/iv_picture" app:layout_constraintTop_toBottomOf="@id/tv_title" /> <TextView android:id="@+id/tv_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_marginTop="@dimen/dp_20" android:text="现场情况" android:textColor="@color/gray_9" android:textSize="@dimen/sp_16" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/iv_picture" /> <TextView android:id="@+id/tv_work" android:layout_width="0dp" android:layout_height="@dimen/dp_36" android:layout_marginStart="@dimen/dp_20" android:layout_marginTop="@dimen/dp_12" android:layout_marginEnd="5dp" android:background="@drawable/shape_gray11_bg_4" android:gravity="center" android:text="正常" android:textColor="@color/gray_9" android:textSize="@dimen/sp_14" android:textStyle="bold" app:layout_constraintEnd_toStartOf="@id/tv_error" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_label" /> <TextView android:id="@+id/tv_error" android:layout_width="0dp" android:layout_height="@dimen/dp_36" android:layout_marginStart="@dimen/dp_5" android:layout_marginTop="@dimen/dp_12" android:layout_marginEnd="@dimen/dp_20" android:background="@drawable/shape_gray11_bg_4" android:gravity="center" android:text="异常" android:textColor="@color/gray_9" android:textSize="@dimen/sp_14" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/tv_work" app:layout_constraintTop_toBottomOf="@id/tv_label" /> <EditText android:id="@+id/et_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/dp_20" android:layout_marginTop="@dimen/dp_12" android:background="@drawable/shape_gray_3_bg_4" android:gravity="top|start" android:hint="请输入现场情况描述,最多可输入200字" android:minHeight="@dimen/dp_91" android:padding="@dimen/dp_12" android:text="@={viewModel.desc}" android:textColor="@color/gray_9" android:textColorHint="@color/gray_6" android:textSize="@dimen/sp_14" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_work" /> <TextView android:id="@+id/tv_count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/dp_12" android:layout_marginBottom="@dimen/dp_12" android:text="@{viewModel.countNotice}" android:textColor="@color/gray_6" android:textSize="@dimen/sp_11" app:layout_constraintBottom_toBottomOf="@id/et_input" app:layout_constraintEnd_toEndOf="@id/et_input" /> <TextView android:id="@+id/tv_notice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_4" android:text="@={viewModel.noticeLabel}" android:textColor="@color/color_ec5340" android:textSize="@dimen/sp_11" android:visibility="gone" app:layout_constraintStart_toStartOf="@id/et_input" app:layout_constraintTop_toBottomOf="@id/et_input" tools:visibility="visible" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_list" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/dp_17" android:layout_marginTop="@dimen/dp_9" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_notice" tools:itemCount="5" tools:layoutManager="GridLayoutManager" tools:listitem="@layout/item_picture_operation" tools:spanCount="5" /> </androidx.constraintlayout.widget.ConstraintLayout> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@color/gray_4" /> <com.google.android.material.button.MaterialButton android:id="@+id/btn_error_upload" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/dp_20" android:layout_marginVertical="@dimen/dp_12" android:backgroundTint="@color/blue_5" android:text="提交" android:onClick="@{viewModel.onClick}" android:textSize="@dimen/sp_16" android:textStyle="bold" app:cornerRadius="@dimen/dp_4" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> </layout> app/src/main/res/layout/activity_site_nav.xml
@@ -363,12 +363,18 @@ android:textColor="@color/gray_7" android:textSize="@dimen/sp_14" /> <View android:layout_width="match_parent" android:layout_height="1px" android:layout_marginTop="@dimen/dp_38" android:background="@color/gray_4" /> <com.google.android.material.button.MaterialButton android:id="@+id/btn_error_upload" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/dp_20" android:layout_marginTop="@dimen/dp_50" android:layout_marginVertical="@dimen/dp_12" android:backgroundTint="@color/blue_5" android:text="现场情况上报" android:textSize="@dimen/sp_16" app/src/main/res/layout/item_picture_operation.xml
New file @@ -0,0 +1,23 @@ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/dp_5"> <ImageView android:id="@+id/iv_picture" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@mipmap/ic_add_picture" /> <ImageView android:id="@+id/iv_delete" android:layout_width="@dimen/dp_24" android:layout_height="@dimen/dp_24" android:layout_gravity="end" android:padding="@dimen/dp_4" android:src="@mipmap/icon_circle_line_black" android:visibility="gone" tools:visibility="visible" /> </FrameLayout> app/src/main/res/mipmap-xhdpi/ic_add_picture.png
app/src/main/res/mipmap-xhdpi/icon_circle_line_black.png
common/src/main/java/com/xw/common/utils/GlideEngine.java
@@ -3,6 +3,9 @@ import android.content.Context; import android.widget.ImageView; import androidx.annotation.IdRes; import androidx.annotation.NonNull; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; @@ -101,6 +104,28 @@ Glide.with(context).resumeRequests(); } /** * 加载图片 * * @param imageView 图片控件 * @param url 链接 * @param error 加载异常占位图资源id * @param placeHolder 占位图资源id * @param radius 圆角 单位dp */ public void load(@NonNull ImageView imageView, String url, @IdRes int error, @IdRes int placeHolder, float radius) { float value = radius * imageView.getContext().getResources().getDisplayMetrics().density; Glide.with(imageView) .load(url) .transform(new CenterCrop(), new RoundedCorners((int) value)) .placeholder(placeHolder) .error(error) .into(imageView); } private GlideEngine() { } common/src/main/res/values/colors.xml
@@ -67,6 +67,7 @@ <color name="gray_8">#DB31456A</color> <color name="gray_9">#FF31456A</color> <color name="gray_10">#FF0F1521</color> <color name="gray_11">#0831456A</color> <!-- 中性色语义化别名 --> <color name="color_background">@color/gray_1</color> @@ -79,5 +80,7 @@ <color name="color_transparent">#00000000</color> <color name="color_838fa6">#ff838fa6</color> <color name="color_ec5340">#ffec5340</color> </resources>