I use a phone with Android 2.3 and an animation to move an ImageView.
Here is the animation:
TranslateAnimation anim = new TranslateAnimation(0, xDest, yDest, yDest);
anim.setDuration(1000);
anim.setFillAfter(true);
MoveImagesOutsideOfScreen();
view.setVisibility(View.VISIBLE);
view.startAnimation(anim);
After the animation, when I use the following code to detect touch on my imageview and move it, nothing happens:
ImageView imageView=(ImageView)findViewById(R.id.imageSimple);
imageView.setOnTouchListener(new View.OnTouchListener()
{
PointF DownPT = new PointF(); // Record Mouse Position When Pressed Down
PointF StartPT = new PointF(); // Record Start Position of 'img'
#Override
public boolean onTouch(View v, MotionEvent event)
{
Log.i(TAG,"Touch started");
int eid = event.getAction();
switch (eid)
{
case MotionEvent.ACTION_MOVE:
PointF mv = new PointF(event.getX() - DownPT.x, event.getY() - DownPT.y);
v.setX((int) (StartPT.x + mv.x));
v.setY((int) (StartPT.y + mv.y));
StartPT = new PointF(v.getX(), v.getY());
Log.i(TAG,"Moved ");
break;
case MotionEvent.ACTION_DOWN:
DownPT.x = event.getX();
DownPT.y = event.getY();
StartPT = new PointF(v.getX(), v.getY());
break;
case MotionEvent.ACTION_UP:
// Nothing have to do
break;
default:
break;
}
return true;
}
});
I checked the log and the message Touch started was never shown. What prevents it?
UPDATE: Holy #%*! It seems that an animation doesn't move the actual view but instead some sort of copy (I don't see the concept of it, I think creating a copy is wasteful and most of the times people want to use the moved object).
I saved the layout params at the onCreate, and when I set it back, my views are placed randomly. What should I do to make my view be there where the animation puts its wasteful twin?
paramsSimple= (RelativeLayout.LayoutParams) aq.id(R.id.imageSimple).getImageView().getLayoutParams();
paramsExpert= (RelativeLayout.LayoutParams) aq.id(R.id.imageExpert).getImageView().getLayoutParams();
public void onAnimationEnd(Animation animation)
{
view.setLayoutParams(view.getId()==R.id.imageSimple?paramsSimple:paramsExpert);
}
Related
I want to apply some animation whenever user touch on button, like-
on touch/hover = scale down,
move finger out of the view bound = scale up to previous position,
on release/click = scale up to previous position
On touch animation is working perfectly but I am unable to figure out scale up animation to it's previous position when finger is being released. Also I am not too much familiar with Motion touch event, so please tell me which Motion Event will be appropriate to do this. Can anyone please help me. here is my code:
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
imageView.animate().scaleX(0.5f).scaleY(0.5f).start();
break;
case MotionEvent.ACTION_CANCEL:
imageView.animate().scaleX(2.0f).scaleY(2.0f).start();
break;
case MotionEvent.ACTION_UP:
imageView.animate().scaleX(2.0f).scaleY(2.0f).start();
startActivity(new Intent(ActivityOne.this, ActivityTwo.class));
break;
}
return true;
}
});
I have also tried with object animator, something like that:
private void scaleAnimation(View view) {
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(view, "scaleX", 0.5f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(view, "scaleY", 0.5f);
scaleDownX.setDuration(150);
scaleDownY.setDuration(150);
//scaleDownX.setRepeatMode(ValueAnimator.REVERSE);
//scaleDownY.setRepeatMode(ValueAnimator.REVERSE);
//scaleDownX.setRepeatCount(1);
//scaleDownY.setRepeatCount(1);
animatorSet = new AnimatorSet();
//animatorSet.play(scaleDownX).with(scaleDownY);
animatorSet.playTogether(scaleDownX, scaleDownY);
animatorSet.start();
}
Alright after a long experiment I have discovered the answer by myself. Here it is:
After touch, if user move his finger then we need to cancel button click
boolean isMove;
// initialize
isMove = false;
Set scale down and scale up animation
private void startScaleAnimation(View view) {
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(view, "scaleX", 0.8f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(view, "scaleY", 0.8f);
scaleDownX.setDuration(150);
scaleDownY.setDuration(150);
scaleDownX.start();
scaleDownY.start();
}
private void cancelScaleAnimation(View view) {
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f);
scaleDownX.setDuration(150);
scaleDownY.setDuration(150);
scaleDownX.start();
scaleDownY.start();
}
Now, apply this animation along with onTouch listener
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startScaleAnimation(imageView);
break;
case MotionEvent.ACTION_MOVE:
cancelScaleAnimation(imageView);
isMove =true;
break;
case MotionEvent.ACTION_UP:
cancelScaleAnimation(imageView);
if (!isMove){
isMove = false;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(ActivityOne.this, ActivityTwo.class));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
overridePendingTransition(R.anim.enter_slide_left, R.anim.exit_slide_left);
}
}
},150);
}else {
isMove = false;
}
break;
}
return true;
}
});
Code
private RelativeLayout mToolbar;
mToolbar = (RelativeLayout) myview.findViewById(R.id.toolbar);
mToolbar.setOnTouchListener(new View.OnTouchListener() {
WindowManager.LayoutParams updatedParameters = finalParameters;
double x;
double y;
double pressedX;
double pressedY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = updatedParameters.x;
y = updatedParameters.y;
pressedX = event.getRawX();
pressedY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
updatedParameters.x = (int) (x + (event.getRawX() - pressedX));
updatedParameters.y = (int) (y + (event.getRawY() - pressedY));
wm.updateViewLayout(myview, updatedParameters);
default:
break;
}
return false;
}
});
I have a service and this above code can move around that service in the screen... It worked before when i had to touch a button and move it around. I switched it to layout now and it does.t work anymore
Why doesn't this work? The same code i used it with a button instead and it worked fine. Does onTouch always have to be button or can it be layouts or textviews as well?
You should return true from onTouch method
If you return false when you get MotionEvent.ACTION_DOWN,
Android assumes that you're not interested in handling touch events and simply doesn't pass any other motion events to you (including MotionEvent.ACTION_MOVE that you're expecting)
You need to update the return part of onTouch Method
public boolean onTouch(View v, MotionEvent event) {
// if return is true means touch enabled
// If return is false means touch is disabled
return true;
}
I have looked around the net and stackover flow and seen some answers on how to create a motionevent/drag for an image in my app.
So far I have implemented the following:
private void dragAndDrop(){
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) image
.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
int x_cord = (int) event.getRawX();
int y_cord = (int) event.getRawY();
if (x_cord > windowwidth) {
x_cord = windowwidth;
}
if (y_cord > windowheight) {
y_cord = windowheight;
}
layoutParams.leftMargin = x_cord - 25;
layoutParams.topMargin = y_cord - 75;
image.setLayoutParams(layoutParams);
break;
default:
break;
}
return true;
}
});
}
Now this works to an extent, but every time I click on the image, the image will jump below about a few centimetres below my finger, I am not sure why
But I can move the image around just fine.
But my question is, is this now the updated way to do it? Have I missed an easy to use class to let the user move the image around?
Thanks
I created an onTouchEvent to find where the user touches and move my object to that position. what I would like to do is if the user presses up on the screen, the object moves a certain distance straight up. and the same for the other directions. I know that I need a few if statements to do this but I don't know how to do it. does anyone have any advice or know how to do this, thanks
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN) {
// the new image position became where you touched
x = ev.getX();
y = ev.getY();
// if statement to detect where user presses down
if(){
}
// redraw the image at the new position
Draw.this.invalidate();
}
return true;
}
Try this
public boolean onTouchEvent(MotionEvent ev) {
initialise boolean actionDownFlag = false;
if(ev.getAction() == MotionEvent.ACTION_DOWN) {
// the new image position became where you touched
x = (int) ev.getX();
y = (int) ev.getY();
// if statement to detect where user presses down
if(actionDownFlag){
catcher.moveDown();
}
// redraw the image at the new position
Draw.this.invalidate();
}
return true;
}
public void moveDown(){
posX -= //WhereEver you want to move the position (-5);
}
try this:
layout_counter.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event)
{
if (currentState != State.EDIT_MOVE) return false;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
if (view.getId() != R.id.layout_counter) return false;
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
params.topMargin = (int) event.getRawY() - view.getHeight();
params.leftMargin = (int) event.getRawX() - (view.getWidth() / 2);
view.setLayoutParams(params);
break;
case MotionEvent.ACTION_UP:
params.topMargin = (int) event.getRawY() - view.getHeight();
params.leftMargin = (int) event.getRawX() - (view.getWidth() / 2);
view.setLayoutParams(params);
break;
case MotionEvent.ACTION_DOWN:
view.setLayoutParams(params);
break;
}
return true;
}
});
You need to use OnLongClickListener which suits better with drag and drop framework of android:
Observe the following example:
public class MainActivity extends Activity {
private ImageView myImage;
private static final String IMAGEVIEW_TAG = "The Android Logo";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myImage = (ImageView)findViewById(R.id.image);
// Sets the tag
myImage.setTag(IMAGEVIEW_TAG);
// set the listener to the dragging data
myImage.setOnLongClickListener(new MyClickListener());
findViewById(R.id.toplinear).setOnDragListener(new MyDragListener());
findViewById(R.id.bottomlinear).setOnDragListener(new MyDragListener());
}
private final class MyClickListener implements OnLongClickListener {
// called when the item is long-clicked
#Override
public boolean onLongClick(View view) {
// TODO Auto-generated method stub
// create it from the object's tag
ClipData.Item item = new ClipData.Item((CharSequence)view.getTag());
String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN };
ClipData data = new ClipData(view.getTag().toString(), mimeTypes, item);
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag( data, //data to be dragged
shadowBuilder, //drag shadow
view, //local data about the drag and drop operation
0 //no needed flags
);
view.setVisibility(View.INVISIBLE);
return true;
}
}
class MyDragListener implements OnDragListener {
Drawable normalShape = getResources().getDrawable(R.drawable.normal_shape);
Drawable targetShape = getResources().getDrawable(R.drawable.target_shape);
#Override
public boolean onDrag(View v, DragEvent event) {
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackground(targetShape); //change the shape of the view
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
v.setBackground(normalShape); //change the shape of the view back to normal
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
// if the view is the bottomlinear, we accept the drag item
if(v == findViewById(R.id.bottomlinear)) {
View view = (View) event.getLocalState();
ViewGroup viewgroup = (ViewGroup) view.getParent();
viewgroup.removeView(view);
//change the text
TextView text = (TextView) v.findViewById(R.id.text);
text.setText("The item is dropped");
LinearLayout containView = (LinearLayout) v;
containView.addView(view);
view.setVisibility(View.VISIBLE);
} else {
View view = (View) event.getLocalState();
view.setVisibility(View.VISIBLE);
Context context = getApplicationContext();
Toast.makeText(context, "You can't drop the image here",
Toast.LENGTH_LONG).show();
break;
}
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
v.setBackground(normalShape); //go back to normal shape
default:
break;
}
return true;
}
}
}
The above code taken from here demonstrates how to drag and drop and how to do something while dragging..
I've used something similar as well.
I’m working on an app in which I want to drag a button. I have written two programs. The problem is that each of them is fulfilling only a specific part of what I want. I want a button which can be moved freely on the screen (no disappearing and stuff) and I also need the program to give me the coordinates of the local button position while moving (permanent).
In the first program is the problem that the button disappears while dragging. This happens for the negative values of x and y and also for positive x values (not for positive y values; here is everything perfect). Positive y values are everything above the button, positive x values everything on the right side of the button and so on. For the negative values the button disappears like there is wall which covers the button. For the positive x values the button vanishes with rising x value (a little bit like a fizzing tablet in water).
Here is the code:
seat_leftright = (ImageButton) findViewById(R.id.seat_leftright);
seat_leftright.setOnTouchListener(new OnTouchListener() {
int k = 0;
int prevX,prevY;
int x=0;
int y=0;
#Override
public boolean onTouch(final View v,final MotionEvent event)
{
final LinearLayout.LayoutParams par=(LinearLayout.LayoutParams)v.getLayoutParams();
switch(event.getAction())
{
case MotionEvent.ACTION_MOVE:
{
if(k == 0){ //otherwise there would be an offset when touching the button the first time
prevY=(int)event.getRawY();
prevX=(int)event.getRawX();
}
y+=prevY -(int)event.getRawY();
prevY=(int)event.getRawY();
par.bottomMargin = y;
x+=(int)event.getRawX()-prevX;
prevX=(int)event.getRawX();
par.leftMargin = x;
Log.i("LOG","x: "+ x +", y: " + y );
k++;
v.setLayoutParams(par);
return true;
}
case MotionEvent.ACTION_UP:
{
par.bottomMargin=0;
par.leftMargin=0;
k=0;
y=0;
x=0;
v.setLayoutParams(par);
return true;
}
}
return false;
}
});
}
In the second program I used the DragShadowBuilder function. The button works perfectly in this program, so it is not disappearing or the like. Here I have problems with receiving the values. I constantly need the x and y position of the button while moving. I tried it with the Action_drag_location, but it only returns the coordinates when I’m dragging the button above another button (here it is the button “arrow_down”). Replacing the “arrow_down” button with my background for constantly receiving the coordinates didn’t work at all. I also tried to combine my first program with the second with the result that I didn’t received any values at all.
I hope you can help me with this. I’m grateful for every kind of help!
Below the code of the second program.
OnTouchListener myOnTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
view);
view.startDrag(null, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
}
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
view.setVisibility(View.VISIBLE);}
return true;
}
};
OnDragListener myDragListener = new OnDragListener() {
#Override
public boolean onDrag(View layoutview, DragEvent dragevent) {
int action = dragevent.getAction();
View view = (View) dragevent.getLocalState();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
Log.i("LOG","DragStarted");
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_LOCATION:
float x = (int)layoutview.getX();
float y = (int)layoutview.getY();
Log.i("COORDS","X: " + x +" Y: " + y);
break;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DROP:
break;
case DragEvent.ACTION_DRAG_ENDED:
Log.d("LOG", "Drag ended");
if (dropEventNotHandled(dragevent)) {
view.setVisibility(View.VISIBLE);
}
break;
default:
break;
}
return true;
}
private boolean dropEventNotHandled(DragEvent dragEvent) {
return !dragEvent.getResult();
}
};
findViewById(R.id.arrow_up).setOnTouchListener(myOnTouchListener);
findViewById(R.id.arrow_down).setOnDragListener(myDragListener);
#Jay: Thanks for your help, but that didn't solve the problem. The disappearing buttons were due to my layout, where I had this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/seat" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="20dp"
android:layout_marginBottom="160dp"
android:orientation="vertical" >
<ImageButton
android:id="#+id/seat_updown"
android:layout_width="120dp"
android:layout_height="140dp"
android:scaleType="fitCenter"
android:src="#drawable/doublearrow"
android:rotation="90" /> />
</LinearLayout>
Because the ImageButton was imbedded in the LinearLayout it disappeared!
For button drag & drop I share my code here check it.
Here button touch listener.
MultiTouchListener touchListener = new MultiTouchListener(this);
onButton.setOnTouchListener(touchListener);
Touch listener class.
public class MultiTouchListener implements OnTouchListener {
private float mPrevX;
private float mPrevY;
public MainActivity mainActivity;
public MultiTouchListener(MainActivity mainActivity1) {
mainActivity = mainActivity1;
}
#Override
public boolean onTouch(View view, MotionEvent event) {
float currX, currY;
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
mPrevX = event.getX();
mPrevY = event.getY();
break;
}
case MotionEvent.ACTION_MOVE: {
currX = event.getRawX();
currY = event.getRawY();
MarginLayoutParams marginParams = new MarginLayoutParams(
view.getLayoutParams());
marginParams.setMargins((int) (currX - mPrevX),
(int) (currY - mPrevY), 0, 0);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
marginParams);
view.setLayoutParams(layoutParams);
break;
}
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
Sure, you can get these, make sure the views are drawn atleast once before you try to get the positions. You could try to get the positions in onResume() and try these functions
view.getLocationInWindow() or view.getLocationOnScreen()
or if you need something relative to the parent, use
view.getLeft(), view.getTop()
Follow this link for coordinates.
Retrieve the X & Y coordinates of a button in android?