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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.