Parcourir la source

1.添加Luban图片压缩库

王鹏鹏 il y a 2 ans
Parent
commit
8efd03760e

+ 4 - 0
.idea/misc.xml

@@ -43,6 +43,8 @@
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_home_page_search.xml" value="0.155" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_home_page_title.xml" value="0.155" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_recommended_doctor.xml" value="0.155" />
+        <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_select_pic.xml" value="0.155" />
+        <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_select_pic_item.xml" value="0.155" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_selected_item.xml" value="0.155" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_sick_item.xml" value="0.155" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/drawable/bg_sick_selected.xml" value="0.155" />
@@ -57,7 +59,9 @@
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/activity_doctor_details.xml" value="0.42051756007393715" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/activity_health_consultation.xml" value="0.4" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/activity_main.xml" value="0.23697916666666666" />
+        <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/dialog_select_pic.xml" value="0.536" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/item_consultation.xml" value="0.3953084274543875" />
+        <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/item_image.xml" value="0.536" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/item_recommend_doctor.xml" value="0.6" />
         <entry key="..\:/workspace/hcp-pad/healthconsultation/src/main/res/layout/item_sick_time.xml" value="0.8800000000000001" />
         <entry key="..\:/workspace/hcp-pad/home/src/main/res/drawable/anim_loading.xml" value="0.2185" />

+ 81 - 0
baselib/src/main/java/com/yingyangfly/baselib/adapter/XBaseAdapter.kt

@@ -0,0 +1,81 @@
+package com.yingyangfly.baselib.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.yingyangfly.baselib.R
+import com.yingyangfly.baselib.utils.ViewTool
+import kotlinx.android.synthetic.main.rv_empty.view.*
+
+/**
+ * Author: YongChao
+ * Date: 19-8-30 下午4:29
+ * Description: RecyclerView.Adapter 基础类封装
+ */
+open class XBaseAdapter<T>(
+    val layoutResourceId: Int,
+    var items: List<T>,
+    var bindView: (View, T, Int) -> Unit
+) :
+    RecyclerView.Adapter<XBaseAdapter.ViewHolder<T>>() {
+    /**
+     * 0:空布局  1: 非空布局
+     */
+    val VIEW_TYPE_ITEM = 1
+    val VIEW_TYPE_EMPTY = 0
+    var isShowEmptyView = true
+    var emptyLayout = R.layout.rv_empty
+    var emptyText = ""
+    var recyclable = true  //是否服用Item  true: 是
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<T> {
+        if (isShowEmptyView && viewType == VIEW_TYPE_EMPTY) {
+            val viewEmpty = LayoutInflater.from(parent.context).inflate(emptyLayout, parent, false)
+            val view = ViewTool.inflateLayoutPixels(parent.context, viewEmpty, 1194, 834)
+            return ViewHolder(view, bindView)
+        }
+        val viewLayout =
+            LayoutInflater.from(parent.context).inflate(layoutResourceId, parent, false)
+        val view = ViewTool.inflateLayoutPixels(parent.context, viewLayout, 1194, 834)
+        return ViewHolder(view, bindView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder<T>, position: Int) {
+        if (items.isNotEmpty()) {
+            holder.bindForecast(items[position], position)
+            holder.setIsRecyclable(recyclable)
+        } else if (isShowEmptyView) {
+            holder.itemView.iv_empty?.visibility =
+                if (emptyText.isEmpty()) View.VISIBLE else View.GONE
+            holder.itemView.empty_view_message?.visibility =
+                if (emptyText.isEmpty()) View.GONE else View.VISIBLE
+            holder.itemView.empty_view_message?.text = emptyText
+        }
+    }
+
+    override fun getItemViewType(position: Int): Int {
+        return if (isShowEmptyView && items.isEmpty()) VIEW_TYPE_EMPTY else VIEW_TYPE_ITEM
+    }
+
+    override fun getItemCount() = if (isShowEmptyView && items.isEmpty()) 1 else items.size
+
+    class ViewHolder<in T>(view: View, val bindView: (View, T, Int) -> Unit) :
+        RecyclerView.ViewHolder(view) {
+        fun bindForecast(item: T, position: Int) {
+            bindView(itemView, item, position)
+        }
+    }
+
+    open fun setEmpytView(eLayout: Int) {
+        this.emptyLayout = eLayout
+    }
+
+    open fun setEmpytText(text: String) {
+        this.emptyText = text
+    }
+
+    open fun setIsShowEmptyView(isShow: Boolean) {
+        isShowEmptyView = isShow
+    }
+}

+ 2 - 3
baselib/src/main/java/com/yingyangfly/baselib/utils/FileMultipartBuilder.java

@@ -19,11 +19,10 @@ public class FileMultipartBuilder {
         for (int i = 0; i < files.size(); i++) {
             File file = files.get(i);
             RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
-            builder.addFormDataPart("dirName[" + position + "]", position + file.getName().substring(file.getName().indexOf(".")), requestBody);
+            builder.addFormDataPart("dirName", "yingyangfly" + position + file.getName().substring(file.getName().indexOf(".")), requestBody);
         }
         builder.setType(MultipartBody.FORM);
-        MultipartBody multipartBody = builder.build();
-        return multipartBody;
+        return builder.build();
     }
 
     public static List<MultipartBody.Part> filesToMultipartBodyParts(List<File> files) {

+ 247 - 0
baselib/src/main/java/com/yingyangfly/baselib/utils/GlideImgUtil.java

@@ -0,0 +1,247 @@
+package com.yingyangfly.baselib.utils;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.drawable.Drawable;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.bumptech.glide.load.resource.bitmap.CenterCrop;
+import com.bumptech.glide.load.resource.bitmap.CircleCrop;
+import com.bumptech.glide.request.RequestOptions;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
+import com.yingyangfly.baselib.R;
+import com.yingyangfly.baselib.utils.img.GlideRoundTransform;
+import com.yingyangfly.baselib.utils.img.TransformationUtils;
+
+import java.io.ByteArrayOutputStream;
+
+import io.reactivex.annotations.Nullable;
+
+/**
+ * Author: YongChao
+ * Date: 19-8-21 下午5:49
+ * Description:
+ */
+public class GlideImgUtil {
+
+    public static void loadImgFace(Context context, String face_url, final ImageView img) {
+        RequestOptions options = new RequestOptions()
+                .fitCenter()
+                .diskCacheStrategy(DiskCacheStrategy.NONE);
+        Glide.with(context)
+                .load(face_url)
+                .into(new SimpleTarget<Drawable>() {
+                    @Override
+                    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
+                        img.setImageDrawable(resource);
+                    }
+                });
+    }
+
+    public static void loadImgCircle(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .apply(RequestOptions.bitmapTransform(new CircleCrop()))
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+
+        Glide.with(context).load(imgUrl).apply(options).into(img);
+    }
+
+    public static void loadImgHeadCircle(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .apply(RequestOptions.bitmapTransform(new CircleCrop()))
+                .diskCacheStrategy(DiskCacheStrategy.NONE);
+
+        Glide.with(context).load(imgUrl).apply(options).into(img);
+    }
+
+    public static void loadAvatarRound(Context context, String imgUrl, ImageView img) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(R.mipmap.icon_place_holder)
+                .error(R.mipmap.icon_place_holder)
+                .transform(new CenterCrop(), new GlideRoundTransform(context, 5))
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+
+        Glide.with(context).load(imgUrl).apply(options).into(img);
+    }
+
+    public static void loadImgCircle(Context context, String imgUrl, ImageView img) {
+        loadImgCircle(context, imgUrl, img, R.mipmap.icon_place_holder, R.mipmap.icon_place_holder);
+    }
+
+    /**
+     * @param: [context, imgUrl, img]
+     * @return: void
+     * @description: 设置加载占位符及加载失败
+     */
+    public static void loadImgPlaceHolderError(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+
+        Glide.with(context).load(imgUrl).apply(options).into(img);
+    }
+
+    public static void loadImg(Context context, String imgUrl, ImageView img) {
+        loadImgPlaceHolderError(context, imgUrl, img, R.mipmap.icon_place_holder, R.mipmap.icon_place_holder);
+    }
+
+    public static void loadImgNoPlaceHolder(Context context, String imgUrl, ImageView img) {
+        RequestOptions options = new RequestOptions()
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+        Glide.with(context).load(imgUrl).apply(options).into(img);
+    }
+
+    public static void loadGifImg(Context context, int imgUrl, ImageView img) {
+        Glide.with(context).asGif().load(imgUrl).into(img);
+    }
+
+    public static void zoomImg(Context context, String imgUrl, ImageView img) {
+        Glide.with(context)
+                .asBitmap()
+                .load(imgUrl)
+                .into(new TransformationUtils(img));
+    }
+
+    /**
+     * 圆角图片
+     *
+     * @param context
+     * @param imgUrl
+     * @param img
+     * @param dPlaceHolder
+     * @param dError
+     */
+    public static void loadRoundImg(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError) {
+        loadRoundImg(context, imgUrl, img, dPlaceHolder, dError, 5);
+    }
+
+    public static void loadRoundImg(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError, int radius) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+        Glide.with(context).load(imgUrl).transform(new GlideRoundTransform(context, radius)).apply(options).into(img);
+    }
+
+    public static void loadRoundImg(Context context, int imgLocoalSrc, ImageView img, int radius) {
+        Glide.with(context).load(imgLocoalSrc).transform(new GlideRoundTransform(context, radius)).into(img);
+    }
+
+    public static void loadRoundImg(Context context, String imgUrl, ImageView img) {
+        loadRoundImg(context, imgUrl, img, R.mipmap.icon_place_holder, R.mipmap.icon_place_holder);
+    }
+
+    public static void loadBitmap(Context context, Bitmap bitmap, ImageView imageView) {
+        Glide.with(context).load(bitmap).diskCacheStrategy(DiskCacheStrategy.NONE).into(imageView);
+    }
+
+    public static void loadImage(Context context, int id, ImageView imageView) {
+        Glide.with(context).load(id).into(imageView);
+    }
+
+    /**
+     * Bitmap转换成byte[]并且进行压缩,压缩到不大于maxkb
+     *
+     * @param bitmap
+     * @param maxKb
+     * @return
+     */
+    public static byte[] bmpToByteArray(Bitmap bitmap, long maxKb, boolean needRecycle) {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
+        int options = 100;
+//        int fileSize = output.toByteArray().length;
+//        options = (int) Math.max(1, maxKb * 100 / fileSize);
+//        LogUtil.Companion.i("output option " + options);
+        while (output.toByteArray().length > maxKb && options > 0) {
+            output.reset(); //清空output
+            bitmap.compress(
+                    Bitmap.CompressFormat.JPEG,
+                    options,
+                    output
+            ); //这里压缩options%,把压缩后的数据存放到output中
+//            LogUtil.Companion.i("output " + output.toByteArray().length);
+            options -= 10;
+        }
+        if (needRecycle) {
+            bitmap.recycle();
+        }
+        return output.toByteArray();
+    }
+
+
+    /**
+     * 加载自定义宽高圆角图片
+     */
+    public static void loadRoundImgWidth(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError, int radius, int width) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+
+        ViewGroup.LayoutParams params = img.getLayoutParams();
+        params.height = width;
+        params.width = width;
+        img.setLayoutParams(params);
+
+        Glide.with(context).load(imgUrl).transform(new GlideRoundTransform(context, radius)).apply(options).into(img);
+    }
+
+    /**
+     * 加载自定义宽高圆角图片
+     */
+    public static void loadRoundImgWidthThumbnail(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError, int radius, int width) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+
+        ViewGroup.LayoutParams params = img.getLayoutParams();
+        params.height = width;
+        params.width = width;
+        img.setLayoutParams(params);
+        Glide.with(context).load(imgUrl).thumbnail(0.1f).transform(new GlideRoundTransform(context, radius)).apply(options).into(img);
+    }
+
+    /**
+     * 加载自定义宽高圆角图片
+     */
+    public static void loadRoundImgWidthThumbnail(Context context, String imgUrl, ImageView img, int dPlaceHolder, int dError, int radius, int width, float sizeMultiplier) {
+        RequestOptions options = new RequestOptions()
+                .placeholder(dPlaceHolder)
+                .error(dError)
+                .diskCacheStrategy(DiskCacheStrategy.ALL);
+        ViewGroup.LayoutParams params = img.getLayoutParams();
+        params.height = width;
+        params.width = width;
+        img.setLayoutParams(params);
+
+        Glide.with(context).load(imgUrl).thumbnail(sizeMultiplier).transform(new GlideRoundTransform(context, radius)).apply(options).into(img);
+    }
+
+    public static Bitmap convertBitmapSize(Bitmap bm, int newWidth, int newHeight) { // 获得图片的宽高
+        int width = bm.getWidth();
+        int height = bm.getHeight();
+        // 计算缩放比例
+        float scaleWidth = Float.parseFloat(newWidth + "") / width;
+        float scaleHeight = Float.parseFloat(newHeight + "") / height;
+        // 取得想要缩放的matrix参数
+        Matrix matrix = new Matrix();
+        matrix.postScale(scaleWidth, scaleHeight);
+        // 得到新的图片
+        return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
+    }
+
+}

+ 148 - 17
healthconsultation/src/main/java/com/yingyang/healthconsultation/consultationsheet/ConsultationSheetActivity.kt

@@ -7,6 +7,10 @@ import android.os.Environment
 import android.text.TextUtils
 import android.view.MotionEvent
 import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.ProgressBar
+import androidx.recyclerview.widget.GridLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.alibaba.android.arouter.facade.annotation.Route
@@ -14,13 +18,17 @@ import com.donkingliang.imageselector.utils.ImageSelector
 import com.yingyang.healthconsultation.R
 import com.yingyang.healthconsultation.adapter.SickTimeAdapter
 import com.yingyang.healthconsultation.databinding.ActivityConsultationSheetBinding
+import com.yingyang.healthconsultation.dialog.SelectPicDialog
+import com.yingyang.healthconsultation.entity.UploadImgBean
 import com.yingyang.healthconsultation.utils.CommonUtils
-import com.yingyangfly.baselib.ext.getEndAnimation
-import com.yingyangfly.baselib.ext.getScaleAnimation
-import com.yingyangfly.baselib.ext.toast
+import com.yingyangfly.baselib.adapter.XBaseAdapter
+import com.yingyangfly.baselib.ext.*
 import com.yingyangfly.baselib.mvvm.BaseMVVMActivity
 import com.yingyangfly.baselib.router.RouterUrlCommon
+import com.yingyangfly.baselib.utils.FileMultipartBuilder
+import com.yingyangfly.baselib.utils.GlideImgUtil
 import com.yingyangfly.baselib.utils.LogUtil
+import okhttp3.internal.notify
 import top.zibin.luban.Luban
 import top.zibin.luban.OnCompressListener
 import java.io.File
@@ -35,6 +43,10 @@ class ConsultationSheetActivity :
 
     private val REQUEST_MEDICALRECORDS_CAMERA = 1
     private val REQUEST_MEDICALRECORDS_IMG = 2
+    var imageList = mutableListOf<UploadImgBean>()
+    private lateinit var emptyUploadImgBean: UploadImgBean
+    private lateinit var imageAdapter: XBaseAdapter<UploadImgBean>
+
     private val sickTimes = mutableListOf<String>()
     private val sickTimeAdapter by lazy { SickTimeAdapter() }
 
@@ -50,6 +62,91 @@ class ConsultationSheetActivity :
             rvSickTime.adapter = sickTimeAdapter
             sickTimeAdapter.setData(sickTimes)
         }
+        initImageRv()
+    }
+
+    /**
+     * 初始化问诊单图片
+     */
+    private fun initImageRv() {
+        emptyUploadImgBean = UploadImgBean()
+        imageList.add(emptyUploadImgBean)
+        binding.rvPic.layoutManager = object : GridLayoutManager(mContext, 4) {
+            override fun canScrollVertically(): Boolean {
+                return false
+            }
+        }
+        imageAdapter = XBaseAdapter(
+            R.layout.item_image,
+            imageList
+        ) { view: View, bean: UploadImgBean, i: Int ->
+            val img = view.findViewById<ImageView>(R.id.img)
+            val ivAdd = view.findViewById<ImageView>(R.id.iv_add)
+            val imgDelete = view.findViewById<ImageView>(R.id.img_delete)
+            img.show(bean.isEmpty().not())
+            ivAdd.show(bean.isEmpty())
+            imgDelete.show(bean.isEmpty().not())
+            if (bean.isEmpty().not()) {
+                val params = img.layoutParams
+                params.height = params.width
+
+                if (!bean.uploadFlag) {
+                    GlideImgUtil.loadImage(mContext, R.mipmap.icon_add_pic, img)
+                }
+                if (bean.remotePath.isEmpty()) {
+                    upLoadImg(i, img)
+                } else {
+                    GlideImgUtil.loadRoundImg(
+                        mContext,
+                        if (bean.localPaht.isEmpty()) bean.remotePath else bean.localPaht,
+                        img
+                    )
+                }
+            }
+            ivAdd.setOnSingleClickListener {
+                if (bean.isEmpty()) {
+                    selectPic()
+                } else if (!bean.uploadFlag) {
+
+                }
+            }
+        }
+        binding.rvPic.adapter = imageAdapter
+    }
+
+    /**
+     * 图片选择弹框
+     */
+    private fun selectPic() {
+        val dialog = SelectPicDialog()
+        dialog.onDialogClickListener = {
+            if (TextUtils.equals("album", it)) {
+                ImageSelector.builder()
+                    .useCamera(false) // 设置是否使用拍照
+                    .setSingle(false) //设置是否单选
+                    .canPreview(true) //是否点击放大图片查看,,默认为true
+                    .setMaxSelectCount(if (getImgLocalPaths().size > 0) 9 - getImgLocalPaths().size else 9) // 图片的最大选择数量,小于等于0时,不限数量
+                    .start(this, REQUEST_MEDICALRECORDS_IMG) // 打开相册
+            } else {
+                ImageSelector.builder()
+                    .useCamera(true)
+                    .onlyTakePhoto(true)
+                    .setCrop(false)
+                    .setSelected(getImgLocalPaths())
+                    .start(this, REQUEST_MEDICALRECORDS_CAMERA)
+            }
+        }
+        dialog.show(supportFragmentManager, "SelectPicDialog")
+    }
+
+    fun getImgLocalPaths(): ArrayList<String> {
+        val localList = arrayListOf<String>()
+        imageList.forEach {
+            if (it.localPaht.isNullOrEmpty().not())
+                localList.add(it.localPaht)
+        }
+        return localList
+
     }
 
     @SuppressLint("ClickableViewAccessibility")
@@ -79,14 +176,7 @@ class ConsultationSheetActivity :
                         finish()
                     }
                     R.id.btnSubmit -> {
-                        ImageSelector.builder()
-                            .useCamera(true) // 设置是否使用拍照
-                            .setSingle(false) //设置是否单选
-                            .canPreview(true) //是否点击放大图片查看,,默认为true
-                            .setMaxSelectCount(
-                                9
-                            ) // 图片的最大选择数量,小于等于0时,不限数量。
-                            .start(this, REQUEST_MEDICALRECORDS_CAMERA) // 打开相册
+
                     }
                 }
             }
@@ -115,9 +205,16 @@ class ConsultationSheetActivity :
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         super.onActivityResult(requestCode, resultCode, data)
         if (resultCode == Activity.RESULT_OK) {
-            val images = data?.getStringArrayListExtra(ImageSelector.SELECT_RESULT)
-            images?.let {
-                withLs(it, "medicalrecords")
+            if (requestCode == REQUEST_MEDICALRECORDS_CAMERA) {//拍照
+                val images = data?.getStringArrayListExtra(ImageSelector.SELECT_RESULT)
+                images?.let {
+                    withLs(it)
+                }
+            } else if (requestCode == REQUEST_MEDICALRECORDS_IMG) {//选择图片
+                val images = data?.getStringArrayListExtra(ImageSelector.SELECT_RESULT)
+                images?.let {
+                    withLs(it)
+                }
             }
         }
     }
@@ -125,7 +222,7 @@ class ConsultationSheetActivity :
     /**
      * 开启luban图片压缩
      */
-    private fun withLs(photos: List<String>, selectType: String) {
+    private fun withLs(photos: List<String>) {
         Luban.with(this)
             .load(photos)
             .ignoreBy(100)
@@ -141,7 +238,7 @@ class ConsultationSheetActivity :
                     override fun onSuccess(file: File) {
                         val data = mutableListOf<String>()
                         data.add(file.path)
-
+                        addImages(data)
                     }
 
                     override fun onError(e: Throwable) {
@@ -150,8 +247,24 @@ class ConsultationSheetActivity :
                 }).launch()
     }
 
+    @SuppressLint("NotifyDataSetChanged")
+    fun addImages(data: List<String>) {
+        data.forEach {
+            val upload = UploadImgBean()
+            upload.localPaht = it
+            imageList.add(upload)
+        }
+        if (imageList.isEmpty().not() && imageList.contains(emptyUploadImgBean)) {
+            imageList.remove(emptyUploadImgBean)
+        }
+        if (imageList.size < 9) {
+            imageList.add(0, emptyUploadImgBean)
+        }
+        imageAdapter.notifyDataSetChanged()
+    }
+
     private fun getPath(): String {
-        val path = Environment.getExternalStorageDirectory().path + "/xioaliu/image/"
+        val path = Environment.getExternalStorageDirectory().path + "/hcp/image/"
         val file = File(path)
         return if (file.mkdirs()) {
             path
@@ -165,4 +278,22 @@ class ConsultationSheetActivity :
         }
         super.onDestroy()
     }
+
+    /**
+     * 图片上传
+     */
+    private fun upLoadImg(position: Int, imgView: ImageView) {
+        if (imageList.isEmpty().not()) {
+            val uploadBean = imageList[position]
+            if (uploadBean.isEmpty().not()) {
+                val listFile = mutableListOf<File>()
+                listFile.add(File(uploadBean.localPaht))
+                viewModel.uploadFile(listFile, position, fail = {
+                    it.toast()
+                }, success = {
+
+                })
+            }
+        }
+    }
 }

+ 16 - 0
healthconsultation/src/main/java/com/yingyang/healthconsultation/consultationsheet/ConsultationSheetViewModel.kt

@@ -3,6 +3,9 @@ package com.yingyang.healthconsultation.consultationsheet
 import com.yingyang.healthconsultation.entity.UserInfoBean
 import com.yingyang.healthconsultation.net.HEALTHCONSULTATION_API
 import com.yingyangfly.baselib.mvvm.BaseViewModel
+import com.yingyangfly.baselib.utils.FileMultipartBuilder
+import okhttp3.MultipartBody
+import java.io.File
 
 /**
  * @author 王鹏鹏
@@ -18,4 +21,17 @@ class ConsultationSheetViewModel : BaseViewModel() {
         success,
         fail
     )
+
+    fun uploadFile(
+        listFile: List<File>,
+        position: Int,
+        fail: ((msg: String) -> Unit)? = null,
+        success: ((success: Unit?) -> Unit)? = null,
+    ) = launchFlow(false) {
+        val mBody = FileMultipartBuilder.filesToMultipartBody(listFile, position)
+        HEALTHCONSULTATION_API.uploadFile(mBody)
+    }.runUI(
+        success,
+        fail
+    )
 }

+ 91 - 0
healthconsultation/src/main/java/com/yingyang/healthconsultation/dialog/SelectPicDialog.kt

@@ -0,0 +1,91 @@
+package com.yingyang.healthconsultation.dialog
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.fragment.app.DialogFragment
+import com.gyf.immersionbar.BarHide
+import com.gyf.immersionbar.ktx.immersionBar
+import com.yingyang.healthconsultation.R
+import com.yingyangfly.baselib.ext.setOnSingleClickListener
+import com.yingyangfly.baselib.utils.ViewTool
+
+class SelectPicDialog : DialogFragment(), View.OnTouchListener {
+
+    private var albumLayout: LinearLayout? = null
+    private var tvAlbum: TextView? = null
+    private var cameraLayout: LinearLayout? = null
+    private var tvCamera: TextView? = null
+
+    var onDialogClickListener: ((type: String) -> Unit)? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        isCancelable = true
+        dialog?.setCanceledOnTouchOutside(true)
+    }
+
+    override fun onStart() {
+        super.onStart()
+        dialog?.window?.setLayout(
+            ViewGroup.LayoutParams.WRAP_CONTENT,
+            ViewGroup.LayoutParams.WRAP_CONTENT
+        )
+        dialog?.window?.setBackgroundDrawableResource(R.color.transparent)
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        immersionBar {
+            hideBar(BarHide.FLAG_HIDE_BAR)
+            navigationBarColor(R.color.transparent)
+        }
+        val rootView = ViewTool.inflateFragmentPixels(
+            activity, R.layout.dialog_select_pic, container, 1194, 834
+        )
+        findId(rootView)
+        init()
+        return rootView
+    }
+
+    private fun findId(rootView: View) {
+        albumLayout = rootView.findViewById(R.id.albumLayout)
+        tvAlbum = rootView.findViewById(R.id.tvAlbum)
+        cameraLayout = rootView.findViewById(R.id.cameraLayout)
+        tvCamera = rootView.findViewById(R.id.tvCamera)
+    }
+
+    private fun init() {
+        albumLayout?.setOnSingleClickListener {
+            onDialogClickListener?.invoke("album")
+            dismiss()
+        }
+        tvAlbum?.setOnSingleClickListener {
+            onDialogClickListener?.invoke("album")
+            dismiss()
+        }
+        cameraLayout?.setOnSingleClickListener {
+            onDialogClickListener?.invoke("camera")
+            dismiss()
+        }
+        tvCamera?.setOnSingleClickListener {
+            onDialogClickListener?.invoke("camera")
+            dismiss()
+        }
+    }
+
+    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+        if (isCancelable && dialog?.isShowing == true) {
+            dismiss()
+            return true
+        }
+        return false
+    }
+}

+ 9 - 0
healthconsultation/src/main/java/com/yingyang/healthconsultation/net/HealthConsultationApiService.kt

@@ -3,6 +3,9 @@ package com.yingyang.healthconsultation.net
 import com.yingyang.healthconsultation.entity.ConsultationBean
 import com.yingyang.healthconsultation.entity.UserInfoBean
 import com.yingyangfly.baselib.net.BaseResp
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import retrofit2.http.Body
 import retrofit2.http.POST
 
 interface HealthConsultationApiService {
@@ -26,4 +29,10 @@ interface HealthConsultationApiService {
     @POST("app/user/info")
     suspend fun getUserInfo(): BaseResp<UserInfoBean>
 
+    /**
+     * 上传文件接口
+     */
+    @POST("common/upload")
+    suspend fun uploadFile(@Body multipartBody: MultipartBody): BaseResp<Unit>
+
 }

+ 7 - 0
healthconsultation/src/main/res/drawable/bg_select_pic.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="ResourceName">
+    <corners android:radius="@dimen/divider_40px" />
+    <solid android:color="@color/color_B3000000" />
+</shape>

+ 7 - 0
healthconsultation/src/main/res/drawable/bg_select_pic_item.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="ResourceName">
+    <corners android:radius="@dimen/divider_20px" />
+    <solid android:color="@android:color/white" />
+</shape>

+ 79 - 0
healthconsultation/src/main/res/layout/dialog_select_pic.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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"
+    tools:ignore="ResourceName">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="@dimen/divider_684px"
+        android:layout_height="@dimen/divider_296px"
+        android:background="@drawable/bg_select_pic">
+
+        <LinearLayout
+            android:id="@+id/albumLayout"
+            android:layout_width="@dimen/divider_112px"
+            android:layout_height="@dimen/divider_112px"
+            android:layout_marginStart="@dimen/divider_180px"
+            android:layout_marginTop="@dimen/divider_82px"
+            android:background="@drawable/bg_select_pic_item"
+            android:gravity="center"
+            android:orientation="vertical"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <androidx.appcompat.widget.AppCompatImageView
+                android:layout_width="@dimen/divider_60px"
+                android:layout_height="@dimen/divider_60px"
+                android:background="@mipmap/icon_album" />
+
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/tvAlbum"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/divider_212px"
+            android:layout_marginTop="@dimen/divider_13px"
+            android:text="@string/album"
+            android:textColor="@android:color/white"
+            android:textSize="@dimen/divider_24px"
+            android:textStyle="bold"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/albumLayout" />
+
+        <LinearLayout
+            android:id="@+id/cameraLayout"
+            android:layout_width="@dimen/divider_112px"
+            android:layout_height="@dimen/divider_112px"
+            android:layout_marginStart="@dimen/divider_100px"
+            android:layout_marginTop="@dimen/divider_82px"
+            android:background="@drawable/bg_select_pic_item"
+            android:gravity="center"
+            android:orientation="vertical"
+            app:layout_constraintStart_toEndOf="@+id/albumLayout"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <androidx.appcompat.widget.AppCompatImageView
+                android:layout_width="@dimen/divider_60px"
+                android:layout_height="@dimen/divider_60px"
+                android:background="@mipmap/icon_camera" />
+
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/tvCamera"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/divider_164px"
+            android:layout_marginTop="@dimen/divider_13px"
+            android:text="@string/camera"
+            android:textColor="@android:color/white"
+            android:textSize="@dimen/divider_24px"
+            android:textStyle="bold"
+            app:layout_constraintStart_toEndOf="@+id/tvAlbum"
+            app:layout_constraintTop_toBottomOf="@+id/cameraLayout" />
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</layout>

+ 32 - 0
healthconsultation/src/main/res/layout/item_image.xml

@@ -0,0 +1,32 @@
+<?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="wrap_content"
+    tools:ignore="ResourceName">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_add"
+        android:layout_width="@dimen/divider_196px"
+        android:layout_height="@dimen/divider_196px"
+        android:layout_marginTop="@dimen/divider_15px"
+        android:layout_marginEnd="@dimen/divider_15px"
+        android:scaleType="center"
+        android:src="@mipmap/icon_add_pic" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/img"
+        android:layout_width="@dimen/divider_196px"
+        android:layout_height="@dimen/divider_196px"
+        android:layout_marginTop="@dimen/divider_15px"
+        android:layout_marginEnd="@dimen/divider_15px"
+        android:scaleType="center" />
+
+    <ImageView
+        android:id="@+id/img_delete"
+        android:layout_width="@dimen/divider_32px"
+        android:layout_height="@dimen/divider_32px"
+        android:layout_gravity="right|top"
+        android:src="@mipmap/icon_close"
+        tools:ignore="RtlHardcoded" />
+</FrameLayout>

BIN
healthconsultation/src/main/res/mipmap-xxhdpi/icon_album.png


BIN
healthconsultation/src/main/res/mipmap-xxhdpi/icon_camera.png


BIN
healthconsultation/src/main/res/mipmap-xxhdpi/icon_close.png


+ 2 - 0
healthconsultation/src/main/res/values/colors.xml

@@ -17,4 +17,6 @@
     <color name="color_FFFFFFFF" tools:ignore="ResourceName">#FFFFFFFF</color>
     <color name="color_FF000000" tools:ignore="ResourceName">#FF000000</color>
     <color name="color_FF666666" tools:ignore="ResourceName">#FF666666</color>
+    <color name="color_B3000000" tools:ignore="ResourceName">#B3000000</color>
+    <color name="transparent" tools:ignore="ResourceName">#00000000</color><!-- 透明   -->
 </resources>

+ 4 - 0
healthconsultation/src/main/res/values/dimens.xml

@@ -3,6 +3,7 @@
     <dimen name="divider_1194px" tools:ignore="ResourceName">1194px</dimen>
     <dimen name="divider_834px" tools:ignore="ResourceName">834px</dimen>
     <dimen name="divider_689px" tools:ignore="ResourceName">689px</dimen>
+    <dimen name="divider_684px" tools:ignore="ResourceName">684px</dimen>
     <dimen name="divider_616px" tools:ignore="ResourceName">616px</dimen>
     <dimen name="divider_561px" tools:ignore="ResourceName">561px</dimen>
     <dimen name="divider_533px" tools:ignore="ResourceName">533px</dimen>
@@ -38,6 +39,7 @@
     <dimen name="divider_320px" tools:ignore="ResourceName">320px</dimen>
     <dimen name="divider_313px" tools:ignore="ResourceName">313px</dimen>
     <dimen name="divider_307px" tools:ignore="ResourceName">307px</dimen>
+    <dimen name="divider_296px" tools:ignore="ResourceName">296px</dimen>
     <dimen name="divider_290px" tools:ignore="ResourceName">290px</dimen>
     <dimen name="divider_289px" tools:ignore="ResourceName">289px</dimen>
     <dimen name="divider_285px" tools:ignore="ResourceName">285px</dimen>
@@ -59,6 +61,7 @@
     <dimen name="divider_220px" tools:ignore="ResourceName">220px</dimen>
     <dimen name="divider_214px" tools:ignore="ResourceName">214px</dimen>
     <dimen name="divider_213px" tools:ignore="ResourceName">213px</dimen>
+    <dimen name="divider_212px" tools:ignore="ResourceName">212px</dimen>
     <dimen name="divider_207px" tools:ignore="ResourceName">207px</dimen>
     <dimen name="divider_203px" tools:ignore="ResourceName">203px</dimen>
     <dimen name="divider_201px" tools:ignore="ResourceName">201px</dimen>
@@ -71,6 +74,7 @@
     <dimen name="divider_180px" tools:ignore="ResourceName">180px</dimen>
     <dimen name="divider_176px" tools:ignore="ResourceName">176px</dimen>
     <dimen name="divider_173px" tools:ignore="ResourceName">173px</dimen>
+    <dimen name="divider_164px" tools:ignore="ResourceName">164px</dimen>
     <dimen name="divider_163px" tools:ignore="ResourceName">163px</dimen>
     <dimen name="divider_160px" tools:ignore="ResourceName">160px</dimen>
     <dimen name="divider_158px" tools:ignore="ResourceName">158px</dimen>

+ 2 - 0
healthconsultation/src/main/res/values/strings.xml

@@ -23,4 +23,6 @@
     <string name="upload_disease_description_related_medical_record_data" tools:ignore="ResourceName">上传疾病描述相关病历资料(最多上传9张)</string>
     <string name="photos_only_visible_doctors_themselves" tools:ignore="ResourceName">(照片仅医生及自己可见)</string>
     <string name="i_have_read_relevant_agreements_privacy_policies" tools:ignore="ResourceName">我已阅读相关协议及隐私政策</string>
+    <string name="album" tools:ignore="ResourceName">相册</string>
+    <string name="camera" tools:ignore="ResourceName">拍摄</string>
 </resources>