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.
Related
I'm kind of new, but having a really good time figuring this stuff out. Hope you don't mind helping me where I'm stuck.
Here is my OnTouchListener. It is for the display of a timer and I want the timer to turn off if someone moves the view that displays the time.
I need it so that the view is moved past a certain point and then it implements. Otherwise it gets a little confused with the a click gesture. I'm going to set it so that the timer pauses on click.
The problem is. I'll set the view as "GONE", so that you won't see it after it moves, but I still need the view to go back to it's original place so that when the next timer is started again, it will be reset.
//setOnTouchListener Here
zoneATimerText.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
destroyCountDownTimer();
view.animate()
.x(event.getRawX() + dX)
.y(event.getRawY() + dY)
.setDuration(0)
.start();
Log.v("on move", "you're moving");
break;
default:
return true;
}
return true;
}
});
Save the original position of the view i.e x,y at class level, and when your animation is done you hide the view with visibility gone at that time simply reset the position position of the view with method(view.setX(),view.setY()).
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
I have a GridView with images. On long click the screen gets dark (with black half transparent image that gets visible) and another image become visible that has the same resource of the image long clicked from the grid.
What i want is to be able to drag that image (which i have succeeded), but the image shows at the top corner (as i designed the layout in the XML) and I want it to show up where I clicked (To be precised, i want the center of the dragable picture to be where I perfumed the long click).
My image is fill_parent on FrameLayout and is set on matrix scale to control position...
this is the image part of the XML:
<ImageView
android:id="#+id/imgMainSelectedMovie"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="matrix"
android:visibility="invisible"
android:src="#drawable/escape" />
and this is the OnTouch() part:
public boolean onTouch(View v, MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
X = ev.getX();
Y = ev.getY();
if (longClicked) return true;
break;
case MotionEvent.ACTION_MOVE:
if (longClicked) {
if (!dragStarted) {
dragStarted = true;
myImageView.setX(X);
myImageView.setY(Y);
}
matrix.postTranslate((ev.getX() - X), (ev.getY() - Y));
X = ev.getX();
Y = ev.getY();
myImageView.setImageMatrix(matrix);
return true;
}
break;
case MotionEvent.ACTION_UP:
if (longClicked) {
dark.setVisibility(View.INVISIBLE);
myImageView.setVisibility(View.INVISIBLE);
longClicked = false;
return true;
}
}
return false;
}
thist is what I tried to solve the problem:
if (!dragStarted) {
dragStarted = true; //Changed to true when OnItemLongClick called
myImageView.setX(X);
myImageView.setY(Y);
}
But it only changes the "start point" of the image layout to the entered X and Y.
Problem solved :)
What I did is when onItemLongClick calls I took the X and Y measured from the ACTION_DOWN case in the onTouch, took the matrix current location and did postTranslate to the coordinates from the ACTION_DOWN minus the location of the image.
this is the solution part from the onItemLongCliick:
matrix.getValues(values);
matrixX = values[Matrix.MTRANS_X];
matrixY = values[Matrix.MTRANS_Y];
matrix.postTranslate(X-matrixX, Y-matrixY);
myImageView.setImageMatrix(matrix);
I'm wondering why they didn't put some kind of "setPlace" method for matrix...
Is it possible to create a list view in android that is not fixed to a particular position and user can move the list view on a gesture some what floating listview that can be moved anywhere on the screen?I tried finding it but could not find some link.Does any one have some idea about it?
You can achieve this by setting an OnTouchListener on the list view and overriding it's onTouch() method. In the onTouch() method you will have to handle the touch events like(ACTION_DOWN, ACTION_MOVE). Here is how you can handle touch event:
#Override
public boolean onTouch (View v, MotionEvent event)
{
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
start.set(event.getX(), event.getY()); //saving the initial x and y position
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if(mode == DRAG) {
float scrollByX = event.getX() - start.x; //computing the scroll in X
float scrollByY = event.getY() - start.y; //computing the scroll in Y
v.scrollBy((int)scrollByX/20, 0);
}
break;
}
return false;
}
When the user places the finger down on the screen the ACTION_DOWN event is triggered and when the user drags his finger on the screen ACTION_MOVE event is triggered. Hence a drag event is a combination of ACTION_DOWN and ACTION_MOVE.
Once you have the scrollX and scrollY value the you can move the view on the screen by passing these values to the scrollBy() method of the View class.
Here in the code there are two things to notice:
first is that I have passed 0 as the value of scrollY as it will prevent the list view to be dragged and scrolled simultaneously.
second is that the return value is false as you want the android to handle the scrolling of the list items
Here you can find the complete code for this
I would move the listview using the margins from the layout.
Outline:
Override OnTouch, and based on the event.getX() and event.getY(), update the margins of the listview as follows:
if the parent is a relative layout:
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)mListView.getLayoutParams();
lp.leftMargin = event.getX();
lp.topMargin = event.getY();
mListView.setLayoutParams(lp);
Add the dispatchTouchEvent to your activity so that events from the listview get passed up to onTouch:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
Hope this helps.
Although it's hard to maintain, AbsoluteLayout lets you specify a position in (x,y) coordinates. You would just declare your ListView inside a AbsoluteLayout, get a handle to it in java code where you intercept the clicks and then set new coordinates.
In the Android framework, the word "floating" is usually synonymous with new Window (such as a Dialog). It depends somewhat on what your end goal is, but if you want to create a ListView that floats over the rest of the content in your hierarchy, that you can easily hide and show, you should probably consider wrapping that view inside a PopupWindow, which has methods to allow you to easily show the window with showAsDropdown() and shotAtLocation() and also move it around while visible with update().
This is how the newer versions of the SDK create pop-up lists for Spinner and Menu
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)