效果图如下:

图片


代码如下


import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.graphics.*
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.view.*
import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.alibaba.fastjson.JSON
import com.google.gson.Gson
import com.lzy.okgo.model.Response
import kotlinx.android.synthetic.main.hybrid_activity_image_gallery.*
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStream
import kotlin.math.abs/*** 支持画廊式查看大图的弹窗*/
class ImageGalleryDialog1 : DialogFragment() {companion object {const val END_ITEM_VIEW_TYPE = 0const val ITEM_VIEW_TYPE = 1/*** @param dataSourceJson H5传递过来的json*/fun newInstance(dataSourceJson: String): ImageGalleryDialog {val args = Bundle()args.putString("imageData", dataSourceJson)val fragment = ImageGalleryDialog()fragment.arguments = argsreturn fragment}}/*** 源数据*/private var dataSource: GalleryImageActivityBean? = nullprivate var adapter: ImageGalleryAdapter? = nullprivate var pageSize: Int = 0private var pageIndex: Int = 0private val selfTag = "ImageGalleryDialog"/*** 如果是重拍,这个值会不等于-1*/private var reviewPhotoPosition = -1var resultJson = ""var onImageDialogDismissListener: OnImageDialogDismissListener? = nulloverride fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {return inflater.inflate(R.layout.hybrid_activity_image_gallery, container, false)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)initData()}override fun onActivityCreated(savedInstanceState: Bundle?) {dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)super.onActivityCreated(savedInstanceState)dialog?.window?.setBackgroundDrawable(ColorDrawable(0x00000000))dialog?.window?.setLayout(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.MATCH_PARENT)}private fun initData() {val imageDataJson = arguments?.getString("imageData", "")kotlin.runCatching {dataSource = Gson().fromJson(imageDataJson, GalleryImageActivityBean::class.java)pageSize = dataSource?.imageList?.size?: 0pageIndex =if (dataSource?.currentPosition?: 0 >= pageSize) 0 else dataSource?.currentPosition?: 0}.onSuccess {initWidget()}.onFailure {ToastUtil.showToast("数据错误!")dismissAllowingStateLoss()}}/*** 初始化控件*/@SuppressLint("SetTextI18n")private fun initWidget() {adapter = ImageGalleryAdapter(context, dataSource?.imageList, dataSource?.isReview)imagePager.offscreenPageLimit = 2imagePager.setPageTransformer(ImageGalleryZoomOutPageTransformer())imagePager.adapter = adaptertvIndex.text = "${pageIndex}/${adapter?.itemCount}"imagePager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {override fun onPageSelected(position: Int) {super.onPageSelected(position)pageIndex = positiontvIndex.text = "${pageIndex + 1}/${adapter?.itemCount}"if (adapter?.getItemViewType(position) != ITEM_VIEW_TYPE || dataSource?.isReview == false) {ivReset.visibility = View.GONEivDeleted.visibility = View.GONE}else {ivReset.visibility = View.VISIBLEivDeleted.visibility = View.VISIBLE}if ((imagePager?.getChildAt(0) is RecyclerView)) {if ((imagePager?.getChildAt(0) as RecyclerView).findViewHolderForAdapterPosition(adapter?.selectedPosition?:0) is ImageGalleryViewHolder) {val oldHolder = (imagePager?.getChildAt(0) as RecyclerView).findViewHolderForAdapterPosition(adapter?.selectedPosition?:0) as ImageGalleryViewHolderoldHolder.itemRootView?.isSelected = false}if ((imagePager?.getChildAt(0) as RecyclerView).findViewHolderForAdapterPosition(position) is ImageGalleryViewHolder) {val newSelectedHolder = (imagePager?.getChildAt(0) as RecyclerView).findViewHolderForAdapterPosition(position) as ImageGalleryViewHoldernewSelectedHolder.itemRootView?.isSelected = true}}adapter?.selectedPosition = position}})adapter?.onImageGalleryAddPhotoClickListener = object : OnImageGalleryAddPhotoClickListener {override fun onAddPhotoItemClick() {if (dataSource?.imageList?.size ?: 0 < 9) {takePhoto()}}}ivReset.click {// 重拍reviewPhotoPosition = imagePager.currentItemtakePhoto()}ivDeleted.click {// 删除照片if (adapter?.getItemViewType(imagePager.currentItem) == ITEM_VIEW_TYPE) {val currentPosition = imagePager.currentItemdataSource?.imageList?.removeAt(currentPosition)adapter?.notifyItemRemoved(currentPosition)imagePager?.post {imagePager?.requestTransform()}}}imageGalleryRootView.click {// 点击空白区域关闭dismiss()}}override fun onDismiss(dialog: DialogInterface) {super.onDismiss(dialog)if (dataSource?.isReview == true) {resultJson = Gson().toJson(dataSource)}onImageDialogDismissListener?.onDismiss(resultJson)dismiss()}/*** 去拍照*/private fun takePhoto() {context?.let { context ->val isHuar = TextUtils.equals("KNC", Build.MANUFACTURER) || TextUtils.equals("X1", Build.MODEL)var camera_type = SharedPreferenceUtil.getIntValueFromSP("hbdPicture" , CAMERA_TYPE , -1)camera_type = if(isHuar) { // 华瑞安机器if(camera_type == -1) AXXCameraActivity.CAMERA_TYPE_FRONT else camera_type} else {if(camera_type == -1) AXXCameraActivity.CAMERA_TYPE_BACK else camera_type}val cameraWrapper = AXXAlbumCamera(context).image().cameraType(camera_type)cameraWrapper.onResult {showLoadingDialog()getToken(filePath = it)}.onCancel {}.start()}}private fun showLoadingDialog() {if (context is BaseActivity) {(context as BaseActivity).showLoadingProgressDialog()}}private fun hideLoadingDialog() {if (context is BaseActivity) {(context as BaseActivity).dismissLoadingProgressDialog()}}/*** 图片上传成功了*/private fun onUploadSuccess(itemBean: GalleryImageItemBean) {if (reviewPhotoPosition != -1) {// 重拍的dataSource?.imageList?.set(reviewPhotoPosition, itemBean)adapter?.notifyItemChanged(reviewPhotoPosition)reviewPhotoPosition = -1}else {// 新增的dataSource?.imageList?.add(itemBean)if (dataSource?.imageList?.size?:0 >= 9) {adapter?.notifyItemRangeChanged(0, 9)imagePager?.post {imagePager?.requestTransform()}}else {adapter?.notifyItemInserted((dataSource?.imageList?.size?:0) - 1)}}}/**↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓下面这一坨是拍照上传的逻辑↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/// 摄像头类型(2 前 or  1 后)private val CAMERA_TYPE = "camera_type"/*** 获取Token*/private fun getToken(filePath: String) {GGGGRequest.startRequest(SDKConfig.getBaseUrl() + "api/common/storageToken",GGGGRequest.GET,HashMap<String, String>(),object : GGGGGStringCallback() {override fun onResponseSuccess1(response: Response<*>?, code: Int, result: String) {ReportLog.method(selfTag,"takeJzxPhoto","获取Token onResponseSuccess: $code result: $result")val resultJson = JSON.parseObject(result)val body = resultJson.getJSONObject("body")val token = body.getString("token")upload(token, filePath)}override fun onResponseError1(response: Response<*>?, code: Int, message: String?) {ReportLog.method(selfTag,"takeJzxPhoto","获取Token onResponseError: $code result: $result")hideLoadingDialog()}})}/*** 上传图片*  if (isHuar) convertBitmap(BitmapUtil.getBitmapFormPath(filePath)) else*/private fun upload(token: String, filePath: String) {val isHuar =TextUtils.equals("KNC", Build.MANUFACTURER) || TextUtils.equals("X1", Build.MODEL)val originalBitmap = getBitmapFormPath(filePath , isHuar)if (originalBitmap?.bitmap == null) {ReportLog.method(selfTag , "takeJzxPhoto" ,  "originalBitmap == null")hideLoadingDialog()return}// 写入存储,用于记录是前摄还是后摄SharedPreferenceUtil.setIntDataIntoSP("", CAMERA_TYPE , originalBitmap?.source)val convertBitmap = if (originalBitmap?.source == AXXCameraActivity.CAMERA_TYPE_FRONT) {convertBitmap(originalBitmap?.bitmap!!)} else {originalBitmap.bitmap}val bitmapToBase64 = BitmapUtil.bitmapToBase64(convertBitmap)Upload.upload(0,token,true,bitmapToBase64,"${System.currentTimeMillis()}.jpg",false,object : Upload.UploadListener {override fun uploadSuccess(vararg p0: String?) {deletePath(filePath)val key = p0[0]val url = p0[1] ?: ""ReportLog.method(selfTag, "takeJzxPhoto", "图片上传 uploadSuccess: $key : $url")onUploadSuccess(GalleryImageItemBean(url, key))hideLoadingDialog()}override fun uploadError() {ReportLog.method(selfTag, "takeJzxPhoto", "图片上传失败")hideLoadingDialog()}})}/*** 镜像转换*/private fun convertBitmap(srcBitmap: Bitmap): Bitmap? {val width = srcBitmap.widthval height = srcBitmap.heightval canvas = Canvas()val matrix = Matrix()matrix.postScale(-1f, 1f)val newBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, width, height, matrix, true)canvas.drawBitmap(newBitmap,Rect(0, 0, width, height),Rect(0, 0, width, height), null)return newBitmap}/*** 删除文件*/private fun deletePath(filePathName: String): Boolean {if (TextUtils.isEmpty(filePathName)) return falseval file = File(filePathName)if (file.exists() && file.isFile) {if (file.delete()) {return true}}return false}/*** 通过图片判断前摄还是后摄*/data class BitmapEntity(var bitmap: Bitmap? = null,var source: Int = 0)/*** 从文件路径中读取Bitmap*/@Throws(IOException::class)fun getBitmapFormPath(path: String? , isHuar: Boolean) {val bitmapEntity = BitmapEntity()var input: InputStream = FileInputStream(File(path))val onlyBoundsOptions = BitmapFactory.Options()onlyBoundsOptions.inJustDecodeBounds = trueonlyBoundsOptions.inDither = trueonlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888BitmapFactory.decodeStream(input, null as Rect?, onlyBoundsOptions)input.close()val originalWidth = onlyBoundsOptions.outWidthval originalHeight = onlyBoundsOptions.outHeightif(isHuar) {// 通过分辨率判断是不是后摄if(originalWidth == 4096|| originalHeight == 4096) {bitmapEntity.source = AXXCameraActivity.CAMERA_TYPE_BACK} else {bitmapEntity.source = AXXCameraActivity.CAMERA_TYPE_FRONT}} else {bitmapEntity.source = -1 // 无记录}return if (originalWidth != -1 && originalHeight != -1) {var hh = 720.0fvar ww = 1080.0fif(originalWidth < originalHeight) {hh = 1080.0fww = 720.0f}var be = 1if (originalWidth > originalHeight && originalWidth.toFloat() > ww) {be = (originalWidth.toFloat() / ww).toInt()} else if (originalWidth < originalHeight && originalHeight.toFloat() > hh) {be = (originalHeight.toFloat() / hh).toInt()}if (be <= 0) {be = 1}val bitmapOptions = BitmapFactory.Options()bitmapOptions.inSampleSize = bebitmapOptions.inDither = truebitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888input = FileInputStream(File(path))val bitmap = BitmapFactory.decodeStream(input, null as Rect?, bitmapOptions)input.close()bitmapEntity.bitmap = bitmapbitmapEntity} else {bitmapEntity}}/**↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑上面这一坨是拍照上传的逻辑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/}/*** 图片列表的适配器*/
class ImageGalleryAdapter1(var context: Context?,var list: ArrayList<GalleryImageItemBean>?,var isReview: Boolean? = true,var onImageGalleryAddPhotoClickListener: OnImageGalleryAddPhotoClickListener? = null
) : RecyclerView.Adapter<ImageGalleryViewHolder>() {var selectedPosition = 0override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageGalleryViewHolder {if (!isEndItemView(viewType)) {return ImageGalleryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.hybrid_item_image_gallery, parent, false))}return ImageGalleryViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.hybrid_item_image_gallery_photograph, parent, false))}override fun onBindViewHolder(holder: ImageGalleryViewHolder, position: Int) {if (!isEndItemView(getItemViewType(position))) {list?.get(position)?.imgUrl?.apply {holder.ivPhoto?.loadImageByUrl(this)}} else {holder.itemRootView?.click {onImageGalleryAddPhotoClickListener?.onAddPhotoItemClick()}}}override fun getItemCount(): Int {if (list?.size ?: 0 >= 9) {return 9}return if(isReview == true) (list?.size ?: 0) + 1 else (list?.size ?: 0)}override fun getItemViewType(position: Int): Int {if (position < list?.size ?: 0 - 1) {return ITEM_VIEW_TYPE}return END_ITEM_VIEW_TYPE}private fun isEndItemView(viewType: Int): Boolean {return viewType == END_ITEM_VIEW_TYPE}}/*** 点击继续拍照的点击事件回调*/
interface OnImageGalleryAddPhotoClickListener1 {fun onAddPhotoItemClick()
}class ImageGalleryViewHolder1(itemView: View) : RecyclerView.ViewHolder(itemView) {var itemRootView: ConstraintLayout? = nullvar ivPhoto: ImageView? = nullvar ivAddPhoto: ImageView? = nullinit {ivPhoto = itemView.findViewById(R.id.ivPhoto)ivAddPhoto = itemView.findViewById(R.id.ivAddPhoto)itemRootView = itemView.findViewById(R.id.itemRootView)ivPhoto?.setRound(itemView.context.resources.getDimensionPixelSize(R.dimen.hybrid_image_gallery_dialog_round_size).toFloat())}
}class ImageGalleryZoomOutPageTransformer1 : ViewPager2.PageTransformer {override fun transformPage(view: View, position: Float) {val pageWidth = view.widthval pageHeight = view.heightval scaleFactor = MIN_SCALE.coerceAtLeast(1 - abs(position))val vertMargin = pageHeight * (1 - scaleFactor) / 2val horzMargin = pageWidth * (1 - scaleFactor) / 2when {position < -1 -> {view.translationX = horzMargin - vertMargin / 2// [-Infinity,-1)// This page is way off-screen to the left.view.alpha = MIN_ALPHAview.scaleX = MIN_SCALEview.scaleY = MIN_SCALE}position <= 1 -> {// [-1,1]if (position < 0) {view.translationX = horzMargin - vertMargin / 2view.scaleX = 1 + 0.3f * positionview.scaleY = 1 + 0.3f * position} else {view.translationX = -horzMargin + vertMargin / 2view.scaleX = 1 - 0.3f * positionview.scaleY = 1 - 0.3f * position}// Scale the page down (between MIN_SCALE and 1)// Fade the page relative to its size.view.alpha =MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)}else -> { // (1,+Infinity]view.translationX = -horzMargin + vertMargin / 2view.scaleX = MIN_SCALEview.scaleY = MIN_SCALEview.alpha = MIN_ALPHA}}}companion object {private const val MIN_SCALE = 0.7fprivate const val MIN_ALPHA = 0.5f}
}interface OnImageDialogDismissListener1 {fun onDismiss(resultJson:String)
}
class AXXAlbumCamera(var context: Context): Camera<AXXImageCameraWrapper, VideoCameraWrapper> {override fun image(): AXXImageCameraWrapper {return AXXImageCameraWrapper(context)}override fun video(): VideoCameraWrapper {return VideoCameraWrapper(context)}
}
public class AXXCameraActivity extends BaseActivity {public static final String INSTANCE_CAMERA_TYPE = "INSTANCE_CAMERA_TYPE";private int cameraType = 1; // 前置、后置 1 后置 2 前置private static final int CODE_PERMISSION_IMAGE = 1;public static final int CAMERA_TYPE_BACK = 1; // 后public static final int CAMERA_TYPE_FRONT = 2; // 前private static final int CODE_ACTIVITY_TAKE_IMAGE = 1;public static Action<String> sResult;public static Action<String> sCancel;private String mCameraFilePath;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);SystemBar.setStatusBarColor(this, Color.TRANSPARENT);SystemBar.setNavigationBarColor(this, Color.TRANSPARENT);SystemBar.invasionNavigationBar(this);if (savedInstanceState == null) {Bundle bundle = getIntent().getExtras();assert bundle != null;cameraType = bundle.getInt(INSTANCE_CAMERA_TYPE);requestPermission(PERMISSION_TAKE_PICTURE , CODE_PERMISSION_IMAGE);} else {cameraType = savedInstanceState.getInt(INSTANCE_CAMERA_TYPE);}}@Overrideprotected void onPermissionGranted(int code) {super.onPermissionGranted(code);if(code == CODE_PERMISSION_IMAGE) {mCameraFilePath = AlbumUtils.randomJPGPath(this);ReportLog.INSTANCE.method("AXXCameraActivity", "onPermissionGranted", "要拍照的路径:" + mCameraFilePath);takeImage(this, CODE_ACTIVITY_TAKE_IMAGE, new File(mCameraFilePath));}}@Overrideprotected void onPermissionDenied(int code) {super.onPermissionDenied(code);if(code == CODE_PERMISSION_IMAGE) {ToastUtil.showToast("您还没有拍照和存储的权限,请前往权限中心进行设置");callbackCancel();}}/*** 拍照* @param activity* @param requestCode* @param outPath*/private void takeImage(@NonNull Activity activity, int requestCode, File outPath) {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);Uri uri = AlbumUtils.getUri(activity, outPath);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);if(cameraType == CAMERA_TYPE_FRONT) {intent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true);} else {intent.putExtra("android.intent.extra.USE_FRONT_CAMERA", false);}intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);activity.startActivityForResult(intent, requestCode);}@Overridepublic void onSaveInstanceState(Bundle outState) {outState.putInt(INSTANCE_CAMERA_TYPE, cameraType);super.onSaveInstanceState(outState);}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);switch (requestCode) {case CODE_ACTIVITY_TAKE_IMAGE: {if (resultCode == RESULT_OK) {callbackResult();} else {callbackCancel();}break;}default: {throw new AssertionError("This should not be the case.");}}}private void callbackResult() {if (sResult != null) sResult.onAction(mCameraFilePath);sResult = null;sCancel = null;finish();}private void callbackCancel() {if (sCancel != null) sCancel.onAction("User canceled.");sResult = null;sCancel = null;finish();}
}

hybrid_activity_image_gallery.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/imageGalleryRootView"android:background="#00000000"xmlns:app="http://schemas.android.com/apk/res-auto"><androidx.appcompat.widget.AppCompatTextViewandroid:id="@+id/tvIndex"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toTopOf="@+id/pageGroup"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"android:text="0/0"android:textColor="@color/white"android:textStyle="bold"android:textSize="16sp"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintVertical_bias="0.8"/><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/pageGroup"android:layout_width="0dp"android:layout_height="0dp"android:clipChildren="false"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintHeight_percent="0.6"><androidx.viewpager2.widget.ViewPager2android:id="@+id/imagePager"android:layout_width="0dp"android:layout_height="0dp"android:clipChildren="false"android:overScrollMode="never"app:layout_constraintHeight_percent="1"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintDimensionRatio="h,548:750"/></androidx.constraintlayout.widget.ConstraintLayout><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/ivReset"app:layout_constraintTop_toBottomOf="@+id/pageGroup"app:layout_constraintLeft_toLeftOf="@id/pageGroup"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintRight_toLeftOf="@+id/ivDeleted"app:layout_constraintHorizontal_chainStyle="packed"android:src="@mipmap/icon_image_gallery_reset"app:layout_constraintDimensionRatio="64:100"app:layout_constraintHeight_percent="0.09"android:layout_marginRight="17dp"android:layout_width="0dp"android:layout_height="0dp"/><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/ivDeleted"app:layout_constraintTop_toBottomOf="@+id/pageGroup"app:layout_constraintRight_toRightOf="@id/pageGroup"app:layout_constraintLeft_toRightOf="@+id/ivReset"app:layout_constraintBottom_toBottomOf="parent"android:src="@mipmap/icon_image_gallery_deleted"android:layout_marginLeft="17dp"app:layout_constraintDimensionRatio="64:100"app:layout_constraintHeight_percent="0.09"android:layout_width="0dp"android:layout_height="0dp"/></androidx.constraintlayout.widget.ConstraintLayout>

hybrid_item_image_gallery.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/itemRootView"xmlns:app="http://schemas.android.com/apk/res-auto"android:background="@drawable/hybrid_bg_photo_grallery"><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/ivPhoto"android:layout_width="0dp"android:layout_height="0dp"android:scaleType="centerCrop"app:layout_constraintTop_toTopOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintBottom_toBottomOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>

hybrid_item_image_gallery_photograph.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/itemRootView"android:background="@drawable/hybrid_bg_add_photo_grallery"xmlns:app="http://schemas.android.com/apk/res-auto"><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/ivAddPhoto"android:layout_width="0dp"android:layout_height="0dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintDimensionRatio="100:83"app:layout_constraintWidth_percent="0.13"android:src="@mipmap/icon_photograph"/></androidx.constraintlayout.widget.ConstraintLayout>

Android 仿照微信查看大图相关推荐

  1. 【Android视图效果】共享元素实现仿微信查看大图效果

    在之前的文章中,我们通过动画实现了这个,具体可以查看[Android 动画]动画详解之仿微信查看大图效果(四),这里,我们用过度动画来实现. 什么是共享元素? 它是Android 5.0新加入的一种过 ...

  2. android 点击查看大图_你是不是遇到,在花瓣网部分图片详情页,点击“放大镜”无法预览高清大图?...

    大家好,此篇文章您可以花 3 分钟学习到:如何借助率叶插件,恢复花瓣网图片详情页预览高清大图. 新品推送:这是什么神仙功能,尽然可以在Photoshop里上花瓣网.站酷.阿里图标等网站! 2020-0 ...

  3. Android 点击查看大图(长按保存图片)

    通常会看到点击ImageView弹出一个Dialog上面有一张大图,然后长按大图可以保存 activity_main.xml <?xml version="1.0" enco ...

  4. android点击查看大图(长按保存图片)

    通常会看到点击ImageView弹出一个Dialog上面有一张大图,然后长按大图可以保存,这就好像成为了一个固定的 流程,那么,我们就来实现这一系列的功能. 1.xml文件,特别简单,只有一个Imag ...

  5. Android仿微信朋友圈图片查看器

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/40264551 看博文之前,希望大家先打开自己的微信点到朋友圈中去,仔细观察是不是发 ...

  6. android仿微信头像点击放大查看,仿微信查看图片(带大小图切换查看)

    之前一直想仿微信朋友圈那样做个图片查看,但是看了网上很多demo都觉得比较简单,少了从小图切换到大图的加载过程,都只是在所有预览里加载大图,点击进去也是加载大图,于是在网上下载了别人的demo自己修改 ...

  7. android 图片查看动画,Android 共享动画实现点击列表图片跳转查看大图页面

    主要内容使用系统提供的 API 实现共享动画 在实现过程中遇到的问题图片点击和关闭之后会出现短暂的黑屏问题实现的动画效果如下: 共享动画.gif 具体实现这个效果是在两个页面之间的切换动画,既然是两个 ...

  8. 微信小程序——焦点图 可预览查看大图缩放(多张可左右滑动) 带页码 loading 加载中 / https不显示图

    微信小程序焦点图,可以滑动预览大图缩放 微信小程序自带焦点图swiper ,但是没有页码,只有小圆点,所以要自己写 (在查看大图时遇到一个问题,安卓上查看大图部分图不显示,经排查,发现不显示的图片地址 ...

  9. Android下QQ空间查看大图特效

    最近在做一个项目,里面有一个功能是实现Android QQ好友动态里面的缩略图放大,查看大图的效果.用过都知道,这个特效很赞的,没用过的下载个玩玩吧.我刚开始以为放大的那个大图是一个Activity或 ...

最新文章

  1. 中文repo“霸榜”GitHub Trending,国外开发者不开心了
  2. Netflix创始人:我不要求996,一样市值1万亿
  3. 滥用网络爬虫技术,多家公司被查!互金行业风控外包时代终结
  4. if else复合语句
  5. 【学习笔记】JAVA IO与NIO(new IO)的对比与不同IO模型的理解
  6. android 复制u盘文件到手机本地_如何导出Android中的文件(把Android当做U盘)
  7. 字符串匹配算法之KMP
  8. linux进行硬盘分区挂载-了解系统,最更好的开发
  9. C 标准库—— string.h
  10. C# IntPtr转struct
  11. Vue+ bootStrap 实现员的增删改查 离职操作 全选单选
  12. 数据库表历史数据备份(定时任务)
  13. Simulink中步长、powergui采样时间、模块采样时间、控制周期的关系
  14. 跨时钟域处理所用到的同步器
  15. null id in entry (don‘t flush the Session after an exception occurs)解决思路
  16. A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHM
  17. c语言能让键盘失灵怎么办,电脑键盘个别字母失灵的三种解决方法
  18. [JavaScript]只需一行代码,轻松搞定快捷留言-V2升级版javascript
  19. 基于ShineBlink物联网开发板和机智云平台开发的“针对短期内宠物无人照顾的智能宠物屋”系统
  20. 消息中间件 一 之 AMQP译文(下)

热门文章

  1. android 跳转oppo应用中心_Android 遍历手机应用,跳转应用市场详情页面
  2. 实习一月记——美团点评云计算部
  3. 苹果黑屏就断开无线网连接服务器,跪求苹果手机黑屏以后断开无线网的解决方案!...
  4. html5的canvas制作口红机闯关游戏(一)
  5. bbqsql安装使用踩坑总结
  6. 互联网晚报 | 12月30日 星期四 | 百度网盘青春版正式上线;汽车之家回应“年底大裁员”;A股年内成交额创历史新高...
  7. echarts 好看的柱形图
  8. 社保管理系统连接不上服务器,社保费客户端登录服务器异常
  9. 研究生发论文的流程?
  10. Arcmap制图调色