How do I program a Scrollable SurfaceView in Android Java? - java

I am trying to draw an image that is larger than the screen, and let the user scroll around it. The image is some graphs that are calculated by my code from some data. (This is in Android using Java).
What I want is a View (actually a SurfaceView) that can be scrolled by the user. I have tried putting a SurfaceView inside a ScrollView but the whole image drawn by the SurfaceView is very large and so (a) there are performance issues as my app is drawing the whole SurfaceView when it should only need to do the part that is in the viewport and (b) my app crashes with "dimensions too large... out of memory" errors.
It would be best for me if the View could implement scrolling (vertical only) and then pass the y-value to my code so it could draw the visible part of my image in the viewport.
Alternatively I could capture the 'mouse' events and calculate the y-value myself.
Does anyone have any code so that I can do this?
Update: I should clarify, the image is drawn by my program code using Canvas.drawLine() and the like. I can calculate which parts of the image fit within my viewport, provided I have the state of the scroll as a y-value, and I can calculate the absolute y-coordinate of each point by subtracting scroll y-value. What I need is something that works to find when the user scrolls the image and what the resulting y-value is. A scrollbar would also be nice.
Update: I am using SurfaceView so that I can update the image from another Thread and so improve user interface performance.

if you really have just a draw content... you don't need a scrollable client then...
have a model (x,y,lines, etc)
have a pan & zoom
draw a scaled/zoomed instance of the model
just draw the content (sorry - no scroller in this solution)
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean isProcessed = scaleGestureDetector.onTouchEvent(event);
if (isProcessed) {
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
start.set(event.getX(), event.getY());
tap( event.getX(), event.getY() );
mode = DRAG_OR_TAP;
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG_OR_TAP) {
doPan(event.getX() - start.x, event.getY() - start.y);
start.set(event.getX(), event.getY());
}
break;
}
}
myView.scale(currentPan, currentScaleFactor);
invalidate();
return true;
}
private void doPan(float panX, float panY) {
currentPan.x = currentPan.x + panX;
currentPan.y = currentPan.y + panY;
}
private void tap(float x, float y) {
...
}
and last not least use the scaleListener
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
float value = detector.getScaleFactor();
currentScaleFactor = currentScaleFactor * value;
// don't let the object get too small or too large.
boolean doesntMatch = false;
if (currentScaleFactor < 1f || currentScaleFactor > 20f){
currentScaleFactor = Math.max(1f, Math.min(currentScaleFactor, 20f));
doesntMatch = true;
}
if(!doesntMatch){
//scale the viewport as well
currentPan.x = currentPan.x*value;
currentPan.y = currentPan.y*value;
}
return true;
}
}

you can simply use a WebView to display an image
provides pan
provides zoom
no library required
has a scrollbar
Android: Easiest way to make a WebView display a Bitmap?
i'm not sure if i really hit your question...

Related

Panning, Flinging, Zooming, and Correct Borders in a Custom Layout

Hello! Thank you for reading.
I've been looking for ways to correctly create a multi-direction scrollable Android layout of a certain size (5x that of the user's screen), that can be flinged (& panned) and that can also be zoomed on.
To note that having the child (ConstraintLayout) be the wanted size (5x the user's screen) is not the problem here.
Obviously, I found many answers online for ways to do this with different ways to integrate it. Originally, I was about to post all the different integration I had unsuccessfully tried so far, until I encountered Oded's solution. In this one, everything that didn't work correctly worked.
This means:
The layout allowed scrolling the entire width and height of the child but no more
The bounds/borders of the scrollable area scaled correctly with the Zooming (this was the deal-breaker, almost no custom layout could do this)
The layout could be panned
The pivot point was correct (in the middle).
This was a huge relief, as modifying different already-made but lacking integrations (to fix bounds+zooming issues mostly) had already taken days.
I would recommend anyone having a similar issue in the future to use this integration.
In any case, there are a few issues, including: goes back to (0,0) upon screen orientation changes, no double-tap-to-zoom, and no flinging. I don't believe it to be hard to fix those two first issues, however this third one is quite problematic. I want the user to be able to freely view this large area. Not having the ability to fling will make moving in the app slower than preferable.
I've already tried different ways to do this, such as using the Scroller class with a GestureDetector, using a "Flinger" runnable class (containing a Scroller), using some form of the Choreographer, and others.
I've been unable to get it to work, and solutions often completely break the way this layout is doing scrolling (for instance, I've noticed scrollX never changes, and no scrollTo function is present (it is replaced by mPosX)). Usually correct solutions to the addition of Flinging seem impossible to use here, and in some cases, implementations have caused the scroller to go several thousand units from where it should be.
Here is my backup copy of Odid's solution, with the only changes being minor adjustments to avoid Android Studio warnings.
Snippet (mandatory):
#Override
public boolean onTouchEvent(MotionEvent ev) {
mOnTouchEventWorkingArray[0] = ev.getX();
mOnTouchEventWorkingArray[1] = ev.getY();
mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray);
ev.setLocation(mOnTouchEventWorkingArray[0], mOnTouchEventWorkingArray[1]);
mScaleDetector.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;
// Save the ID of this pointer
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
if (mIsScaling && ev.getPointerCount() == 1) {
// Don't move during a QuickScale.
mLastTouchX = x;
mLastTouchY = y;
break;
}
float dx = x - mLastTouchX;
float dy = y - mLastTouchY;
float[] topLeft = {0f, 0f};
float[] bottomRight = {getWidth(), getHeight()};
/*
* Corners of the view in screen coordinates, so dx/dy should not be allowed to
* push these beyond the canvas bounds.
*/
float[] scaledTopLeft = screenPointsToScaledPoints(topLeft);
float[] scaledBottomRight = screenPointsToScaledPoints(bottomRight);
dx = Math.min(Math.max(dx, scaledBottomRight[0] - mCanvasWidth), scaledTopLeft[0]);
dy = Math.min(Math.max(dy, scaledBottomRight[1] - mCanvasHeight), scaledTopLeft[1]);
mPosX += dx;
mPosY += dy;
mTranslateMatrix.preTranslate(dx, dy);
mTranslateMatrix.invert(mTranslateMatrixInverse);
mLastTouchX = x;
mLastTouchY = y;
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & 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;
}
Thank you very much for your help.

Bridge building algorithm in Java?

I am making a bridge building game for Android. As you know there are two coordinates for drawing a line.
Firstly, When we push "put" button and select a dot then it's the first coordinate of the line, secondly the coordinates where we keep touching on screen is always displayed as the second coordinate, lastly, where we release our finger is decided as the second coordinate of the line. And there will be more than one lines.
I'd be glad if anyone explain these to me.
You will have to override the onTouchEvent function of the respective activity:
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked();
float x = event.getX();
float y = event.getY();
if (action == MotionEvent.ACTION_DOWN) {
// save the coordinates somewhere
} else if (action == MotionEvent.ACTION_UP) {
// save the coordinates as well
} else if (action == MotionEvent.ACTION_MOVE) {
// display the coordinates
}
}
Then you simply have to use the stored coordinates to draw a line between the coordinates, e.g. within a canvas that is located on your activity.
You will find a sophisticated example here: http://www.vogella.com/tutorials/AndroidTouch/article.html

Make bitmap size and position the same on every device

I've been trying to figure out how to do it, I have the size of the screen and the size of the emulator I use, how do I change the size to fit all devices (Including tablets and phones) and also position them correctly because it seems like the X and Y on a tablet is different than one that is on the phone.
EDIT:
I tried converting pixels to DPI that way:
public CreatorView(Context c) {
super(c);
this.c=c;
WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
this.screenw= display.getWidth();
this.screenh=display.getHeight();
this.PixelDetect = BitmapFactory.decodeResource( getResources(), R.drawable.custom_pixel);
this.smallpixel = Bitmap.createScaledBitmap(PixelDetect, (int)getPixelsFromDip(3,c), (int)getPixelsFromDip(3,c), false);
this.grass=BitmapFactory.decodeResource(getResources(), R.drawable.block_grass);
this.grassSide=BitmapFactory.decodeResource(getResources(), R.drawable.block_grassside);
this.grassTop=BitmapFactory.decodeResource(getResources(), R.drawable.block_grasstop);
this.orange=BitmapFactory.decodeResource(getResources(), R.drawable.block_cube1);
this.dirt=BitmapFactory.decodeResource(getResources(), R.drawable.block_dirt);
this.dirt2=BitmapFactory.decodeResource(getResources(), R.drawable.block_dirt2);
this.dirt3=BitmapFactory.decodeResource(getResources(), R.drawable.block_dirt3);
this.arrowno=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_noclick);
this.arrown=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_normal);
this.arrowl=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_left);
this.arrowr=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_right);
this.arrowu=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_up);
this.arrowd=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_down);
this.arrowul=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_upperleft);
this.arrowur=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_upperright);
this.arrowdl=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_downleft);
this.arrowdr=BitmapFactory.decodeResource(getResources(), R.drawable.arrow_downright);
this.arrowno=Bitmap.createScaledBitmap(arrowno, arrowno.getWidth()*3, arrowno.getHeight()*3, false);
this.save=BitmapFactory.decodeResource(getResources(), R.drawable.button_save);
this.bin_Empty=BitmapFactory.decodeResource(getResources(), R.drawable.bin_empty);
this.bin_Full=BitmapFactory.decodeResource(getResources(), R.drawable.bin_full);
this.bin_Empty=Bitmap.createScaledBitmap(bin_Empty, bin_Empty.getWidth()*3, bin_Empty.getHeight()*3, false);
this.bin_Full=Bitmap.createScaledBitmap(bin_Full, bin_Full.getWidth()*3, bin_Full.getHeight()*3, false);
this.arrown=Bitmap.createScaledBitmap(arrown, arrown.getWidth()*3, arrown.getHeight()*3, false);
this.arrowl=Bitmap.createScaledBitmap(arrowl, arrowl.getWidth()*3, arrowl.getHeight()*3, false);
this.arrowr=Bitmap.createScaledBitmap(arrowr, arrowr.getWidth()*3, arrowr.getHeight()*3, false);
this.arrowu=Bitmap.createScaledBitmap(arrowu, arrowu.getWidth()*3, arrowu.getHeight()*3, false);
this.arrowd=Bitmap.createScaledBitmap(arrowd, arrowd.getWidth()*3, arrowd.getHeight()*3, false);
this.arrowul=Bitmap.createScaledBitmap(arrowul, arrowul.getWidth()*3, arrowul.getHeight()*3, false);
this.arrowur=Bitmap.createScaledBitmap(arrowur, arrowur.getWidth()*3, arrowur.getHeight()*3, false);
this.arrowdl=Bitmap.createScaledBitmap(arrowdl, arrowdl.getWidth()*3, arrowdl.getHeight()*3, false);
this.arrowdr=Bitmap.createScaledBitmap(arrowdr, arrowdr.getWidth()*3, arrowdr.getHeight()*3, false);
Menu_Add(arrowno,0,true,"arrows");
Menu_Add(bin_Empty,1,false,"bin");
Menu_Add(save,2,false,"save");
Menu_Add(grassTop,1,true,"grasstop");
Menu_Add(grassSide,2,true,"grassside");
Menu_Add(grass,3,true,"grass");
Menu_Add(dirt,4,true,"dirt");
Menu_Add(orange,5,true,"orange");
arrowsp=new Point();
arrowsp.x=0;
arrowsp.y=0;
}
private void Menu_Add(Bitmap b,int order,boolean vertical,String name)
{
Point p=new Point();
if(order==0){
p.x=0;
p.y=0;
MenuButton m=new MenuButton(order,b , vertical, p,name);
menuButtonList.add(m);
}
else{
for (MenuButton m : menuButtonList) {
if((m.isVertical()==vertical||order==1)&&m.getOrder()+1==order ){
if(vertical){
p.x=0;
p.y=m.getP().y+m.getBit().getHeight()+(int)getPixelsFromDip(2,c);
}
else{
p.x=m.getP().x+m.getBit().getWidth()+(int)(getPixelsFromDip(2,c));
p.y=0;
}
MenuButton m2=new MenuButton(order,b , vertical, p,name);
menuButtonList.add(m2);
return;
}
}
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paintAlpha = new Paint();
paintAlpha.setAlpha(200);
canvas.drawARGB(255, 86, 194, 243);
for(MenuButton m : menuButtonList){
switch(m.getName()){
case "bin":
if(bin_isEmpty){
canvas.drawBitmap(bin_Empty, getPixelsFromDip(m.getP().x,c), getPixelsFromDip(m.getP().y,c),paintAlpha);
}
else{
canvas.drawBitmap(bin_Full, getPixelsFromDip(m.getP().x,c), getPixelsFromDip(m.getP().y,c),paintAlpha);
}
break;
case "arrows":
canvas.drawBitmap(m.getBit(),getPixelsFromDip(m.getP().x,c),getPixelsFromDip(m.getP().y,c),paintAlpha);
switch (arrowcheck) {
case "normal":
canvas.drawBitmap(arrown, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "left":
canvas.drawBitmap(arrowl, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "right":
canvas.drawBitmap(arrowr, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "down":
canvas.drawBitmap(arrowd, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "up":
canvas.drawBitmap(arrowu, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "upleft":
canvas.drawBitmap(arrowul, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "upright":
canvas.drawBitmap(arrowur, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "downleft":
canvas.drawBitmap(arrowdl, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
case "downright":
canvas.drawBitmap(arrowdr, getPixelsFromDip(arrowsp.x,c), getPixelsFromDip(arrowsp.y,c),paintAlpha);
break;
}
break;
default:
canvas.drawBitmap(m.getBit(),getPixelsFromDip(m.getP().x,c),getPixelsFromDip(m.getP().y,c),paintAlpha);
break;
}
}
}
public static float getPixelsFromDip(float dip,Context context)
{
//TODO move this to aplication class?
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics());
}
this is how it shows in the emulator (correct):
http://puu.sh/ehhHp/05c1530218.png
this is how it shows in my phone:
http://puu.sh/ehhKX/b28ee357e3.png
please help :(
What you don't want to do is to use pixels. What you most probably also don't want to do is to speficy the width/height using dps unless you're prepared to set different values for your different resolution devices (by specifying the values in #dimen and overriding them for different sizes).
If you know approximately how much of the screen width (or height) you would like your ImageView to occupy, the easiest thing you can do to achieve it is to use weights within a LinearLayout.
An example would be this (handwritten and missing all the NS prefixes)
<LinearLayout
...
...
orientation=vertical>
<some empty filler here with weight=1 and width="match_parent"/>
<ImageView
...
...
width="match_parent"
scaleType=fitCenter (or whatever works for your images)
weight=1 />
<some empty filler here with weight=1 width="match_parent"/>
</LinearLayout>
What this would do is to make sure your ImageView takes 1/3rd of the screen width as determined by weights. You then control the image scaling by setting the correct scaleType. This will work universally across all phone sizes and tablets and will always take 1/3rd of the width of the screen regardless of the resolution or the orientation of the device (which may or may not be what you want).
You can also play around with the weights if you want more/less than 1/3rd of the screen width for your images.
Other solutions (using dp for instance) are already mentioned but they're a bit more involved in that you have to override them for different resolutions as described above.
Why not use percents?
As example - percent_x = device.widht / 100;
And begin draw image in this position * percent_x?
In every device if should be look similar, but with streches.
use dp to define width and height of image. Or we can calculate the percentage of image size of our screen.
ok if you use an xml layout just defing layout_width and layout_hight using density pixel value "10dp" for example. those scale with the screen size so you get the same result according to screen size.
if you use canvas then when you set the hight and width of an objecs use the following method:
/**
* get width or hight as density independent pixels and return the real
* amount of pixels requiered for the current screen
* used to programaticlly set width and hight using dip
* #param dip - the amount of dip
* #param context - the activity used in
* #return - return the real amount of pixels required for the current screen
*/
public static float getPixelsFromDip(float dip,Context context)
{
//TODO move this to aplication class?
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics());
}
another option is to calculate max screen size, and the precent from it you need
here is the method for the max size:
/**
* get maximum width and hight as dp avaliable in the screen
* #param context
* #return
*/
public static float[] getMaxPixels(Context context)
{
//TODO move this to application class
float result[]=new float[2];
DisplayMetrics displayMetrics=context.getResources().getDisplayMetrics();
float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;
result[0]=screenWidthInDp;
result[1]=screenHeightInDp;
return result;
}
last but not least rule of thumb density is:mdpi=1, hdpi=1.5 and ldpi is 0.75
so once you get the pixels for one screen size you can multiply by those values to get a rough estimate for the value in the other
enjoy.
Positioning in terms of pixels will definitely differ as there are different type of devices with different DPI.
So declaring Imageview with widht, height in dp should serve your problem. Coming to position, it should be maintained Relatively or through gravity.
We need your code to understand what exactly the problem is and what more you need.
EDIT:
Convert Dip to pixel and the apply it to your Bitmap size.
It will maintain physical size and gets resolution according to device.
public static int convertDipToPixels(float dips)
{
return (int) (dips * appContext.getResources().getDisplayMetrics().density + 0.5f);
}
Edit 2:
Just give a trail changing your loop with this code snippet and check it it replicates same on all devices
for (MenuButton m : menuButtonList) {
if((m.isVertical()==vertical||order==1)&&m.getOrder()+1==order ){
if(vertical){
p.x=0;
p.y=(int)getPixelsFromDip(100,c);
}
else{
p.x=m(int)(getPixelsFromDip(100,c));
p.y=0;
}
MenuButton m2=new MenuButton(order,b , vertical, p,name);
menuButtonList.add(m2);
return;
}
}

Disabling specific region of screen in android for touchevent

I'm developing an application in which I want to touch the screen vertically from top to bottom, and with the movement of finger I'm changing background.
I got that part of app.
The issue is that if a user touches the middle or the bottom part (coordinates) of the screen, It changes the background.
I want that user starts from top and move to bottom and if the user touches the middle or the bottom part (coordinates) of the screen, application shouldn't show any reaction but a toast should be shown saying
"Start touching from the top of the screen".
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
if(MatchReservedPixels(x,y))
{
return false;
}
return true;
}
//and here is your MatchReservedPixels function
private boolean MatchReservedPixels(int x,int y)
{
//Here goes your pixel matching logic
}
and don't forget to apply touchevent on avtivity.

Android Bitmap snap to grid

Does anyone know if there is a simple way to make images snap to grid when dragging a bitmap?
At the moment I can touch a bitmap and move it smoothly around the screen. I want to be able to make it snap to an invisible grid whilst you are dragging.
It's what I do in an application I'm just finishing at the moment. When the user is dragging something on the screen, I display a visible snap grid, and the object is snapped to that grid when the dragging has finished. To show a grid, my approach is to use a separate custom View that I named GridOverLayView. It is overlaid over the entire screen area and it very simply draws a snap grid in its onDraw() method. It is made visible only when something is being dragged.
Now, concerning the actual Activity in which dragging and dropping is handled, one particular constant I've defined is:
static final int SNAP_GRID_INTERVAL = 20;
When the object is being dragged around, i.e. when processing event.getAction()==MotionEvent.ACTION_MOVE events within my OnTouchListener, I perform snapping of the object's location to grid using the following:
RelativeLayout.LayoutParams par = (RelativeLayout.LayoutParams) mThingBeingDragged.getLayoutParams();
par.topMargin = Math.round((event.getRawY() - draggedInitialY) / SNAP_GRID_INTERVAL ) * SNAP_GRID_INTERVAL;
par.leftMargin = Math.round((event.getRawX() - draggedInitialX) / SNAP_GRID_INTERVAL ) * SNAP_GRID_INTERVAL;
mThingBeingDragged.setLayoutParams(par);
...where draggedInitialY and draggedInitialX store the initial touch position recorded during the initial MotionEvent.ACTION_DOWN.
A further nice touch is to allow the object being dragged to be moved around without snapping, but have it snap to the grid only in the .ACTION_UP when the user lifts their finger. In practice, this feels much nicer to use.
private PointF touchDown;
private int gridCellSize = 10;
private OnTouchListener touchListener = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
touchDown = new PointF(event.getRawX(), event.getRawY());
break;
}
case MotionEvent.ACTION_MOVE:
{
RelativeLayout.LayoutParams par = (RelativeLayout.LayoutParams) v.getLayoutParams();
float yDeff = ((event.getRawY() - touchDown.y) / gridCellSize ) * gridCellSize;
float xDeff = ((event.getRawX() - touchDown.x) / gridCellSize ) * gridCellSize;
if(Math.abs(xDeff) >= gridCellSize)
{
par.leftMargin += (int)(xDeff / gridCellSize) * gridCellSize;
touchDown.x = event.getRawX() - (xDeff % gridCellSize);
}
if(Math.abs(yDeff) >= gridCellSize)
{
par.topMargin += (int)(yDeff / gridCellSize) * gridCellSize;
touchDown.y = event.getRawY() - (yDeff % gridCellSize);
}
v.setLayoutParams(par);
break;
}
default :
{
break;
}
}
return true;
}
};

Categories

Resources