JourneyWithAndroid
JourneyWithAndroid

Reputation: 250

Needle rotating about its pointer head

enter image description hereI have a needle image that I need to rotate when a given value changes. The values obtained are random.

I created the Image in xml which is an imageview.

      <RelativeLayout
    android:id="@+id/relativeLayout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerInParent="false" >

    <ImageView
        android:id="@+id/meter_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_centerInParent="true"
        android:layout_marginTop="54dp"
        android:src="@drawable/gauge_meter" />

    <ImageView
        android:id="@+id/meter_needle_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/meter_image"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="14dp"
        android:src="@drawable/meter_needle" />
</RelativeLayout>

I rotated using the following code but then it rotates not at its bottom axis

 RotateAnimation rpmNeedleDeflection = new RotateAnimation((float) (0.5f), (float) (90), 130, 0);

     rpmNeedleDeflection.setDuration(500);

     rpmNeedleDeflection.setFillAfter(true);

     rpmArrowView.startAnimation(rpmNeedleDeflection);

I am still figuring out how rotation works and in my case I need to set the angle based on the speed. But right now given a value how do I make it to turn around from the bottom of the needle and around that axis?

EDIT: The needle is 31* 113 and the bottom image is 224*224

Upvotes: 2

Views: 786

Answers (2)

Gil Moshayof
Gil Moshayof

Reputation: 16761

To solve this issue, you have 2 options:

Option 1:

Resize your needle image to be exactly the same size as the background image, meaning from 31 by 113, to 224 by 224. When you do this, make sure you don't actually just scale the image to this size (this will result in a weird stretched needle image). What you want to do is to create a transparent image 224x224, and copy paste the needle image in the original size (31x113) into this new transparent image, so that the needle's base circle is exactly in the center of the 224x224 transparent image, and is correctly aligned with the "imaginary" background. Save and export the image to a png format, and use this image as your needle image.

All you need to do now is to make sure the 2 images are perfectly aligned with each other. This shouldn't be difficult since they should both be the same size. When you rotate the needle image, you will get the desired result.

Option 2:

Let's say you can't resize the image - perhaps because it is used by other parts of your programs, or some other reason. Your 2nd option would be to position the image, and use pivot points to make sure that it is correctly positions via the code.

To do this, you'll want to centre the image horizontally, and vertically, you'll want to align it so that the needle's base is directly in the centre of the background.

As far as positioning goes, it will require some try and error to get it perfect, but it seems like you've already got that part nailed. What you're missing is the pivot point to rotate around. Lets see how we can calculate it:

Math time!

I'm going to guess that the diameter is equal to the width of the image, since it is its widest part. This means that the horizontal centre of the needle is at half the width of the image:

final int pivotX = rpmArrowView.getMeasuredWidth() / 2;

The vertical centre of the image should be the same, except from the bottom of the image:

final int pivotY = rpmArrowView.getMeasuredHeight() - rpmArrowView.getMeasuredWidth() / 2;

Now, before you animate, make sure to set the pivot point:

rpmArrowView.setPivotX(pivotX);
rpmArrowView.setPivotY(pivotY);

Then to animate:

rpmArrowView.animate().rotation(someDegree).setDuration(someDuration)

And that's it! It might require a bit more tweaking to get the positioning perfect, but that's the gist of it.

Hope one of these options helps you.

Upvotes: 4

and_dev
and_dev

Reputation: 3861

You only have to make the needle image the same size as the bottom image, center both. You have to create another 224*224 transparent image with needle at the center, then the rotation should easily match the center. Then it will be sufficient to use the following Rotation Constructor:

RotateAnimation(float fromDegrees, float toDegrees)

Upvotes: 1

Related Questions