Android Scaling Animation: translate and scale to parent's parent's centre - android

I'm trying to build an app where if you click on a profile pic, the pic will expand to the centre of the screen with the background of the app dimmed (similar to what you would experience if you click on a profile pic on whatsapp). Clicking anywhere on the dimmed area would reverse the animation and the profile pic will reset back into the original position.
I have the following xml layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:id="#+id/profilepage"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/brown_400"
android:id="#+id/profileBox">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/profilepic"
android:src="#drawable/ic_person_black_24dp"
/>
<TextView
android:layout_toRightOf="#+id/profilepic"
android:layout_alignTop="#+id/profilepic"
android:textSize="20sp"
android:textColor="#color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/profileName"
tools:text="Johnny Appleseed"/>
</RelativeLayout>
...other layout stuff like buttons etc to be put here...
</LinearLayout>
I want to click on the little man above and it should translate and scale to the middle of the screen.
I found some code here Translate and Scale animation in parallel which serve my purpose:
private void moveViewToScreenCenter( final View view ){
view.bringToFront(); //brings the view to the front
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics( dm );
int originalPos[] = new int[2];
view.getLocationOnScreen( originalPos );
int xDelta = (dm.widthPixels - view.getMeasuredWidth() - originalPos[0])/2;
int yDelta = (dm.heightPixels - view.getMeasuredHeight() - originalPos[1])/2;
AnimationSet animSet = new AnimationSet(true);
animSet.setFillAfter(true);
animSet.setDuration(1000);
animSet.setInterpolator(new BounceInterpolator());
TranslateAnimation translate = new TranslateAnimation( 0, xDelta , 0, yDelta);
animSet.addAnimation(translate);
ScaleAnimation scale = new ScaleAnimation(1f, 2f, 1f, 2f, ScaleAnimation.RELATIVE_TO_PARENT, .5f, ScaleAnimation.RELATIVE_TO_PARENT, .5f);
animSet.addAnimation(scale);
view.startAnimation(animSet);
}
However, the code would only scale relative to the parent of the profile pic ImageView, which in my case is the RelativeLayout (#+id/profileBox) and not the parent's parent (#+id/profilepage) which is what I want it to do.
Also, the code: view.bringToFront(); doesn't bring the profile picture to the front of the LinearLayout (profilepage) to scale and translate, but instead brings it to the front of the RelativeLayout (profileBox).
How can I bring it to the front of profilepage and scale it appropriately so that it will be centered in my app screen?

I managed to find an answer to first question: Android View Disappearing When Go Outside Of Parent
I needed to set this for profileBox:
android:clipChildren="false"
android:clipToPadding="false"
And this for profilepage:
android:clipChildren="false"
But I am starting to realise that this might not be the correct strategy for what I want to do as I want the background to be dimmed when the profile pic is translating / scaling and the buttons behind the profile picture not to be accessible as the activity is in a Paused state.
My code above will only translate / scale the image without pausing the activity below so clicking on 'Log Out' will log out the user.

Related

Stop animation from taking my view out of screen android

This is my xml:
<?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"
>
<Button
android:id="#+id/bounceBallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Bounce Ball" />
<ImageView
android:id="#+id/bounceBallImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/bounceBallButton"
android:src="#drawable/ball" />
</RelativeLayout>
and this is my animation code to bounce my imageview:
Button bounceBallButton = (Button) findViewById(R.id.bounceBallButton);
final ImageView bounceBallImage = (ImageView) findViewById(R.id.bounceBallImage);
bounceBallImage.clearAnimation();
TranslateAnimation transAnim = new TranslateAnimation(0, 0, 0, getDisplayHeight());
transAnim.setStartOffset(500);
transAnim.setDuration(3000);
transAnim.setFillAfter(true);
transAnim.setInterpolator(new BounceInterpolator());
bounceBallImage.startAnimation(transAnim);
My problem is that the animation takes my imageview below my screen. I want it to hit at the bottom of my screen and bounce and not go below it.
You animate Y position to getDisplayHeight(). Which means, that you tell the framework:
animate this view's top Y position to the screen's bottom.
And framework does exactly what you say.
What you want to do is to animate to getDisplayHeight() - bounceBallImage.getHeight(). But as soon as you do that, you'll find out, that it gives you the same result. That's because getHeight() returns 0, and that's because your view's hasn't been drawn, hence it has not height.
See here how to know the height of the view as soon as it is measured. You'd be using getMeasuredHeight() instead of getHeight().

change position of image view

i can't change the position of the login button.Because when i try, it can't be moved from the original position. I' ve set the android:layout_gravity and android:gravity but i want it in a specific position.
how i can set the coordinates (x,y) of the image?
this is the login_fragment.xml
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
<ImageView
android:id="#+id/login"
android:layout_width="400px"
android:layout_height="100px"
android:src="#drawable/login_button" />
You cant do it within the xml itself, you need to create an instance of that ImageView in your activity and call its setX() or setY() method to set the coordinates.
Beware that every screen has different number of pixels, you might have different result on different devices.
Sample:
ImageView s = (ImageView) findViewById(R.id.your_id);
s.setY(number);
s.setX(number);
TranslateAnimation animation = new TranslateAnimation(0.0f, 50.0f, 0.0f, 0.0f);
animation.setDuration(700);
animation.setRepeatCount(5);
animation.setRepeatMode(2);
animation.setFillAfter(true);
image.startAnimation(animation);

ImageView moves when scaled/rotated

Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#android:color/transparent"
android:id="#+id/globeViewStreamInfoPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:id="#+id/streamIndicator"
android:src="#drawable/nv_tidestreamindicator"
android:scaleType="matrix"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:maxHeight="40dp"
android:maxWidth="40dp"
android:layout_width="40dp"
android:layout_height="40dp"/>
Code (streamIndicator is the ImageView):
streamIndicatorMatrix.reset();
streamIndicatorMatrix.setScale(size,size);
// rotate indicator in the direction of the flow
streamIndicatorMatrix.setRotate((float)(stream.currentStream.direction));
streamIndicator.setImageMatrix(streamIndicatorMatrix);
When I rotate, or scale, or both, the ImageView moves in the layout.
Weird thing is, when I break on the line after setImagematrix and inspect streamIndicator, mTop, mLeft, mWidth and mHeight all look correct. size and my rotation angle are always legal, sensible values.
I just know this is something stupid, what have I missed?
Thanks!
[EDIT]
Here's a pic, the red arrow was added by me to point to the errant ImageView:
Matrix.setRotate uses the (0, 0) pivot point by default. This is the reason your image moves in the layout. There is a overloaded version of the Matrix.setRotate method that allows you to speficy the pivot point.
final float density = getResources().getDisplayMetrics().density;
final int center = Math.round(20 * density);
streamIndicatorMatrix.setScale(size,size, center, center);
streamIndicatorMatrix.setRotate((float)(stream.currentStream.direction), center, center);

Android - Translating view bigger than screen size causes smearing

I am trying to make a game with several "screen". If the user goes to the edge of a screen, an animation should pop in that shifts out the current screen and shifts in the new screen.
I wanted to do this with a TranslateAnimation. First I calculate an bitmap which contains the first and the second screen and then i want to play this in the view 'transitionView' while i hide the view 'levelView', which originally contained the first screen. After the transition is finished, i want to hide 'transitionView' again and display the new screen in 'levelView'.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewGroup"
android:layout_width="match_parent"
android:layout_height="match_parent">
<view
class="at.test.game.ScreenTransitionTest2$LevelView"
android:id="#+id/levelView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<view
class="at.test.game.ScreenTransitionTest2$TransitionView"
android:id="#+id/transitionView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
</RelativeLayout>
I first tried to to it with an ImageView, but it would always scale down the bitmap regardless of the settings i used. So I now created my own View, which just draws the image from (0, 0).
Since clipping occured, I disabled it in the onCreate method:
((RelativeLayout)findViewById(R.id.viewGroup)).setClipChildren(false);
The animation looks like this:
this.transitionView.setBitmap(calculateBitmap(screen1, screen2));
TranslateAnimation a = new TranslateAnimation(
Animation.ABSOLUTE, startx, Animation.ABSOLUTE, endx,
Animation.ABSOLUTE, starty, Animation.ABSOLUTE, endy);
a.setDuration(3000);
a.setFillAfter(true);
this.transitionView.setAnimation(a);
a.start();
My problem: Only 480x800 of the bitmap is rendered/moved correctly (the bitmap is about 1000x880 and its starting coordinates are like (-40, -40), endcoordinates (-520, -40)) outside this area (so on the bottom of the screen and to the right as the 2nd frame should move in) instead of displaying the rest of the bitmap nothing is drawn or just smeared (see screenshot)
Why does the bitmap not get correctly drawn in the animation? Did I miss some settings? I tried 'wrap_content' for the viewgroup, but that did not help either. Or is it just not possible to slide bigger bitmaps through the whole screen?
screenshot - nothing is drawn on bottom and smearing occurs on the right

Full example of how to programmatically do RotateAnimations?

I want to have an animation with various steps that do moves (translations) and rotations like "straight on, turn left, straight on, ...." of a car.
I am able to do this in an AnimationSet, but fail at rotating around the center of my car image with the "RELATIVE_TO_SELF" setting. I know about
Animation a = new RotateAnimation(0,90,Animation.RELATIVE_TO_SELF,0.5f,... )
for this purpose. Still the rotation occurs around the upper left corner of the screen (or canvas?).
Currently I am solving this by manually keeping track of the position after each animation step, but this is suboptimal.
I suspect that my initial layout setup is bogus:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<!-- view that draws some background -->
<de.bsd.turtlecar.SampleView android:id="#+id/graph_view"
android:layout_height="350px"
android:layout_width="fill_parent"
android:visibility="invisible"
/>
<!-- the car -->
<ImageView android:id="#+id/car_view"
android:src="#drawable/turtle_car"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="invisible"/>
</FrameLayout>
<Button ... onClick="run" ... />
</LinearLayout>
This shows the car in the upper left corner (should show up in a different place -- basically where the animation later starts. And it should be move later).
In my code that is triggered through the run button I do:
ImageView carView = (ImageView) findViewById(R.id.car_view);
print(carView);
AnimationSet animationSet = new AnimationSet(true);
TranslateAnimation a = new TranslateAnimation(
Animation.ABSOLUTE,200, Animation.ABSOLUTE,200,
Animation.ABSOLUTE,200, Animation.ABSOLUTE,200);
a.setDuration(1000);
animationSet.addAnimation(a);
RotateAnimation r = new RotateAnimation(0f, -90f,200,200); // HERE
r.setStartOffset(1000);
r.setDuration(1000);
animationSet.addAnimation(r);
...
So at the point with here, the rotation works, but I have to keep track. if I rotate RELATIVE_TO_SELF, the rotation happens around (0,0) of the screen.
Additional question: what can I do in order to keep the car on screen after the animation has finished?
Or am I completely on the wrong track?
Try adding setFillAfter(true) to your Animations. That will certainly keep the car in its final place and it may solve your rotation point problems too
TranslateAnimation a = new TranslateAnimation(
Animation.ABSOLUTE,200, Animation.ABSOLUTE,200,
Animation.ABSOLUTE,200, Animation.ABSOLUTE,200);
a.setDuration(1000);
a.setFillAfter(true); //HERE
animationSet.addAnimation(a);
RotateAnimation r = new RotateAnimation(0f, -90f,200,200); // HERE
r.setStartOffset(1000);
r.setDuration(1000);
r.setFillAfter(true); //HERE
animationSet.addAnimation(r);
...

Categories

Resources