Xamarin.Forms - как скопировать метку и размер с помощью Measure ()? Пытаюсь установить размер шрифта автоматически. (Головоломка!) - PullRequest
0 голосов
/ 05 августа 2020

Есть отличный пример проекта Xamarin.Forms под названием Empirical Font Size , который вычисляет максимально возможный размер шрифта для Label в содержащем его представлении. Он берет рассматриваемую метку, использует VisualElement.Measure() для получения некоторых запросов размера для метки на основе ее свойств и сравнивает запрошенные размеры с размером контейнера, чтобы увидеть, подойдет ли метка к этому размеру шрифта. Он выполняет пересчет до тех пор, пока не будет найден наиболее подходящий. Он отлично работает, но я хочу изменить его, чтобы сделать больше.

К сожалению, я столкнулся с некоторыми неприятными препятствиями в моих модификациях, и я не уверен, связаны ли они с C# или Xamarin . Вот что я хотел бы сделать.

  • Извлечь вычисления в их собственную функцию для использования где угодно. -> Оригинал этого не делает. Этот бит на самом деле уже выполнен, но следующие цели не работают, поэтому хорошо использовать его в качестве отправной точки.
  • (ФОКУСИРОВАТЬ ЗДЕСЬ) Избегайте использования исходных данных метки в функции. (Сделайте копию.) -> Я добавляю некоторые функции, которые требуют от меня активного изменения текстовых данных метки во время расчета размера, но изменение метки, которую я изменяю, может вызвать проблемы (не всегда с размером, но другими способами). Мне нужен способ дублировать метку для изменения размера шрифта, чтобы защитить исходные данные. (Подробнее о том, что я пробовал ниже).
  • Абстрагируйте функцию, чтобы разрешить изменение размеров других представлений. -> Прямо сейчас рассчитывается только максимальный размер шрифта метки. Если возможно, я хотел бы поддерживать автоматическое изменение размера шрифта для других представлений, таких как сборщик, запись и т. Д. c. Пища для размышлений при выяснении №2.

Цель №2 - вот где у меня проблемы. Я не могу найти способ дублировать этикетку, а затем выполнить калибровку расчеты по временной копии. Вот что я пробовал и как каждая попытка не удалась.

  • Сделайте мелкую копию. (например, Label copyLabel = origLabel;) -> Как и ожидалось, это не работает, потому что новая копия этикетки все еще ссылается на те же исходные данные этикетки в памяти. Так что если я установлю copyLabel.Text = "hello", тогда origLabel.Text также изменится на «привет». Не очень хорошо.
  • JSON копировать -> Я видел рекомендаций по использованию JSON преобразователей для сериализации, а затем десериализации представления, чтобы выполнить быстрое глубокое копирование, но я получил исключение, когда попробовал это. Что-то о self-referencing loop в дочерних элементах метки. (У меток вообще есть дочерние элементы ??)
  • ICloneable -> Я буду запускать эту функцию в классе stati c, поэтому я не могу этого сделать. Однако это может не иметь значения из-за следующей попытки.
  • Создайте новый объект Label и скопируйте некоторые значения. -> Кажется, это почти работает, но загвоздка здесь - VisualElement.Measure() расчет. На новой этикетке отсутствует что-то, что требуется для правильной работы расчетов, и я не знаю, что это такое.

Чтобы любой из них работал, мне нужно было бы скопировать этикетку немедленно выполнить вычисления на копии и применить полученный размер шрифта к оригиналу. Потом копия исчезает. Пуф! К сожалению, любая копия, которую я делаю, приводит к различным вычислениям, так что именно здесь я и застрял.

Кто-то упомянул в другом месте, что, возможно, размер не работает, потому что новая метка не является частью макета и таким образом, размер не может быть изменен, но они не объяснили, поэтому я не понимаю, к чему они пришли.

Чтобы увидеть, что работает, а что нет, вот небольшой пример проекта Xamarin с измененным версия проекта Empirical Font Size. Это простой A / B-тест. Две метки с одинаковым текстом имеют размер двух почти идентичных функций: одна использует исходную метку, а другая пытается использовать копию. Они должны заполнить верхнюю и нижнюю половины предоставленного макета стека, но копия не работает. Я бы хотел помочь в этой работе.

ИЗМЕНЕННЫЙ ОБРАЗЕЦ ПРОЕКТА: https://drive.google.com/file/d/1mWxE3p6u53jkIdaIEFVFnkI7BC-kfske/view?usp=sharing

1 Ответ

0 голосов
/ 31 августа 2020

Я нашел безопасное и простое решение этой проблемы, которую я называю «призрачным размером». Вы можете создать невидимую «призрачную метку» и поместить ее на страницу, где будет изменен размер метки. Его не видно, поэтому он не меняет макет вообще, но его можно использовать для расчета размеров. Вы передаете текст метки, размер которой хотите изменить, в призрачную метку, размер призрачной метки до желаемого пространства и применяете возвращенное значение размера к целевой метке.

XAML:

<!--  for sizing other elements without breaking bindings  -->
<Label x:Name="ghostLabel" IsVisible="false" />

C# код программной части:

ghostLabel.Text = String.Copy(myLabel.Text);

...
double labelFontSize = ...// do font size calculations here using the ghostLabel object
...

myLabel.FontSize = labelFontSize;

Я сделал для этого свой собственный класс размера шрифта, если вам интересно.

Github repo

дополнительные примечания к размерам фантомных размеров

...