TranslateAnimation ImageView - android

Im facing the next 2 problems:
1) When I translate an imageview from outside the screen to inside the screen, when the image is moving the image is cropped, and when finishes moving the imageview fixes and shows ok. Why this is happening?
2) I use translateAnimation to move an imageview for example from (0,0) to (300,0).
I have implemented the on touch listener. When I try to move the imageview that translate before, when I try to move with the finger the ontouch not works, but if a touch with the finger in the position (0,0) the imageview moves but the image not shows! I don’t understand what is happening.
I try to move the imageView with the finger in the position (300,0) but not work, and when i touch in the position (0,0) moves. But if i move for example 100 in x axis, the imageview is not in position (100,0), its in (400,0)!! i dont understand what is happening. Something is missing, i think the imageview saves the position that start to move or someting, i dont understand. If i remove the translate animation to that imageview, the ontouch works OK!
I hope I was clear.
Here is my code for problem 1:
public void showImageFromOutside(ImageView image){
image.setImageResource(obtenerImagen(cartasJugador.get(0).toString()));
TranslateAnimation animation1 = new TranslateAnimation(100, 425, 100, 525);
animation1.setDuration(800);
animation1.setFillAfter(true);
animation1.setAnimationListener(animationListener);
image.startAnimation(animation1);
}
Here is my code for problem 2:
public void moveImageView(Imageview image){
animation = new TranslateAnimation(0, 300, 0, 0);
animation.setDuration(250);
animation.setFillAfter(true);
animation.setAnimationListener(animationListener);
image.startAnimation(animation);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
seMueve = true;
break;
case MotionEvent.ACTION_MOVE:
if (seMueve) {
x = (int) event.getRawX() - v.getWidth()/2;
y = (int) event.getRawY() - v.getHeight();
v.setX(x);
v.setY(y);
}
break;
case MotionEvent.ACTION_UP:
seMueve = false;
break;
}
v.performClick();
return seMueve;
}
Greets

Takes a look:
http://developer.android.com/guide/topics/graphics/prop-animation.html#property-vs-view
especially to
...another disadvantage of the view animation system is that it only modified where the View was drawn, and not the actual View itself. For instance, if you animated a button to move across the screen, the button draws correctly, but the actual location where you can click the button does not change, so you have to implement your own logic to handle this.
I think that you can not use onTouchListener with Animation. You shoulds use ObjectAnimator, its easy.
If your API is lower than 11 you can try with http://nineoldandroids.com/.
Regards

Related

Android - Drag and Drop - Animation shadow to destination

I want to animate a ShadowView to some coordinates (to destination view).
I'm using D&D and if user drops (DragEvent.ACTION_DROP) then the view in some area I want to animate the view (from the drop location) to some destination view.
I don't want to animate view from the source location but want to do from the DROP location.
I tried a lot of things but nothing works. How can I get access to the ShadowView? This also not working:
EventDragShadowBuilder.getView()
I think TranslateAnimation should work for this but I need access to the "shadow" view during the D&D.
Image:
First implement onTouchlistener on the view
llDragable.setOnTouchListener(this);
Make a view draggable
#Override
public boolean onTouch(View view, MotionEvent event) {
float dX = 0;
float dY = 0;
switch (view.getId()){
case R.id.dragableLayout :{
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
lastAction = MotionEvent.ACTION_DOWN;
break;
case MotionEvent.ACTION_MOVE:
view.setY(event.getRawY() + dY);
view.setX(event.getRawX() + dX);
lastAction = MotionEvent.ACTION_MOVE;
break;
case MotionEvent.ACTION_UP:
//Animate
animate();
if (lastAction == MotionEvent.ACTION_DOWN)
//Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
break;
default:
return false;
}
return true;
}
}
return false;
}
Then you can use object animator at case MotionEvent.ACTION_UP using object animation . You need to have the position of the destination.
private void animate() {
Path path = new Path();
path.moveTo(destinationX, destinationY);
path.lineTo(destinationX, destinationY);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mButton, View.X, View.Y, path);
objectAnimator.setDuration(duration);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
}
One possible thing could be
once the drag event has finished, you can move the "view" to the location of the drop and then you can start an animation to move the view from the dropped location to the destination.
Keep in mind here the drag shadow is not being animated but the view itself is being animated.
As a workaround, you can try to add a selector with transparent and black-gradient drawables, depended on appropriate state. In this case you will decide, when your "shadow" should be shown and when it should be gone.
Here is a question about "shadow" bordered layouts:
Android LinearLayout : Add border with shadow around a linearLayout
Don't sure, is it a good way... But it might work.
Good luck!
Create a duplicate view of the one you are dragging. Once drag ends, you get the location or drop off co-ordinates of the view. Once this happens, set the visibility of your "real" view to View.INVISIBLE. Then set the x and y of the temp invisible view to that of the drop-off point and make it visible. After that, create a translate animation that animates the temp view to the desired position, and don't forget to set the setFillEnabled and setFillAfter properties of the translate animation to true.

Android: How to Prevent Down Press animation of a button when scrolling a list?

So i have an ImageView that I want to use as a button. When I press this button it scales a little bit down and when i release it, the button scales back to original size.
To do this I attach an onTouchListener to the image:
#Override
public boolean onTouch(View v, MotionEvent event) {
Animation anim;
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
// Scale down ImageView when finger is down
anim = AnimationUtils.loadAnimation(getContext(), R.anim.poster_scale_down);
v.startAnimation(anim);
return true;
case MotionEvent.ACTION_UP:
// Scale up ImageView when finger is up
anim = AnimationUtils.loadAnimation(getContext(), R.anim.poster_scale_normal);
v.startAnimation(anim);
break;
case MotionEvent.ACTION_CANCEL:
// Scale up ImageView when action is canceled
anim = AnimationUtils.loadAnimation(getContext(), R.anim.poster_scale_normal);
v.startAnimation(anim);
break;
}
return false;
}
I have a series of these ImageViews in a RecyclerView. So when I am scrolling, it will trigger the ACTION_DOWN pressed animation of where my finger was. This is really annoying!
How do I prevent this? Is there a better way to add an animation as a selector for an ImageView?
EDIT WITH A SORT OF WORKAROUND:
case MotionEvent.ACTION_CANCEL:
v.clearAnimation();
break;
When you scroll it will cancel your current touch on the list item, so just clear the animation. This isn't perfect because it will still cause the animation to start just slightly if you're not swiping fast enough
Simply maintain the state with a variable by yourself.
E.g. when first press down, set the variable to true, if the variable is true, do not perform the animation. When it is released, set the variable to false.

Moving any RelativeLayout with finger (without changing layout params)

I have a view, and I want to move it with finger. I wanted to get the xDelta and yDelta and just translate the matrix of the view (not image view, any view, RelativeLayout for example).
I am wondering how to do that:
Overriding RelativeLayout's onDraw and apply translation matrix there. Is that possible?
I am currently doing it with applying animation on each onTouch event. The animation is with duration 0 and the start/end of x/y is the same (setFillAfter = true). It just puts the view where I want. But isn't that too expensive?
Can't I manipulate the matrix of any view directly through onDraw? I tried something like this:
#Override
protected void onDraw(Canvas canvas) {
if (getDx() != 0 && getDy() != 0) {
m = canvas.getMatrix();
m.postTranslate(dx, dy);
canvas.setMatrix(m);
}
super.onDraw(canvas);
}
But it seems that I am doing it wrong.
If you want to implement drag gesture then you can use onTouchListener and in its MotionEvent.ACTION_MOVE set padding using setPadding to that view.
Here is the sample code:
case MotionEvent.ACTION_MOVE:
yourView.setPadding((int)event.getRawX(), (int)event.getRawY(), 0, 0);
Sample for onTouchListener :-
OnTouchListener drag= new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_MOVE:
img.setPadding((int)event.getRawX(), (int)event.getRawY(), 0, 0);
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
} return true;
}
};
You need to create the dragging image at run time and have to adjust its position. In this sample code I have not adjusted the position so the dragged image is not created at the position of touch. You also need to consider the height and width of the image to be dragged.
Hope it helps !
I hate to be the one to tell you that your problem is even easier than you thought, but here's what it looks like:
#Override
protected void onDraw(Canvas canvas) {
if (getDx() != 0 && getDy() != 0) {
canvas.translate(getDx(), getDy());
}
super.onDraw(canvas);
}
Hope this helps!
If you want to Move your layout permanently (In case of temporary, we can use animation ) then Use Drag And Drop API from android Official Page . Hope this will help you
Couple of things that would help in achieving it:
Make sure that your view originally has enough space in the direction you want to use. Like 'match_parent' etc
Use GestureDetector.onSimpleGestureListener and override onDraw ( return true;) , onScroll -- connect it using onTouchEvent and you will directly get the distance , or you can calculate yourself by using the event1 and event2
Store this information in variable(s) and call invalidate()
in your onDraw method - use this information by canvas.translate(..use those variables..); super.onDraw(canvas);
and your will achieve the result
PS: The drawing starts by taking left-top as 0,0

keep ontouch event when view is removed and add

I have a view in a linearlayout. When the view is longpressed the view will be removed from this linearlayout and placed, on the same position of the screen, to a relative layout. On this way a can move the view over the screen with my finger.
it almost works:
i got the longpress event working (remove the view and place the view to the relativelayout). after that i add an ontoucheventlistener so my view stays with my finger, but only for a second. the last time the touchevent is fired i got "MotionEvent.ACTION_CANCEL". When i remove my finger and place my finger again to the view i can go feature with my movement, then it will keep until i remove my finger.
I think that my problem is that the view it removed for a short moment, at that time i get a "MotionEvent.ACTION_CANCEL", however, there are still some unhandled events, they will be fired first. Thats why i got for about 1 second still ontouchevents. (this is just a thought).
someone a idee how i can keep the ontouchevent, or let the ontouchevent fired without replacing my finger?
Edited
My thought is not correct. When i do a longpress the view stays with my finger, however i lost the view as soon as i move about 50 to 100 pixels to any direction.
Edited 2
the longpress code of the view inside the linearlayout
view.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
_linearLayout.removeView(v);
moveView(v);
return true;
}
});
moveView will be called by the longpress
private void moveView(View v) {
_relativeLayout.addView(v);
v.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_MOVE:
int x = (int) event.getRawX();
int y = (int) event.getRawY();
v.layout(x, y, x + v.getWidth(), y + v.getHeight());
break;
case MotionEvent.ACTION_UP:
_relativeLayout.removeView(v);
v = null;
break;
case MotionEvent.ACTION_CANCEL:
//it comes here when i move my finger more then 100 pixels
break;
}
return true;
}
});
}
of corse, this is the relevant part of the code and not the original code
Have a look at the Experience - Android Drag and Drop List post. There is also a source code that does something very similar to what are you trying to get. Eric, the author of that post, uses a separate temporary ImageView to hold a dragged view image, taken with getDrawingCache(). He also hides the original list item by setVisibility(View.INVISIBLE).
In the DragNDrop project (link above) you can replace drag(0,y) calls by drag(x,y) in DragNDrop.java to see a dragging in all directions.
Just throwing some possibilities in because I can't see the code but MotionEvent.ACTION_CANCEL could be being called as the parent layout is switched and the view is getting redrawn.
You could try overriding the onTouchEvent and at the point the ACTION_CANCEL event is sent try get hold of an equivalent view in the new layout and operate on that but I still think the better idea is to redesign so it all takes place in the same layout.

Android touchevent--- need help/suggestion according to scenario

Now I have an ImageView and its a circle which is at the slightly below than center position (But this should not matter).
I have written code onTouch of ImageView for ACTION_DOWN,ACTION_UP ,now consider as user have put finger on circle and move and move.... I want to active some code when user move finger and exceed the region of CIRCLE image(As soon as user exceed the region the code should be ececuted onlly once)
Here is my code
ImageView view1 = (ImageView) findViewById(R.id.fccircledetectionarea);
view1.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView imageView=(ImageView) findViewById(R.id.fccircledetectionarea);
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
final float x=imageView.getTop();
Toast.makeText(PlayScreen.this, "Top Position:"+x, Toast.LENGTH_SHORT).show();
break;
case MotionEvent.ACTION_UP:
Toast.makeText(PlayScreen.this, "Over", Toast.LENGTH_SHORT).show();
break;
case MotionEvent.ACTION_MOVE:
Toast.makeText(PlayScreen.this, "Over", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
I cannot archive my goal through ACTION_MOVE: as it start to work if user move finger within the circle
And my second query is that How to set alpha of this imageview I have used
view1.setAlpha(0);
But is not working and I have also made this imageview invisible but than my onTouch code is not working
Within your onTouch method record a boolean to check if the user is touching within the bounds of the circle.
boolean inCircle = java.lang.Math.sqrt(x*x + y*y) <= circleRadius
Where x is taken from event.getX() - circleCenterX and y is taken from event.getY() - circleCenterY (touch position's offset from center of the circle)

Categories

Resources