Перейти к содержанию
Fire Monkey от А до Я

Brovin Yaroslav

Администраторы
  • Постов

    2 124
  • Зарегистрирован

  • Посещение

  • Победитель дней

    390

Ответы сообщества

  1. Пост Brovin Yaroslav - сообщение в Как создать свой итем для TListBox на основе уже существующего? был отмечен как ответ   
    Не до конца разобрались.
     
    TListBoxItem - это обычные контролы, поэтому они так же допускают вставку других контролов друг в друга. Поэтому, чтобы добавить надпись сбоку, достаточно поместить TLabel внутрь итема, выровнить по правому краю и задать правы отступ (Margins.Right = 10). Так же для такой метки в FireMonkey предусмотрен специальный стиль "listboxitemdetaillabel". 
     
    Обратите внимание, что таким образом можно разместить любой контрол.
     
    Здесь следует четко разделить два подхода:
    Стилизация итемов. Если у нас лист бокс содержит большое число итемов, то лучше использовать подход с созданием отдельного стиля. Поскольку при прокрутке итемов TListBox выгружает стили для итемов, которые не видны на экране и тем самым экономит память. Однако, для большого числа итемов лучше использовать TListView, так как он адаптирован и оптимизирован для работы с большим количеством итемов. В то время, как TListBox рассчитан для создания небольших меню.  Непосредственное создание дополнительных контролов в итеме. Этот подход удобен в своем использовании и рекомендуется для варианта использования TListBox, как небольшое меню приложения. Например у меня по такому рецепту получился вот такой вариант:

  2. Пост Brovin Yaroslav - сообщение в Как сделать промежутки между подгруппами итемов? был отмечен как ответ   
    Тогда нужно сделать свой стиль в TStyleBook и задать его для этого итема.
    1. Кидаем на форму TListBox и создаем итемы. Для разделения групп настроек вставляем TListBoxGroupHeader. У меня получился такой вариант:

    2. Кидаем на форму TStyleBook и открываем редактор стиля, двойным кликом на TStyleBook.
    3. Перетаскиваем TLayout к корню стиля в Structure и задаем название стиля как "listboxgroupheader".

    4. Подключаем стиль бук в дизайнере к форме Form.StyleBook = StyleBook и задаем произвольную высоту для разделителей групп итемов.

     
    P.S. Если хотите оставить текст на разделителях, то нужно в стиль добавить контрол для вывода текст (TText или TLabel) с название стиля "text"
    О том, почему некоторые контролы имеют фиксированный размер написано тут: Почему для некоторых контролов нельзя поменять высоту или ширину? О том, как снять это ограничение (но не рекомендуется) написано тут: Как снять запрет изменения размера контролов
  3. Пост Brovin Yaroslav - сообщение в Вызов цифровой клавиатуры на мобильных платформах был отмечен как ответ   
    Для мобильных устройств FireMonkey поддерживает все стандартные типы виртуальной клавиатуры (обычная, цифровая, ввод электронных адресов). Задание типа клавиатуры осуществляется через свойство: TEdit.KeyboardType. (Описание)
     
    Когда вы указываете TEdit, что он будет использовать цифровую клавиатуру, то в момент начала ввода в TEdit (установка фокуса в TEdit), появится клавиатура, выбранного типа.
     
     
  4. Пост Brovin Yaroslav - сообщение в Почему для некоторых контролов нельзя поменять высоту или ширину? был отмечен как ответ   
    Ответ на этот вопрос дан здесь: [Android] Не получается увеличить высоту TProgressBar 
     
    По умолчанию каждая платформа определяет свои правила построения пользовательского интерфейса. Это выражается, например, в том, что в ios и в Андроиде прогресс бар должен быть фиксированной высоты. Чтобы не нарушать руководство по проектированию пользовательских интерфейсов каждой платформы, FireMonkey принудительно запрещает менять размеры некоторых контролов. 
     
    Обойти это ограничение можно, однако, не стоит забывать, что стили для мобильных платформ растровые, а значит при масштабировании будет наблюдаться потеря качества.
     
    Обратите внимание на приведенную выше ссылку в начале ответа. В ней рассказывает, как снять ограничение. Там же в конце на скриншоте приведен пример потери качества при изменении высоты.
  5. Пост Brovin Yaroslav - сообщение в Как задать API-level для андроид приложения? был отмечен как ответ   
    Приложения FireMonkey для Андроида полностью совместимы с версиями Андроид, начиная с версии 2.3 (GingerBread). Поэтому приложение, собранное с последней версии Android SDK, будет успешно работать и на всех предыдущих версия до 2.3 включительно.
     
    Однако, если вы хотите поменять используемую для сборки версию Андроид SDK, это можно сделать в настройках SDK профиля.
     
    Меню->Tools->SDK Manager (слева в дереве) Выбираем профиль SDK для андроида и в самом низу в поле SDK API-Level Location меняем путь на путь к другой версии SDK. (смотрите прикрепленный скриншот)
  6. Пост Brovin Yaroslav - сообщение в Как открыть ссылку в стандартном браузере под iOS? был отмечен как ответ   
    uses FMX.Helpers.iOS, iOSapi.Foundation function OpenURL(const AUrl: string): Boolean; var Url: NSURL; begin Url := TNSUrl.Wrap(TNSUrl.OCClass.URLWithString(NSStr(AUrl))); Result := SharedApplication.openUrl(Url); end;
  7. Пост Brovin Yaroslav - сообщение в Как я могу скрыть / показать клавиатуру под "Android"? был отмечен как ответ   
    Русский
    За управление виртуальной клавиатурой в FireMonkey отвечает сервис IFMXVirtualKeyboardService (Embarcadero Doc Wiki). Который позволяет отображать и скрывать клавиатуру.
    Для скрытия клавиатуры достаточно выполнить следующий код:
    uses FMX.Platform, FMX.VirtualKeyboard; procedure TForm5.ButtonHideKeybordClick(Sender: TObject); var KeyboardService: IFMXVirtualKeyboardService; begin // Запрашиваем сервис виртуальной клавиатуры if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(KeyboardService)) then KeyboardService.HideVirtualKeyboard; end; Чтобы показать клавиатуру для контрола:
    procedure TForm5.ButtonShowKeyboardClick(Sender: TObject); var KeyboardService: IFMXVirtualKeyboardService; begin // Запрашиваем сервис виртуальной клавиатуры if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(KeyboardService)) then KeyboardService.ShowVirtualKeyboard(Edit1); end;

    English 
    FireMonkey has special service for managing Virtual Keyboard. It is IFMXVirtualKeyboardService (Embarcadero Doc Wiki). It allows show and hide keyboard.
    For showing virtual keyboard use next code: uses FMX.Platform, FMX.VirtualKeyboard; procedure TForm5.ButtonHideKeybordClick(Sender: TObject); var KeyboardService: IFMXVirtualKeyboardService; begin // Request service of visrtual keyboard if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(KeyboardService)) then KeyboardService.HideVirtualKeyboard; end; For showing virtual keyboard for control:
    procedure TForm5.ButtonShowKeyboardClick(Sender: TObject); var KeyboardService: IFMXVirtualKeyboardService; begin // Request service of visrtual keyboard if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(KeyboardService)) then KeyboardService.ShowVirtualKeyboard(Edit1); end;
  8. Пост Brovin Yaroslav - сообщение в [Android] Открытие HTML страницы в браузере по умолчанию был отмечен как ответ   
    Открытие ссылки под Андроид: 

    uses FMX.Helpers.Android, Androidapi.JNI.Net, Androidapi.JNI.GraphicsContentViewText; function OpenURL(const AUrl: string): Boolean; var Uri: Jnet_Uri; OpenLinkIntent: JIntent; begin Uri := StrToJURI(AUrl); // Формируем намерение об открытии ссылки Uri в стандартном браузере OpenLinkIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, Uri); // Устанавливаем тип данных OpenLinkIntent.setType(StringToJString('text/html')); // Задаем категорию активити, который будет открывать нашу страницу. OpenLinkIntent.addCategory(TJIntent.JavaClass.CATEGORY_BROWSABLE); // Запускаем приложение и передаем ему наше намерение SharedActivity.startActivity(OpenLinkIntent); end; А чтобы открыть файл, нужно сформировать урл AUrl в виде: "file:/ //tmp/android.txt" (убрать пробелы) Согласно принятому стандарту оформления ссылок.
  9. Пост Brovin Yaroslav - сообщение в Как ускорить добавление итемов в TListBox? был отмечен как ответ   
    Процесс добавления итема дорогостоящая операция. Так как после добавления итема идет операция выравнивания контента. И так происходит с каждым новым добавляемым TListBoxItem.
     
    Однако, у каждого контрола есть два метода, которые позволяют избежать лишних вызовов и ускорить процесс добавления дочерних объектов - TControl.BeginUpdate и TControl.EndUpdate.
     
    Решение простое, перед тем, как добавлять итем в листбокс, нужно вызывать метод BeginUpdate. А по окончании добавления всех итемов - EndUpdate.
    var I: Integer; ListItem: TListBoxItem; begin ListBox1.BeginUpdate; try for I := 0 to 1000 do begin ListItem := TListBoxItem.Create(Self); ListItem.Parent := ListBox1; ListItem.Text := I.ToString; end; finally ListBox1.EndUpdate; end; end;
  10. Пост Brovin Yaroslav - сообщение в [Android] Не получается увеличить высоту TProgressBar был отмечен как ответ   
    По умолчанию, каждая платформа определяет свои правила оформления пользовательского интерфейса, согласно Руководству пользовательского интерфейса Андроида TProgressBar не может быть по высоте другого размера. Поэтому стиль андроид платформы в Firemonkey запрещает изменять высоту некоторых контролов, в том числе TProgressBar. Аналогичная ситуация в Eclipse для андроида. Там также нельзя менять для этого компонента его высоту.
     
    Фиксация размера происходит путем сохранения в стиле свойств FixedHeight  и FixedWidth (не доступного в дизайнере). Если эти свойства больше 0, значит контрол будет иметь фиксированный размер.
     
    Решение
    Если вы вдруг захотели нарушить стандарты, рекомендованные Google по оформлению UI, вы можете сделать следующее:
    1. Открыть BitmapStyleDesigner (находится в папке bin студии bin\BitmapStyleDesigner.exe)
     
    2. В выпадающем списке первой кнопки на панели инструментов Создать новый стиль (светлый или темный) для платформы андроид. Редактор автоматически создаст вам стандартный стиль для андроида.

     
    3. Сохранить стиль для Firemonkey. В диалоге сохранения выбрать тип файла "FireMonkey Style (*.style)"

     
    4. Открыть сохраненный файл стиля в текстовом редакторе и найти в нем стиль TProgressBar - "progressbarstyle".

     
    5. Удалить из стиля строчку:
    FixedHeight = 10 6. Сохранить стиль и загрузить файл стиля в TStyleBook.

     
    Теперь для TProgressBar можно менять высоту. Однако, учтите, что стили для Андроид и iOS растровые. Это значит, что при растровое исходное изображение прогресс бара рассчитано на высоту в 10 пикселей и при увеличении высоты, вы потеряете качество отрисовки прогресс бара (смотрите рисунок выше).
  11. Пост Brovin Yaroslav - сообщение в Можно ли уменьшить размер приложения для андроида? был отмечен как ответ   
    Если говорить о размере приложения. То первоначально нужно понять, что входить в состав пакета? Затем определить, что нужно и не нужно?
     
    Давайте посмотрим на примере состав пакета небольшого Андроида приложения, написанного в RAD Studio XE5 Delphi. В качестве примера, я взял приложение PhotoEditorDemo, доступный на официальном Open Source проекте примеров RAD Studio XE5
     
    Это пример кроссплатформенного простого фоторедактора:
    Описание примера: http://docwiki.embarcadero.com/CodeExamples/XE5/en/FMX.Mobile.PhotoEditorDemo_Sample_(Delphi) Исходники: http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RadStudio_XE5_Update/FireMonkeyMobile/Delphi/PhotoEditorDemo/ Размер сжатого приложения
    Собираем приложение и смотрим на результирующий пакет PhotoEditorDemo.apk (Он располагается в директории .\Android\Debug\PhotoEditorDemo\bin относительно корня проекта).
     
    После сборки приложения его размер ~6 760 КБ (в зависимости от Debug or Release сборки). Это размер сжатого пакета нативного приложения.
     
    Размер распакованного приложения
    Если мы распакуем ZIP архиватором этот файл, то увидим его содержание:

    В распакованном виде, пакет занимает 21,7 МБ.
     
    Состав пакета
    Что же входит в его состав:
    lib - место хранения собранных натиных библиотек приложения. Поскольку приложение нативное, то оно работает на основании библиотеки .so. res - место хранения ресурсов приложения (картинки, иконки и тд) META-INF - хранение подписи приложения, контрольные суммы файлов ресурсов (картинок, звуков и т.д.) AndroidManifest.xml - манифест приложения (расширенный аналог VersionInfo в Windows) classes.dex - файл с java реализацией дополнительного функционала FireMonkey. resources.arsc - таблица ресурсов. В этом файле собраны xml-описания всех ресурсов. Самый значительный вклад в размер пакета вносят:
    libPhotoEditorDemo.so (20 060 КБ) - непосредственно сам бинарник приложения classes.dex (1 948 КБ) - частичная реализация FireMonkey на java. Размер самого приложения большой потому, что включает в себя полностью все Delphi библиотеки, которые используется FireMonkey. А это:
    RTL Хедеры для доступа к Android API Нативные стили для Android (три стиля - 1х, 1.5x, 2х, 3х скалирования экрана). Каждый стиль содержит исходную png картинку нативного стиля. Фильтры и эффекты FireMonkey Вся остальная реализация FireMonkey. Довольно большой набор того, что нужно включить в пакет и тяжело выбросить.
     
    Если говорить о приложении написанном в Eclipse, то приложение включает в себя только часть пользовательского кода. И размер мал за счет того, что весь Android API находится перманентно на самом устройстве (не в пакете).
     
    Если бы используемая часть библиотек FireMonkey находилась на каждом устройстве, то размер приложения сократился бы раза в четыре. 
     
    Вывод
    Размер установочного пакета приложения, написанного на FireMonkey не большой для нативных приложений порядка 6 760 КБ для реализации простого фоторедактора (Хотя для кого-то это может быть много). В установленном виде приложение занимает от 20 000 КБ. Основная причина полная интеграция используемых библиотек в пакет приложения. Вероятность уменьшить этот размер маловероятна. Однако увеличение функционала приложения не так сказывается на дальнейший рост приложения.
     
    Можно попробовать сделать усеченные библиотеки, сократить функциональность. Но это не даст ощутимого уменьшения результирующего размера приложения. 
     
    На сколько важен размер приложения для конкретной работы приложения каждый заказчик решает сам.
     
    P.S. Цель этого ответа дать подробный ответ о причинах такого размера, а не попытка вызвать обсуждение на тему сравнения сред разработки. Каждый framework обладает своими достоинствами и недостатками. И выбор средства разработки диктуется совокупностью требования заказчика. 
  12. Пост Brovin Yaroslav - сообщение в Как сделать перемещение контрола мышкой/пальцем? был отмечен как ответ   
    Добрый вечер,
     
    Перемещение контрола можно сделать двумя способами:
    Используя обычный набор событий OnMouseDown, OnMouseMove, OnMouseUp. Использовать для перемещения жесты. 1. Реализация с использованием событий мыши
    Эти события реализованы для всех платформ. В том числе они эмулируются на мобильных платформ, где понятия мыши, как такового нету. Это означает, что их можно использовать для реализации перетаскивания контрола. Это можно сделать, например, следующим образом:
     
    а) Создаем форму и кидаем на нее картинку. Я назвал ее DraggableImage.

    б) Заводим два поля.
    TForm5 = class(TForm) DraggableImage: TImage; procedure DraggableImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); procedure DraggableImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); procedure FormCreate(Sender: TObject); procedure DraggableImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); private FStartPos: TPointF; FPressed: Boolean; end; FStartPos - начальная локальная позиция мыши внутри нашего контрола (картинки), когда пользователь зажал кнопку мышки или опустил палец на экран. FPressed - флаг для сигнализирования, что пользователь опустил палец (зажал кнопку мыши) на нашу картинку и до текущего момента не снял с экрана. в) В конструкторе формы для перетаскиваемого контрола ОБЯЗАТЕЛЬНО задаем AutoCapture = True. Это позволит контролу генерировать события перемещения мыши, даже если курсор мыши ушел за локальные границы контрола.
    procedure TForm5.FormCreate(Sender: TObject); begin DraggableImage.AutoCapture := True; end;  г) В момент нажатия на картинку сохраняем локальную позицию мыши и задаем флаг FPressed = True
    procedure TForm5.DraggableImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin FPressed := True; FStartPos := TPointF.Create(X, Y); end; д) В момент отпускания кнопки мыши или убирания пальца с экрана сбрасываем флаг FPressed:
    procedure TForm5.DraggableImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin FPressed := False; end; е) И собственно меняем позицию картинки, когда мы ведем мышкой по картинке:
    procedure TForm5.DraggableImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); var MoveVector: TVector; begin if FPressed then begin // Вычисляем локальное смещение относительно первоначальной позиции MoveVector := TVector.Create(X - FStartPos.X, Y - FStartPos.Y, 0); // Вычисляем смещение в координатах формы, чтобы учесть изменение // координат при смещении родительских контролов MoveVector := DraggableImage.LocalToAbsoluteVector(MoveVector); if DraggableImage.ParentControl <> nil then      MoveVector := DraggableImage.ParentControl.AbsoluteToLocalVector(MoveVector); // Перемещаем картинку на вычисленный вектор // Для RAD Studio XE5 DraggableImage.Position.Point := DraggableImage.Position.Point + MoveVector.ToPointF; // Для новых версий // DraggableImage.Position.Point := DraggableImage.Position.Point + TPointF(MoveVector); end; end; Этот кусок стоит прокомментировать, чтобы корректно выполнить перетаскивание контролу обязательно нужно вычислять смещение в абсолютных координатах формы. Причина в том, что если контрол повернут или входит один в другой, то нужно учитывать смещения всей цепочки родительских контролов до формы. Поэтому мы вначале вычисляем смещение в локальных координатах, затем вычисляем его в абсолютных координатах формы. А затем обратно переводим в локальные координаты родительского контрола. После чего изменяем позицию контрола на вычисленное смещение.
     
    Такой подход используется, в частности, в контроле TSelection, который так же можно перемещать мышкой или пальцем.
     
    P.S. Чтобы лучше понять это, нарисуйте на листке бумаги положения контрола и попробуйте вручную выполнить этот алгоритм с преобразованием координат. 
     
    Собственно говоря, такой подход отлично работает везде и не требует использования системы жестов.
    2. Реализация с использованием жестов
    Этот способ будет работать только на мобильных платформах, поскольку нужный жест Pan (если я правильно помню) не поддерживается под Windows. Поэтому в целом, первый вариант является универсальным и лучшим решением. 
  13. Пост Brovin Yaroslav - сообщение в Включение своих файлов в приложение был отмечен как ответ   
    Добрый вечер,
     
    Тут есть два способа:
    Работа с Deployment менеджером. Он довольно подробно описан на Embarcadero Doc Wiki: http://docwiki.embarcadero.com/RADStudio/XE5/en/Deployment_Manager Работа через менеджер ресурсов и их получение через ResourceStream. Этот способ описал MyDelphiPw в сообщении выше тут. 1. Deployment Manager
    Специальная настройка проекта, которая позволяет указать, какие файлы нужно включить в состав пакета (Андроид) или бандла (iOS). Суть его работы простая, вы указываете какие файлы с вашего компьютера нужно перенести на устройство (в какое место). А далее работаете с ними из приложения так, как при обычной работе с файлами под Windows.
     
    На мобильных платформах нужно учесть специфику возможных местоположений файла. Пакет/Бандл (приложение) не допускает изменения внутренних файлов, потому что подписывается сертификатом. Поэтому теоретически при изменении файлов приложения, вы нарушаете целостность подписи. Именно по этому файлы внутри пакета/бандла доступны только на ЧТЕНИЕ.
     
    Однако, мобильные платформы предлагают широкий круг специальных мест для хранения (временные папки, песочницы, документы, карточка памяти и тд) изменяемых файлов (например файл локальной базы данных, или настройки в ini файле и тд).
     
    Описание всех вариантов местоположений с описанием путей есть в записе TPath (RTL): http://docwiki.embarcadero.com/RADStudio/XE5/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms. 

    Общие действия для использования менеджера развертывания такие:
    1. Открываем менеджер развертывания: Системное Меню -> Project -> Deployment.

    2. Выбираем в верхнем выпадающем меню платформу и конфигурацию сборки.

    3. Нажимаем кнопку добавить файл и выбираем нужный файл.
     
    4. Указываем местоположение файла, куда он должен поместиться после развертывания приложения на устройстве. Тут есть особенность, если файл нужен только на чтение, то пути менять не надо. Если возможна ситуация, когда файл может быт изменен, то файл нужно поместить под iOS в Startup\Documents\ (регистр важен)

    Под Андроид в assets\internal (регистр важен) - для внутреннего доступа из пакета приложения или assets - для внешнего доступа

    5. Получаем пути к расположению файлов:
    Под iOS:
    TPath.Combine(TPath.GetDocumentsPath, 'filename') Под Андроид:
    TPath.Combine(TPath.GetDocumentsPath, 'filename') { Внутренний доступ} TPath.Combine(TPath.GetSharedDocumentsPath, 'filename') { Внешний доступ } Полезные ссылки
    Подробное руководство по добавлению файлов для iOS: http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_an_iOS_App#Loading_and_Deploying_Files Подробное руководство по добавлению файлов для Android: http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_an_Android_App#Loading_and_Deploying_Files
  14. Пост Brovin Yaroslav - сообщение в Как получить текущее положение пальца на экране? был отмечен как ответ   
    Здесь есть два варианта решения:
     
    1. Использовать сервис FMX.Types.IFMXMouseService
    Этот сервис позволяет получить координаты последнего положения курсора мыши, нажатия или перемещения пальца по экрану. Однако если пользователь оторван палец от экрана, то сервис вернет последнее положение пальца на экране. Этот метод хорош тем, что позволяет узнать положение в любой момент в любом месте экрана. Метод возвращает абсолютные координаты в СК формы. При использовании этого варианта и при частой необходимости получать координаты, сервис лучше сохранить локально в отдельную переменную, чтобы каждый раз не выполнять запрос на получение сервиса. Так как эта функция требует дополнительных ресурсов.
    var MouseService: IFMXMouseService; MousePos: TPointF; begin // MouseService - лучше вынести отдельным полем класса и инициализировать ее например при создании формы. if TPlatformServices.Current.SupportsPlatformService(IFMXMouseService, IInterface(MouseService)) then MousePos := MouseService.GetMousePos end; 2. Использовать глобальный объект Screen: TScreen
    В FireMonkey есть глобальный объект, который предоставляет информацию о экране. Он внутри использует несколько сервисов.
    В частности, у него есть метод:
    Screen.MousePos Который использует 1 подход и вернет такой же результат. Но в отличии от первого способа, тут не нужно запрашивать сервис, это сделано в TScreen.
    3. Использовать стандартные события OnMouseDown, OnMouseMove, OnMouseUp
    Собственно способ заключается в определении текущего положения пальца через событие OnMouseMove. Однако, этот способ подходит только для контролов, которые могут перехватывать события мыши (HitTest = True). Идея 
  15. Пост Brovin Yaroslav - сообщение в Фоновое выполнение операции без "замораживания" отрисовки был отмечен как ответ   
    Вся отрисовка выполняется в главном потоке приложения. Поэтому, если вы пытаетесь выполнить скачивание файла в основном потоке, то вся отрисовка приостановится до момента окончания вашей операции. Поэтому правило хорошего тона - это вынесение долгих операций (загрузка, ответ авторизации и тд) в отдельный поток. 
     
    Примерный код приведен ниже:
    1. Создаем отдельный поток, в котором вы будите скачивать файл (я поставил для эмуляции скачивания просто паузу на 5 секунд):
    type TMyTask = class (TThread) protected FOnTaskStarted: TThreadMethod; FOnTaskFinished: TThreadMethod; procedure DoStarted; procedure DoFinished; procedure Execute; override; public property OnTaskStarted: TThreadMethod read FOnTaskStarted write FOnTaskStarted; property OnTaskFinished: TThreadMethod read FOnTaskFinished write FOnTaskFinished; end; Реализация:
    { TMyTask } procedure TMyTask.DoFinished; begin if Assigned(OnTaskFinished) then OnTaskFinished; end; procedure TMyTask.DoStarted; begin if Assigned(OnTaskStarted) then OnTaskStarted; end; procedure TMyTask.Execute; begin Synchronize(DoStarted); try Sleep(5000); // Эмуляция выполнения 5 Секундной задачи finally Synchronize(DoFinished); end; end; Само использование такого потока будет следующим (в моем примере после выполнения операции, появится сообщение):
    TForm3 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private FMyTask: TMyTask; public procedure DoTaskStarted; // Callback, вызываемый в начале старта операции procedure DoTaskFinished; // Callback, вызываемый в конце выполнения операции. Аналог OnTerminate procedure StartMyTask; // Запуск задачи end; procedure TForm3.Button1Click(Sender: TObject); begin StartMyTask; end; procedure TForm3.DoTaskStarted; begin end; procedure TForm3.DoTaskFinished; begin ShowMessage('Выполнение задачи окончено'); end; procedure TForm3.StartMyTask; begin if FMyTask <> nil then begin FMyTasl.OnTaskStarted := nil; FMyTasl.OnTaskFinished := nil; FMyTask.Free; end; FMyTask := TMyTask.Create(True); FMyTask.OnTaskStarted := DoTaskStarted; FMyTask.OnTaskFinished := DoTaskFinished; FMyTask.Start; end; При таком подходе главный поток не будет блокироваться и будет корректно отрисовываться и работать.
  16. Пост Brovin Yaroslav - сообщение в [TWebBrowser] Отображение html-страницы в WebBrowser из текстовой переменной до XE7 был отмечен как ответ   
    В текущей версии среды Rad Studio XE5, открыть страницу можно только предварительно создав временный файл с html-текстом страницы. А затем открыть ее в браузере, передав, ссылку на временный файл. В будущем, не исключено, что появится более удобный способ загрузки своей страницы напрямую, без использования временного файла.
     
    Решение может выглядеть так (Но нужно проверить, у меня нету сейчас под рукой устройства):
    Создаем TStringList и заполняем код html-страницы (Возможно нужно будет указать кодировку) Получаем директорию, где хранятся в текущей системе временные файлы. TPath.GetTempPath (Все варианты путей есть здесь TPath) Сохраняем html-страницу в временный файл Открываем страницу, используя формат URL для открытия файлов.
     
    P.S. Будет здорово, если вы проверите работоспособность кода и отпишитесь здесь о результатах.
  17. Пост Brovin Yaroslav - сообщение в [TTabControl] Эффект многостраничности в рамках одной вкладки TTabControl был отмечен как ответ   
    Решение у этой задачи простое - это вложенные Таб контролы. Для этого нужно:
    Разместить на форме TTabControl, у которого вкладки будут отображаться снизу (TabPosition = tpBotttom); Создать в табконтроле вкладки; Разместить еще один TTabControl на вкладке и задать ему (TabPosition = tpNone).
  18. Пост Brovin Yaroslav - сообщение в Почему не изменяется Font.Style и Font.Size? был отмечен как ответ   
    Label1.StyledSettings := Label1.StyledSettings - [TStyledSetting.Size]; В FireMonkey все, что отвечает за визуальную часть (отображение контрола) обычно выносится в стиль. Однако, не всегда удобно создавать новый стиль, только, когда нужно, например, поменять размер шрифта в TLabel. Поэтому, чтобы позволить пользователям удобно менять такие настройки, как шрифт. Шрифт выделен в отдельное свойство TLabel.Font. При выделении шрифта отдельным свойством, нужно понимать, что при таком подходе контрол "не знает", откуда ему брать шрифт: то ли из свойства, то ли из стиля.
     
    Поэтому, чтобы контрол знал, откуда ему брать шрифт для отображения: из стиля или из свойства Font, введено свойство TLabel.StyledSetting. Которое говорит контролу, какие характеристики шрифта нужно брать из стиля, а какие можно взять из свойства TLabel.Font. По умолчанию, StyledSettings настроены так, что все берется из стиля. В вашем случае, нужно сбросить галку напротив значения ssSize и ssFont.
     
    Подробная информация есть на Embarcadero Doc Wiki: http://docwiki.embarcadero.com/RADStudio/XE5/en/Setting_Text_Parameters_in_FireMonkey
  19. Пост Brovin Yaroslav - сообщение в Как сделать панель для выбора действий на подобии UIActionSheet? был отмечен как ответ   
    Здесь есть несколько вариантов:
    Создать самостоятельно из компонентов FireMonkey: TLayout, TButton. Сделать специальные стили для кнопок и затемнения и в IOS написать код по выдвижению панели, как описано в этой теме: "Как создать выдвигаемую панель?". Такой вариант будет кроссплатформенным и вы сможете легко настроить его на ваш вкус. Использовать нативный компонент в iOSAPI UIActionSheet. В этом варианте решение будет только для iOS, но зато вам не надо будет думать о специфичной стилизации. Стиль будет браться системный. Использовать готовый OpenSource компонент TfgActionSheet, который использует под каждой мобильной платформой нативные контролы. В том числе под iOS используется тот же UIActionSheet. Под андроид это сделано в виде диалога с кнопками действий. компонент входит в состав этого пакета для Delphi fgx_0.3.0.11.zip. Однако, нужно правильно настроить правила сборки этого пакета.
  20. Пост Brovin Yaroslav - сообщение в Как рисовать на "чужих" контролах? был отмечен как ответ   
    Как и в любой задаче, здесь есть несколько вариантов решения. Каждый вариант обладает своими достоинствами и характеризуется степенью сложности реализации. На вскидку, мне кажется, что следующий вариант будет лучшем в вашем случае:
     
    Отдельный компонент-контрол TSnowFall
    Назовем его условно TSnowfall (снегопад). Он будет рисовать на себе падающие снежинки. Мы располагаем его в корне формы и растягиваем на весь экран Align = alContent, так же всегда располагаем его поверх всех остальных контролов (BringToFront) и запретим ему перехватывать события мыши (HitTest = False), чтобы он не нарушал логику работы всех остальных контролов. Затем в перекрытом методе TControl.Paint выполняем отрисовку снежинок с текущими позициями. А в созданном вручную таймере по каждому тику меняем текущее положение всех снежинок и вызываем метод перерисовки TControl.Repaint. 
     
    На мой взгляд этот вариант хорош:
    Полное отделение логики от кода формы. То есть код формы будет проще за счет убирания всего кода работы с отрисовкой снежинок в отдельный юнит. Легкое расположение занавеса снежинок в любом месте. С возможностью привязки к любому контролу и без. Повторное использование в любом другом месте. Постусловие
    Каждая форма FireMonkey имеет одну канву. Поэтому все контролы по сути рисуются на ней, в отличии от VCL, где каждый контрол с оконным хендлом имеет свой графический контекст -> канву.
    Когда форма получает запрос на отрисовку, она по шаблону цепочка ответственности делегирует всем контролам по дереву запрос на отрисовку.
    В каждом контроле происходит подготовка общей канвы под отрисовку нужного контрола, который в текущий момент отрисовывается. То есть задается матрица трансформации, чтобы контрол работал в своей локальной системе координат, а не в абсолютной СК формы. И тд. Поэтому теоретически вы можете рисовать поверх любых контролов в TForm.OnPaint, но это правильно. Лучше использовать мой предложенный подход, описанный выше.
  21. Пост Brovin Yaroslav - сообщение в [TTabControl] Как сделать плавное переключение двух вкладок в TTabControl? был отмечен как ответ   
    Самый простой вариант использования эффекта прокручивания основывается на использовании компонента TTabControl, который реализует переключение табов (вкладок) с анимацией. Для этого достаточно:
    Поместить TTabControl на форму и растянуть его на всю область TTabControl.Align = alClient. Создать вкладки. Одну вкладку на один логический экран (слайд, представление и тд). На каждую вкладку помещаете любой контент. В вашем случае TListBox. Вызвать в нужный момент метод переключения вкладок с анимацией: TTabControl.SetActiveTabWithTransition(const ATab: TTabItem; ATransition: TTabTransition; const ADirection: TTabTransitionDirection = TTabTransitionDirection.tdNormal) Где, 
    ATab: TTabItem - Вкладка, которую нужно отобразить ATransition: TTabTransition - Отобразить вкладку мгновенно или с эффектом сдвига (В вашем случае нужно второе TTabTransition.ttSlide) ADirection: TTabTransitionDirection - направление эффекта сдвига: Слева на право (TTabTransitionDirection.tdNormal) или с права налево (TTabTransitionDirection.tdReversed). Второй способ
    Аналогично создаем Таб контрол с вкладками, но для переключения вкладок используем стандартное действие TChangeTabAction, которое выполняет те же действия, что и SetActiveTabWithTransition. Действия доступны в редакторе TActionList "New Standart Action..."
     

  22. Пост Brovin Yaroslav - сообщение в Как объединить системный StatusBar и ToolBar в iOS7? был отмечен как ответ   
    Чтобы сделать прозрачным статус бар, нужно отредактировать стиль панели, и либо задать альфа канал для заливки прямоугольника панели (если стиль панели векторный), либо изменить прозрачность используемой png. Цвет можно поменять только поменял исходник, либо сделав свой стиль. Объединить системный статус бар и тулбар включительно до версии RAD Studio XE5 не удастся. Только поддержка старого варианта: отдельно системный статус бар. 
  23. Пост Brovin Yaroslav - сообщение в Как программно изменить положение курсора мыши? был отмечен как ответ   
    Для OSX нужно воспользоваться следующим куском кода, не забыв подключить Macapi.CoreGraphics:
    uses Macapi.CoreGraphics; procedure TForm5.ButtonSetMousePosClick(Sender: TObject); begin CGWarpMouseCursorPosition(CGPointMake(100, 100)); end;
  24. Пост Brovin Yaroslav - сообщение в Как создать выдвигаемую панель? был отмечен как ответ   
    Такой вариант можно сделать:
    Добавить контейнер (например TPanel, TLayout и тд), которую будет выдвигаться; Добавить аниматор (TFloatAnimation) на y-позицию панели Panel.Position.Y и настроить параметры анимации согласно вашим требованиям.  В момент наступления события запускать в ручную анимацию методом TFloatAnimation.Start.  P.S. TTabControl для этих целей лучше не использовать, потому что сам TabControl определяет все возможные варианты смены вкладок. Можно, конечно, переопределить класс TTabControl и добавить свои варианты смены, но этот способ сложнее и не обоснован для вашей задачи.
  25. Пост Brovin Yaroslav - сообщение в Почему не стилизуется рамка окна? был отмечен как ответ   
    Не все стили FireMonkey содержат стилизацию рамки окна. В вашем случае стиль не поддерживает стилизацию рамки. Поэтому свойство TForm.Border.Styling не оказывает никакого эффекта на стилизацию рамки. А в примере по ссылку используется другой стиль, который видимо поддерживает стилизацию рамки.
     
    Наличие поддержки стиля рамки окна можно проверить двумя способами:
    Непосредственно загрузив стиль и запустив приложение. Открыть стиль в дизайнере стиля в TStyleBook и проверить наличие стиля "windowborderstyle". Именно этот стиль используется для стилизации рамки окна.
×
×
  • Создать...