From a1f5a40ba5ee620b16b6908e9db23950f12f089e Mon Sep 17 00:00:00 2001 From: renhaoting <370797079@qq.com> Date: Wed, 5 Nov 2025 15:25:22 +0800 Subject: [PATCH] =?UTF-8?q?bg=E4=B8=8A=E4=BC=A0=20=E5=88=9D=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/response/ChatBackground.kt | 23 +- .../entity/response/ChatBackgroundBase.kt | 9 + .../entity/response/ChatBackgroundUpload.kt | 10 + .../visualnovel/extension/glide/GlideExt.kt | 10 + .../chat/setting/customui/ChatSettingView.kt | 33 +-- .../ExpandBackgroundSubView.kt | 118 ++++++-- .../utils/imagepick/EpalPickerPresenter.kt | 272 ++++++++++++++++++ .../utils/imagepick/ImagePickUtils.kt | 178 ++++++++++++ .../imageviewer/viewer/MyImageLoader.kt | 2 +- .../layout/layout_item_setting_background.xml | 11 - .../layout_item_setting_background_upload.xml | 33 +++ .../app/src/main/res/values/colors.xml | 2 + 12 files changed, 639 insertions(+), 62 deletions(-) create mode 100644 VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundBase.kt create mode 100644 VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundUpload.kt create mode 100644 VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/EpalPickerPresenter.kt create mode 100644 VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/ImagePickUtils.kt create mode 100644 VisualNovel/app/src/main/res/layout/layout_item_setting_background_upload.xml diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackground.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackground.kt index cfb7396..941ef14 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackground.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackground.kt @@ -1,20 +1,15 @@ package com.remax.visualnovel.entity.response +import android.net.Uri import com.remax.visualnovel.entity.model.base.BasePhoto -/** - * Created by HJW on 2025/8/18 - */ + data class ChatBackground( - var backgroundId: Int? = 0, - var imgUrl: String? = "", + var imageId: Long? = 0L, + var imageUrl: String? = "", + + var localUri: Uri? = null, var isDefault: Boolean = false, - var select: Boolean = false, - var isSelected: Boolean? = null, - var deletable: Boolean = false, - var isUploadLocalItem: Boolean = false -) : BasePhoto() { - override fun paramId(): Long { - return imgUrl.hashCode().toLong() - } -} + var isSelected: Boolean = false, + var isCustomBg: Boolean = false, +) : ChatBackgroundBase() diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundBase.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundBase.kt new file mode 100644 index 0000000..d35843f --- /dev/null +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundBase.kt @@ -0,0 +1,9 @@ +package com.remax.visualnovel.entity.response + +import android.net.Uri +import com.remax.visualnovel.entity.model.base.BasePhoto + + +abstract class ChatBackgroundBase( + +) diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundUpload.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundUpload.kt new file mode 100644 index 0000000..000a70e --- /dev/null +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/entity/response/ChatBackgroundUpload.kt @@ -0,0 +1,10 @@ +package com.remax.visualnovel.entity.response + +import android.net.Uri + + +data class ChatBackgroundUpload( + var imageId: Long? = 0L, + var imageUrl: String? = "", + var localUri: Uri? = null, +) : ChatBackgroundBase() diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/extension/glide/GlideExt.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/extension/glide/GlideExt.kt index 0c83201..9b63898 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/extension/glide/GlideExt.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/extension/glide/GlideExt.kt @@ -2,6 +2,7 @@ package com.remax.visualnovel.extension.glide import android.graphics.Bitmap import android.graphics.drawable.Drawable +import android.net.Uri import android.view.View import android.widget.ImageView import android.widget.TextView @@ -112,6 +113,15 @@ fun ImageView.load(url: String?) { .into(this) } +fun ImageView.load(uri: Uri) { + visibility = View.VISIBLE + Glide.with(context) + .load(uri) + .centerCrop() + .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) + .into(this) +} + fun TextView.loadNinePatch(nineImageUrl: String?) { Glide.with(context) .asBitmap() diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/ChatSettingView.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/ChatSettingView.kt index e80d830..4d564f9 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/ChatSettingView.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/ChatSettingView.kt @@ -11,6 +11,7 @@ import androidx.core.graphics.toColorInt import com.remax.visualnovel.R import com.remax.visualnovel.databinding.LayoutChatMenuViewBinding import com.remax.visualnovel.entity.response.ChatBackground +import com.remax.visualnovel.entity.response.ChatBackgroundUpload import com.remax.visualnovel.entity.response.ChatBubble import com.remax.visualnovel.entity.response.ChatHistory import com.remax.visualnovel.entity.response.ChatMode @@ -291,36 +292,30 @@ class ChatSettingView @JvmOverloads constructor( fun initBackgroundSelectView() { val items = listOf( ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", + imageId = 1, + imageUrl = "https://vsn.s3.cn-north-1.amazonaws.com.cn/coverImage/fe8e3c7b-5b22-40f4-bacc-0183888c5149_test.png" ), ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", + imageId = 1, + imageUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png" ), ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", + imageId = 1, + imageUrl = "https://vsn.s3.cn-north-1.amazonaws.com.cn/coverImage/fe8e3c7b-5b22-40f4-bacc-0183888c5149_test.png" ), ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", + imageId = 1, + imageUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png" ), ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", + imageId = 1, + imageUrl = "https://vsn.s3.cn-north-1.amazonaws.com.cn/coverImage/fe8e3c7b-5b22-40f4-bacc-0183888c5149_test.png" ), ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", + imageId = 1, + imageUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png" ), - ChatBackground( - backgroundId = 1, - imgUrl = "https://cdhrss.chengdu.gov.cn/cdrsj/xhtml/images/2022_logo.png", - deletable = true - ), - ChatBackground( - isUploadLocalItem = true + ChatBackgroundUpload( ) ) diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/expandableSelector/ExpandBackgroundSubView.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/expandableSelector/ExpandBackgroundSubView.kt index 2ca8941..46bc90c 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/expandableSelector/ExpandBackgroundSubView.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/ui/chat/setting/customui/expandableSelector/ExpandBackgroundSubView.kt @@ -8,6 +8,7 @@ import android.widget.LinearLayout import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import com.drake.brv.annotaion.DividerOrientation +import com.drake.brv.utils.addModels import com.drake.brv.utils.bindingAdapter import com.drake.brv.utils.divider import com.drake.brv.utils.grid @@ -17,13 +18,28 @@ import com.remax.visualnovel.R import com.remax.visualnovel.databinding.LayoutItemSettingBackgroundBinding import com.remax.visualnovel.databinding.LayoutSettingBgSubViewBinding import com.remax.visualnovel.entity.response.ChatBackground +import com.remax.visualnovel.entity.response.ChatBackgroundBase +import com.remax.visualnovel.entity.response.ChatBackgroundUpload +import com.remax.visualnovel.extension.glide.load +import com.remax.visualnovel.extension.toast +import com.remax.visualnovel.utils.imagepick.EpalPickerPresenter +import com.remax.visualnovel.widget.imagepicker.ImagePicker +import com.remax.visualnovel.widget.imagepicker.bean.ImageItem +import com.remax.visualnovel.widget.imagepicker.bean.MimeType +import com.remax.visualnovel.widget.imagepicker.bean.PickerError +import com.remax.visualnovel.widget.imagepicker.bean.SelectMode +import com.remax.visualnovel.widget.imagepicker.data.OnImagePickCompleteListener2 +import com.remax.visualnovel.widget.imageviewer.utils.activity + + class ExpandBackgroundSubView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : android.widget.LinearLayout(context, attrs, defStyleAttr) { - private lateinit var items: List +) : LinearLayout(context, attrs, defStyleAttr) { + + private lateinit var items: List private var mBinding: LayoutSettingBgSubViewBinding @@ -42,36 +58,104 @@ class ExpandBackgroundSubView @JvmOverloads constructor( orientation = DividerOrientation.VERTICAL }.setup { addType(R.layout.layout_item_setting_background) + addType(R.layout.layout_item_setting_background_upload) onClick(R.id.root) { - val chatBackground = getModel() - if (!chatBackground.select) { - itemsRv.bindingAdapter.models?.filterIsInstance()?.forEach { item -> - item.select = item == chatBackground + when (val item = getModel(it)) { + is ChatBackground -> { + val chatBackground = getModel() + if (!chatBackground.isSelected) { + itemsRv.bindingAdapter.models?.filterIsInstance()?.forEach { item -> + item.isSelected = item == chatBackground + } + itemsRv.bindingAdapter.notifyDataSetChanged() + } + } + is ChatBackgroundUpload -> { + selectCustomBg() } - itemsRv.bindingAdapter.notifyDataSetChanged() } + + /*when (itemViewType) { + R.layout.layout_item_setting_background -> { + + } + + R.layout.layout_item_setting_background_upload -> { + selectCustomBg() + } + }*/ } - onBind { - val item = getModel() - with(getBinding()) { - if (!item.imgUrl.isNullOrEmpty()) { - //ivBackgroundSrc.load(item.imgUrl) - } - ivDel.visibility = if (item.deletable) VISIBLE else GONE - ivUpload.isVisible = item.isUploadLocalItem - ivBackgroundSrc.isVisible = !item.isUploadLocalItem + onBind { + when (itemViewType) { + R.layout.layout_item_setting_background -> { + val item = getModel() + with(getBinding()) { + if (!item.imageUrl.isNullOrEmpty()) { + ivBackgroundSrc.load(item.imageUrl) + } else if (item.localUri != null) { + ivBackgroundSrc.load(item.localUri!!) + } + + ivDel.visibility = if (item.isCustomBg) VISIBLE else GONE + ivBackgroundSrc.isVisible = item.isSelected + } + } + + R.layout.layout_item_setting_background_upload -> { + val item = getModel() + } } } } } - fun setItems(newItems: List) { + fun setItems(newItems: List) { items = newItems mBinding.itemsRv.models = items } + private fun selectCustomBg(showCamera: Boolean = true) { + ImagePicker.withMulti(EpalPickerPresenter()) + .setMaxCount(1) + .setSelectMode(SelectMode.MODE_SINGLE) + .setColumnCount(3) + .mimeTypes(MimeType.ofImage()) + .filterMimeTypes(MimeType.GIF) + .showCamera(showCamera) + .setPreview(true) + .setSinglePickImageOrVideoType(true) + .pick(activity, object : OnImagePickCompleteListener2 { + override fun onPickFailed(error: PickerError?) { + activity?.toast(error?.message) + } + + override fun onImagePickComplete(items: ArrayList?) { + appendCustomBg(items) + uploadImageAndRequest(items) + } + + + }) + } + + private fun appendCustomBg(items: ArrayList?) { + val customBgList = items?.map { imageItem -> + ChatBackground( + imageId = imageItem.id, + imageUrl = imageItem.path, + localUri = imageItem.uri + ) + } + mBinding.itemsRv.addModels(customBgList) + } + + private fun uploadImageAndRequest(items: ArrayList?) { + // TODO + } + + } \ No newline at end of file diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/EpalPickerPresenter.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/EpalPickerPresenter.kt new file mode 100644 index 0000000..e99c85c --- /dev/null +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/EpalPickerPresenter.kt @@ -0,0 +1,272 @@ +package com.remax.visualnovel.utils.imagepick + +import android.app.Activity +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.view.View +import android.widget.ImageView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.DecodeFormat +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.gif.GifDrawable +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.Target +import com.remax.visualnovel.R +import com.remax.visualnovel.app.widget.LoadingDialog +import com.remax.visualnovel.extension.findActivityContext +import com.remax.visualnovel.extension.toast +import com.remax.visualnovel.widget.imagepicker.adapter.PickerItemAdapter +import com.remax.visualnovel.widget.imagepicker.bean.ImageItem +import com.remax.visualnovel.widget.imagepicker.bean.selectconfig.BaseSelectConfig +import com.remax.visualnovel.widget.imagepicker.data.ICameraExecutor +import com.remax.visualnovel.widget.imagepicker.data.IReloadExecutor +import com.remax.visualnovel.widget.imagepicker.data.ProgressSceneEnum +import com.remax.visualnovel.widget.imagepicker.presenter.IPickerPresenter +import com.remax.visualnovel.widget.imagepicker.views.PickerUiConfig +import com.remax.visualnovel.widget.imagepicker.views.PickerUiProvider +import com.remax.visualnovel.widget.imagepicker.views.base.PickerControllerView +import com.remax.visualnovel.widget.imagepicker.views.base.PickerFolderItemView +import com.remax.visualnovel.widget.imagepicker.views.base.SingleCropControllerView +import com.remax.visualnovel.widget.imagepicker.views.wrapper.BottomBar +import com.remax.visualnovel.widget.imagepicker.views.wrapper.FolderItemView +import com.remax.visualnovel.widget.imagepicker.views.wrapper.TitleBar +import com.remax.visualnovel.widget.uitoken.handleUIToken +import java.util.* + + +/** + * Created by HJW on 2020/10/13 + */ +class EpalPickerPresenter(private val isAlbum: Boolean = false) : IPickerPresenter { + /** + * 提示 + * + * @param context 上下文 + * @param msg 提示文本 + */ + override fun tip(context: Context?, msg: String?) { + context?.let { + if (!msg.isNullOrBlank()) { + it.toast(msg) + } + } + } + + /** + * 选择超过数量限制提示 + * + * @param context 上下文 + * @param maxCount 最大数量 + */ + override fun overMaxCountTip(context: Context?, maxCount: Int) { + tip(context, String.format(context?.getString(R.string.upload_up_to_images) ?: "", maxCount)) + } + + /** + * 显示loading加载框,注意需要调用show方法 + * + * @param activity 启动加载框的activity + * @param progressSceneEnum {@link ProgressSceneEnum} + * + *

+ * 当progressSceneEnum==当ProgressSceneEnum.loadMediaItem 时,代表在加载媒体文件时显示加载框 + * 目前框架内规定,当文件夹内媒体文件少于1000时,强制不显示加载框,大于1000时才会执行此方法 + *

+ *

+ * 当progressSceneEnum==当ProgressSceneEnum.crop 时,代表是剪裁页面的加载框 + *

+ * @return DialogInterface 对象,用于关闭加载框,返回null代表不显示加载框 + */ + override fun showProgressDialog(activity: Activity?, progressSceneEnum: ProgressSceneEnum?): DialogInterface { + return LoadingDialog().build(activity!!).getDialog().thisShow() + } + + /** + * 拦截选择器取消操作,用于弹出二次确认框 + * + * @param activity 当前选择器页面 + * @param selectedList 当前已经选择的文件列表 + * @return true:则拦截选择器取消, false,不处理选择器取消操作 + */ + override fun interceptPickerCancel(activity: Activity?, selectedList: ArrayList?): Boolean { + return false + } + + /** + *

+ * 图片点击事件拦截,如果返回true,则不会执行选中操纵,如果要拦截此事件并且要执行选中 + * 请调用如下代码: + *

+ * adapter.preformCheckItem() + *

+ *

+ * 此方法可以用来跳转到任意一个页面,比如自定义的预览 + * + * @param activity 上下文 + * @param imageItem 当前图片 + * @param selectImageList 当前选中列表 + * @param allSetImageList 当前文件夹所有图片 + * @param selectConfig 选择器配置项,如果是微信样式,则selectConfig继承自MultiSelectConfig + * 如果是小红书剪裁样式,则继承自CropSelectConfig + * @param adapter 当前列表适配器,用于刷新数据 + * @param isClickCheckBox 是否点击item右上角的选中框 + * @param reloadExecutor 刷新器 + * @return 是否拦截 + */ + override fun interceptItemClick( + activity: Activity?, + imageItem: ImageItem?, + selectImageList: ArrayList?, + allSetImageList: ArrayList?, + selectConfig: BaseSelectConfig?, + adapter: PickerItemAdapter?, + isClickCheckBox: Boolean, + reloadExecutor: IReloadExecutor? + ): Boolean { + return false + } + + /** + * 拍照点击事件拦截 + * + * @param activity 当前activity + * @param takePhoto 拍照接口 + * @return 是否拦截 + */ + override fun interceptCameraClick(activity: Activity?, takePhoto: ICameraExecutor?): Boolean { + return false + } + + /** + * 图片加载,在安卓10上,外部存储的图片路径只能用Uri加载,私有目录的图片可以用绝对路径加载 + * 所以这个方法务必需要区分有uri和无uri的情况 + * 一般媒体库直接扫描出来的图片是含有uri的,而剪裁生成的图片保存在私有目录中,因此没有uri,只有绝对路径 + * 所以这里需要做一个兼容处理 + * + * @param view imageView + * @param item 图片信息 + * @param size 加载尺寸 + * @param isThumbnail 是否是缩略图 + */ + override fun displayImage(view: View?, imageItem: ImageItem?, size: Int, isThumbnail: Boolean) { + imageItem?.let { item -> + view?.let { v -> + (v.context.findActivityContext() as? Activity)?.also { act -> + if (!act.isDestroyed) { + val loadPath = if (item.uri != null) item.uri.toString() else item.path + Glide.with(act).load(loadPath) + .apply(RequestOptions().format(if (isThumbnail) DecodeFormat.PREFER_RGB_565 else DecodeFormat.PREFER_ARGB_8888)) +// .override(if (isThumbnail) size else Target.SIZE_ORIGINAL) + .listener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target, isFirstResource: Boolean): Boolean { + return false + } + + override fun onResourceReady( + resource: Drawable, + model: Any, + target: Target?, + dataSource: DataSource, + isFirstResource: Boolean + ): Boolean { + return if (resource is GifDrawable) { + if (item.isGif || loadPath.toString().substring(loadPath.toString().lastIndexOf(".") + 1) == "gif") { + false + } else { + if (!loadPath.startsWith("http")) { + (v as ImageView).setImageBitmap(resource.firstFrame) + true + } else { + false + } + } + } else { + false + } + } + + }) + .into(view as ImageView) + } + } + } + } + } + + + /** + * 拦截选择器完成按钮点击事件 + * + * @param activity 当前选择器activity + * @param selectedList 已选中的列表 + * @return true:则拦截选择器完成回调, false,执行默认的选择器回调 + */ + override fun interceptPickerCompleteClick(activity: Activity?, selectedList: ArrayList?, selectConfig: BaseSelectConfig?): Boolean { + return false + } + + /** + * 设置自定义ui显示样式,不可返回null + * 该方法返回一个PickerUiConfig对象 + * + *

+ * 该对象可以配置如下信息: + * 1.主题色 + * 2.相关页面背景色 + * 3.选择器标题栏,底部栏,item,文件夹列表item,预览页面,剪裁页面的定制 + *

+ *

+ * 详细使用方法参考 (@link https://github.com/yangpeixing/YImagePicker/blob/master/YPX_ImagePicker_androidx/app/src/main/java/com/ypx/imagepickerdemo/style/WeChatPresenter.java) + * + * @param context 上下文 + * @return PickerUiConfig + */ + override fun getUiConfig(context: Context?): PickerUiConfig { + val uiConfig = PickerUiConfig() + with(uiConfig) { + //设置主题色 + themeColor = context?.handleUIToken(R.string.color_primary_normal)?.color ?: 0 + //设置是否显示状态栏 + isShowStatusBar = true + //设置状态栏颜色 + statusBarColor = context?.handleUIToken(R.string.color_background_default)?.color ?: 0 + //设置选择器背景 + pickerBackgroundColor = context?.handleUIToken(R.string.color_background_default)?.color ?: 0 + //设置单图剪裁背景色 + singleCropBackgroundColor = context?.handleUIToken(R.string.color_background_default)?.color ?: 0 + //设置预览页面背景色 + previewBackgroundColor = context?.handleUIToken(R.string.color_background_default)?.color ?: 0 + //设置选择器文件夹打开方向 + folderListOpenDirection = PickerUiConfig.DIRECTION_TOP + //设置文件夹列表距离顶部/底部边距 + folderListOpenMaxMargin = 120 + //设置小红书剪裁区域的背景色 + cropViewBackgroundColor = context?.handleUIToken(R.string.color_background_default)?.color ?: 0 + pickerUiProvider = object : PickerUiProvider() { + override fun getTitleBar(context: Context?): PickerControllerView { + return TitleBar(context) + } + + override fun getFolderItemView(context: Context?): PickerFolderItemView { + return FolderItemView(context) + } + + override fun getSingleCropControllerView(context: Context?): SingleCropControllerView { + return com.remax.visualnovel.widget.imagepicker.views.wrapper.SingleCropControllerView(context) + } + + override fun getBottomBar(context: Context?): PickerControllerView { + return BottomBar(context, isAlbum) + } + + override fun getPreviewControllerView(context: Context): com.remax.visualnovel.widget.imagepicker.views.wrapper.PreviewControllerView { + return super.getPreviewControllerView(context) + } + } + } + return uiConfig + } +} \ No newline at end of file diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/ImagePickUtils.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/ImagePickUtils.kt new file mode 100644 index 0000000..853e67d --- /dev/null +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/utils/imagepick/ImagePickUtils.kt @@ -0,0 +1,178 @@ +package com.remax.visualnovel.utils.imagepick + +import android.app.Activity +import com.remax.visualnovel.extension.toast +import com.remax.visualnovel.manager.login.LoginManager +import com.remax.visualnovel.utils.spannablex.utils.dp +import com.remax.visualnovel.widget.imagepicker.ImagePicker +import com.remax.visualnovel.widget.imagepicker.bean.ImageItem +import com.remax.visualnovel.widget.imagepicker.bean.MimeType +import com.remax.visualnovel.widget.imagepicker.bean.PickerError +import com.remax.visualnovel.widget.imagepicker.bean.SelectMode +import com.remax.visualnovel.widget.imagepicker.bean.selectconfig.CropConfig +import com.remax.visualnovel.widget.imagepicker.data.OnImagePickCompleteListener +import com.remax.visualnovel.widget.imagepicker.data.OnImagePickCompleteListener2 + + +/** + * Created by HJW on 2020/10/13 + */ +class ImagePickUtils { + + companion object { + + /** + * 选择单张图片(无剪裁) + */ + fun pickOneWithoutCrop(activity: Activity, showCamera: Boolean = true, imagePickCompleteListener: OnImagePickCompleteListener) { + ImagePicker.withMulti(EpalPickerPresenter()) + .setMaxCount(1) + //设置单选模式,当maxCount==1时,可执行单选(下次选中会取消上一次选中) + .setSelectMode(SelectMode.MODE_SINGLE) + .setColumnCount(3) + .mimeTypes(MimeType.ofImage()) + //设置需要过滤掉加载的文件类型 + .filterMimeTypes(MimeType.GIF) + .showCamera(showCamera) + .setPreview(true) + //设置图片和视频单一类型选择 + .setSinglePickImageOrVideoType(true) + .pick(activity, object : OnImagePickCompleteListener2 { + override fun onPickFailed(error: PickerError?) { + activity.toast(error?.message) + } + + override fun onImagePickComplete(items: ArrayList?) { + imagePickCompleteListener.onImagePickComplete(items) + } + }) + } + + /** + * 用户选择头像 + * VIP才可以选择gif图 + */ + fun pickHeadWithCrop(activity: Activity, margin: Int? = null, cropTaskFrame: Int? = null, onImagePickCompleteListener: OnImagePickCompleteListener) { + val mimeTypes = mutableSetOf(MimeType.JPEG, MimeType.PNG, MimeType.BMP, MimeType.WEBP) + ImagePicker.withMulti(EpalPickerPresenter()) + .setMaxCount(1) + //设置单选模式,当maxCount==1时,可执行单选(下次选中会取消上一次选中) + .setSelectMode(SelectMode.MODE_SINGLE) + .setColumnCount(3) + .mimeTypes(mimeTypes) + .showCamera(true) + .setPreview(true) + //设置图片和视频单一类型选择 + .setSinglePickImageOrVideoType(true) + .cropAsCircle() + .cropRectMinMargin(margin ?: 48.dp) + .setCropTaskFrame(cropTaskFrame ?: 0) + //设置剪裁模式,留白或充满 CropConfig.STYLE_GAP 或 CropConfig.STYLE_FILL + .cropStyle(CropConfig.STYLE_FILL) + //x y 比例 + .setCropRatio(1, 1) + //剪裁完成的图片是否保存在DCIM目录下 + //true:存储在DCIM下 false:存储在 data/包名/files/imagePicker/ 目录下 + .cropSaveInDCIM(false) + .crop(activity, object : OnImagePickCompleteListener2 { + override fun onPickFailed(error: PickerError?) { + activity.toast(error?.message) + } + + override fun onImagePickComplete(items: ArrayList?) { + onImagePickCompleteListener.onImagePickComplete(items) + } + + }) + } + + /** + * 选择单张图片(有剪裁,无gif,默认1 :1) + */ + fun pickOneWithCrop( + activity: Activity, + x: Int = 1, + y: Int = 1, + onImagePickCompleteListener: OnImagePickCompleteListener, + showCamera: Boolean = true + ) { + ImagePicker.withMulti(EpalPickerPresenter()) + .setMaxCount(1) + //设置单选模式,当maxCount==1时,可执行单选(下次选中会取消上一次选中) + .setSelectMode(SelectMode.MODE_SINGLE) + .setColumnCount(3) + .mimeTypes(MimeType.ofImage()) + //设置需要过滤掉加载的文件类型 + .filterMimeTypes(MimeType.GIF) + .showCamera(showCamera) + .setPreview(true) + //设置图片和视频单一类型选择z + .setSinglePickImageOrVideoType(true) + .cropRectMinMargin(48.dp) + //设置剪裁模式,留白或充满 CropConfig.STYLE_GAP 或 CropConfig.STYLE_FILL + .cropStyle(CropConfig.STYLE_FILL) + //x y 比例 + .setCropRatio(x, y) + //剪裁完成的图片是否保存在DCIM目录下 + //true:存储在DCIM下 false:存储在 data/包名/files/imagePicker/ 目录下 + .cropSaveInDCIM(false) + .crop(activity, object : OnImagePickCompleteListener2 { + override fun onPickFailed(error: PickerError?) { + activity.toast(error?.message) + } + + override fun onImagePickComplete(items: ArrayList?) { + onImagePickCompleteListener.onImagePickComplete(items) + } + }) + } + + /** + * 直接剪裁头像 + * UI圆形显示,输出是1:1 + */ + fun cropCircleImage(activity: Activity, imageUrl: String, onImagePickCompleteListener: OnImagePickCompleteListener) { + ImagePicker.crop(activity, EpalPickerPresenter(), CropConfig().apply { + this.cropStyle = CropConfig.STYLE_FILL + isCircle = true + saveInDCIM(false) + cropRectMargin = 48.dp + }, imageUrl, onImagePickCompleteListener) + } + + /** + * 选择多张图片(无剪裁) + */ + fun pickMaxCount( + activity: Activity, + maxCount: Int, + onImagePickCompleteListener: OnImagePickCompleteListener, + showCamera: Boolean = false, + filterGif: Boolean = true, + isAlbum: Boolean = false + ) { + val presenter = EpalPickerPresenter(isAlbum) + ImagePicker.withMulti(presenter) + .setMaxCount(maxCount) + .setColumnCount(3) + .mimeTypes(MimeType.ofImage()) + //设置需要过滤掉加载的文件类型 + .filterMimeTypes(if (filterGif) MimeType.GIF else null) + .setPreview(true) + .showCamera(showCamera) + //设置图片和视频单一类型选择 + .setSinglePickImageOrVideoType(true) + .pick(activity, object : OnImagePickCompleteListener2 { + override fun onPickFailed(error: PickerError?) { + activity.toast(error?.message) + } + + override fun onImagePickComplete(items: ArrayList?) { + onImagePickCompleteListener.onImagePickComplete(items) + } + }) + + } + + } +} \ No newline at end of file diff --git a/VisualNovel/app/src/main/java/com/remax/visualnovel/widget/imageviewer/viewer/MyImageLoader.kt b/VisualNovel/app/src/main/java/com/remax/visualnovel/widget/imageviewer/viewer/MyImageLoader.kt index cd00844..8b697c7 100644 --- a/VisualNovel/app/src/main/java/com/remax/visualnovel/widget/imageviewer/viewer/MyImageLoader.kt +++ b/VisualNovel/app/src/main/java/com/remax/visualnovel/widget/imageviewer/viewer/MyImageLoader.kt @@ -51,7 +51,7 @@ class MyImageLoader : ImageLoader { } is ChatBackground -> { - data.imgUrl + data.imageUrl } is CustomAlbumData -> { diff --git a/VisualNovel/app/src/main/res/layout/layout_item_setting_background.xml b/VisualNovel/app/src/main/res/layout/layout_item_setting_background.xml index e6c5d4f..a50fd2e 100644 --- a/VisualNovel/app/src/main/res/layout/layout_item_setting_background.xml +++ b/VisualNovel/app/src/main/res/layout/layout_item_setting_background.xml @@ -46,17 +46,6 @@ /> - - - + + + + + + + \ No newline at end of file diff --git a/VisualNovel/app/src/main/res/values/colors.xml b/VisualNovel/app/src/main/res/values/colors.xml index 84381fa..534a796 100644 --- a/VisualNovel/app/src/main/res/values/colors.xml +++ b/VisualNovel/app/src/main/res/values/colors.xml @@ -193,6 +193,8 @@ #ff999999 #fff6f6f6 #ff282828 + #fff3f4ff + #ffff3b30