lmw
2023-04-03 16ea883d3c03fd8b910f9282aa1bc08378d40d54
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
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 androidx.annotation.Nullable;
 
import com.facebook.common.internal.Preconditions;
import com.facebook.common.logging.FLog;
import com.facebook.drawee.controller.AbstractDraweeController;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.controller.ControllerListener;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.GenericDraweeView;
 
public class ZoomableDraweeView extends GenericDraweeView
    implements ZoomableController.Listener {
 
  private static final Class<?> TAG = ZoomableDraweeView.class;
 
  private static final float HUGE_IMAGE_SCALE_FACTOR_THRESHOLD = 1.1f;
 
  private final RectF mImageBounds = new RectF();
  private final RectF mViewBounds = new RectF();
 
  private final ControllerListener mControllerListener = new BaseControllerListener<Object>() {
    @Override
    public void onFinalImageSet(
        String id,
        @Nullable Object imageInfo,
        @Nullable Animatable animatable) {
      ZoomableDraweeView.this.onFinalImageSet();
    }
 
    @Override
    public void onRelease(String id) {
      ZoomableDraweeView.this.onRelease();
    }
  };
 
  private DraweeController mHugeImageController;
  private ZoomableController mZoomableController = DefaultZoomableController.newInstance();
 
  public ZoomableDraweeView(Context context) {
    super(context);
    init();
  }
 
  public ZoomableDraweeView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
 
  public ZoomableDraweeView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
  }
 
  private void init() {
    mZoomableController.setListener(this);
  }
 
  public void setZoomableController(ZoomableController zoomableController) {
    Preconditions.checkNotNull(zoomableController);
    mZoomableController.setListener(null);
    mZoomableController = zoomableController;
    mZoomableController.setListener(this);
  }
 
  @Override
  public void setController(@Nullable DraweeController controller) {
    setControllers(controller, null);
  }
 
  private void setControllersInternal(
      @Nullable DraweeController controller,
      @Nullable DraweeController hugeImageController) {
    removeControllerListener(getController());
    addControllerListener(controller);
    mHugeImageController = hugeImageController;
    super.setController(controller);
  }
 
    /**
     * Sets the controllers for the normal and huge image.
     *
     * <p> 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
     */
  public void setControllers(
      @Nullable DraweeController controller,
      @Nullable DraweeController hugeImageController) {
    setControllersInternal(null, null);
    mZoomableController.setEnabled(false);
    setControllersInternal(controller, hugeImageController);
  }
 
  private void maybeSetHugeImageController() {
    if (mHugeImageController != null &&
        mZoomableController.getScaleFactor() > HUGE_IMAGE_SCALE_FACTOR_THRESHOLD) {
      setControllersInternal(mHugeImageController, null);
    }
  }
 
  private void removeControllerListener(DraweeController controller) {
    if (controller instanceof AbstractDraweeController) {
      ((AbstractDraweeController) controller)
          .removeControllerListener(mControllerListener);
    }
  }
 
  private void addControllerListener(DraweeController controller) {
    if (controller instanceof AbstractDraweeController) {
      ((AbstractDraweeController) controller)
          .addControllerListener(mControllerListener);
    }
  }
 
  @Override
  protected void onDraw(Canvas canvas) {
    int saveCount = canvas.save();
    canvas.concat(mZoomableController.getTransform());
    super.onDraw(canvas);
    canvas.restoreToCount(saveCount);
  }
 
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (mZoomableController.onTouchEvent(event)) {
      if (mZoomableController.getScaleFactor() > 1.0f) {
        getParent().requestDisallowInterceptTouchEvent(true);
      }
      FLog.v(TAG, "onTouchEvent: view %x, handled by zoomable controller", this.hashCode());
      return true;
    }
    FLog.v(TAG, "onTouchEvent: view %x, handled by the super", this.hashCode());
    return super.onTouchEvent(event);
  }
 
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    FLog.v(TAG, "onLayout: view %x", this.hashCode());
    super.onLayout(changed, left, top, right, bottom);
    updateZoomableControllerBounds();
  }
 
  private void onFinalImageSet() {
    FLog.v(TAG, "onFinalImageSet: view %x", this.hashCode());
    if (!mZoomableController.isEnabled()) {
      updateZoomableControllerBounds();
      mZoomableController.setEnabled(true);
    }
  }
 
  private void onRelease() {
    FLog.v(TAG, "onRelease: view %x", this.hashCode());
    mZoomableController.setEnabled(false);
  }
 
  @Override
  public void onTransformChanged(Matrix transform) {
    FLog.v(TAG, "onTransformChanged: view %x", this.hashCode());
    maybeSetHugeImageController();
    invalidate();
  }
 
  private void updateZoomableControllerBounds() {
    getHierarchy().getActualImageBounds(mImageBounds);
    mViewBounds.set(0, 0, getWidth(), getHeight());
    mZoomableController.setImageBounds(mImageBounds);
    mZoomableController.setViewBounds(mViewBounds);
    FLog.v(
        TAG,
        "updateZoomableControllerBounds: view %x, view bounds: %s, image bounds: %s",
        this.hashCode(),
        mViewBounds,
        mImageBounds);
  }
}