Причина, по которой он может выбраться из «круга», двояка:
Во-первых, Android не включает пространственное ограничение для переводов.Вы можете перевести элемент с экрана, если хотите (и это часто делается, чтобы создать впечатление исчезновения виджета с экрана).Вы можете закрепить на содержащем макете или на любой понравившейся вам фигуре, чтобы элемент не отображался за его пределами, но он по-прежнему исчезнет с края, не будет удерживаться им.
Во-вторых, все визуальные элементы в Android(и iOS) на самом деле являются прямоугольниками, независимо от того, что нарисовано.Таким образом, даже если вы привязали виджет к краю вашего содержащего макета, он все равно выйдет за границы нарисованного круга, потому что система не имеет понятия, что это такое.
Итак.Вы должны выполнить вычисления самостоятельно и определить, где находятся границы вашего круга, и убедиться, что «перевод X и Y» никогда не выходит за его пределы.См. https://www.mathopenref.com/coordbasiccircle.html для получения справки о том, как сделать это для круга.
Затем вы обнаружите, что у вас возникло дополнительное затруднение в том, что ваш переведенный вид пересекается с границей круга и соответственно корректируется(помните, что переведенный вид на самом деле представляет собой прямоугольник, содержащий ваш «нарисованный объект»).Если ваш «нарисованный объект» является точным кругом, это легко (вы настраиваете его радиус).Учитывая, что вы работаете с кругами, вы можете захотеть перевести стандартную декартову систему координат в полярную и использовать радианы.
Если вы используете библиотеку CV, она может прийти с методом расчета, если точкаили объект находится в области или если две области пересекаются.Вы также можете посмотреть здесь https://en.m.wikipedia.org/wiki/Point_in_polygon для некоторых подсказок.Игровые библиотеки обычно содержат богатый выбор таких алгоритмов, чтобы делать именно такие вещи, поэтому вы также можете проверить некоторые из них (есть несколько библиотек с открытым исходным кодом).
Если вам действительно не нужнорисовать символы, я бы избегал их, если вам нужен точный эффект перевода, так как типографика имеет встроенные отступы, к которым у вас обычно нет доступа.В вашем случае используйте форму круга Drawable в качестве фона для View или FrameLayout, а не TextView.
Как утверждает @ G.hakim, использование Drawable в качестве фона - самый простой способ создать круг.Если вы хотите что-то более сложное, вам придется создать свой собственный класс и переопределить Draw или использовать что-то вроде библиотеки SkiaSharp (что, кстати, здорово).Кроме того, как он утверждает, вы можете легко переводить измерения плотности (dp и sp) в пиксели, используя стандартные преобразования, подобные следующим:
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;
}
}
Удачи!