Stop animation from taking my view out of screen android - 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().

Related

How to put views on top of an ImageView, in relation to the ImageView's content size?

Background
Suppose I want to show an image of the something using an ImageView, and I want to put new views on top of it (animated ImageViews that show pins on a world map image, for example, or a Switch view on top of a smartphone image).
This means that no matter how the ImageView shows the image, the views should be in it, inside correct spot, with the same size as specified, or in a size related to the imageView itself
The problem
As opposed to other views, the ImageView can have a certain size, but its content is something else (to keep aspect ratio).
What I tried
I tried to use ConstraintLayout, but this can't really help, because the ImageView can change its size (for example when changing orientation), and thus ruining the position I've given the views compared to the ImageView.
I've found some libraries that can handle a similar thing (like here) and I even asked a similar question before (here), but all those solutions are for a static image within the ImageView, yet what I search for is adding a view on top of an ImageView.
The question
How do I put the views on top of the ImageView's content correctly?
How do I also scale the views down/up compared to the size of the ImageView's content ?
Can ConstraintLayout be used to change the scale of the views according to the ImageView's size ?
Make FrameLayout with wrap_content around ImageView. Then you could set SwitchView on top of ImageView. You could align it to center, side or corners and using margins to get some fine position.
It still won't scale with image, but you can get pretty good results. If that doesn't fit you, you can programatically get width/height of ImageView and alter position (or margins) of SwitchView accordingly.
With below you can manage width of switch or any other view as per image view width
android:layout_alignLeft="#+id/imageView"
android:layout_alignRight="#+id/imageView"
<Switch
android:id="#+id/swi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/imageView"
android:layout_alignRight="#+id/imageView" />
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/swi"
android:src="#drawable/download" />
In Java,
ImageView imgView = (ImageView) findViewById(R.id.imageView);
imageView.setBackgroundResource(R.drawable.yourDrawable);
int width = imgView.getDrawable().getIntrinsicWidth();
Switch switchKey = (Switch) findViewById(R.id.switchKey);
switchKey.setMinimumWidth(width);
And in XML, align it with alignLeft and alignRight with ImageView.
As far as i get it, you need the image size displayed inside the image view and set that as the max width of your switch view right?
You need both Java and XML for this,
The XML file is basically as RelativeLayout with the view stacked as needed.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:src="#drawable/nonet_icon"
android:id="#+id/iconView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.v7.widget.SwitchCompat
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true"
android:layout_height="wrap_content"
android:id="#+id/switchView"/>
</RelativeLayout>
And the Java Code gets the imageWidth and sets it to the SwitchView.
mSwitchCompat.setVisibility(View.VISIBLE);
// 20% x 25% of Content in ImageView
final float x = mImageView.getDrawable().getIntrinsicWidth()*.2f;
final float y = mImageView.getDrawable().getIntrinsicHeight()*.25f;
// waiting for the view to be drawn
mSwitchCompat.post(new Runnable() {
#Override
public void run() {
// scale current view W.r.t. x and y values
mSwitchCompat.setScaleX((float)mSwitchCompat.getWidth()/x);
mSwitchCompat.setScaleY((float)mSwitchCompat.getHeight()/y);
}
});
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);
// 30% x 35% of content, for location
int xMargin = Math.round(mImageView.getDrawable().getIntrinsicWidth()*.3f);
int yMargin = Math.round(mImageView.getDrawable().getIntrinsicHeight()*.35f);
// set margin values, can optionally add for top and bottom
layoutParams.setMargins(xMargin,0,yMargin,0);
mSwitchCompat.setLayoutParams(layoutParams);
Ref: Getting Displayed image size of an ImageView
Trying to get the display size of an image in an ImageView
Ref: Dynamic size values
Do comment if you need a detailed explaination.
Example: Check this image!
Scaled View on Image: Scaled View on Image!
You can use MarginLayoutParams with Relative Layout to set left and top position in ImageView.
image = (ImageView) findViewById(R.id.imageID);
MarginLayoutParams marginParams = new MarginLayoutParams(image.getLayoutParams());
marginParams.setMargins(left_margin, top_margin, right_margin, bottom_margin);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
image.setLayoutParams(layoutParams);
find complete information for this in below link :
MarginLayoutParams
Try this, may be it will help you.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/img_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/semi_transparent"
android:layout_margin="#dimen/spacing_small"
android:layout_alignTop="#+id/img_background"
android:layout_alignBottom="#id/img_background">
//this layout will expand according to your image size
</RelativeLayout>
</RelativeLayout>
Do you want to show switch that lay on imageview ?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_download"
android:layout_width="100dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:orientation="vertical">
<ImageView
android:src="#android:drawable/btn_star_big_on"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Switch
android:id="#+id/mySwitch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Switch" />
</RelativeLayout>

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

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.

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);

After rotating a linearlayout, the onclick events do not change position after the rotation

I have a vertical linearlayout with three clickable imageviews within the linearlayout. When i rotate the linearlayout by 90 degrees using simple animation the problem arises. The imageviews are rotated correctly but the onclick events for the imageviews are not rotated along with the linearlayout and remain in the original position as before the animation.
Below is my main java code
westplayer = (LinearLayout) findViewById(R.id.linearLayout_west);
// Create an animation instance
Animation an = new RotateAnimation(0.0f, 180.0f, 32, 180);
// Set the animation's parameters
an.setDuration(0); // duration in ms
an.setRepeatCount(0); // -1 = infinite repeated
an.setRepeatMode(Animation.REVERSE); // reverses each repeat
an.setFillAfter(true); // keep rotation after animation
// Apply animation to linearlayout
westplayer.setAnimation(an);
The code above handles the animation part. The code below follows the animation and is supoosed to update the layout positions but is not working for me.
// Update Layout
int top=westplayer.getTop();
int bottom=westplayer.getBottom();
int left=westplayer.getLeft();
int right=westplayer.getRight();
westplayer.layout(left, top , right, bottom );
The xml is as follows:
<LinearLayout
android:id="#+id/linearLayout_west"
android:layout_width="42dp"
android:layout_height="250dp"
android:layout_alignParentLeft="true"
android:layout_below="#+id/linearLayout_north"
android:duplicateParentState="false"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageViewW1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/spades_14"
/>
<ImageView
android:id="#+id/imageViewW2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/spades_14"
android:layout_marginTop="-15dp"
/>
<ImageView
android:id="#+id/imageViewW3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/spades_14"
android:layout_marginTop="-15dp"
/>
</LinearLayout>
I have got the update layout code from this and also found another solution that i have also tried this and still no positive results. I need this to work for API 10. Any help is much appreciated
Yes, you got the expected result.
Since Animation in android only try to apply a transformation matrix on the bitmap of view, it doesn't change the position and size of view.
So after your animation, although you setFillAfter(true) to let the view looks rotated, but in fact the view are still in the same place and doesn't move a little bit.
The problem you face, is because you use a Tween Animation. The View will rotate and only the visible part will move. But the positions of the ImageView will remain the same like defined in the layout. That's why the clickable area stays the same.
To redefine the position, according to the animation you will have to use a Property Animation, like a ObjectAnimator or a ValueAnimator. With this the propertys defined in xml will be updated. Now the clickable areas move along with the views.

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);

Categories

Resources