This is a little bit complicated to explain, so apologies.
The basic requirement is annotator app on Android, which allows the user to draw over the desktop, take a snapshot and one or two other things.
When the app starts it shows a single icon. This can be moved about the desktop.
When this icon is single clicked (touch) 6 icons spread evenly centred around the central icon appear.
So far so good. Now we move the central icon, and re-calculate the positions of the 6 outer icons centred around the new position of the central icon.
What we find is the outer icons are off centre relative to the central icon. The displacement looks to be roughly equal (bot X and Y) by the position of the touch within the central icon.
I will attempt to draw what happens.
First when the touch point on the drag/move is in the centre, everything lines up perfectly:
When the touch point is to the right, the displacement is leftwards as below:
When the touch is at the bottom the displacement is upwards:
The position of the "x" relative to the icon is it seems from
int shiftX = event.getX();
int shiftY = event.getY();
The position of the moved icon is from :
view.getLocationInWindow(locWXY);
int X = locWXY[0];
int Y = locWXY[1];
So, the positions of the satellite icons are calculated as:
final double angle = 30.000;
final double rad = angle * Math.PI / 180.000;
final int radius = 100;
final int penX = (int) (X + radius * cos(rad) + shiftX);
final int penY = (int) (Y - radius * sin(rad) + shiftY);
final int clearX = X ;
final int clearY = (int) (Y - radius + shiftY);
final int closeX = (int) (X - radius * cos(rad) + shiftX);
final int closeY = (int) (Y - radius * sin(rad) + shiftY);
final int iFlipX = (int) (X - radius * cos(rad) + shiftX);
final int iFlipY = (int) (Y + radius * sin(rad) + shiftY);
final int sshotX = X + shiftX;
final int sshotY = (int) (Y + radius + shiftY);
final int iFolderX = (int) (X + radius * cos(rad) + shiftX);
final int iFolderY = (int) (Y + radius * sin(rad) + shiftY);
penLP= new RelativeLayout.LayoutParams(70, 70);
penLP.leftMargin = penX;
penLP.topMargin = penY;
imbBlackPen.setLayoutParams(penLP);
clearLP = new RelativeLayout.LayoutParams(70, 70);
clearLP .leftMargin = clearX;
clearLP .topMargin = clearY;
imbClearScreen.setLayoutParams(clearLP );
folderLP = new RelativeLayout.LayoutParams(70, 70);
folderLP .leftMargin = iFolderX ;
folderLP .topMargin = iFolderY;
imbFolder.setLayoutParams(folderLP );
sshotLP = new RelativeLayout.LayoutParams(70, 70);
sshotLP .leftMargin = sshotX ;
sshotLP .topMargin = sshotY;
imbScreenCapture.setLayoutParams(sshotLP );
iFlipLP = new RelativeLayout.LayoutParams(70, 70);
iFlipLP .leftMargin = iFlipX ;
iFlipLP .topMargin = iFlipY;
imbIflipChart.setLayoutParams(iFlipLP );
closeLP = new RelativeLayout.LayoutParams(70, 70);
closeLP .leftMargin = closeX ;
closeLP .topMargin = closeY;
imbClose.setLayoutParams(closeLP );
I have tried setting shiftX and shiftY to zero, calculating X and X + shiftX/2. All to no avail. The strange thing is that on a small 10 inch tablet with resolution 1920 x 1200 it looks almost perfect, but on a large 65 inch touch screen the displacement is extremely pronounced.
We must be missing something, but I cannot figure out what.
As commented above ...
Fixed. The icon position calculation code above needed to be executed on ACTION_UP as well as ACTION_DOWN. Refactored this as a method and called it on both these events.
Related
I am trying to create dynamic buttons at the center of spesific areas of the ImageView. To figure out center of any area, I am using this function:
TextView createButton(int i, String[] boundingBoxArray) {
String[] coorArray = boundingBoxArray[i].split(",");
int[] coordinates = new int[4];
int x11 = Integer.parseInt(coorArray[0].replace(" ", ""));
int y11 = Integer.parseInt(coorArray[1].replace(" ", ""));
int x22 = Integer.parseInt(coorArray[2].replace(" ", ""));
int y22 = Integer.parseInt(coorArray[3].replace(" ", ""));
coordinates[0] = x11;
coordinates[1] = y11;
coordinates[2] = x22;
coordinates[3] = y22;
TextView buttonn = new TextView(context);
buttonn.setText(String.valueOf(i + 1));
buttonn.setTextSize(15);
buttonn.setId(i + 1);
buttonn.setBackgroundResource(R.drawable.circle);
RelativeLayout.LayoutParams rel_btn
= new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
Rect bounds = imageView.getDrawable().getBounds();
int scaledHeight = bounds.height();
int scaledWidth = bounds.width();
double scale;
double differWidth = 0;
double differHeight = 0;
imageViewHeight = imageView.getHeight();
imageViewWidth = imageView.getWidth();
if (scaledHeight > scaledWidth) {
scale = ((double) imageViewHeight / (double) scaledHeight);
differWidth = (imageViewWidth - (scaledWidth * scale)) / 2;
} else {
scale = ((double) imageViewWidth / (double) scaledWidth);
differHeight = (imageViewHeight - (scaledHeight * scale)) / 2;
}
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int swidth = displaymetrics.widthPixels;
int buttonWidth = swidth / 30;
double a = ((double) (x11 + x22) / 2) * scale - buttonWidth + differWidth;
double b = ((double) (y11 + y22) / 2) * scale - buttonWidth + differHeight;
rel_btn.leftMargin = (int) a;
rel_btn.topMargin = (int) b;
rel_btn.width = 2 * buttonWidth;
rel_btn.height = 2 * buttonWidth;
buttonn.setGravity(Gravity.CENTER);
buttonn.setLayoutParams(rel_btn);
return buttonn;
}
When the activity starts, this function is called in for loop (number of loop is depends on number of areas) to create buttons on the ImageView. When all buttons are created, user can click on one of any dynamic button to focus on the spesific area.
If the user click on any button, the createButton() function is called again (it doesnt necessary but it doesnt make an issue either) for some purposes.
The problem is height of ImageView is not fixed. At the first time of calling createButton() function, the height returns as greater than the normal height. Then if you call createButton() again, the height returns the normal value.
imageViewHeight = imageView.getHeight();
imageViewWidth = imageView.getWidth();
The class has 2-3 nested thread, so maybe this is cause of problem. But I tried lots of things like:
I used CountDownLatch to handle threads and functions
I used mImageView.post(new Runnable...) to be sure to call functions after imageView is created.
I called imageView.getHeight() lots of
different places, but nothing is changed.
I keep the expression long, because I couldn't decided if the information is enough to understand. And as you realize, English is not my native. Thank you.
Edit: I forgot to mention: Below API 19, everything is cool (getHeight() value is returning as the normal size, either at the first time of calling createButton() methor or later ). API 20 and above, I get this error.
I luckily found the solution.. I use fullscreen mode at my app, but I didn't use AreaSelectActivity in fullscreen. After activity opened, status bar is coming down in a while. That's why height is changed but length is not. I put AreaSelectActivity in fullscreen mode and bum ! it is fixed now.
I'm in a tremendous bind with a last minute request on a consulting project I'm working on.
Essentially here is what I am trying to accomplish:
I have a surfaceview that draws a series of randomly sized circles. Each circle can have a radius from 50-100.
The x,y values are randomly generated along with a random radius
Each circle is created as an object representing that circle (x, y coord's and radius) and it is added to a list.
Once they are all created they are drawn.
The problem is I want to make sure none of these circles overlap.
I'm struggling a bit. This seems like it's shouldn't be all that difficult but it is for me unfortunately.
Here's my code so far (I know it's not close...be kind):
x = 100 + (int) (Math.random() * (mCanvasWidth - 200));
y = 100 + (int) (Math.random() * (mCanvasHeight - 200));
radius = 50 + (int) (Math.random() * 99);
color[0] = (float) (Math.random() * 360);
color[1] = 1;
color[2] = 1;
String radVal = String.valueOf(radius);
circle circ = new circle(x, y, radius, Color.HSVToColor(128, color), radVal);
boolean addit = true;
for (dot d : Dots) {
int leftSide = d.get_x() - radius;
int rightSide = d.get_x() + radius;
int xBoundary = x + radius;
int yBoundary = y + radius;
int exist_xLeft = d.get_x() - d.get_radius();
int exist_xRight = d.get_x() + d.get_radius();
int exist_yTop = d.get_y() - d.get_radius();
int exist_yBottom = d.get_y() + d.get_radius();
if ((xBoundary > exist_xLeft) && (xBoundary < exist_xRight))
{
if (yBoundary > (exist_yTop) && (yBoundary < exist_yBottom)) {
addit = false;
break;
}
}
}
if (addit)
circles.add(mdot);
if (circles.size() >= 5)
running = false;
Then it iterates the circles list and draws them to the canvas.
Any suggestions on where I'm failing in the collision detection?
You can detect if 2 circles are colliding like this:
Given:
centerpoints cx1,cy1 & cx2,cy2
and given radii r1 & r2,
Then you can determine if the 2 circles are colliding:
areColliding=((cx2-cx1)*(cx2-cx1)+(cy2-cy1)*(cy2-cy1))<((r1+r2)*(r1+r2));
How can I get current position of thumb in pixel for SeekBar?
Currently I am trying to get the position on the bases of calculation.
Screen width, Seek Bar width, current seek progress and all. But I am not able to get exact position out of it.
Do any one have any idea?
Coding for same is as below.
I want to drow one component on top of SeekBar thumb.
translation = calculateTranslation(this.deviceScreenWidth, seekBarWidth, seekBar1T.getMax(), Integer.valueOf(ConstantData.seekbar_fifth.toString()), topComponentWidth, 0);
if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB){
TranslateAnimation anim = new TranslateAnimation(translation - 1,
translation, 0, 0);
anim.setFillAfter(true);
anim.setDuration(0);
edtTextRodUpDown.startAnimation(anim);
}else{
edtTextRodUpDown.setTranslationX(translation);
}
and calculate Translation like
private float calculateTranslation(int screenWidth, int seekBarWidth, int seekMaxProgress, int currentProgress, int componentWidth, int extraDifference){
double calculatedPosition = 0f;
calculatedPosition = (double)((double)(seekBarWidth-((screenWidth-seekBarWidth))) / (double)seekMaxProgress) * (double)currentProgress;
calculatedPosition = calculatedPosition - (double)(componentWidth/2);
calculatedPosition = calculatedPosition + extraDifference;
Double d = new Double(calculatedPosition);
if(d < 0){
return 0.0f;
}else if(d + componentWidth > screenWidth){
return screenWidth-componentWidth;
}else{
return d.floatValue();
}
}
I did this:
int width = seekBar.getWidth()
- seekBar.getPaddingLeft()
- seekBar.getPaddingRight();
int thumbPos = seekBar.getPaddingLeft()
+ width
* seekBar.getProgress()
/ seekBar.getMax();
You can use the getBounds() to get this info.
This sample code below is for instance aligning a TextView with the seekbar thumb position.
TextView sliderIndicator = ...
Rect bounds = seekBar.getThumb().getBounds();
sliderIndicator.setTranslationX(seekBar.getLeft() + bounds.left);
The seekbar thumb has a thumb offset, which is basically a slight shift to the right. So you have to make sure that you take this into account as well:
int thumbPos = seekbar.getMeasuredWidth() * seekbar.getProgress() / seekbar.getMax() - seekbar.getThumbOffset();
i have an image that rotates around an arbitrary point. but i need 3 such images to rotate simultaneously
this is how i try to implement the same
private void rotateLogo(float degrees){
Matrix matrix1 = new Matrix();
//int radius = turntable.getWidth()/2;
double radians = degrees* (Math.PI/180);
double xcoordinate = 220 * Math.cos(radians)- 60;
double ycoordinate = 220 * Math.sin(radians) + 50;
matrix1.postRotate((int)radians, 220, 220);
// people image
FrameLayout.LayoutParams linLay = (FrameLayout.LayoutParams) peopleLogo.getLayoutParams();
linLay.bottomMargin = (int)ycoordinate + 10;
linLay.rightMargin = (int)xcoordinate + 10;
peopleLogo.setImageMatrix(matrix1);
peopleLogo.setLayoutParams(linLay);
rotateLogo2(degrees - 2);
}
private void rotateLogo2(float degrees){
double radians = degrees* (Math.PI/180);
double xcoordinate = 220 * Math.cos(radians)- 60;
double ycoordinate = 220 * Math.sin(radians) + 50;
// people image
FrameLayout.LayoutParams linLay = (FrameLayout.LayoutParams) serverLogo.getLayoutParams();
linLay.bottomMargin = (int)ycoordinate + 10;
linLay.rightMargin = (int)xcoordinate + 10;
serverLogo.setLayoutParams(linLay);
}
in the above code i reduced the angle and rotate the second image using the same code, but the image doesnt rotate, it just disappears on touch.
i also tried to take the layout params of the first image before rotation and apply the same to the second image, but this doesnt work too..
the image disappears on rotation though at times it appears and then disappears
can anyone help me as to where i could be wrong or suggest any other approaches for the same?
You can refactor the code
private void rotateLogo(View logo, float degrees){
Matrix matrix1 = new Matrix();
//int radius = turntable.getWidth()/2;
double radians = degrees* (Math.PI/180);
double xcoordinate = 220 * Math.cos(radians)- 60;
double ycoordinate = 220 * Math.sin(radians) + 50;
matrix1.postRotate((int)radians, 220, 220);
// people image
FrameLayout.LayoutParams linLay = (FrameLayout.LayoutParams) logo.getLayoutParams();
linLay.bottomMargin = (int)ycoordinate + 10;
linLay.rightMargin = (int)xcoordinate + 10;
if (logo isInstanceOf ImageView) {
logo.setImageMatrix(matrix1);
}
logo.setLayoutParams(linLay);
}
and call the method twice with different parameters..
rotateLogo(peopleLogo, degrees);
rotateLogo(serverLogo, degrees-2);
Ok, this should be simple enough, but I'm tripping myself up on the math. Using AndEngine BTW>
I'm using some of the tutorials out there... hero on the left of the screen (landscape) shooting right. Everything works wonderfully. Now I'd like to have the hero on the right side of the screen shooting left. I'm going in circles and would great appreciate some help. Here is the code I'm using for left hero, shooting right.
/** shoots a projectile from the player's position along the touched area */
private void shootProjectile(final float pX, final float pY) {
int offX = (int) (pX - (hero.getX()));
int offY = (int) (pY - (hero.getY() + hero.getHeight()/2));
if (offX <= 0) return;
// position the projectile on the player and set up path
projectile = pPool.obtainPoolItem();
int realX = (int) (mCamera.getWidth() - (hero.getX() ) );
float ratio = (float) realX / (float) offX;
int realY = (int) ((offY * ratio));
float length = (float) Math.sqrt((realX * realX) + (realY * realY));
float velocity = 280.0f / .5f; // 480 pixels per (sec)f on screen
float realMoveDuration = length / velocity;
// defining a moveBymodifier from the projectile's position to the
// calculated one
//this code angles the projectile sprite
double PI = 3.14159265;
float dx = pX - hero.getX();
float dy = pY - hero.getY()-50;
double Radius = Math.atan2(dy,dx);
double Angle = Radius * 180 / PI;
projectile.setRotation((float)Angle); // sets the angle of the projectile
//Move modifier for projectile
MoveByModifier movMByod = new MoveByModifier(realMoveDuration, realX, realY);
final ParallelEntityModifier par = new ParallelEntityModifier(movMByod);
DelayModifier dMod = new DelayModifier(0.001f);
dMod.addModifierListener(new IModifierListener<IEntity>() {
#Override
public void onModifierStarted(IModifier<IEntity> arg0, IEntity arg1) {
}
#Override
public void onModifierFinished(IModifier<IEntity> arg0, IEntity arg1) {
// TODO Auto-generated method stub
shootingSound.play();
projectile.setVisible(true);
projectile.setPosition(hero.getX(), hero.getY() + hero.getHeight() / 2);
projectilesToBeAdded.add(projectile);
projectile.animate(50);
}
});
SequenceEntityModifier seq = new SequenceEntityModifier(dMod, par);
projectile.registerEntityModifier(seq);
projectile.setVisible(false);
mMainScene.attachChild(projectile, 1);
I've got the hero positioned fine on the right side. What do I need to do to get the projectile to move to the left correctly?
Thanks a ton for any help.
MWM
You shouldn't use DelayModifier the way you do. Instead create a PhysicsHandler for your sprites and then set velocity to the PhysicsHandler. Something like:
PhysicsHandler phys = new PhysicsHandler();
projectile.registerUpdateHandler(phys);
phys.setVelocityX(50);
and this will take care of moving your projectile. You can also set acceleration on the physics handler the same way. So if you set the initial velocity to point up and left and then set the acceleration pointing down, the projectile will first fly left and up and then gradually fall down. And you don't have to do any calculations yourself.
This code looks like the one from http://jimmaru.wordpress.com/2011/09/28/andengine-simple-android-game-tutorial/
if it is, try this:
private void shootProjectile(final float pX, final float pY) {
int side = 1;
int offX = (int) (pX - (hero.getX()));
int offY = (int) (pY - (hero.getY() + hero.getHeight()/2));
if (offX <= 0){
side=-1
}
// position the projectile on the player and set up path
projectile = pPool.obtainPoolItem();
int realX = (int) (mCamera.getWidth() - (hero.getX() ) ) * side;
....
I got the same problem with the code from link, with this change i could shoot fot both sides with a player in the middle of screen.