package de.luhmer.owncloudnewsreader.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.RelativeLayout;
import org.greenrobot.eventbus.EventBus;
import de.luhmer.owncloudnewsreader.events.podcast.VideoDoubleClicked;
//http://stackoverflow.com/questions/10013906/android-zoom-in-out-relativelayout-with-spread-pinch
public class ZoomableRelativeLayout extends RelativeLayout {
private static final int INVALID_POINTER_ID = -1;
private static final int INVALID_SIZE = -1;
public boolean disableScale = false;
public void setDisableScale(boolean disableScale) {
this.disableScale = disableScale;
}
private static final String TAG = "ZoomableRelativeLayout";
private GestureDetector mDoubleTapDetector;
private ScaleGestureDetector mScaleDetector;
float mScaleFactor = 1;
public float getScaleFactor() {
return mScaleFactor;
}
float mPosX;
float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId;
private float mInitHeight = INVALID_SIZE;
private float mInitWidth = INVALID_SIZE;
public ZoomableRelativeLayout(Context context) {
super(context);
initZoomView(context);
}
public ZoomableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initZoomView(context);
}
public ZoomableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initZoomView(context);
}
boolean mPositionReady = false;
public boolean isPositionReady() {
return mPositionReady;
}
/*
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if(hasWindowFocus) {
readVideoPosition();
mPositionReady = true;
}
super.onWindowFocusChanged(hasWindowFocus);
}
*/
public void readVideoPosition() {
int position[] = new int[2];
getLocationOnScreen(position);
mVideoXPosition = position[0];
mVideoYPosition = position[1];
mPositionReady = true;
Log.d(TAG, "Grabbing new Video Wrapper Position. X:" + mVideoXPosition + " - Y:" + mVideoYPosition);
//mVideoXPosition = getX();
//mVideoYPosition = getY();
}
private void initZoomView(Context context) {
// Create our ScaleGestureDetector
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
}
/*
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScaleFactor, mScaleFactor, mPosX, mPosY);
super.dispatchDraw(canvas);
canvas.restore();
}*/
private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
// event when double tap occurs
@Override
public boolean onDoubleTap(MotionEvent e) {
float x = e.getX();
float y = e.getY();
Log.d("Double Tap", "Tapped at: (" + x + "," + y + ")");
EventBus.getDefault().post(new VideoDoubleClicked());
return true;
}
}
private float mVideoXPosition;
private float mVideoYPosition;
public float getVideoXPosition() {return mVideoXPosition;}
public float getVideoYPosition() {return mVideoYPosition;}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
if(!disableScale) {
readVideoPosition();
}
super.onScaleEnd(detector);
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
if(disableScale)
return true;
if(mInitWidth == INVALID_SIZE) {
mInitWidth = getWidth();
mInitHeight = getHeight();
}
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
if(mScaleFactor < 1)
mScaleFactor = 1;
Log.d(TAG, "Scale:" + mScaleFactor);
getLayoutParams().width = (int)(mInitWidth * mScaleFactor);
getLayoutParams().height = (int)(mInitHeight * mScaleFactor);
setLayoutParams(getLayoutParams());
//invalidate();
return true;
}
}
/*
public void restore() {
mScaleFactor = 1;
this.invalidate();
}*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
mDoubleTapDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.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;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
}