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!