Перемещение / анимация TextView в области круга xamarin android - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть TextView с текстом "O".Я хочу переместить / оживить его в области круга, и я не хочу, чтобы он выходил за пределы этой области.Я могу оживить его, используя следующий фрагмент кода:

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

, который меняет translationY на 850. Я могу сделать это и для translationX, но он может выйти из круга.Значение для перевода (в коде это 850) рандомизировано, и я думаю, что 850 это px, а не dp.Это моя первая проблема. Я не могу анимировать объект со значениями dp. Есть ли способ исправить это?

Если я могу найти способ переместить объект со значением dp, я могу анимировать его внутрикруг с небольшим количеством математики.Но если для этого нет способа, как можно анимировать / переместить мой объект в области круга?

1 Ответ

0 голосов
/ 26 февраля 2019

Причина, по которой он может выбраться из «круга», двояка:

Во-первых, 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;
    }

}

Удачи!

...