Why my animation does not stop in the to-x given value? - android

I want to move a view on touch and when the user unholds this view, it is started an animation which moves my view to the end of its parent.
This is my layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/time_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<AbsoluteLayout
android:id="#+id/slide_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:background="#0000FF" >
<View
android:id="#+id/slide_to_pause"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00FFFF" />
</AbsoluteLayout>
</RelativeLayout>
This is how I set the view to move in my onCreate:
slideView = ((View) findViewById(R.id.slide_to_pause));
slideView.setOnTouchListener(this);
This is how I move the view and starts the animation:
#Override
public boolean onTouch(View view, MotionEvent event) {
AbsoluteLayout.LayoutParams layoutParams = (AbsoluteLayout.LayoutParams) view.getLayoutParams();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mX = event.getRawX();
break;
case MotionEvent.ACTION_UP:
int endOfAnimation = findViewById(R.id.slide_layout).getWidth() - view.getWidth();
mSlideAnimation = new TranslateAnimation(0, endOfAnimation - layoutParams.x, 0, 0);
mSlideAnimation.setDuration(1000);
view.startAnimation(mSlideAnimation);
Log.d(TAG, "endOfAnimation = " + layoutParams.x + " | " + endOfAnimation);
break;
case MotionEvent.ACTION_MOVE:
layoutParams.x = (int) event.getRawX();
view.setLayoutParams(layoutParams);
break;
}
return true;
}
The problem is that when the view arrives at the end it comes back to a point in the midle of the screen, which is the point where the user unholds the view.
How can I fix this?
Thank you!

You need to use
mSlideAnimation.setFillAfter(true);
to make it not revert back to the start.
If that doesn't work you might have to follow the suggestion on Animation.setFillAfter/Before - Do they work/What are they for?

You can simulate animation manually (move views yourself, without animation framework) by using
View.offsetLeftAndRight(int offset)
View.offsetTopAndBottom(int offset)

Related

Make two ImageViews coincident zooming

I have two ImageViews on a layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:id="#+id/root">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/zoom" />
<ImageView
android:layout_width="55dp"
android:layout_height="55dp"
android:id="#+id/drag"
android:layout_gravity="center_horizontal|top"
android:layout_alignParentTop="false" />
</RelativeLayout>
The ImageView with id zoom has implemented the PhotoViewAttacher which makes the ImageView zoomable.
The other ImageView with id = drag has a OnTouchListener:
drag.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
//Definition MotionEvent.ACTION_MASK: Bit mask of the parts of the action code that are the action itself.
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
int i = lParams.leftMargin;
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
v.setLayoutParams(layoutParams);
break;
}
viewGroup.invalidate();
return true;
}
});
So the drag ImageView is moveable around the screen.
What I want is: If I zoom in, the drag ImageView shall be zoomed in too. Same the other way while zooming out.
How can I place the drag ImageView in a way that it is "docked" on the zoom ImageView. So if I move the zoom image around the screen, the drag image have to stay on the position it left.
For example:
drag is moved to center of the screen.
zoom is zoomed in
zoom moved to right so the drag image is moved outside the screen
zoom moved back to the center where the drag image is docked
I hope you understand what I want to do
Kind Regards!!

Android center Bitmap in ImageView matrix

I am working on an app where user can move his image within the screen, and then save it.
The problem is positioning Bitmap in ImageView on start of the activity.
Here is the XML:
<RelativeLayout
android:id="#+id/image_content_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/top_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:scaleType="matrix"
android:gravity="center|center_vertical"
android:layout_gravity="center|center_vertical"/>
</RelativeLayout>
I am moving the ImageView (well, not ImageView, but its matrix) with onTouch, and it works well.
#Override
public boolean onTouch(View v, MotionEvent event)
{
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
mode = DRAG;
start.set((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
{
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
}
break;
}
view.setImageMatrix(matrix);
return true;
}
The problem is the position of Bitmap on the start of Activity. It is aligned on Top|Left instead of Center. Like this:
Can anyone please help me center it on start in ImageView?
If you want to align bitmap to center then you ImageView layout should be:
<ImageView
android:id="#+id/top_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"/>
EDIT:
In case if you need scaleType "matrix" then use next solution:
<ImageView
android:id="#+id/top_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
/>
And then in code change offset of image:
final ImageView imageView = (ImageView) findViewById(R.id.top_image);
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Drawable drawable = imageView.getDrawable();
Rect rectDrawable = drawable.getBounds();
float leftOffset = (imageView.getMeasuredWidth() - rectDrawable.width()) / 2f;
float topOffset = (imageView.getMeasuredHeight() - rectDrawable.height()) / 2f;
Matrix matrix = imageView.getImageMatrix();
matrix.postTranslate(leftOffset, topOffset);
imageView.setImageMatrix(matrix);
imageView.invalidate();
}
});
This worked for me.
<ImageView
android:id="#+id/top_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
/>

Change width of the Activity's layout based on MotionEvent

What I am trying to do is to Override the dispatchTouchEvent(MotionEvent ev) method, get the actions, calculate the movement, and then show the bottom part based on the movements.
Here is my basic idea:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = ev.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_DOWN:
mDownX = ev.getRawX();
mDownY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float deltaY = ev.getRawY() - mDownY;
Log.d(TAG, "delta y: " + deltaY);
if (deltaY < -50f) {
// show bottom part
}
if (deltaY > 50f) {
// close bottom part
}
break;
default:
break;
}
return false;
}
My question is: What should I use to change the width of this Activity's width and show the bottom part?
Thanks in advance :-)
Ok, so I love layout hacks.
For this example, I will have a top section and a bottom section, which is the section you would like to expose on motion event.
On your swipe function, set the visibility of the bottomBlock to visible, the animateLayoutChanges will make it look like it's sliding up.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0"
android:layout_weight="1"
android:orientation="vertical"
android:animateLayoutChanges="true" >
<LinearLayout
android:id="#+id/topBlock"
android:layout_width="match_parent"
android:layout_height="0"
android:layout_weight="1" >
</LinearLayout>
<LinearLayout
android:id="#+id/bottomBlock"
android:layout_width="match_parent"
android:layout_height="100dp"
android:visibility="gone" >
</LinearLayout>
</LinearLayout

Using a Viewflipper with Gridview

I've created a calendar which works fine, using a GridView which has an OnClickListener.
Now I wrapped the two GridViews in a ViewFlipper. The ViewFlipper has an OnTouchListener which also works fine, I can change the view by using ontouch when dragging. The problem is though that I have to drag on the EMTPY space in the Activity in order to use the ViewFlipper. When I drag on the GridView, nothing happends at all. But I can click on the GridView for OnClickListener.
xml:
<ViewFlipper android:id="#+id/details"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<GridView
android:id="#+id/weeks"
android:numColumns="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="8">
</GridView>
<GridView
android:id="#+id/calendar"
android:numColumns="7"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</GridView>
</LinearLayout>
android code:
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// Get the action that was done on this touch event
switch (arg1.getAction())
{
case MotionEvent.ACTION_DOWN:
{
// store the X value when the user's finger was pressed down
downXValue = arg1.getX();
break;
}
case MotionEvent.ACTION_UP:
{
// Get the X value when the user released his/her finger
currentX = arg1.getX();
// going backwards: pushing stuff to the right
if (currentX - downXValue < -(arg0.getWidth()/3))
{
mdh.nextMonth();
calendar.add(Calendar.MONTH, 1);
currentMonth.setText(new SimpleDateFormat("MMMM yyyy").format(calendar.getTime()));
cAdapter.notifyDataSetChanged();
updateWeeks();
// Set the animation
vf.setInAnimation(arg0.getContext(), R.anim.push_left_in);
vf.setOutAnimation(arg0.getContext(), R.anim.push_left_out);
// Flip!
vf.showPrevious();
}
// going forwards: pushing stuff to the left
if (currentX - downXValue > arg0.getWidth()/3)
{
mdh.previousMonth();
calendar.add(Calendar.MONTH, -1);
currentMonth.setText(new SimpleDateFormat("MMMM yyyy").format(calendar.getTime()));
cAdapter.notifyDataSetChanged();
updateWeeks();
// Set the animation
vf.setInAnimation(arg0.getContext(), R.anim.push_right_in);
vf.setOutAnimation(arg0.getContext(), R.anim.push_right_out);
// Flip!
vf.showNext();
}
break;
}
gridview.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
return detector.onTouchEvent(event);
}
});
I had the same issue with a ViewFlipper and ScrollViews.
Try adding the onTouchListener to your GridView aswell and it should work.

Android: Scrollable (horizontal and vertical) ImageView with Buttons overlayed

I want to implement an activity where the only thing you see is a big image, which can be scrolled horizontally and vertically.On Top of that image I want to display buttons, that can be clicked and trigger certain actions (like creating an intent to start a new activity).
First I was thinking about a ScrollView, that has a FrameLayout as a child. The FrameLayout could have the image as a background and can have the buttons as childs. Because I know the position of my buttons exactly I could place them with absolute coordinates. Here is my first code:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:layout_width="1298px"
android:layout_height="945px"
android:background="#drawable/myimage">
<Button
android:id="#+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="115px"
android:layout_y="128px"/>
</FrameLayout>
</ScrollView>
The Problem is, that you can only scroll a ScrollView vertically. HorizontalScrollView doesn't solve the Problem, cause it only scrolls in one direction either. Can I mix them somehow? Is there another solution?
I found some similar threads on stackoverflow, where people put the image into a WebView and get horizonzal/vertical scrolling for free (here). Or someone put the image in an imageview and gave the imageview an onTouchListener to handle scrolling (here). The Problem with both ways is, that I either way I dont think you can put Buttons on top of the image, which is what I need to do.
I would very appreciate if someone help me out.
Using the (deprecated!!!) AbsoluteLayout and giving it and onTouchListener solved my problem:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:src="#drawable/myImage"
android:layout_width="1298px"
android:layout_height="945px"
android:layout_x="0px"
android:layout_y="0px" />
<Button
android:id="#+id/myButton"
android:text="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="50px"
android:layout_y="300px"
android:tag="1"/>
</AbsoluteLayout>
private float mx;
private float my;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
final Button button = (Button)findViewById(R.id.myButton);
button.setOnClickListener (new View.OnClickListener(){
// OnClickAction
});
final AbsoluteLayout switcherView = (AbsoluteLayout) this.findViewById(R.id.myLayout);
switcherView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent event) {
float curX, curY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
break;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
switcherView.scrollBy((int) (mx - curX), (int) (my - curY));
mx = curX;
my = curY;
break;
case MotionEvent.ACTION_UP:
curX = event.getX();
curY = event.getY();
switcherView.scrollBy((int) (mx - curX), (int) (my - curY));
break;
}
return true;
}
});
}

Categories

Resources