I am calculating the swipe area in android tab. Requirement is that when user swipes on the top 10% of the screen in tab a popup should come.
How can i achieve it by using the touch event of onFling();
Right now I am doing it like below, (arg0 and arg1 are Motion events)
int height = this.webview.getHeight();
float x = arg0.getRawX();
float y = arg0.getRawY();
float x2 = arg1.getRawX();
float y2 = arg1.getRawY();
if (x < 2000.00 && x2 < 2000.00 && y < 200.00 && y2 < 80.00) {
showPopUp();
}
But, I dont want to use the hardcoded values like 2000.00 or 80.00. Instead of this the swipe should be calculated based on the device height. Though this is working fine.
Any idea how to do it?
You can get the screen height via WindowManager
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// This is the height of the screen
size.y;
You can then easily use that to determine if a swipe is in the top 10%.
Depending on where you're needing to calculate the height, you could cache this value in a member (in onResume() for an Activity) so that it gets updated when the config changes (device rotation, etc.)
int height = this.webview.getHeight();
int width = this.webview.getWidth();
float maxHeight = height*.10f; //10% of 1000 is 100
float maxWidth = width*.10f; //10% of 500 is 50
float x = arg0.getRawX();
float y = arg0.getRawY();
float x2 = arg1.getRawX();
float y2 = arg1.getRawY();
if (x > 0 && x2 < maxWidth && y > 0 && y2 < maxHeight) {
showPopUp();
}
Related
I have game field which is a Group with Actors. The Group locketed in Table wich is locketed in ScrollPane. I have two Buttons to zoom in and zoom out the game field. Here is my code how I do it:
TextButton zoomInBtn = new TextButton("+", menuBtnStyle);
zoomInBtn.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
float width = fieldGroup.getWidth();
float height = fieldGroup.getHeight();
float newWidth = width + width * 0.1f;
if (newWidth > myWorld.getMaxWidth()) {
newWidth = myWorld.getMaxWidth();
}
float newHeight = height * newWidth / width;
fieldGroup.setWidth(newWidth);
fieldGroup.setHeight(newHeight);
myWorld.setWidth(Math.round(newWidth));
fieldGroup.reinitialiseChildren();
Cell cell = fieldTable.getCell(fieldGroup);
cell.clearActor();
cell.setActor(fieldGroup);
}
});
TextButton zoomOutBtn = new TextButton("-", menuBtnStyle);
zoomOutBtn.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
float width = fieldGroup.getWidth();
float height = fieldGroup.getHeight();
float newWidth = width - width * 0.1f;
if (newWidth < myWorld.getMinWidth()) {
newWidth = myWorld.getMinWidth();
}
float newHeight = height * newWidth / width;
Actor widget = scrollPane.getWidget();
fieldGroup.setWidth(newWidth);
fieldGroup.setHeight(newHeight);
myWorld.setWidth(Math.round(newWidth));
fieldGroup.reinitialiseChildren();
Cell cell = fieldTable.getCell(fieldGroup);
cell.clearActor();
cell.setActor(fieldGroup);
}
});
I change the size of my fieldGroup with Image Actors in it. And then readding it to Table.
The problem is: when I zoom with buttons it always zoom around left corner. I want it to zoom from canter of ScrollPane. I know that I can do it with Ortographic Camera, but it would be difficult, I think, to make it movements so smooth as ScrollPane. So maybe there is some way to do it with ScrollPane.
Every time you zoom in or out you would have to change the x and y position of the group relative to the zoom. You can do this using the setScrollx (and y) of your scroll pane.
You need to set so that the middle of the part you are viewing stays in the middle of the scrollpane. You can work out middle of newWidth by dividing it by 2. If the scrollPane is fullScreen you can half the value obtained by Gdx.graphics.getwidth();. The difference between these two is then the value which will keep the middles aligned.
newXvalue =(newWidth/2) - ((Gdx.graphics.getWidth())/2);
scrollPane.setScrollx(newXvalue);
The same should be done for y.
Note: if you want to zoom and move at same time, this will not work, I would recommend using orthographic camera with a gesture listener for that.
I have 2 photos, one has a dimension of 300x300 and the other one is 1200x1200.
I drew one text to the position A = (50, 40) in the 300x300 image.
How can I calculate the same position A on the 1200x1200 image?
UPDATE 2:
IF dimension is not round (such as 523 x 412...) - x, y after multiply will be deflected
you may go with relative position calculation as follows.
AAx = (50/300)*1200;
AAy = (50/300)*1200;
so your new position will be AA = (200,200)
The scaling factor for both x and y is 1200/300 = 4.
Then, simply multiply both x and y by 4 (your scaling factor).
int scaleFactor = 1200 / 300;
int newX = oldX * scaleFactor;
int newY = oldY * scaleFactor;
So, given that oldX = 50 and oldY = 40, the expectex values for newX and newY are 200 and 160, respectively.
I am creating a game which involves shooting in the direction where user clicked.
So from point A(x,y) to point B(x1,y1) i want the bullet bitmap to animate and i have done some calculation/math and figured out some way to do it, but it's not that great-looking doesn't feel so natural.
My approach to doing this is calculate the difference between x and x1 and y and y1 and just scale it.
In example if the X difference between x and x1 is 100 and Y difference between y and y1 i calculate X/Y and get 2.0 which is equal to 2:1 so I know that I should move X two times faster than Y.
Here is my code, if anyone has any suggestions how to make it better, let me know.
float proportion;
float diffX = (x1 - x);
if(diffX == 0) diffX = 0.00001f;
float diffY = (y1 - y);
if(diffY == 0) diffY = 0.00001f;
if(Math.abs(diffX)>Math.abs(diffY)){
proportion = Math.abs(diffX)/Math.abs(diffY);
speedY = 2;
speedX = proportion * speedY;
}
else if(Math.abs(diffX)<Math.abs(diffY)){
proportion = Math.abs(diffY)/Math.abs(diffX);
speedX = 2;
speedY = proportion * speedX;
}
else{
speedX = speedY = 2;
}
if(diffY<0) speedY = -speedY;
if(diffX<0) speedX = -speedX;
if(speedX>=10) speedX = 9;
if(speedX<=-10) speedX = -9;
if(speedY>=10) speedY = 9;
if(speedY<=-10) speedY = -10;
The following implements LERP (linear interpolation) to move you along a straight line.
// move from (x1, y1) to (x2,y2) with speed "speed" (that must be positive)
final double deltay = y2-y1;
final double deltax = x2-x1;
double deltalen = sqrt(deltay*deltay + deltax*deltax);
if (deltalen <= speed)
display(x2, y2);
else {
double finalx = x1 + deltax * speed/deltalen; // surely deltalen > 0, since speed >=0
double finaly = y1 + deltay * speed/deltalen;
display(finalx, finaly);
}
Here is the code to elaborate on my comment:
float slope = (x2 -x1)/(y2 - y1);
float dx = 0.1f; // tweake to set bullet's speed
float x = x1;
while(x < x2)
{
float y = slope*(x - x1) + y1;
DisplayBullet(x, y);
x += dx;
}
// at this point x = x2 and, if everything went right, y = y2
Here I'm assuming that x1 < x2. You'll have to swap points when that's not the case.
I trying to get x,y for any object inside the layout but I got this values when object at end corner of the screen :
Object X : 266
Object Y : 361
Screen Width : 320
Screen Height: 480
how can I know where is the object exactly for the screen? (end,top,left,center).
Hope this helps..
public Rect locateView(View view) {
Rect loc = new Rect();
int[] location = new int[2];
if (view == null) {
return loc;
}
view.getLocationOnScreen(location);
loc.left = location[0];
loc.top = location[1];
loc.right = loc.left + view.getWidth();
loc.bottom = loc.top + view.getHeight();
return loc;
}
And I used the method this way:
Rect r = TVGridUtils.locateView(activity.findViewById(R.id.imageview));
float touchX=r.left+((r.right-r.left)/2);
float touchY=(r.bottom);
Note: I had to get the middle point of the imageview which i touched
I think you need to add the width and height of the objects to x and y values
To know where is the object exactly for the screen
X= 0,Y= 0 TOP LEFT
X= screenWidth-objectWidth,Y= 0 TOP RIGHT
X= 0,Y= screenHeight-objectHeight BOTTOM LEFT
X= screenWidth-objectWidth,Y= screenHeight-objectHeight BOTTOM RIGHT
Button b;
int x1 = b.getX();
int x2 = x1 + b.getWidth();
int y1 = b.getY();
int y2 = y1 + b.getHeight();
In my app I need to let users to check the eyes at some photo.
In OnTouchListener.onTouch(...) I get the coordinates of the ImageView.
How can I convert this coordinates to the point at the bitmap that was touched?
this works for me at least with API 10+:
final float[] getPointerCoords(ImageView view, MotionEvent e)
{
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix matrix = new Matrix();
view.getImageMatrix().invert(matrix);
matrix.postTranslate(view.getScrollX(), view.getScrollY());
matrix.mapPoints(coords);
return coords;
}
Okay, so I've not tried this, but giving it a bit of thought, here's what I've got as a suggestion:
ImageView imageView = (ImageView)findViewById(R.id.imageview);
Drawable drawable = imageView.getDrawable();
Rect imageBounds = drawable.getBounds();
//original height and width of the bitmap
int intrinsicHeight = drawable.getIntrinsicHeight();
int intrinsicWidth = drawable.getIntrinsicWidth();
//height and width of the visible (scaled) image
int scaledHeight = imageBounds.height();
int scaledWidth = imageBounds.width();
//Find the ratio of the original image to the scaled image
//Should normally be equal unless a disproportionate scaling
//(e.g. fitXY) is used.
float heightRatio = intrinsicHeight / scaledHeight;
float widthRatio = intrinsicWidth / scaledWidth;
//do whatever magic to get your touch point
//MotionEvent event;
//get the distance from the left and top of the image bounds
int scaledImageOffsetX = event.getX() - imageBounds.left;
int scaledImageOffsetY = event.getY() - imageBounds.top;
//scale these distances according to the ratio of your scaling
//For example, if the original image is 1.5x the size of the scaled
//image, and your offset is (10, 20), your original image offset
//values should be (15, 30).
int originalImageOffsetX = scaledImageOffsetX * widthRatio;
int originalImageOffsetY = scaledImageOffsetY * heightRatio;
Give this idea a try and see if it works for you.
besides considering the offset due to padding (margin is part of the layout, it's space outside the view and doesn't have to be considered), if the image is scaled you can get the image matrix (ImageView.getImageMatrix()) to scale coordinates.
EDIT:
You can get x/y scaling factor and translation amount getting the values array and using respective index constants:
float[] values;
matrix.getValues(values);
float xScale = values[Matrix.MSCALE_X];
note that translation doesn't include padding, you still would have to consider that separately. translation is used for instance in FIT_CENTER scaling when there's some "blank" space.
I'd say you probably need to offset the coordinates from the ImageView with any padding or margins in the layout to get the correct coordinates of the BitMap.
To add to kcoppock's answer, I just want to add that:
//original height and width of the bitmap
int intrinsicHeight = drawable.getIntrinsicHeight();
int intrinsicWidth = drawable.getIntrinsicWidth();
may return an answer you're not expecting. These values depend on the dpi of the drawable folder you load the image from. For instance, you might get a different value if you load the image from /drawable vs /drawable-hdpi vs /drawable-ldpi.
Get floor Width and height
float floorWidth = floorImage.getWidth();
float floorHeight = floorImage.getHeight();
Calculate protionate value
float proportionateWidth = bitmapWidth / floorWidth;
float proportionateHeight = bitmapHeight / floorHeight;
Your X & Y
float x = 315;
float y = 119;
Multiple with PropotionateValue
x = x * proportionateWidth;
y = y * proportionateHeight;
As I came accross this question and tried it out myself, here is my solution.
It seems to work with stretched and centered images.
class MyEditableImageView(context: Context, attrs: AttributeSet) :
androidx.appcompat.widget.AppCompatImageView(context, attrs) {
override fun onTouchEvent(event: MotionEvent): Boolean {
val image = drawable.toBitmap().copy(Bitmap.Config.ARGB_8888, true)
val xp = (event.x - imageMatrix.values()[Matrix.MTRANS_X]) / imageMatrix.values()[Matrix.MSCALE_X]
val yp = (event.y - imageMatrix.values()[Matrix.MTRANS_Y]) / imageMatrix.values()[Matrix.MSCALE_Y]
if (xp >= 0 && xp < image.width && yp >= 0 && yp < image.height) {
doSomethingOnImage(image, xp, yp)
setImageBitmap(image)
}
return super.onTouchEvent(event)
}
...
}