Get the width of the parent layout
Asked Answered
P

2

12
Android Studio 2.0 beta 6

I am trying to use ViewPropertyAnimator to move a ImageView (ivSettings) inside a toolbar so that it is 20dp from the right and 20dp from the top, from is current location. And move the ImageView (ivSearch) 20dp from the left and top.

The imageViews are contained in a Toolbar.

This is the initial state and I want to move the icons into the upper corners inside the toolbar.

enter image description here

The code I am using is this to get the width and then subtract a value to get the ivSettings to be 20dp from the right.

final DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
final float widthPx = displayMetrics.widthPixels;

ivSearch.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(20)
    .y(20)
    .setDuration(250)
    .start();

ivSettings.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(widthPx - 160)
    .y(20)
    .setDuration(250)
    .start();

However, having tried this on different screen size I can't get the exact width calculation. Is there a better way of doing this?

Many thanks for any suggestions

Picturesque answered 8/3, 2016 at 16:19 Comment(10)
Try using width from toolbar instead.Majolica
I have set the width to 'match_parent' so toolbar.getWidth() will always return 0.Picturesque
Are you converting dp to pixel, or is widthPx - 160 the expression for calculating width on each device?Majolica
where you calling this code for getting width? in onCreate()?Pact
@Ajinkya, The code is called in a button click event in the fragments onCreateView() method.Picturesque
@Piyush, the widthPx - 160, that was me just trying out different values I wasn't trying to convert anything.Picturesque
@Picturesque "I can't get the exact width calculation" what do you exactly want to say? means displayMetrics not returning you correct width, let me know if i am correctPact
@Majolica I am trying to animate the image on the right so it will be 20dp from the right margin of the toolbar. I thought I could get the width of the toolbar and then subtract 20dp from it and then set the x value to the the result of the subtract value. Thanks.Picturesque
@Picturesque is an animation necessary or are you trying to simply place your views in the toolbar 20 dp away from the edges? I've posted an answer which should help you animate your views, but it would help if you clarified.Proudhon
@ant2009, would help immensely if you could clarify your question. I'm unsure what the initial and final position for your animation are and if you deliberately want to animate the views or simply place them there i.e. if they are statically placed.Proudhon
P
7

You should be able to use the translationX and translationY properties to achieve the effect you want. These properties act as offsets from the original X and Y coordinates of the View.

Essentially translationX will displace the a View towards the right for a positive value and left for a negative value from it's X coordinate. Similarly translationY displaces the View towards the bottom for positive and top for negative values from it's Y coordinate.

Coming to your question, I am assuming that the final position you want to reach is the top left corner for the search icon, and the top right corner for the settings icon with zero padding for each view.

For the search icon I suggest you start by placing it in the top left corner of the toolbar. Then set both the translationX and translationY to 20p. That should place the search icon in the same place as your image. To move your search icon to the top left all you have to do is animate translationX & Y from 20dp to 0 dp.

Repeat the same for the settings icon, but set translationX to -20dp and translationY to 20dp. This way it'll be placed at the same position as your image. Animate both values to 0 to achieve your desired animation.

Here's the animation code for reference.

ivSearch.animate()
    .setInterpolator(new AccelerateInterpolator())
    .translationX(0) // Takes value in pixels. From 20dp to 0dp
    .translationY(0) // Takes value in pixels. From 20dp to 0dp
    .setDuration(250)
    .start();

ivSettings.animate()
    .setInterpolator(new AccelerateInterpolator())
    .translationX(0) // Takes value in pixels. From -20dp to 0dp
    .translationY(0) // Takes value in pixels. From 20dp to 0dp
    .setDuration(250)
    .start();

// To get pixels from dp
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());

The great thing about this approach is that you no longer need to know the dimensions of the parent. All you care about is the offsets that you have specified via translationX and translationY.

Proudhon answered 12/3, 2016 at 18:11 Comment(0)
G
5

I believe the problem is that the Animator methods are expecting the values to be in raw pixel values. It looks like the code would only work as you intend on a medium density screen. E.g. A hdpi screen would require 30px instead of 20px to be located at the same location. On higher density screens the code as it exists would push the icons closer to the edges...

That means we need to translate the expected dp value into raw pixel values and use those for animation. There is a handy method for converting dp to px so that it's correct on every device. I'm assuming that you want the left side of the gear to be 160dp from the right(Note I'm specifically saying the left side of the gear because the 160dp value should also include the width of the gear image as the x property is from the left of the image). So 160dp = gear image width + desired right margin distance. Say you have a resource called ic_gear: Drawable drawable = getResources().getDrawable(R.drawable.ic_gear); float bitmapWidth = getIntrinsicWidth();

float rawPX20DPValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());

float rawPXLeftOffset = rawPX20DPValue + bitmapWidth;

ivSearch.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(rawPX20DPValue)
    .y(rawPX20DPValue)
    .setDuration(250)
    .start();


ivSettings.animate()
    .setInterpolator(new AccelerateInterpolator())
    .x(widthPx - rawPXLeftOffset)
    .y(rawPX20DPValue)
    .setDuration(250)
    .start();

Also check on the offsets(padding) of the gear and search icon before the move as that will likely affect the end result as well.

Glabrate answered 11/3, 2016 at 13:17 Comment(2)
The 160 value was something I was just playing around with. What I am trying to do is animate both images so the one of the left will be 20dp from the left of the toolbar, and the one of the right will be 20dp from the right of the toolbar. For the one of the right, What I was trying to do is calculate the total width of the toolbar and then subtract a value to make it be 20dp from the right margin. I hope you understand more now. Thanks.Picturesque
@Picturesque I've updated it to give you the calculation for the image size. Note that if you have padding on the ImageView you will need to add that into the calculation as well. Let me know if you need further help :)Glabrate

© 2022 - 2024 — McMap. All rights reserved.