0

I have a TextView with the Text "O". I want to move/animate it in a circle area and I don't want it to go outside of that area. I can animate it using the follwoing code snippet:

ObjectAnimator.OfFloat(txtTitle,"translationY",850).SetDuration(1000).Start();

which changes translationY to 850. I can do it for translationX too but it can get out of the circle. The value for translation (in the code it is 850) is randomized and I think 850 is px and not dp. This is my first problem.I can't animate the object with dp values.Is there a way to fix it?

if I can find a way to move the object with dp value, I can animate it inside a circle with a little bit of math. But if there's no way for that, how can animate/move my object in circle area?

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
Hope Rises
  • 3
  • 1
  • 6
  • How are you making this circle? – FreakyAli Feb 22 '19 at 08:05
  • @G.hakim i'm using a Linearlayout with background of drawable for circle.it's a amature way to draw a circle, but i just wanted a circle background to see the circle borders.is there easier way to draw circle ? (i'm new to xamarin android) – Hope Rises Feb 22 '19 at 08:21
  • No this is fine, now all you need is the layout params of this circle then you can decide on that basis how to animate – FreakyAli Feb 22 '19 at 08:25
  • @G.hakim i've made layout_width and layout_height 300dp.when i use `ObjectAnimator.OfFloat(txtTitle,"translationY",450).SetDuration(1000).Start();` the object(textview) goes to the bottom of linearlayout.i don't know how 450 value is equal to 300dp – Hope Rises Feb 22 '19 at 08:30
  • 1
    you can check this for that convert pixel to dp https://stackoverflow.com/questions/40819194/how-to-convert-dp-to-px-in-xamarin-android – FreakyAli Feb 22 '19 at 08:39
  • @G.hakim It worked.thanks.I just need to add a few lines to calculate the circle area so that it doesn't go outside that. – Hope Rises Feb 22 '19 at 09:25
  • Yes see to it you keep a 3dp distance from the inner circumference so it will look good – FreakyAli Feb 22 '19 at 10:10
  • And yeah feel free if you need anymore help! – FreakyAli Feb 22 '19 at 10:35

1 Answers1

0

The reason that it can get out of the ‘circle’ is twofold:

First, Android does not include a spatial limit for translations. You can translate an item off the screen if you like (and this is often done to give the impression of a widget disappearing off the screen). You can clip to the containing layout or to any shape you like, so an item is not drawn outside it but it will still disappear at the edge, not be contained by it.

Second, all visual elements in Android (and iOS) are actually rectangles, no matter what is drawn. So even if you bound a widget to the edge of your containing layout, it will still exit the boundaries of your drawn circle, because the system has no concept of what that is.

So. You need to do the calculations yourself, and work out where the boundaries of your circle are and ensure that the ‘translation X and Y’ never extend beyond it. See this https://www.mathopenref.com/coordbasiccircle.html for a reference on how to do this for a circle.

You will then find you have the added complication of working out where your translated view intersects with the circle boundary and adjusting accordingly (remember that the translated view is actually a rectangle containing your ‘drawn object’). If your ‘drawn object’ is an exact circle, this is easy (you adjust by its radius). Given that you are working with circles you may wish to translate the standard Cartesian coordinate system to a Polar one and use Radians.

If you are using a CV library, it may come with a method for calculating if a point, or an object, is within a region or if two regions intersect. You can also look here https://en.m.wikipedia.org/wiki/Point_in_polygon for some hints. Games libraries usually contain a rich selection of such algorithms to do exactly this sort of thing, so you may also want to check some of those out (there are several open source libraries out there).

Unless you actually need to draw characters, I would avoid them if you want an exact translation effect, as typography has inbuilt padding which you usually don’t have access to. In your case, use a ring shape Drawable as the background of a View or FrameLayout rather than a TextView.

As @G.hakim states, using a drawable as the background is the easiest way to create your circle. If you want some thing more complex you’ll have to create you own class and override Draw or use something like the SkiaSharp library (which is awesome by the way). Also as he states you can easily translate between density measurements (dp and sp) and pixels using standard conversions like this:

public static class PixelSizeConverter
{
    private static float _density = -1f;
    public static float Density
    {
        get
        {
            if (_density == -1)
                _density = Resources.System.DisplayMetrics.Density;
            return _density;
        }
    }

    private static float _scaledDensity = -1f;
    public static float ScaledDensity
    {
        get
        {
            if (_scaledDensity == -1)
                _scaledDensity = Resources.System.DisplayMetrics.ScaledDensity;
            return _scaledDensity;
        }
    }

    public static int DpToPx(float dp)
    {
        return (int) (dp * Density);
    }
    public static float PxToDp(float px)
    {
        return px / Density;
    }
    public static int SpToPx(float sp)
    {
        return (int) (sp * ScaledDensity);
    }

    public static float PxToSp(float px)
    {
        return px / ScaledDensity;
    }

}

Good luck!

  • Thank you for your help, but i managed to find a solution for my problem and here's the solution steps : 1-the circle has a radius of **r** 2-i make a random number between **-r** and **r** and i relate it to `translateY` value 3-then i make a random number between **-r** and **r** for `translateX` but i have to make sure that these two values are less than **r** (inside circle) so `if( Sqrt( (translateY*translateY) + (translateX*translateX) ) < r){ \\inside circle }` – Hope Rises Feb 27 '19 at 10:11