I'm able to rotate image view on ACTION_DOWN.
but its not working for ACTION_MOVE & ACTION_UP.
public class RotateImage extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Rotate rotate;
rotate = new Rotate(this);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(rotate);
}
}
public class Rotate extends ImageView {
Paint paint;
int direction = 0;
private float x;
private float y;
int degree = 0;
float a, b, c;
private float centerX ;
private float centerY ;
private float newX ;
private float newY ;
public Rotate(Context context) {
super(context);
// TODO Auto-generated constructor stub
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(2);
paint.setStyle(Style.STROKE);
this.setImageResource(R.drawable.direction1);
}
#Override
protected void onDraw(Canvas canvas) {
int height = this.getHeight();
int width = this.getWidth();
centerX = width/2;
centerY = height/2;
canvas.rotate(direction, width / 2, height / 2);
super.onDraw(canvas);
}
public void setDirection(int direction) {
this.direction = direction;
this.invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("now i'm in BEFORE calling MotionEvent.ACTION_MOVE ");
if (event.getAction() == MotionEvent.ACTION_DOWN) {
x = event.getX();
y = event.getY();
newX = centerX-x;
newY = centerY-y;
updateRotation( newX, newY);
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
x = event.getX();
y = event.getY();
newX = centerX-x;
newY = centerY-y;
updateRotation( newX, newY);
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
x = event.getX();
y = event.getY();
newX = centerX-x;
newY = centerY-y;
updateRotation( newX, newY);
}
return super.onTouchEvent(event);
}
private void updateRotation(float newX2, float newY2) {
// TODO Auto-generated method stub
degree = (int)Math.toDegrees(Math.atan2(newY, newX))-90;
setDirection(degree);
}
}
any suggestion would be appropriated
Return true instead of super.onTouchEvent(event) in your onTouchEvent method. This will inform the OS that you are handling the touch event allowing it to provide you with further touch events (e.g. MotionEvent.ACTION_MOVE).
Related
I'm having trouble figuring out how to get a dynamic collection of custom views to display as movable rectangles inside a canvas. The canvas is a bar with bar stools and I want the restaurant manager to be able to create the layout of his/her bar that other pages can utilize.
I have it working, but not well and the individual "BarSpots" won't move and the onTouchEvent of the ViewBarSpot isn't firing - however - the onTouchEvent of the ViewBarCanvas IS firing. What am I missing??
ActivityBarLayout:
private FrameLayout flCanvas;
List<BarSpot> dbBarSpots;
...
private void LoadBar(List<BarSpot> barSpots) {
try{
flCanvas.removeAllViews();
View viewBarCanvas = new ViewBarCanvas(getApplicationContext(), barSpots);
flCanvas.addView(viewBarCanvas);
}
catch(Exception e){
LogUtil.log(e.getMessage());
}
}
ViewBarCanvas:
Context mContext;
public List<ViewBarSpot> mBoxs;
public List<BarSpot> mBarSpots;
public ViewBarCanvas(Context context, List<BarSpot> barSpots) {
super(context);
mContext = context;
mBarSpots = barSpots;
mBoxs = new ArrayList<>();
for (BarSpot barSpot : barSpots) {
mBoxs.add(new ViewBarSpot(context, barSpot));
}
init(null);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (ViewBarSpot viewBarSpot : mBoxs) {
canvas.drawRect(viewBarSpot.mRectangle, viewBarSpot.mPaintBackground);
canvas.drawRect(viewBarSpot.mRectangle, viewBarSpot.mStrokePaint);
canvas.drawText(viewBarSpot.mText, viewBarSpot.mStart, viewBarSpot.mStart + viewBarSpot.mNumberOfCharacters, viewBarSpot.mRectangle.exactCenterX(), viewBarSpot.mRectangle.exactCenterY(), viewBarSpot.mPaintText);
}
}
ViewBarSpot:
public float mPosX;
public float mPosY;
public float mLastTouchX;
public float mLastTouchY;
#Override
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
switch (event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN: {
// Remember where we started
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
// Move the object
if (mRectangle.left < x && mRectangle.right > x && mRectangle.top < y && mRectangle.bottom > y) {
mPosX += dx;
mPosY += dy;
// Invalidate to request a redraw
postInvalidate();
}
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP:
/*realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
mBarSpot.setPositionLeft((int)mPosX - SQUARE_SIZE/2);
mBarSpot.setPositionRight((int)mPosX + SQUARE_SIZE/2);
mBarSpot.setPositionTop((int)mPosY - SQUARE_SIZE/2);
mBarSpot.setPositionBottom((int)mPosY + SQUARE_SIZE/2);
}
});*/
}
postInvalidate();
return true;
}
public ViewBarSpot(Context context, BarSpot barSpot) {
super(context);
mContext = context;
mBarSpot = barSpot;
mText = barSpot.getDescription();
mRectangle = new Rect(mBarSpot.getPositionLeft(), mBarSpot.getPositionTop(), mBarSpot.getPositionLeft() + SQUARE_SIZE, mBarSpot.getPositionTop()+ SQUARE_SIZE);
mPaintBackground = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintBackground.setColor(mContext.getResources().getColor(R.color.themeColor1));
mPaintBackground.setStyle(Paint.Style.FILL);
mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mStrokePaint.setStyle(Paint.Style.STROKE);
mStrokePaint.setColor(mContext.getResources().getColor(R.color.themeColor3));
mStrokePaint.setStrokeWidth(2);
mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintText.setColor(mContext.getResources().getColor(R.color.themeColor3));
mPaintText.setTextSize(TEXT_SIZE);
mPaintText.setTextAlign(Paint.Align.CENTER);
mNumberOfCharacters = mPaintText.breakText(mText,true, SQUARE_SIZE,null);
mStart = (mText.length()- mNumberOfCharacters)/2;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
I am currently in need of making ChatHeads like Facebook. Following the tutorials I found, I can make a ChatHead start from Service. However, when I added Rebound API from Facebook to make it smooth, I created a customized view like this post: Adding natural dragging effect to ImageView same as Facebook Messanger chat heads using Rebound library ;
but it seems to block every background touch. I can only drag the ChatHead around without able to touch anything else. How can I make a ChatHead that is still smooth draggable and also can interact with the background also (just the same as Facebook)? Any help is appreciated.
Thanks in advanced
BTW, this is my view
class ChatHeadView extends View implements SpringListener, SpringSystemListener {
private Spring xSpring;
private Spring ySpring;
private SpringSystem springSystem;
private final SpringConfig COASTING;
private float x;
private float y;
private boolean dragging;
private float radius = 100;
private float downX;
private float downY;
private float lastX;
private float lastY;
private VelocityTracker velocityTracker;
private float centerX;
private float centerY;
int screenWidth, screenHeight;
private Paint mPaint = new Paint();
private Bitmap mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
public ChatHeadView(Context context, int width, int height) {
super(context);
springSystem = SpringSystem.create();
springSystem.addListener(this);
COASTING = SpringConfig.fromOrigamiTensionAndFriction(0, 0.5);
COASTING.tension = 0;
xSpring = springSystem.createSpring();
ySpring = springSystem.createSpring();
xSpring.addListener(this);
ySpring.addListener(this);
getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
centerX = getWidth() / 2f;
centerY = getHeight() / 2f;
xSpring.setCurrentValue(centerX).setAtRest();
ySpring.setCurrentValue(centerY).setAtRest();
getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
}
});
screenWidth = width;
screenHeight = height;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, x - mBitmap.getWidth() / 2,
y - mBitmap.getHeight(), mPaint);
}
#SuppressLint("Recycle")
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getRawX();
float touchY = event.getRawY();
boolean ret = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = touchX;
downY = touchY;
lastX = downX;
lastY = downY;
velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
if (downX > x - radius && downX < x + radius && downY > y - radius
&& downY < y + radius) {
dragging = true;
ret = true;
}
break;
case MotionEvent.ACTION_MOVE:
if (!dragging) {
break;
}
velocityTracker.addMovement(event);
float offsetX = lastX - touchX;
float offsetY = lastY - touchY;
xSpring.setCurrentValue(xSpring.getCurrentValue() - offsetX)
.setAtRest();
ySpring.setCurrentValue(ySpring.getCurrentValue() - offsetY)
.setAtRest();
checkConstraints();
ret = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (!dragging) {
break;
}
velocityTracker.addMovement(event);
velocityTracker.computeCurrentVelocity(1000);
dragging = false;
ySpring.setSpringConfig(COASTING);
xSpring.setSpringConfig(COASTING);
downX = 0;
downY = 0;
xSpring.setVelocity(velocityTracker.getXVelocity());
ySpring.setVelocity(velocityTracker.getYVelocity());
ret = true;
}
lastX = touchX;
lastY = touchY;
return ret;
}
#Override
public void onSpringUpdate(Spring s) {
x = (float) xSpring.getCurrentValue();
y = (float) ySpring.getCurrentValue();
invalidate();
}
#Override
public void onSpringActivate(Spring s) {
}
#Override
public void onSpringAtRest(Spring s) {
}
#Override
public void onSpringEndStateChange(Spring s) {
}
#Override
public void onBeforeIntegrate(BaseSpringSystem springSystem) {
}
#Override
public void onAfterIntegrate(BaseSpringSystem springSystem) {
checkConstraints();
}
private void checkConstraints() {
if (x + radius >= screenWidth) {
xSpring.setVelocity(-xSpring.getVelocity());
xSpring.setCurrentValue(xSpring.getCurrentValue()
- (x + radius - screenWidth), false);
}
if (x - radius <= 0) {
xSpring.setVelocity(-xSpring.getVelocity());
xSpring.setCurrentValue(xSpring.getCurrentValue() - (x - radius),
false);
}
if (y + radius >= screenHeight) {
ySpring.setVelocity(-ySpring.getVelocity());
ySpring.setCurrentValue(ySpring.getCurrentValue()
- (y + radius - screenHeight), false);
}
if (y - radius <= 0) {
ySpring.setVelocity(-ySpring.getVelocity());
ySpring.setCurrentValue(ySpring.getCurrentValue() - (y - radius),
false);
}
}
}
this is where I add View with WindowManager:
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
chatHeadView = new ChatHeadView(this, screenWidth, screenHeight);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT);
windowManager.addView(chatHeadView, params);
In the documentation WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
Window flag: even when this window is focusable (its FLAG_NOT_FOCUSABLE is not set), allow any pointer events outside of the window to be sent to the windows behind it. Otherwise it will consume all pointer events itself, regardless of whether they are inside of the window.
It's saying about your problem.
Instead, try WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE flag.
you can get TouchEvent on the view and it won't consume other events.
I try to make a activity and a View on the screen, cause the activity have the buttons which I need. My question is how can I do it, that when I start the app I see the buttons from the activity and the ball and the box from the view class??
How should I take the view in the layout?
that is the activity:
public class GameView extends Activity implements OnClickListener {
private Button bPAUSE;
private TextView tvTries;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameview);
initialize();
}
public void onClick(View v) {
}
public void initialize(){
bPAUSE = (Button) findViewById(R.id.button1);
bPAUSE.setOnClickListener(this);
tvTries = (TextView) findViewById(R.id.textView1);
}
}
that the View class:
public class BouncingBallView extends View {
private Ball ball;
private Box box;
// For touch inputs - previous touch (x, y)
private float previousX;
private float previousY;
// Constructor
public BouncingBallView(Context context) {
super(context);
box = new Box(0xff00003f); // ARGB
ball = new Ball(Color.GREEN);
// To enable keypad
this.setFocusable(true);
this.requestFocus();
// To enable touch mode
this.setFocusableInTouchMode(true);
}
// Called back to draw the view. Also called after invalidate().
#Override
protected void onDraw(Canvas canvas) {
// Draw the components
box.draw(canvas);
ball.draw(canvas);
// Update the position of the ball, including collision detection and reaction.
ball.moveWithCollisionDetection(box);
// Delay
try {
Thread.sleep(30);
} catch (InterruptedException e) { }
invalidate(); // Force a re-draw
}
// Called back when the view is first created or its size changes.
#Override
public void onSizeChanged(int w, int h, int oldW, int oldH) {
// Set the movement bounds for the ball
box.set(0, 0, w, h);
}
int touchCounter = 2;
#Override
public boolean onTouchEvent(MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
float deltaX, deltaY;
float scalingFactor = 1.0f / ((box.xMax > box.yMax) ? box.yMax : box.xMax);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchCounter = 2;
if (currentX >= previousX) {
deltaX = currentX - previousX;
ball.speedX += deltaX * scalingFactor;
} else if (previousX >= currentX) {
deltaX = previousX - currentX;
ball.speedX += deltaX * scalingFactor;
} if (currentY >= previousY) {
deltaY = currentY - previousY;
ball.speedX += deltaY * scalingFactor;
} else if (previousY >= currentY) {
deltaY = previousY - currentY;
ball.speedY += deltaY * scalingFactor;
}
//vorherig(previous) - aktuell
break;
case MotionEvent.ACTION_UP:
touchCounter = 1;
// Modify rotational angles according to movement
break;
}
// Save current x, y
previousX = currentX;
previousY = currentY;
return true; // Event handled
}
}
I actually tries to do this in the activity class but the layout is missing...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View BouncingBallView= new BouncingBallView(this);
setContentView(BouncingBallView);
initialize();
}
I'm trying to make a simple app, with an imageview that can be zoomed in and out with buttons, and when zoomed, user could move around it with his fingers.
I've been reading the whole day, here and there, found different solutions. But I can't seem to make my picture move. Thing is, I want to keep the program like it is now, but just maybe change the imageview OnTouchEvent.
I'm adding my code:
public class LoadMap extends Activity {
ZoomControls zoom;
ImageView img;
ImageButton linkButton;
float startX, startY;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_map);
zoom = (ZoomControls) findViewById(R.id.zoomControls1);
img = (ImageView) findViewById(R.id.imageView1);
linkButton = (ImageButton) findViewById(R.id.infopoint);
startX = img.getScaleX();
startY = img.getScaleY();
img.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == MotionEvent.ACTION_MOVE) {
RelativeLayout.LayoutParams mParams = (RelativeLayout.LayoutParams) img.getLayoutParams();
int x = (int) event.getRawX();
int y = (int) event.getRawY();
mParams.leftMargin = x;
mParams.topMargin = y;
img.setLayoutParams(mParams);
}
return false;
}
});
linkButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Uri uri = Uri.parse("just some site");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
zoom.setOnZoomInClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
float x = img.getScaleX();
float y = img.getScaleY();
img.setScaleX((float) (x+1));
img.setScaleY((float) (y+1));
}
});
zoom.setOnZoomOutClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
float x = img.getScaleX();
float y = img.getScaleY();
if((x>startX) & (y>startY)) {
img.setScaleX((float) (x-1));
img.setScaleY((float) (y-1));
}
}
});
}
Is there a way to just change some things inside this method without messing my app too much and is this even possible the way I'm trying to make it work or my program logic is wrong.
img.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == MotionEvent.ACTION_MOVE) {
RelativeLayout.LayoutParams mParams = (RelativeLayout.LayoutParams) img.getLayoutParams();
int x = (int) event.getRawX();
int y = (int) event.getRawY();
mParams.leftMargin = x;
mParams.topMargin = y;
img.setLayoutParams(mParams);
}
return false;
}
});
Sorry, if it has been asked before, but i searched alot and couldn't find anything specific for my 'problem'.
Thanks alot to whoever spends some time on my problem :).
try this code,
put this code on image setOnTouchListener,
img.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
LayoutParams layoutParams = (LayoutParams) img
.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
int x_cord = (int) event.getRawX();
int y_cord = (int) event.getRawY();
if (x_cord > windowwidth) {
x_cord = windowwidth;
}
if (y_cord > windowheight) {
y_cord = windowheight;
}
layoutParams.leftMargin = x_cord - 25;
layoutParams.topMargin = y_cord - 75;
img.setLayoutParams(layoutParams);
break;
default:
break;
}
return true;
}
});
I hope it will solve your problem..
Try using a custom ImageVIew
public class ZoomableImageView extends ImageView implements OnTouchListener {
private Context mContext;
final private float MAX_SCALE = 2f;
private Matrix mMatrix;
private final float[] mMatrixValues = new float[9];
// display width height.
private int mWidth;
private int mHeight;
private int mIntrinsicWidth;
private int mIntrinsicHeight;
private float mScale;
private float mMinScale;
private float mPrevDistance;
private boolean isScaling;
private int mPrevMoveX;
private int mPrevMoveY;
private GestureDetector mDetector;
final String TAG = "ScaleImageView";
public ZoomableImageView(Context context, AttributeSet attr) {
super(context, attr);
this.mContext = context;
initialize();
}
public ZoomableImageView(Context context) {
super(context);
this.mContext = context;
initialize();
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
this.initialize();
}
#Override
public void setImageResource(int resId) {
super.setImageResource(resId);
this.initialize();
}
private void initialize() {
this.setScaleType(ScaleType.MATRIX);
this.mMatrix = new Matrix();
Drawable d = getDrawable();
if (d != null) {
mIntrinsicWidth = d.getIntrinsicWidth();
mIntrinsicHeight = d.getIntrinsicHeight();
setOnTouchListener(this);
}
mDetector = new GestureDetector(mContext,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDoubleTap(MotionEvent e) {
maxZoomTo((int) e.getX(), (int) e.getY());
cutting();
return super.onDoubleTap(e);
}
});
}
#Override
protected boolean setFrame(int l, int t, int r, int b) {
mWidth = r - l;
mHeight = b - t;
mMatrix.reset();
int rNorm = r - l;
mScale = (float) rNorm / (float) mIntrinsicWidth;
int paddingHeight = 0;
int paddingWidth = 0;
// scaling vertical
if (mScale * mIntrinsicHeight > mHeight) {
mScale = (float) mHeight / (float) mIntrinsicHeight;
mMatrix.postScale(mScale, mScale);
paddingWidth = (r - mWidth) / 2;
paddingHeight = 0;
// scaling horizontal
} else {
mMatrix.postScale(mScale, mScale);
paddingHeight = (b - mHeight) / 2;
paddingWidth = 0;
}
mMatrix.postTranslate(paddingWidth, paddingHeight);
setImageMatrix(mMatrix);
mMinScale = mScale;
zoomTo(mScale, mWidth / 2, mHeight / 2);
cutting();
return super.setFrame(l, t, r, b);
}
protected float getValue(Matrix matrix, int whichValue) {
matrix.getValues(mMatrixValues);
return mMatrixValues[whichValue];
}
protected float getScale() {
return getValue(mMatrix, Matrix.MSCALE_X);
}
public float getTranslateX() {
return getValue(mMatrix, Matrix.MTRANS_X);
}
protected float getTranslateY() {
return getValue(mMatrix, Matrix.MTRANS_Y);
}
protected void maxZoomTo(int x, int y) {
if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) {
// threshold 0.1f
float scale = mMinScale / getScale();
zoomTo(scale, x, y);
} else {
float scale = MAX_SCALE / getScale();
zoomTo(scale, x, y);
}
}
public void zoomTo(float scale, int x, int y) {
if (getScale() * scale < mMinScale) {
return;
}
if (scale >= 1 && getScale() * scale > MAX_SCALE) {
return;
}
mMatrix.postScale(scale, scale);
// move to center
mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2,
-(mHeight * scale - mHeight) / 2);
// move x and y distance
mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
setImageMatrix(mMatrix);
}
public void cutting() {
int width = (int) (mIntrinsicWidth * getScale());
int height = (int) (mIntrinsicHeight * getScale());
if (getTranslateX() < -(width - mWidth)) {
mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
}
if (getTranslateX() > 0) {
mMatrix.postTranslate(-getTranslateX(), 0);
}
if (getTranslateY() < -(height - mHeight)) {
mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));
}
if (getTranslateY() > 0) {
mMatrix.postTranslate(0, -getTranslateY());
}
if (width < mWidth) {
mMatrix.postTranslate((mWidth - width) / 2, 0);
}
if (height < mHeight) {
mMatrix.postTranslate(0, (mHeight - height) / 2);
}
setImageMatrix(mMatrix);
}
private float distance(float x0, float x1, float y0, float y1) {
float x = x0 - x1;
float y = y0 - y1;
return FloatMath.sqrt(x * x + y * y);
}
private float dispDistance() {
return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mDetector.onTouchEvent(event)) {
return true;
}
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
if (touchCount >= 2) {
float distance = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
mPrevDistance = distance;
isScaling = true;
} else {
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
}
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaling) {
float dist = distance(event.getX(0), event.getX(1),
event.getY(0), event.getY(1));
float scale = (dist - mPrevDistance) / dispDistance();
mPrevDistance = dist;
scale += 1;
scale = scale * scale;
zoomTo(scale, mWidth / 2, mHeight / 2);
cutting();
} else if (!isScaling) {
int distanceX = mPrevMoveX - (int) event.getX();
int distanceY = mPrevMoveY - (int) event.getY();
mPrevMoveX = (int) event.getX();
mPrevMoveY = (int) event.getY();
mMatrix.postTranslate(-distanceX, -distanceY);
cutting();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
if (event.getPointerCount() <= 1) {
isScaling = false;
}
break;
}
return true;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return super.onTouchEvent(event);
}
}
Try it that way:
img.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
return true;
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
RelativeLayout.LayoutParams mParams = (RelativeLayout.LayoutParams) img.getLayoutParams();
int x = (int) event.getRawX();
int y = (int) event.getRawY();
mParams.leftMargin = x;
mParams.topMargin = y;
img.setLayoutParams(mParams);
}
return false;
}
});
You need to return true when the ACTION_DOWN event is triggered to indicate that you are interested in the subsequent calls relating to that same event.
I have a problem!I load a large image (1600x1200) and when the app starts the view is the upper left corner.
I want to show the center or something else position when it starts.
Or it will be better if i gave certain coordinates and view starts from this point.
Do you have any idea??
Thanks in advance!
You don't show us any code, so we don't know about the layout or restrictions you have, but assuming there's an ImageView over the whole screen; one way to solve this is having a ScrollView with an ImageView-child. Then you can scroll wherever you want with the ScrollView-method scrollTo(int x, int y).
Read more here: http://developer.android.com/reference/android/widget/ScrollView.html
My code is :
public Scroll(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
mGestureDetector = new GestureDetector(this);
mScale = 1;
mZoomController = new ZoomButtonsController(this);
mZoomController.setAutoDismissed(true);
mZoomController.setOnZoomListener(this);
mZoomController.setZoomSpeed(25);
mZoomController.setZoomInEnabled(mScale < MAX_ZOOM);
mZoomController.setZoomOutEnabled(mScale > MIN_ZOOM);
makeZoomLabel(context, mZoomController);
mZoomFormat = NumberFormat.getPercentInstance();
mZoomLabel.setText("Zoom: " + mZoomFormat.format(mScale));
mPicture = makeContent();
setVerticalScrollBarEnabled(true);
setHorizontalScrollBarEnabled(true);
TypedArray a = context.obtainStyledAttributes(R.styleable.Scroll);
initializeScrollbars(a);
a.recycle();
mMatrix = new Matrix();
mDst = new float[2];
}
public Scroll(Context context) {
this(context, null);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mZoomController.setVisible(false);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
if (mScroller.computeScrollOffset()) {
mX = mScroller.getCurrX();
mY = mScroller.getCurrY();
invalidate();
}
mMatrix.reset();
mMatrix.preTranslate(mX * mScale, mY * mScale);
int w = getWidth();
int h = getHeight();
float pivotX = Math.max(Math.min(-mX, w / 2), 2 * w - WIDTH - mX);
float pivotY = Math.max(Math.min(-mY, h / 2), 2 * h - HEIGHT - mY);
mMatrix.preScale(mScale, mScale, pivotX, pivotY);
canvas.concat(mMatrix);
// draw content
mPicture.draw(canvas);
canvas.restore();
}
#Override
protected int computeHorizontalScrollExtent() {
return Math.round(computeHorizontalScrollRange() * getWidth() / (WIDTH * mScale));
}
#Override
protected int computeHorizontalScrollOffset() {
mMatrix.mapPoints(mDst, SRC);
float x = -mDst[0] / mScale;
return Math.round(computeHorizontalScrollRange() * x / WIDTH);
}
#Override
protected int computeVerticalScrollExtent() {
return Math.round(computeVerticalScrollRange() * getHeight() / (HEIGHT * mScale));
}
#Override
protected int computeVerticalScrollOffset() {
mMatrix.mapPoints(mDst, SRC);
float y = -mDst[1] / mScale;
return Math.round(computeVerticalScrollRange() * y / HEIGHT);
}
public boolean onDown(MotionEvent e) {
mZoomController.setVisible(false);
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int minX = (int) (getWidth() - WIDTH);
int minY = (int) (getHeight() - HEIGHT);
mScroller.fling((int) mX, (int) mY, (int) velocityX, (int) velocityY, minX, 0, minY, 0);
invalidate();
return true;
}
public void onLongPress(MotionEvent e) {
mZoomController.setVisible(true);
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
mX -= distanceX / mScale;
mY -= distanceY / mScale;
mX = Math.max(getWidth() - WIDTH, Math.min(0, mX));
mY = Math.max(getHeight() - HEIGHT, Math.min(0, mY));
invalidate();
return true;
}
public void onShowPress(MotionEvent e) {
}
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public void onVisibilityChanged(boolean visible) {
}
public void onZoom(boolean zoomIn) {
mScale += zoomIn? 0.1 : -0.1;
mScale = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, mScale));
mZoomLabel.setText("Zoom: " + mZoomFormat.format(mScale));
invalidate();
mZoomController.setZoomInEnabled(mScale != MAX_ZOOM);
mZoomController.setZoomOutEnabled(mScale != MIN_ZOOM);
}
private void makeZoomLabel(Context context, ZoomButtonsController zoomController) {
ViewGroup container = zoomController.getContainer();
View controls = zoomController.getZoomControls();
LayoutParams p0 = controls.getLayoutParams();
container.removeView(controls);
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
mZoomLabel = new TextView(context);
mZoomLabel.setPadding(12, 0, 12, 0);
mZoomLabel.setTypeface(Typeface.DEFAULT_BOLD);
mZoomLabel.setTextColor(0xff000000);
PaintDrawable d = new PaintDrawable(0xeeffffff);
d.setCornerRadius(6);
mZoomLabel.setBackgroundDrawable(d);
mZoomLabel.setTextSize(20);
mZoomLabel.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams p1 = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
p1.gravity = Gravity.CENTER_HORIZONTAL;
layout.addView(mZoomLabel, p1);
layout.addView(controls);
container.addView(layout, p0);
}
private Picture makeContent() {
Picture picture = new Picture();
Canvas c = picture.beginRecording(WIDTH, HEIGHT);
//draw something
picture.endRecording();
return picture;
}
}