赞
踩
Bitmap
缩放和平移Bitmap
可能为宽高相同的正方形,也可能为宽高不同的矩形Bitmap
中心缩放,包含了缩放和平移两个操作,不可拆开Bitmap
其余四个方向的缩放,可以单独缩放不带平移,也可以缩放带平移XML
文件<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.yang.app.MyRelativeLayout android:id="@+id/real_rl" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="30dp" android:layout_marginBottom="30dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:background="@color/gray"> <com.yang.app.MyImageView android:id="@+id/real_iv" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="30dp" android:layout_marginBottom="30dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" /> </com.yang.app.MyRelativeLayout> <ImageView android:layout_width="match_parent" android:layout_height="200dp" android:layout_weight="0" android:background="#00ff00" /> </LinearLayout>
Activity
代码const val TAG = "Yang" class MainActivity : AppCompatActivity() { var mRealView : MyImageView ?= null var mRelativeLayout : MyRelativeLayout ?= null var tempBitmap : Bitmap ?= null var mHandler = Handler(Looper.getMainLooper()) var screenWidth = 0 var screenHeight = 0 var srcRect = RectF() var destRect = RectF() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mRealView = findViewById(R.id.real_iv) mRelativeLayout = findViewById(R.id.real_rl) // 屏幕宽高的一半作为临时RectF, 用于压缩Bitmap screenWidth = resources.displayMetrics.widthPixels screenHeight = resources.displayMetrics.heightPixels val tempRect = RectF(0f, 0f, screenWidth.toFloat() / 2, screenHeight.toFloat() / 2) CoroutineScope(Dispatchers.IO).launch { tempBitmap = getBitmap(resources, tempRect, R.drawable.fake) withContext(Dispatchers.Main) { mRelativeLayout?.post { // 获取初始区域的RectF srcRect.set( 0f, 0f, mRelativeLayout?.width?.toFloat()!!, mRelativeLayout?.height?.toFloat()!! ) // 获取结束区域的RectF mRelativeLayout?.forEach { childView -> if (childView is MyImageView) { destRect.set( 0f, 0f, childView.width.toFloat(), childView.height.toFloat() ) } } scaleRectFun(tempBitmap, srcRect, destRect) } } } } fun scaleRectFun(tempBitmap: Bitmap?, srcRect : RectF, destRect: RectF){ tempBitmap?.let { bitmap-> mRelativeLayout?.setBitmap(bitmap) val animator = ValueAnimator.ofFloat(0f, 1f) animator.duration = 5000L animator.interpolator = DecelerateInterpolator() animator.addUpdateListener { val value = it.animatedValue as Float // 中心缩放 mRelativeLayout?.setDestRectCenterWithTranslate(srcRect, destRect, value) // 左上角不带平移缩放 // mRelativeLayout?.setDestRectLeftTopNoTranslate(srcRect, destRect, value) // 左上角平移缩放 // mRelativeLayout?.setDestRectLeftTopWithTranslate(srcRect, destRect, value) // 右上角不带平移缩放 // mRelativeLayout?.setDestRectRightTopNoTranslate(srcRect, destRect, value) // 右上角平移缩放 // mRelativeLayout?.setDestRectRightTopWithTranslate(srcRect, destRect, value) // 左下角不带平移缩放 // mRelativeLayout?.setDestRectLeftBottomNoTranslate(srcRect, destRect, value) // 左下角平移缩放 // mRelativeLayout?.setDestRectLeftBottomWithTranslate(srcRect, destRect, value) // 右下角不带平移缩放 // mRelativeLayout?.setDestRectRightBottomNoTranslate(srcRect, destRect, value) // 右下角平移缩放 // mRelativeLayout?.setDestRectRightBottomWithTranslate(srcRect, destRect, value) } animator.start() } } } fun getBitmap(resources : Resources, destRect : RectF, imageId: Int): Bitmap? { var imageWidth = -1 var imageHeight = -1 val preOption = BitmapFactory.Options().apply { // 只获取图片的宽高 inJustDecodeBounds = true BitmapFactory.decodeResource(resources, imageId, this) } imageWidth = preOption.outWidth imageHeight = preOption.outHeight // 计算缩放比例 val scaleMatrix = Matrix() // 确定未缩放Bitmap的RectF var srcRect = RectF(0f, 0f, imageWidth.toFloat(), imageHeight.toFloat()) // 通过目标RectF, 确定缩放数值,存储在scaleMatrix中 scaleMatrix.setRectToRect(srcRect, destRect, Matrix.ScaleToFit.CENTER) // 缩放数值再映射到原始Bitmap上,得到缩放后的RectF scaleMatrix.mapRect(srcRect) val finalOption = BitmapFactory.Options().apply { if (imageHeight > 0 && imageWidth > 0) { inPreferredConfig = Bitmap.Config.RGB_565 inSampleSize = calculateInSampleSize( imageWidth, imageHeight, srcRect.width().toInt(), srcRect.height().toInt() ) } } return BitmapFactory.decodeResource(resources, imageId, finalOption) } fun calculateInSampleSize(fromWidth: Int, fromHeight: Int, toWidth: Int, toHeight: Int): Int { var bitmapWidth = fromWidth var bitmapHeight = fromHeight if (fromWidth > toWidth|| fromHeight > toHeight) { var inSampleSize = 2 // 计算最大的inSampleSize值,该值是2的幂,并保持原始宽高大于目标宽高 while (bitmapWidth >= toWidth && bitmapHeight >= toHeight) { bitmapWidth /= 2 bitmapHeight /= 2 inSampleSize *= 2 } return inSampleSize } return 1 }
ViewGroup
和View
代码class MyImageView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : AppCompatImageView(context, attrs, defStyleAttr) class MyRelativeLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : RelativeLayout(context, attrs, defStyleAttr) { var mBitmap : Bitmap ?= null var mScaleMatrix = Matrix() var mDestRect = RectF() fun setBitmap(bitmap: Bitmap?) { mBitmap = bitmap } override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) mBitmap?.let { canvas?.drawBitmap(it, mScaleMatrix, Paint().apply { isAntiAlias = true }) } } }
ValueAnimator
动画的初始值为0,开始区域为外层MyRelativeLayout
区域,结束区域为内层MyImageView
区域,缩放区域在这两个区域大小之间变化mDestRect
和Bitmap
宽高的最小宽高比fun setDestRectCenterWithTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = (srcRect.width() - mBitmap?.width!! * scale) / 2
val dy = (srcRect.height() - mBitmap?.height!! * scale) / 2
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectLeftTopNoTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
mScaleMatrix.setScale(scale, scale)
invalidate()
}
左上角不带平移缩放效果图
左上角带平移缩放
fun setDestRectLeftTopWithTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = ((srcRect.width() - destRect.width())/2) * value + (destRect.left - srcRect.left) * value
val dy = ((srcRect.height() - destRect.height())/2) * value + (destRect.top - srcRect.top) * value
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectRightTopNoTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = srcRect.width() - mBitmap!!.width * scale
val dy = 0f
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectRightTopWithTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = ((srcRect.width() - destRect.width())/2) * value + (destRect.left - srcRect.left) * value
val dy = ((srcRect.height() - destRect.height())/2) * value + (destRect.top - srcRect.top) * value
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectLeftBottomNoTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = 0f
val dy = srcRect.height() - mBitmap?.height!! * scale
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectLeftBottomWithTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = ((srcRect.width() - destRect.width())/2 )* value
val dy = ((srcRect.height() - destRect.height())/2 )* value + (destRect.bottom - srcRect.bottom) * value + (srcRect.height()- mBitmap?.height!! * scale)
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectRightBottomNoTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = srcRect.width() - mBitmap!!.width * scale
val dy = srcRect.height() - mBitmap?.height!! * scale
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
fun setDestRectRightBottomWithTranslate(srcRect: RectF, destRect: RectF, value : Float) {
mDestRect = RectF(
srcRect.left + (destRect.left - srcRect.left) * value,
srcRect.top + (destRect.top - srcRect.top) * value,
srcRect.right + (destRect.right - srcRect.right) * value,
srcRect.bottom + (destRect.bottom - srcRect.bottom) * value
)
val scale = Math.min(mDestRect.width() / mBitmap?.width!!, mDestRect.height() / mBitmap!!.height)
val dx = ((srcRect.width() - destRect.width())/2 )* value
val dy = ((srcRect.height() - destRect.height())/2 )* value + (destRect.bottom - srcRect.bottom) * value + (srcRect.height()- mBitmap?.height!! * scale)
mScaleMatrix.reset()
mScaleMatrix.postScale(scale, scale)
mScaleMatrix.postTranslate(dx, dy)
invalidate()
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。