class BigView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr), GestureDetector.OnGestureListener, View.OnTouchListener {
//要加载的图片范围
private val mRect by lazy {
Rect()
}
//Bitmap配置类
private val mOptions by lazy {
BitmapFactory.Options().apply {
//开启内存复用
inMutable = true
//设置图片格式为565
inPreferredConfig = Bitmap.Config.RGB_565
}
}
//手势监听
private val mGestureDetector by lazy {
GestureDetector(context, this)
}
//Scroller,利用这个类进行滑动
private val mScroller by lazy {
Scroller(context)
}
//矩阵,处理图片的缩放
private val mMatrix by lazy {
Matrix()
}
//图片宽高
private var mImageWidth: Int = 0
private var mImageHeight: Int = 0
//展示图片的View的宽高
private var mViewWidth: Int = 0
private var mViewHeight: Int = 0
//缩放因子
private var mScale: Float = 0f
//图片解码器
private var mDecoder: BitmapRegionDecoder? = null
//复用的Bitmap
private var mBitmap: Bitmap? = null
init {
setOnTouchListener(this)
}
//设置图片
fun setImage(inputStream: InputStream) {
//设置inJustDecodeBounds,让其不加载进内存也能获得图片相关信息
mOptions.inJustDecodeBounds = true
BitmapFactory.decodeStream(inputStream, null, mOptions)
//获取图片宽高
mImageWidth = mOptions.outWidth
mImageHeight = mOptions.outHeight
mOptions.inJustDecodeBounds = false
//获取图片解码器
try {
mDecoder = BitmapRegionDecoder.newInstance(inputStream, false)
} catch (e: IOException) {
}
requestLayout()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//获取View视图的宽高
mViewWidth = measuredWidth
mViewHeight = measuredHeight
//计算图片的缩放系数
mScale = mViewWidth.div(mImageWidth.toFloat())
//赋值给图片要加载区域的Rect,要加载进来的高度需要根据缩放系数计算
//缩放之后肯定能够展示更多的高度,所以要算出缩放前需要加载的图片高度
mRect.set(0, 0, mImageWidth, mViewHeight.div(mScale).toInt())
}
//绘制图片
override fun onDraw(canvas: Canvas?) {
if (mDecoder == null) {
return
}
//设置复用的Bitmap
mOptions.inBitmap = mBitmap
//解码器对图片加载的区域进行解码
mBitmap = mDecoder!!.decodeRegion(mRect, mOptions)
//设置矩阵
mMatrix.setScale(mScale, mScale)
//在展示的区域内绘制这个图片,区域之外的图片不会绘制
mBitmap?.let {
canvas?.drawBitmap(it, mMatrix, null)
}
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
//交给手势识别去处理
mGestureDetector.onTouchEvent(event)
return true
}
override fun onDown(e: MotionEvent?): Boolean {
//手指按下的时候,让滑动停止
if (!mScroller.isFinished) {
mScroller.forceFinished(true)
}
return true
}
override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {
//将矩形偏移
mRect.offset(0, distanceY.toInt())
//处理滑动到顶部和底部的情况
if (mRect.top < 0) {
mRect.top = 0
mRect.bottom = mViewHeight.div(mScale).toInt()
}
if (mRect.bottom > mImageHeight) {
mRect.bottom = mImageHeight
mRect.top = mImageHeight.minus(mViewHeight.div(mScale)).toInt()
}
invalidate()
return true
}
override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean {
mScroller.fling(0, mRect.top, 0, -velocityY.toInt(), 0, 0, 0, mImageHeight.minus(mViewHeight.div(mScale)).toInt())
return true
}
override fun computeScroll() {
if (mScroller.isFinished) {
return
}
if (mScroller.computeScrollOffset()) {
mRect.top = mScroller.currY
mRect.bottom = mRect.top.plus(mViewHeight.div(mScale).toInt())
invalidate()
}
}
override fun onShowPress(e: MotionEvent?) {
}
override fun onSingleTapUp(e: MotionEvent?): Boolean = true
override fun onLongPress(e: MotionEvent?) {
}
}
Android长图加载 - 利用Bitmap Options
最新推荐文章于 2024-06-26 17:42:10 发布