A 폰에서 특정 영역에 대해 zoom in/out 을 한 부분을 B 폰에서 특정 영역 zoom in/out 한 부분을 보여주고자 할 때 넘길 좌표값 구하기
이것때문에 개고생을 했지만..
그래도 할 만 했다.
기존 소스 편집한 거라 안 맞는 부분 있을 수 있음.
ZoomLayout.java
public class ZoomLayout extends View {
private static final String TAG = "zoom";
private Context mContext;
private OnTouchResultListener mListener;
private ZoomLayoutTouchListener mZoomLayoutTouchListener;
private ScaleGestureDetector mScaleDetector;
private ScaleListener mScaleListener;
private FrameLayout mParent;
// 사각형 영역의 스케일 값을 보관한다
private float mZoomScale = 1.0f;
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 5.0f;
private boolean mIsScaling = false;
private boolean mIsUp = false;
// 라인 속성
private Paint mPaint;
// FRAME LAYOUT 의 사이즈를 저장
private RectF mFrameRect = null;
// 화면에 그려지는 사각형
private RectF mDrawRect = new RectF();
// 사각형의 중심 좌표값을 갖는다(0~1)
private PointF mZoomCenter = new PointF(0.5f, 0.5f);
public ZoomLayout(Context context, FrameLayout parent, OnTouchResultListener listener) {
super(context);
this.mContext = context;
this.mParent = parent;
this.mListener = listener;
// 프레임 RECT
mFrameRect = new RectF(0, 0, parent.getWidth(), parent.getHeight());
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setStrokeWidth(10);
mPaint.setStyle(Paint.Style.STROKE);
mZoomLayoutTouchListener = new ZoomLayoutTouchListener();
mParent.setOnTouchListener(mZoomLayoutTouchListener);
mScaleListener = new ScaleListener();
mScaleDetector = new ScaleGestureDetector(mContext, mScaleListener);
// 최초 사각형 영역 계산한기
RecalculateLocScl();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 변경된 프레임의 사이즈를 저장
mFrameRect = new RectF(0, 0, w, h);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mDrawRect, mPaint);
}
// X, Y, Scale 값을 다시 계산함
private void RecalculateLocScl()
{
// 사각형의 가로, 세로 사이즈
float xWidth = mFrameRect.width() * 1.0f / mZoomScale;
float xHeight = mFrameRect.height() * 1.0f / mZoomScale;
float LTx = (mZoomCenter.x * mFrameRect.width()) - xWidth/2;
float LTy = (mZoomCenter.y * mFrameRect.height()) - xHeight/2;
float RBx = LTx + xWidth;
float RBy = LTy + xHeight;
mDrawRect.set(LTx, LTy, RBx, RBy);
mListener.onResult(mZoomCenter.x, mZoomCenter.y, mZoomScale);
// 화면 다시 그리기
invalidate();
}
private void setLocation(float x, float y)
{
float tmpX = x;
float tmpY = y;
// 터치 영역이 FrameLayout 밖을 넘지 않도록 함.
if(tmpX < 0)
tmpX = 0;
if(tmpX > (mFrameRect.width() - 1))
tmpX = mFrameRect.width() -1;
if(tmpY < 0)
tmpY = 0;
if(tmpY > (mFrameRect.height() - 1))
tmpY = mFrameRect.height() -1;
float xWidth = (mFrameRect.width() * 1.0f / mZoomScale);
float xHeight = (mFrameRect.height() * 1.0f / mZoomScale);
// X, Y 최소/최대 범위 지정
if((tmpX - (xWidth/2)) < 0)
tmpX = (xWidth/2);
else if((tmpX + (xWidth/2)) >= mFrameRect.width())
tmpX = mFrameRect.width()-(xWidth/2);
if((tmpY - (xHeight/2)) < 0)
tmpY = (xHeight/2);
else if((tmpY + (xHeight/2)) >= mFrameRect.height())
tmpY = mFrameRect.height()-(xHeight/2);
mZoomCenter.x = tmpX / mFrameRect.width();
mZoomCenter.y = tmpY / mFrameRect.height();
RecalculateLocScl();
}
private void setScale(float scaleFactor)
{
mZoomScale /= scaleFactor;
// mZoomScale *= scaleFactor; // 반대로 그리기
if(mZoomScale <= MIN_ZOOM) mZoomScale = MIN_ZOOM;
if(mZoomScale >= MAX_ZOOM) mZoomScale = MAX_ZOOM;
RecalculateLocScl();
}
public interface OnTouchResultListener {
void onResult(float zoomX, float zoomY, float scale);
}
}
ScaleListener.java
public class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mIsScaling = true;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scaleFactor = detector.getScaleFactor();
setScale(scaleFactor);
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
mIsScaling = false;
}
}
ZoomLayoutTouchListener.java
public class ZoomLayoutTouchListener implements OnTouchListener {
float _begin_x, _begin_y;
float _move_x, _move_y;
public boolean isDrag(float x, float y)
{
float xmove = 0.0f;
if(x > _begin_x)
xmove = x - _begin_x;
else
xmove = _begin_x - x;
float ymove = 0.0f;
if(y > _begin_y)
ymove = y - _begin_y;
else
ymove = _begin_y - y;
double movexy = Math.sqrt(Math.pow(xmove, 2) + Math.pow(ymove, 2));
if(movexy > 10)
return true;
return false;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mIsUp = false;
if(mIsScaling == false) {
_begin_x = event.getX();
_begin_y = event.getY();
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mIsUp = false;
break;
case MotionEvent.ACTION_MOVE:
if(mIsScaling == false && isDrag(event.getX(), event.getY())
== true && mIsUp == false) {
setLocation(event.getX(), event.getY());
_move_x = event.getX();
_move_y = event.getY();
}
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
mIsUp = true;
break;
}
mScaleDetector.onTouchEvent(event);
return true;
}
}
'Study > Android' 카테고리의 다른 글
[공유] 안드로이드에서의 시간과 날짜 - 1 (0) | 2019.08.21 |
---|---|
[Android] Gradle Version 올렸을 때, ExoPlayer Sync 오류나는 현상 (0) | 2019.06.14 |
[Android] Too many open file 에러 해결 (0) | 2019.06.14 |
[Android] ExoPlayer V2 (0) | 2019.06.14 |
[Android] Scale Animation (0) | 2019.06.14 |