lmw
2023-05-12 f67802a41f9e01444d1115f34ecc6e1beb05fc3b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package cn.sinata.xldutils.view
 
import android.content.Context
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.RectF
import android.graphics.drawable.Animatable
import android.util.AttributeSet
import android.view.MotionEvent
import cn.sinata.xldutils.view.util.DefaultZoomableController
import cn.sinata.xldutils.view.util.ZoomableController
import com.facebook.common.internal.Preconditions
import com.facebook.drawee.controller.AbstractDraweeController
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.drawee.interfaces.DraweeController
import com.facebook.drawee.view.GenericDraweeView
 
class ZoomableDraweeView : GenericDraweeView, ZoomableController.Listener {
 
    private val mImageBounds = RectF()
    private val mViewBounds = RectF()
    private val mControllerListener = object : BaseControllerListener<Any>() {
        override fun onFinalImageSet(
                id: String?,
                imageInfo: Any?,
                animatable: Animatable?) {
            this@ZoomableDraweeView.onFinalImageSet()
        }
        override fun onRelease(id: String?) {
            this@ZoomableDraweeView.onRelease()
        }
    }
 
    private var mHugeImageController: DraweeController? = null
    private var mZoomableController = DefaultZoomableController.newInstance()
 
    constructor(context: Context) : super(context) {
        init()
    }
 
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init()
    }
 
    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init()
    }
 
    private fun init() {
        mZoomableController.setListener(this)
    }
 
    fun setZoomableController(zoomableController: ZoomableController) {
        Preconditions.checkNotNull(zoomableController)
        mZoomableController.setListener(null)
        mZoomableController = zoomableController as DefaultZoomableController
        mZoomableController.setListener(this)
    }
 
    override fun setController(controller: DraweeController?) {
        setControllers(controller, null)
    }
 
    private fun setControllersInternal(
            controller: DraweeController?,
            hugeImageController: DraweeController?) {
        removeControllerListener(getController())
        addControllerListener(controller)
        mHugeImageController = hugeImageController
        super.setController(controller)
    }
 
    /**
     * Sets the controllers for the normal and huge image.
 
     *
     *  IMPORTANT: in order to avoid a flicker when switching to the huge image, the huge image
     * controller should have the normal-image-uri set as its low-res-uri.
 
     * @param controller controller to be initially used
     * *
     * @param hugeImageController controller to be used after the client starts zooming-in
     */
    fun setControllers(
            controller: DraweeController?,
            hugeImageController: DraweeController?) {
        setControllersInternal(null, null)
        mZoomableController.isEnabled = true
        setControllersInternal(controller, hugeImageController)
    }
 
    private fun maybeSetHugeImageController() {
        if (mHugeImageController != null && mZoomableController.scaleFactor > HUGE_IMAGE_SCALE_FACTOR_THRESHOLD) {
            setControllersInternal(mHugeImageController, null)
        }
    }
 
    private fun removeControllerListener(controller: DraweeController?) {
        if (controller!=null) {
            (controller as? AbstractDraweeController<*, *>)?.removeControllerListener(mControllerListener)
        }
    }
 
    private fun addControllerListener(controller: DraweeController?) {
        if(controller!=null) {
            (controller as? AbstractDraweeController<*, *>)?.addControllerListener(mControllerListener)
        }
    }
 
    override fun onDraw(canvas: Canvas) {
        val saveCount = canvas.save()
        canvas.concat(mZoomableController.transform)
        super.onDraw(canvas)
        canvas.restoreToCount(saveCount)
    }
 
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (mZoomableController.onTouchEvent(event)) {
            if (mZoomableController.scaleFactor > 1.0f) {
                parent.requestDisallowInterceptTouchEvent(true)
            }
            return true
        }
        return super.onTouchEvent(event)
    }
 
    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        updateZoomableControllerBounds()
    }
 
    private fun onFinalImageSet() {
        if (!mZoomableController.isEnabled) {
            updateZoomableControllerBounds()
            mZoomableController.isEnabled = true
        }
    }
 
    private fun onRelease() {
        mZoomableController.isEnabled = false
    }
 
    override fun onTransformChanged(transform: Matrix) {
        maybeSetHugeImageController()
        invalidate()
    }
 
    private fun updateZoomableControllerBounds() {
        hierarchy.getActualImageBounds(mImageBounds)
        mViewBounds.set(0f, 0f, width.toFloat(), height.toFloat())
        mZoomableController.setImageBounds(mImageBounds)
        mZoomableController.setViewBounds(mViewBounds)
    }
 
    companion object {
        private val HUGE_IMAGE_SCALE_FACTOR_THRESHOLD = 1.1f
    }
}