[ZoomInOutImageView.java]
public class ZoomInOutImageView extends androidx.appcompat.widget.AppCompatImageView {
private final Matrix mMatrix = new Matrix();
private final int WIDTH = 0;
private final int HEIGHT = 1;
private static final float MIN_ZOOM = 0.33333F;
private static final float MAX_ZOOM = 5F;
private PointF mLastTouch = new PointF(0, 0);
private PointF mLastFocus = new PointF(0, 0);
public float mScaleFactor = 1F;
private int mActivePointerId = INVALID_POINTER_ID;
private Paint mPaint;
private Bitmap mBitmapLayout;
private float mMaxScale = 2.0f; //2배 까지 확대
private boolean mIsInit = false;
// private OnFactorChangedListener mListener;
private ScaleGestureDetector mScaleDetector;
public ZoomInOutImageView(Context context) {
super(context);
initializeInConstructor(context);
}
public ZoomInOutImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initializeInConstructor(context);
}
public ZoomInOutImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initializeInConstructor(context);
}
public void initializeInConstructor(Context context) {
mPaint = new Paint();
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mScaleDetector.setQuickScaleEnabled(false);
setScaleType(ScaleType.MATRIX);
}
public void showImage(Uri imageUri, float maxScale) {
this.setImageURI(imageUri);
BitmapDrawable drawble = (BitmapDrawable) getDrawable();
mBitmapLayout = drawble.getBitmap();
this.mMaxScale = maxScale;
}
public void showImage(Bitmap bitmap, float maxScale) {
this.setImageBitmap(bitmap);
BitmapDrawable drawble = (BitmapDrawable) getDrawable();
mBitmapLayout = drawble.getBitmap();
this.mMaxScale = maxScale;
}
private float mLastScaleFactor = 1.0f;
@Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN: {
int pointerIndex = event.getActionIndex();
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
// Remember where we started (for dragging)
mLastTouch = new PointF(x, y);
// Save the ID of this pointer (for dragging)
mActivePointerId = event.getPointerId(0);
}
case MotionEvent.ACTION_POINTER_DOWN: {
if (event.getPointerCount() == 2) {
mLastFocus = new PointF(mScaleDetector.getFocusX(), mScaleDetector.getFocusY());
}
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
int pointerIndex = event.findPointerIndex(mActivePointerId);
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
// Calculate the distance moved
float dx = 0;
float dy = 0;
if (event.getPointerCount() == 1) {
// Calculate the distance moved
dx = x - mLastTouch.x;
dy = y - mLastTouch.y;
Log.d("onTouchEvent - 1", String.valueOf(x) + " / " + String.valueOf(y) + " / " +String.valueOf(dx) + " / " + String.valueOf(dy) );
// Remember this touch position for the next move event
mLastTouch = new PointF(x, y);
// 1:1 스케일의 경우 이미지 이동 되지 않게 고정
if (mScaleFactor <= 1.0f) {
imageScaleSetup();
}
} else if (event.getPointerCount() == 2) {
// Calculate the distance moved
float focusX = mScaleDetector.getFocusX();
float focusY = mScaleDetector.getFocusY();
dx = focusX - mLastFocus.x;
dy = focusY - mLastFocus.y;
Log.d("onTouchEvent - 2", String.valueOf(focusX) + " / " + String.valueOf(focusY) + " / " + String.valueOf(dx) + " / " + String.valueOf(dy) );
// Since we are accumating translation/scaling, we are just adding to
// the previous scale.
mMatrix.postScale(mScaleFactor / mLastScaleFactor, mScaleFactor / mLastScaleFactor, focusX, focusY);
mLastScaleFactor = mScaleFactor;
mLastFocus = new PointF(focusX, focusY);
}
// Translation is cumulative.
mMatrix.postTranslate(dx, dy);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = event.getActionIndex();
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouch = new PointF(event.getX(newPointerIndex), event.getY(newPointerIndex));
mActivePointerId = event.getPointerId(newPointerIndex);
} else {
final int tempPointerIndex = event.findPointerIndex(mActivePointerId);
mLastTouch = new PointF(event.getX(tempPointerIndex), event.getY(tempPointerIndex));
}
break;
}
}
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
if (mBitmapLayout == null) { return; }
if (mIsInit == false) {
mIsInit = true;
imageScaleSetup();
}
canvas.save();
canvas.setMatrix(mMatrix);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(mBitmapLayout,0,0, mPaint);
canvas.restore();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// 줌 In Out 범위 제한
if (mScaleFactor < 1.0f) {
mScaleFactor = 1.0f;
imageScaleSetup();
return true;
} else if (mScaleFactor > mMaxScale) {
mScaleFactor = mMaxScale;
return true;
}
mScaleFactor = Math.max(MIN_ZOOM, Math.min(mScaleFactor, MAX_ZOOM));
Log.d("onScale", String.valueOf(mScaleFactor));
return true;
}
}
/**
* 이미지를 스크린 사이즈에 맞게 맞추고 중앙 정렬
*/
private void imageScaleSetup() {
float[] value = new float[9];
this.mMatrix.getValues(value);
// 뷰 사이즈
int screenWidth = this.getWidth();
int screenHeight = this.getHeight();
// 이미지 사이즈
int imageWidth = mBitmapLayout.getWidth();
int imageHeight = mBitmapLayout.getHeight();
int scaleWidth = (int) (imageWidth * value[0]);
int scaleHeight = (int) (imageHeight * value[4]);
// 이미지가 밖으로 벗어나지 못하게 함.
value[2] = 0;
value[5] = 0;
// 이미지를 스크린 사이즈에 맞게 사이즈 조절
int target = WIDTH;
if (imageWidth < imageHeight) {
target = HEIGHT;
}
if (target == WIDTH) {
value[0] = value[4] = (float) screenWidth / imageWidth;
}
if (target == HEIGHT) {
value[0] = value[4] = (float) screenHeight / imageHeight;
}
scaleWidth = (int) (imageWidth * value[0]);
scaleHeight = (int) (imageHeight * value[4]);
if (scaleWidth > screenWidth) {
value[0] = value[4] = (float) screenWidth / imageWidth;
}
if (scaleHeight > screenHeight) {
value[0] = value[4] = (float) screenHeight / imageHeight;
}
// 가운데 위치하도록
scaleWidth = (int) (imageWidth * value[0]);
scaleHeight = (int) (imageHeight * value[4]);
if (scaleWidth < screenWidth) {
value[2] = (float) screenWidth / 2 - (float) scaleWidth / 2;
}
if (scaleHeight < screenHeight) {
value[5] = (float) screenHeight / 2 - (float) scaleHeight / 2;
}
mMatrix.setValues(value);
}
}
[activity_preview.xml]
<!-- 이미지 레이어-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/top_layer"
android:layout_marginBottom="92dp">
<kr.kfcc.insurance.CustomUI.ZoomInOutImageView
android:id="@+id/iv_canvas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:layout_gravity="center" />
</FrameLayout>
[PreviewActivity.java]
public class PreviewActivity extends AppCompatActivity implements View.OnClickListener {
private ZoomInOutImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preview);
mImageView = (ZoomInOutImageView) findViewById(R.id.iv_canvas);
Bitmap curImageBitmap = ImageBucket.getInstance().getImage(imageSize - 1);
// 이미지 표시
if (curImageBitmap != null) {
try {
mImageView.post(new Runnable() {
@Override
public void run() {
mImageView.showImage(curImageBitmap, 3.0f);
}
});
} catch (IllegalArgumentException e) {
Log.e("Exception", e.getMessage());
}
}
}
}
'Android(Java)' 카테고리의 다른 글
[Java] 앱에서 설치된 앱 삭제하기 (1) | 2024.07.23 |
---|---|
[Java] 설치된 앱 패키지 명으로 이름/아이콘 가져오기 (0) | 2024.07.23 |
[Java] App Link / Deep Link Sceme 데이터 처리 (0) | 2024.06.18 |
[Java] SMS 인증번호 자동 등록하기 (1) | 2024.06.13 |
[Java] Permission 설정 및 거부시 처리 (0) | 2024.04.22 |