I am trying to allow the user to drag and drop and image from on position to another. The screen layout is as follows:
1 2 3
4 5 6
7 8 9
I want the user to grab image 2, 4, 6, or 8 and drag it to image 5. Upon dragging to image 5 I want to load up a fragment. The user can only drag the image in a straight line from it's current position to 5's position. ie image 2 and only drag down and only until it is overtop of image 5, image 4 can only drag right until overtop of 5, etc.
Any insight on how to do this is greatly appreciated.
Thanks,
DMan
So I figured out a way to get it to work. Pretty hacky but I basically use the image positions and transition it via a margin in the direct that I want from it's center until it reaches the desired position.
I created a temp image (mTempImage) and hide my main image because the image had parameters set in the layout that forced it to stay above a specific item in the layout and wouldnt let it margin less than that items height.
Here is a sample from my onTouchListener
int eventX = (int)event.getX();
int eventY = (int)event.getY();
int movingViewHeight = view.getHeight();
int movingViewWidth = view.getWidth();
int destinationTileTop = mTileHere.getTop();
int destinationTileLeft = mTileHere.getLeft();
// Transparent 'Tile Here' image (1)
// Transitional 'Tile Here' image (0 - 1)
// Opaque 'Tile Here' image (0)
float alphaMultiplier = 0;
switch(view.getId()) {
case R.id.item_position_2:
// Only allow sliding down from center of object (positive eventY)
if (eventY > movingViewHeight / 2) {
// Calculate the amount that the image has moved from it's center point
int posFromImgCenter = (eventY - movingViewHeight / 2);
// Check if the image has reached the center point and stop it's motion any farther
if (posFromImgCenter >= destinationTileTop) {
params.setMargins(view.getLeft(), destinationTileTop, 0, 0);
alphaMultiplier = 1;
}
// Slide the image with the positioning of the persons finger
else {
params.setMargins(view.getLeft(), posFromImgCenter, 0, 0);
alphaMultiplier = ((float)posFromImgCenter / (float)destinationTileTop);
}
}
// Attempting to slide in an invalid direction leave the image where it is
else
params.setMargins(view.getLeft(), view.getTop(), 0, 0);
... MORE CODE HERE FOR OTHER ITEM POSITIONS
// AFTER SWITCH STATEMENT COMPLETE UPDATE VIEW ITEMS ACCORDINGLY
// default 0 if not set with valid movement
mTileHere.setAlpha((int)(255 - (255 * alphaMultiplier)));
mTempImage.setLayoutParams(params);
mTempImage.invalidate();
Thanks,
DMan
Related
I have a view and inside a viewpager with images. When I touch the view I display an image where I'm touching.
In the same time I send X and Y position in Firebase.
In another device, I get back those coordinates and display an image at those coordinates.
But the screen size of the tablets are differents, how can I show my image at the same position ? Because if I touch the middle screen of the first tablet, it showing an image en the right bottom of the other one
UPDATE
For user 1, when he touch the view a pointer/cursor is showing
v.animate()
.x(Math.round(event.getX()))
.y(Math.round(event.getY()))
.setDuration(0)
.start();
In the same time he sends coordinates to Firebase and the width and height of his screen.
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Map<String, Object> map = new HashMap<>();
map.put("x", Math.round(event.getX()));
map.put("y", Math.round(event.getY()));
map.put("sizeX", width);
map.put("sizeY", height);
mRefMyPos.updateChildren(map);
The user 2 has a listener and get back those data to display an imageView at the coordinates.
listenerRefCoordonate = mRefCoordonate.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
CoordonateModel coordinateModel = dataSnapshot.getValue(CoordonateModel.class);
if (coordinateModel == null){
//do something
mImageView.setVisibility(View.GONE);
} else {
final Float mScale = Math.min(1.0f * width / coordinateModel.getSizeX(), 1.0f * height / coordinateModel.getSizeY());
if (coordinateModel.getX() != null){
mImageView.setVisibility(View.VISIBLE);
mImageView.animate()
.x(Math.round(coordinateModel.getX() * mScale))
.y(Math.round(coordinateModel.getY() * mScale))
.setDuration(0)
.start();
}
}
}
#Override
public void onCancelled(DatabaseError firebaseError) {
}
});
Seems to be incorrect for example if I have an imageview with ABCDEFGHI.... (match_parent), if I try to show C, it showing E on the other device. Maybe my scale is incorrect ??
I tried to test if the scale is correct. When I touch the screen without displaying imageview where I'm touching but I'm listening what I'm writting on FireBase and displaying imageview with coordinates/with and height of screen device and do the scale and the when I'm displaying the imageview it showing where I'm touching so I guess the scale is correct
I will try to re explain my problem:
Tablet n1, 1024/768
Tablet n2, 1920/1200
Both are on a view full_screen with the same Imageview scale FitXY and match_parent
On the first tablet I'm touching the tail of the pig (Imageview), I'm sending X,Y position of the screen touch (Math.round(event.getX(), Math.round(event.getY()) and the width/height screen size of the tablet. The second tablet displaying (a cursor) around the tail of the pig but not at the exact position....
Can someone help me ?
User tablet 1 touching his screen (RED POINT where he's touching)
User tablet 2 listening X,Y position and draw where the user 1 is touching (RED POINT)
UPDATE 2
I changed and I calculate like this one on this post stackoverflow.com/a/21588683/5845928 I have what you said : tablet 1 the point is (258,230) and tablet 2 (484, 359). the problem seems to be the imageview. How can I solve it ?
** FIXED **
TABLET 2 receive x,y position and width and height of tablet 1.
hisWidth = coordinateModel.getSizeX();
hisHeight = coordinateModel.getSizeY();
float percent_width = Float.valueOf(coordinateModel.getX()) / hisWidth;
float percent_height = Float.valueOf(coordinateModel.getY()) / hisHeight;
float x = percent_width * mWidth;
float y = percent_height * mHeight;
Try to send also device width and height, so you could use them to calculate the exact (X,Y) in other devices
I'm trying to draw a text to the screen and then have a rectangle in the same spot to account for knowing when the user clicks within it (and clicks the text). Problem is when I put the text in one spot on the screen and the rectangle in the same spot, it apparently isn't in the same spot. Is there some setting I need to set somewhere?
private final String[] options = {"Start", "High Scores", "Help", "Quit"};
public void draw(final Canvas g)
{
for (int i = 0; i < options.length; i++)
{
width = HORIZONTALOFFSET * 3 + spaceInvadersTitle.getWidth();
height = GamePanel.getScreenHeight() / 4 - (75 * 2 + TEXT_SIZE) / 2 + i * 75;
rect[i] = new Rect(width, height, width + 325, height + TEXT_SIZE);
g.drawRect(rect[i], paint);
g.drawText(options[i], width, height, paint);
}
}
FYI "width" and "height" are more like x- and y-coords. The horizontal alignment is not the problem - just the vertical. If you'll notice from the code, I'm setting the starting x- and y-coordinates for the drawText and drawRect the same exact position, but that's not how they're showing on the screen. Instead it seems the drawText is using that position as a lowerleft anchorpoint or something like that. Is that how it works? If so, how do I change that?
Also, if you have any suggestions on how to approach listening for when the user clicks on a drawn text, I'm all ears. This is the easiest way I could think of, and how I do it in regular desktop Java.
In short I want a preview similar to Google Plays, where you can slide up and the top image/video preview fades back and the rest of the view is moved up.
I've got a view that I want to be hiden like the video in this example, the action bar can remain stationary at all times, but I need the bottom part to be dragable.
I can't seem to find out which layout that is, or how it is done, all I managed to find were unrelated such as ViewPager. My current min sdk version is 18, the compile version is 21.
The following is the code I used in the app I am working
You will have to use the OnScrollChanged function in your ScrollView. ActionBar doesn't let you set the opacity , so set a background drawable on the actionbar and you can change its opacity based on the amount of scroll in the scrollview. I have given an example workflow
The function sets gives the appropriate alpha for the view locationImage based on its position WRT window .
this.getScrollY() gives you how much the scrollView has scrolled
public void OnScrollChanged(int l, int t, int oldl, int oldt) {
// Code ...
locationImage.setAlpha(getAlphaForView(locationImageInitialLocation- this.getScrollY()));
}
private float getAlphaForView(int position) {
int diff = 0;
float minAlpha = 0.4f, maxAlpha = 1.f;
float alpha = minAlpha; // min alpha
if (position > screenHeight)
alpha = minAlpha;
else if (position + locationImageHeight < screenHeight)
alpha = maxAlpha;
else {
diff = screenHeight - position;
alpha += ((diff * 1f) / locationImageHeight)* (maxAlpha - minAlpha); // 1f and 0.4f are maximum and min
// alpha
// this will return a number betn 0f and 0.6f
}
// System.out.println(alpha+" "+screenHeight +" "+locationImageInitialLocation+" "+position+" "+diff);
return alpha;
}
You can download an example working sample at https://github.com/ramanadv/fadingActionBar
Credit: CommandSpace
I am trying to make a simple face detection app consisting of a SurfaceView (essentially a camera preview) and a custom View (for drawing purposes) stacked on top. The two views are essentially the same size, stacked on one another in a RelativeLayout. When a person's face is detected, I want to draw a white rectangle on the custom View around their face.
The Camera.Face.rect object returns the face bound coordinates using the coordinate system explained here and the custom View uses the coordinate system described in the answer to this question. Some sort of conversion is needed before I can use it to draw on the canvas.
Therefore, I wrote an additional method ScaleFacetoView() in my custom view class (below) I redraw the custom view every time a face is detected by overriding the OnFaceDetection() method. The result is the white box appears correctly when a face is in the center. The problem I noticed is that it does not correct track my face when it moves to other parts of the screen.
Namely, if I move my face:
Up - the box goes left
Down - the box goes right
Right - the box goes upwards
Left - the box goes down
I seem to have incorrectly mapped the values when scaling the coordinates. Android docs provide this method of converting using a matrix, but it is rather confusing and I have no idea what it is doing. Can anyone provide some code on the correct way of converting Camera.Face coordinates to View coordinates?
Here's the code for my ScaleFacetoView() method.
public void ScaleFacetoView(Face[] data, int width, int height, TextView a){
//Extract data from the face object and accounts for the 1000 value offset
mLeft = data[0].rect.left + 1000;
mRight = data[0].rect.right + 1000;
mTop = data[0].rect.top + 1000;
mBottom = data[0].rect.bottom + 1000;
//Compute the scale factors
float xScaleFactor = 1;
float yScaleFactor = 1;
if (height > width){
xScaleFactor = (float) width/2000.0f;
yScaleFactor = (float) height/2000.0f;
}
else if (height < width){
xScaleFactor = (float) height/2000.0f;
yScaleFactor = (float) width/2000.0f;
}
//Scale the face parameters
mLeft = mLeft * xScaleFactor; //X-coordinate
mRight = mRight * xScaleFactor; //X-coordinate
mTop = mTop * yScaleFactor; //Y-coordinate
mBottom = mBottom * yScaleFactor; //Y-coordinate
}
As mentioned above, I call the custom view like so:
#Override
public void onFaceDetection(Face[] arg0, Camera arg1) {
if(arg0.length == 1){
//Get aspect ratio of the screen
View parent = (View) mRectangleView.getParent();
int width = parent.getWidth();
int height = parent.getHeight();
//Modify xy values in the view object
mRectangleView.ScaleFacetoView(arg0, width, height);
mRectangleView.setInvalidate();
//Toast.makeText( cc ,"Redrew the face.", Toast.LENGTH_SHORT).show();
mRectangleView.setVisibility(View.VISIBLE);
//rest of code
Using the explanation Kenny gave I manage to do the following.
This example works using the front facing camera.
RectF rectF = new RectF(face.rect);
Matrix matrix = new Matrix();
matrix.setScale(1, 1);
matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f);
matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f);
matrix.mapRect(rectF);
The returned Rectangle by the matrix has all the right coordinates to draw into the canvas.
If you are using the back camera I think is just a matter of changing the scale to:
matrix.setScale(-1, 1);
But I haven't tried that.
The Camera.Face class returns the face bound coordinates using the image frame that the phone would save into its internal storage, rather than using the image displayed in the Camera Preview. In my case, the images were saved in a different manner from the camera, resulting in a incorrect mapping. I had to manually account for the discrepancy by taking the coordinates, rotating it counter clockwise 90 degrees and flipping it on the y-axis prior to scaling it to the canvas used for the custom view.
EDIT:
It would also appear that you can't change the way the face bound coordinates are returned by modifying the camera capture orientation using the Camera.Parameters.setRotation(int) method either.
I downloaded the CNN iOS app and I seen the wonderful menu!
I post 2 screen
Now I'm asking how can I create that in my application. I will develop in iOS and Android but the same application for Android hasn't that menu..
It's possible to create this menu in Andorid?
Has anyone some advice to create that?
Thank you in advance
Got solution: Create one view with listiview, and one button with background photo. Than take the view out of screen. If the view is x = 320 y = 300 set y = -300 in sotryboard element postition settings and place the button in the top corner.
On button action make a animation of the 2 graphic object of y = +300. That's all.
- (IBAction)makeTheMagicWithButton:(id)sender {
//at first click y + 300 and view comes in
//at the 2nd click y - 300 and return back out the screen
float y;
[sender setSelected:![sender isSelected]];
if ([sender isSelected]) {
y = +300;
self.buttonImage = [UIImage imageNamed:#"menuICONSreturn.png"];
} else {
y = -300;
self.buttonImage = [UIImage imageNamed:#"menuICONS.png"];
}
//animation move the view
[UIView transitionWithView:self.view duration:0.5 options:UIViewAnimationOptionAllowAnimatedContent animations:^{[self.magicView setFrame:CGRectOffset(self.magicView.frame, 0, y)];}
completion:nil];
//animation move button menu
[UIView transitionWithView:self.view duration:0.5 options:UIViewAnimationOptionAllowAnimatedContent animations:^{[self.magicButton setFrame:CGRectOffset(self.magicButton.frame, 0, y)];}
completion:nil];
//change icon
[self.magicButton setBackgroundImage:self.buttonImage forState:UIControlStateNormal];
}
Hope it will help someone..