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

Brovin Yaroslav

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

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

  • Посещение

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

    390

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

  1. Пост Brovin Yaroslav - сообщение в В моем приложении наблюдается подтормаживание отрисовки при использовании нескольких битмапов с анимацией. С чем это может быть связано? был отмечен как ответ   
    Неправильная выбранная частота отрисовки. Проблема вашего примера в том, что вы используете совершенно не нужную частоту обновления кадра - 100 кадров в секунду. Частота съёмки в современном телевидении составляет порядка 24-30 кадра в секунду (Википедия). При большей частоте кадра человеческий глаз не сможет физически отличить 24 кадра от например 100 кадров в секунду. Поэтому в вашем случае достаточно для таймера использовать например 30-40 милисекунд, увеличив скорость изменения картинки в 3-4 раза. После этих изменений, я не вижу подтормаживаний. Как минимум этим вы увеличите скорость в 3-4 раза. Не нужно использовать изображения больше, чем того нужно, которые потом автоматически программным путем каждый раз сжимаются в несколько раз. Это опять же сказывается на производительности вашего приложения. Например в вашем случае, вы используете картинку размером 300х400, а сами в конечном итоге используете изображения только размером 50х50. P.S. FireMonkey не позиционируется, как игровой движок. Поэтому, если вы приняли решение все-таки сделать игру, игнорируя рекомендации, то вам придется очень детально обращать свое внимание на вопросы производительности: грамотное использование ресурсов, движение объектов, использования картинок и другие вопросы.
  2. Пост Brovin Yaroslav - сообщение в Как можно сохранить программные настройки приложения? был отмечен как ответ   
    Для хранения настроек приложения можно использовать обычный Ini файл, который работает на всех платформах одинаково.
    TIniFile - класс для работы с ini файлами. Руководство по использованию TIniFile: Using TIniFile and TMemIniFile
  3. Пост Brovin Yaroslav - сообщение в Что лучше: многократная загрузка изображения из файла или однократная загрузка изображения в память? был отмечен как ответ   
    Если картинка часто используется и она не большая, то лучше ее грузить в память. Операция загрузки картинки из файла дорогостоящая операция, особенно, когда она очень часто используется и изображение очень большое. В вашем случае картинка не большая, поэтому я бы лучше ее загрузил в память и потом использовал в нужных местах.
    Описание включения и использования своих файлов в пакет приложения доступно здесь: Включение своих файлов в приложение
  4. Пост Brovin Yaroslav - сообщение в Как сделать эффект вспышки для контрола, когда он подсвечивается на короткий диапазон времени? был отмечен как ответ   
    Повесить анимацию TFloatAnimation на свойство Opacity Установить длительность анимации в 500 мс. Duration = 0.5 Задать начальное и конечное значения в 0 и 1. StartValue = 0, StopValue = 1. И поставить галку TFloatANimation.AutoReverse для анимации. Ну и вызывать анимацию вручную в нужный момент времени. Перед каждым вызовом анимации задавать Inverse в True.
  5. Пост Brovin Yaroslav - сообщение в Как отобразить контрол поверх всех остальных? был отмечен как ответ   
    Положение контрола по оси Z (направлена перпендикулярно плоскости монитора в направлении пользователя) регулируется порядком в списке дочерних объектов TFmxObject.Children. Первый контрол располагается дальше всего от пользователя, последний - ближе всего.
     
    Чтобы отобразить панель сверху среди объектов своего уровня нужно вызвать метод:
    TFmxObject.BringToFront Если же объект нужно расположить выше всех объектов формы, то нужно расположить объект по иерархии выше, например к форме и опять же вызывать BringToFront. 
     
    Варианта с TopMost, как у формы, у контролов нет.
  6. Пост Brovin Yaroslav - сообщение в Как скрыть системный Status Bar в iOS? был отмечен как ответ   
    FireMonkey позволяет работать со статус баром на уровне формы. Это значит, что каждая форма сама решает, нужно ли отображать системный статус бар или его следует скрыть.
     
    Чтобы скрыть системный статус бар на мобильных платформах, достаточно установить на форме 
    BorderStyle = TFmxFormBorderStyle.bsNone При этом в дизайнере вы увидите, как на форме пропадет или появится статус бар. Любое другое значение BorderStyle приводит к отображению статус бара.
  7. Пост Brovin Yaroslav - сообщение в Как сделать выбор нескольких изображений из системной галереи Андроида? был отмечен как ответ   
    В FireMonkey нету готового механизма для этого. Есть только вариант с выбором одной фотографии из галереи при помощи стандартных действий: TTakePhotoFromLibraryAction или TTakePhotoFromCameraAction. 
     
    Так же самое и в iOS API или Android API не предоставляет ничего готового для этого. Только вариант с выбором одного изображения. Поэтому если вам такой вариант нужен, то вам следует реализовать его самостоятельно для всех платформ: 
    Достать все изображения из системной галереи изображений: На iOS, используя AssetManager, и на Андроиде, используя - MediaStore.  Создать на FireMonkey специальное окно для выбора изображений. Написать стандартное действие для TAсtionList, завернув всю логику по выбору изображения в это действие.
  8. Пост Brovin Yaroslav - сообщение в [TWebBrowser] Как программно задать кодировку страницы в TWebBrowser? был отмечен как ответ   
    Добрый вечер
    Браузер определяет кодировку страницы на основании специального тэга в разметки страницы при помощи атрибута "charset". Если кодировка не указана, то обычно берет текущую системную. Важно знать платформу, на которой у вас возникает такое некорректное поведение. Нужно проверить этот же сайт в стандартном браузере устройства. Если проблема наблюдается и в штатном браузере, то проблема на стороне самого устройства. Обязательно приложите снимок экрана, чтобы было полностью было понятно. Кодировку нельзя задать в TWebBrowser, потому что ее так же нельзя указать системными средствами самих платформ. И как я уже сказал в пункте (1) кодировка определяется самим сайтом. Если же проблема появляется, значит нужно проверить региональные настройки вашего телефона и искать причину в самом аппарате.
     
    Проверил вашу ссылку в браузере FireMonkey TWebBrowser, и у меня во всех случаях на iPhone 5, iOS iPhone Simulator и Nexus 4 страница отображается корректно:


  9. Пост Brovin Yaroslav - сообщение в Как использовать один экземпляр TStyleBook для нескольких форм? был отмечен как ответ   
    Можно с использованием дата модуля.
     
    Делаем так:
    1. Создаем в проекте TDataModule File->New->Other->DelphiFiles->Data Module.
    2. Кидаем на дата модуль стиль бук TStyleBook и загружаем туда нужный стиль:

    3. Открываем остальные формы, и в interface секции модуля в uses добавляем наш дата модуль.
    4. Указываем в свойстве формы
    StyleBook = DataModuleStyle.StyleBook1 Обратите внимание, если вы не подключите в uses дата модуль, то в выпадающем списке не будет варианта указать стильбук с дата модуля.

    5. Меняем порядок создания форм. Дата модуль со стилем обязательно должен создаваться раньше мест использования.

     
    P.S. В дизайнере стилей в дата модуле не доступны контролы FireMonkey, поэтому для создания стиля используйте дизайнер стилей на обычной форме, затем сохраните ваш стиль в файл и загрузите его в стиль бук в дата модуле.
  10. Пост Brovin Yaroslav - сообщение в Как добавить поддержку картинки в кнопках, если картинки хранятся в TStyleBook ? был отмечен как ответ   
    Добрый день,
     
    В TSpeedButton нету функции встраивания изображения. Однако, в аналогичной теме: Как добавить изображение на кнопку SpeedButton? Я рассказал, как добавить такую поддержку и интегрировать это решение с TImageList, основанные на TStyleBook. Так же в моей статье прикреплены исходники этой кнопки. (правда они были сделаны для XE3-4. Так что возможно нужно будет в uses поменять юниты) К TAction сомневаюсь. Так как тут нужен общий подход для всех контролов. Как вариант, вы можете сделать свой наследник TAсtion с поддержкой выбора картинки из TStyleBook, но потом, все равно для всех контролов, которые будут использовать картинки, нужно будет добавлять эту поддержку вручную. Спасибо
  11. Пост Brovin Yaroslav - сообщение в Как определить, какая канва сейчас используется в FireMonkey? был отмечен как ответ   
    После запуска приложения. В любом месте на форме запрашиваем класс канвы:
    Canvas.ClassName Далее по классу определяем канву:
    TCanvasD2D - Direct 2D (Win) TCanvasGdiPlus - GDI + (Win) TCanvasGpu - GPU (Все платормы) TCanvasQuartz - Quartz (iOS, OSX)
  12. Пост Brovin Yaroslav - сообщение в Разработка для Windows Phone был отмечен как ответ   
    Ничего не могу вам ответить. Поживем, увидим.
  13. Пост Brovin Yaroslav - сообщение в Где взять стандартный стиль в FireMonkey для iOS и Android, используемый по умолчанию? был отмечен как ответ   
    Хороший вопрос.
     
    Не все знают, что в RAD Studio XE5 входит дизайнер растровых стилей для VCL (BitmapStyleDesigner), который также позволяет автоматически создавать стили для FireMonkey. Этот дизайнер находится в папке Bin/bitmapStyleDesigner.exe и содержит внутри себя автоматическую конвертацию любого VCL стиля в FireMonkey. 

    Этот дизайнер также предназначен для внесения правок в стандартные системные стили андроида и йос.
     
    Чтобы получить системный стиль Android Dark, Android Light, iOS, iOS 7 нужно:
     
    1. Выбрать дефолтный требуемый стиль: 

    2. Сохранить стиль как стиль FireMonkey:

     
    А дальше использовать файл стиля в своих приложениях.
  14. Пост Brovin Yaroslav - сообщение в Как использовать иконки разного качества для экранов с разным DPI? был отмечен как ответ   
    Здесь есть много решений. Но я приведу на мой взгляд самый оптимальный вариант по простоте и производительности с использованием TStyleBook в качестве TImageList.
     
    Основное нововведение для изображений в мобильных платформах - это использование экранов разной плотности пикселей. Что приводит к тому, что одно и тоже изображение на разных (с разным dpi) экранах имеет разные физические размеры. Подробнее об этом можно прочитать тут: Получаем разрешение экрана устройства, логические и физические размеры экрана в FireMonkey . Если коротко, то это значит, чтобы картинка была четкой на всех экранах нам нужно иметь в своем наборе несколько вариантов этой картинки для основных типов экранов (слева класс экрана - справа коэффициент масштабирования):
    MDPI - 1X HDPI - 1,5X XHDPI - 2X XXHDPI - 3X Например, если у нас есть картинка 48х48 точек для обычного экрана (MDPI - 1X), то нам нужно по хорошему иметь еще три варианта этой картинки других размеров:

    Иначе, картинка или будет сжата, или растянута, что приведет к потере ее качества. Вариант загрузки одного большого изображения не хорош тем, что автоматическое сжатие изображение влечет за собой потерю качества, обычно выраженную в размытии картинки. Попробуйте вручную уменьшать размер изображения, и вы увидите, что в конечном итоге картинка будет либо размытой, либо искаженной в зависимости от алгоритма сжатия. Поэтому как раз и предлагается иметь несколько вариантов исходной картинки, адаптированной под разные варианты экраны.
     
    Теперь на практике. FireMonkey специально для мобильных платформ поддерживает задание нескольких вариантов качества (dpi) одного изображения. Для этого в FireMonkey существует специальный класс TMultiResBitmap (Using Multi-Resolution Bitmaps). Который позволяет указать картинки для разных Scale. Он автоматически вернет картинку нужного качества для текущего устройства. Этот класс используется в TImage. 
     
    1. Делаем форму с лист боксом:

     
    2. Создаем на основе TStyleBook хранилище картинок TImageList по руководству, представленному здесь: Есть ли в fmx класс TImageList?
     
    3. Загружаем для каждой TImage несколько вариантов одного и того же изображения (MultiResBitmap Editor):

     
    4. Далее в режиме выполнения, запрашиваем картинку у ImageBook: TStyleBook. Обратите внимание, что при запросе картинке через TImage.Bitmap - этот метод вернет битмап нужного dpi.
    function TForm5.GetImage(const AImageName: string): TBitmap; var StyleObject: TFmxObject; Image: TImage; begin StyleObject := ImageBook.Style.FindStyleResource(AImageName); if (StyleObject <> nil) and (StyleObject is TImage) then begin Image := StyleObject as TImage; // Здесь мы получим картинку нужного dpi (Scale) Result := Image.Bitmap; end else Result := nil; end; 4. Используя полученную картинку присваиваем ее TListBoxItem:
    const COUNT_ITEMS = 10; var ItemTmp: TListBoxItem; BitmapCloud: TBitmap; I: Integer begin BitmapCloud := GetImage('cloud'); ListBox.BeginUpdate; try ListBox.Clear; for I := 1 to COUNT_ITEMS do begin ItemTmp := TListBoxItem.Create(Self); ItemTmp.Parent := ListBox; ItemTmp.Text := 'Item' + I.ToString; if BitmapCloud <> nil then ItemTmp.ItemData.Bitmap.Assign(BitmapCloud); end; finally ListBox.EndUpdate; end; end; P.S. На устройстве не проверял, но код должен работать. Чуть позже проверю на Nexus 4.
     
    Полезные ссылки
    Получаем разрешение экрана устройства, логические и физические размеры экрана в FireMonkey Есть ли в fmx класс TImageList? Using Multi-Resolution Bitmaps MultiResBitmap Editor
  15. Пост Brovin Yaroslav - сообщение в Клонирование компонента в RunTime был отмечен как ответ   
    Добрый день,
     
    FireMonkey вводит специальный метод TFmxObject.Clone, позволяющий выполнить копирование объекта (без внутреннего состояния) и всех его дочерних объектов путем сериализации/десериализации объекта в памяти.
     
    Соответственно, чтобы получить копию объекта нужно использовать метод:
    function TFmxObject.Clone(const AOwner: TComponent): TFmxObject; У этого метода есть важные особенности:
    Этот метод не копирует родителя Parent у копируемого объекта. Этот метод не копирует обработчики событий. Этот метод не копирует внутреннее состояние объекта. Только если это состояние сериализуется самим объектом. ​Поэтому после выполнения копирования, вы должны задать вручную родителя для копии и требуемые обработчики событий.
     
    Так сделано, поскольку в большинстве случаев после копирования для копии задается другой родитель, поэтому чтобы уменьшить количество не нужных операций по выравниванию контролов и тд, задание родителя отводится пользователю.
  16. Пост Brovin Yaroslav - сообщение в Вопрос как в RunTime при движение компонентов запретить заход одного за другой? был отмечен как ответ   
    Надо при перемещении одного контрола проверять пересечение с остальными. Другого способа нет. Проверять в каждом не нужно. Достаточно проверить только перемещаемый контрол со всеми остальными.  Определение пересечения двух контролов лучше делать по описанным мною способом: Как определить пересекаются ли два контрола или нет? Определение пересечения контрола с границей формы, проще сделать другим способом. Берем у контрола абсолютные координаты его позиции AbsoluteRect, а затем просто проверяем вхождение региона контрола в регион формы. Если форма полностью содержит контрол, значит он не пересекает границу, иначе - пересекает или полностью вне границы. Form1.ClientRect.Contains(Control1.AbsoluteRect)
  17. Пост Brovin Yaroslav - сообщение в Как определить пересекаются ли два контрола или нет? был отмечен как ответ   
    Проще всего определить имеют ли два контрола точки пересечения или нет, используя функцию TRectF.IntersectsWith. Которая позволяет определить пересекаются ли два указанных прямоугольника или нет.
     
    Далее остается определить регионы контролов:
    Контролы имею общего родителя. В этом случае они лежат на одном уровне и являются дочерними объектами одного и того же родителя. А это значит, что в качестве их положения можно взять их регион в родительских координатах TControl.ParentedRect. Контролы не имеют общего родителя. В этом случае нужно воспользоваться регионом взятым в абсолютных координатах формы. То есть TControl.AbsoluteRect. Весь код функции определения пересечения двух контролов представлена ниже:
    function IsControlIntersected(const AControl1: TControl; const AControl2: TControl): Boolean; var ControlRect1: TRectF; ControlRect2: TRectF; begin Assert(AControl1 <> nil); Assert(AControl2 <> nil); if AControl1.Parent = AControl2.Parent then begin ControlRect1 := AControl1.ParentedRect; ControlRect2 := AControl2.ParentedRect; end else begin ControlRect1 := AControl1.AbsoluteRect; ControlRect2 := AControl2.AbsoluteRect; end; Result := ControlRect1.IntersectsWith(ControlRect2); end;  P.S. Мы могли бы всегда вычислять пересечение путем взятия абсолютного положения контролов. Однако, получение абсолютного положения контрола через AbsoluteRect выполняет дополнительные действия по конвертации координат (с учетом матрицы преобразования), что при очень частом использовании может быть не выгодным. Именно по этому правильнее будет использование абсолютных координат только в том, случае, когда это действительно необходимо. Именно по этому код функции IsControlIntersected имеет в себе два подхода.
  18. Пост Brovin Yaroslav - сообщение в Как создать профиль SDK для iOS? был отмечен как ответ   
    Нужно создать профиль SDK в RAD Studio XE5.
    Открыть менеджер SDK. Tools -> Options -> Enviroument Options -> SDK Manager Нажать кнопку "Add" В диалоговом окне "ADD a New SDK" выбрать платформу. В том же окне указать ваш профиль подключения к PAServer. Далее выбрать в этом же окне версию SDK. Поставить галку напротив "Mark the selected SDK active", если вы хотите, чтобы этот SDK использовался по умолчанию на выбранной платформе. Нажать "Ok" Подробное руководство, как это сделать есть на Embarcadero Doc WIki: Adding a Mac OS X or iOS Device SDK
     
     
  19. Пост Brovin Yaroslav - сообщение в Как узнать IP адрес PAServer? был отмечен как ответ   
    Самый простой способ, это спросить ip адрес сервера у PAServer.
    Запускаем PAServer сервер В консоле PAServer вводим команду "i" и нажимаем Enter. Сервер выдаст детальную информацию о используемом IP адресе (смотрите снимок экрана)
    Второй способ, посмотреть IP адрес в настройках сети OSX. Системные настройки -> Сеть -> Ethernet или Wi-Fi (В зависимости от того, что вы используете). На странице адаптера будет написано, что вы используете такой-то адрес (смотрите изображение ниже).

     
    + никто не отменял стандартные средства получения адреса компьютера из командной строки в системе Unix/Linux.
  20. Пост Brovin Yaroslav - сообщение в Как создать освещение на основе TLight и TMaterial? был отмечен как ответ   
    Нужно использовать TLightMaterialSource вместо TColorMaterialSource.
     
    Еще обратите свое внимание на статью на документации: Creating the User Interface (FireMonkey 3D Tutorial)

  21. Пост Brovin Yaroslav - сообщение в Автоматический переход на вторую строку TLabel был отмечен как ответ   
    Да, согласен.
     
    На XE5 Update 2 наблюдается, описанное вами поведение. На текущий момент это уже исправлено. Поэтому предлагаю для XE5 программное решение этой задачи:
    procedure TForm1.FormCreate(Sender: TObject); begin FTextLyout := TTextLayoutManager.DefaultTextLayout.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin FreeAndNil(FTextLyout); end; procedure TForm1.Label1Resize(Sender: TObject); var LabelTmp: TLabel; begin if Sender is TLabel then begin LabelTmp := Sender as TLabel; FTextLyout.BeginUpdate; try FTextLyout.Text := LabelTmp.Text; FTextLyout.MaxSize := TPointF.Create(LabelTmp.Width, 1000); FTextLyout.WordWrap := LabelTmp.WordWrap; FTextLyout.Font := LabelTmp.Font; FTextLyout.HorizontalAlign := LabelTmp.TextAlign; FTextLyout.VerticalAlign := LabelTmp.VertTextAlign; finally FTextLyout.EndUpdate; end; LabelTmp.Height := FTextLyout.Height; end; end; Основная идея следующая: мы используем TTextLayout и параметры метки для вычисления размера текста в TLabel. На основании этого задаем новую высоту для метки.
     
    Обратите внимание, что в этом примере все метки выравнены по верхнему и нижнему краю. Поэтому ширину для текста я указываю равной ширине метки. Если вам нужно вычислить ширину текста, то нужно задавать тогда высоту.
     
    Событие TLabel.Label1Resize нужно задать событию OnResize у меток, где вы хотите автоматически вычислять высоту метки.
     
    Рабочий пример можно скачать тут: LabelAutosizeDemo.zip
  22. Пост Brovin Yaroslav - сообщение в Средства логирования в FireMonkey был отмечен как ответ   
    RAD Studio XE5 предоставляет несколько способов логирования под платформы Андроид и iOS. Давайте их рассмотрим:
    Встроенный в FIreMonkey механизм логирования (кроссплатформенный). Использование системных функция каждой платформы для логирования Использование файлов для вывода логов. Использование сети для передачи сообщений лога 1. Встроенный механизм логирования
    FireMonkey содержит специальный класс FMX.Types.Log для осуществления логирования на всех платформах.
    Этот класс использует на каждой платформе системные средства вывода лога.
    Log = class abstract public class procedure d(const Msg: String); overload; class procedure d(const Fmt: String; const Args: array of const); overload; class procedure d(const Tag: String; const Instance : TObject; const Msg : String); overload; class procedure d(const Tag: String; const Instance : TObject; const Method : String; const Msg : String); overload; class procedure TimeStamp(const Msg: String); overload; class function ObjToString(const Instance : TObject) : String; class function ArrayToString(const AArray : TEnumerable<TFmxObject>) : String; overload; class function ArrayToString(const AArray : TEnumerable<TFmxObject>; MakeStr : ToStringFunc) : String; overload; class procedure DumpFmxObject(const O: TFmxObject; Nest: Integer = 0); end; Он предоставляет довольно много методов по вывода лога. 
    Чтобы его использовать достаточно вызвать любой нужный классовый метод. Например в моем приложении по нажатию на кнопку я буду выводить сообщение: "Log message from FireMonkey application"
    procedure TFormPhone.Button1Click(Sender: TObject); begin Log.d('Log message from FireMonkey application'); end; Далее нужно понять, куда будет выведено это сообщение.
     
    1.1. Андроид
    Под андроид это сообщение попадает в системный журнал. Прочитать его можно в утилите Андроида LogCat - это специальная утилита для просмотра системного лога. Ее можно запустить двумя способами:
    C GUI оболочкой Из командной оболочки (консольный вариант). Первый способ (с GUI). В Eclipse с Android SDK открыть Window->ShowView->LogCat. Откроется окно с GUI интерфейсом, в котором вы сможете увидеть все сообщения, которые отправляют все приложения на телефоне. Стоит отметить, что это вариант LogCat в эклипсе содержит ряд полезных функций по фильтрации лога и его управлению. Поэтому я предпочитаю этот способ, нежели использовать консольный вариант этой же утилиты. Сразу же перед использования советую полностью очистить текущий журнал логов телефона, так как он вначале будет содержать огромное количество сообщений. Для очистки нажмите кнопку очистки лога в окне (кнопка с листком и красным крестиком).

     
    Второй способ (консольный режим). Второй вариант запуска утилиты LogCat заключается в вызове утилиты из командной строки. Утилита просмотра журналов логов входит в общую утилиту ADB.exe. Чтобы запустить лог изз командой строки воспользуйтесь следующей командой:
    .\sdk\platform-tools\adb.exe logcat Утилита лежит в папке platform-tools Android SDK. В вашем случае вы должны указать свой путь к этому файлу. Ключ logcat запускает просмотр журнала логирования.
    Так же как и в первом варианте я советую предварительно очистить лог вызвав logcat с ключом -c:
    .\sdk\platform-tools\adb.exe logcat -с Описание всех ключей утилиты logcat: logcat
    После того, как мы открыли Logcat любым из предложенных способов, запускаем нашу программу и смотрим сообщение в логе:

     
    1.2 Йос
    В йос лог попадает в два журнала в зависимости от того, где вы запускаете свою программу (Симулятор или устройство).
     
    iOS Симулятор. Открываем журнал лога в меню симулятора Отладка->Открыть системный журнал...
     
     
    iOS устройство. Открываем XCode Органайзер и выбираем вкладку Console у вашего устройства.

     
    2. Использование системных функций логирования
    Для тех, кто по каким-то причинам не хочет использовать FireMonkey для этих целей может использовать на каждой платформе системные функции логирования.
     
    2.1 Андроид
    Для андроида в Delphi предусмотрены системные функции из Androidapi.Log:
    { Helper functions } function LOGI(Text: MarshaledAString): Integer; function LOGW(Text: MarshaledAString): Integer; function LOGE(Text: MarshaledAString): Integer; function LOGF(Text: MarshaledAString): Integer;  Каждая из которых выводит сообщение с указанным типом (I - информационное сообщение, W - предупреждение, E - ошибка, F - фатальная ошибка)
     
    2.2 iOS
    В IOS вы можете использовать системную функцию iOSapi.Foundation.NSLog.
    procedure NSLog(format: PNSString); cdecl; varargs; external libFoundation name _PU + 'NSLog'; 3. Логирование в файл
    Является самым стандартным средством. Для его использования вы можете использовать стандартные способы работы с текстовыми файлами, которые полностью работают на всех платформах.
     
    4. Логирование по сети
    Этот способ так же имеет место быть и заключается в создании простого TCP клиента на стороне вашего приложения и FTP сервера на Windows. С приложения вы просто шлете на указанный адрес сервера сообщения, а на стороне сервера просто отображаете. Для этих целей можно использовать стандартные Indy компоненты. 
  23. Пост Brovin Yaroslav - сообщение в Как определить установлено ли другое приложение или нет на Android? был отмечен как ответ   
    Чтобы определить установлено ли нужное приложение или нет, нужно воспользовать следующим кодом:
    uses FMX.Helpers.Android, Androidapi.JNI.GraphicsContentViewText; function IsAppInstalled(const AAppName: string): Boolean; var PackageManager: JPackageManager; begin PackageManager := SharedActivity.getPackageManager; try PackageManager.getPackageInfo(StringToJString(AAppName), TJPackageManager.JavaClass.GET_ACTIVITIES); Result := True; except on Ex: Exception do Result := False; end; end; В качестве параметра указываем полный путь к пакету приложения.
     
    При этом сам вызов использования может быть таким для проверки: "Установлено ли приложение com.embarcadero.Project12 или нет?":
    procedure TForm1.Button1Click(Sender: TObject); begin Label1.Text := BoolToStr(IsAppInstalled('com.embarcadero.Project12'), True); end;
  24. Пост Brovin Yaroslav - сообщение в Делаем в FireMonkey несколько разных форм отдельно для телефона отдельно для планшетов был отмечен как ответ   
    Есть два решения:
    Использовать встроенный в FireMonkey механизм автоматического выбора нужной формы (Для телефона или планшета) При запуске приложения определять тип устройства и создавать нужную формы вручную. Я рассмотрю первый вариант. Поскольку со вторым более менее все понятно. Первое решение основывается на понятии семейства форм. Основная идея следующая, вы определяете какие формы должны быть в вашем приложения без привязки к устройствам.
     
    Например, у вас получилось:
    Основная форма с данными Форма с настройками и тд  То что мы перечислили в FireMonkey называется семейство форм или FormFamily. Далее вы создаете несколько форм в каждой семействе отдельно для телефона, отдельно для планшета, а отдельно для настольных систем. Далее все формы одного семейства помечаются через свойство формы TForm.FormFamily названием семейства (любой строковый идентификатор). Для каждой формы вы указываете через TForm.FormFactor на какие ориентации рассчитана каждый форма и на какие устройства, так же не забываем про размер формы на конечном устройстве.
     
    Далее приложение на основе этой информации автоматически выбирает нужную форму. Чтобы открыть нужную форму в семействе нужно использовать методы, которые по названию семейства вернут экземпляр формы Application: TApplication.
    function GetDeviceForm(const FormFamily: string; const FormFactor: TFormFactor): TCommonCustomForm; overload; function GetDeviceForm(const FormFamily: string): TCommonCustomForm; overload; Для ручной регистрации ваших форм в приложении используйте метод у Application: TApplication:
    procedure RegisterFormFamily(const AFormFamily: string; const AForms: array of TComponentClass); По умолчанию семейство главных форм называется "MainForm".
     
    Теперь то же самое, но на практике:
     
    1. Создаем по отдельной форме для телефона и планшета. Я сделал две формы: PhoneFrm.FormPhone и TabletFrm.FormTablet.

     
    2. Для формы телефона FormPhone указываем размеры формы через TFormFactor и в FormFactor.Devices указываем, что форма рассчитана для телефона iPhone. 

     
    3. Аналогично для формы планшета FormTablet указывает размер формы через TFormFactor и в FormFactor.Devices указываем, что форма рассчитана для планшетов iPad.

     
    4. Для этих форм задаем название семейства форм FormFamily = "MainForm". Это название семейства по умолчанию для главной формы. Обратите внимание, что в файле проекта появились следующие строки:
    program MultiFormsSample; uses System.StartUpCopy, FMX.Forms, PhoneFrm in 'PhoneFrm.pas' {FormPhone}, TabletForm in 'TabletForm.pas' {FormTablet}; {$R *.res} begin Application.Initialize; Application.CreateForm(TFormPhone, FormPhone); Application.CreateForm(TFormTablet, FormTablet); Application.RegisterFormFamily('MainForm', [TFormPhone, TFormTablet]); Application.Run; end. Для нас же самое интересное это метод RegisterFormFamily, который регистрирует в системе наши формы под семейством MainForm. В момент запуска Application выберет нужную форму по заданным параметрам в FormFactor.
     
    5. Наблюдаем результат работы под симулятором iPad и iPhone

     
    P.S. Исходники примера доступны для скачивания тут (RAD Studio XE5 Update 2):MultiFormsSample.zip
  25. Пост Brovin Yaroslav - сообщение в Как закрыть форму на мобильной платформе? был отмечен как ответ   
    Чтобы закрыть форму с выгрузкой ее из памяти, нужно сделать следующее:
    Повесить обработчик на событие формы TForm.OnClose. Установить переданные параметр Action в TCloseAction.caFree procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := TCloseAction.caFree; end; Doc Wiki: Releasing Forms in iOS Apps
×
×
  • Создать...