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

Andrey Efimov

Модераторы
  • Постов

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

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

    123

Активность репутации

  1. Like
    Andrey Efimov получил реакцию от neohost в Проигрывание внутренних ресурсов приложения.   
    Точно конечно не могу сказать, но если мы не можем обратиться к запакованному файлу (в ресурсы приложение) просто указав путь до файла, то напрашивается вывод, что все запакованные таким образом файлы (картинки, звуки) не распаковываются (автоматически). Судя по справке TMediaPlayer, я не вижу варианта проигрывания музыки прямо из ресурсов, т.е. перед проигрыванием придётся извлечь запись и вставить путь в TMediaPlayer.FileName.
  2. Like
    Andrey Efimov отреагировална 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:

     
    А дальше использовать файл стиля в своих приложениях.
  3. Like
    Andrey Efimov отреагировална Brovin Yaroslav в Как использовать иконки разного качества для экранов с разным DPI?   
    Завтра все равно попробую с IBitmapLink.
     
    Так как это работает намного быстрее, при таком подходе картинка существует в одном экземпляре и используется во всех итемах.
  4. Like
    Andrey Efimov получил реакцию от Brovin Yaroslav в Как использовать иконки разного качества для экранов с разным DPI?   
    Ошибка была из-за прошлых экспериментов со стилями, забыл очистить свойство формы StyleBook.
     
    Про этот способ ItemTmp.ItemData.Bitmap.Assign знаю, уже попробовал, не хочет подгружать картинки и всё. Надо попробовать на чистом приложении.
     
    p.s. Ярослав, спасибо вам за помощь и терпение!
     
    UPD.(2:32) Точно надо было идти спать... Нашёл свой косяк. У меня было TImage.StyleName:='folders', а запрашивал я 'folder'. Картинки не грузит… Всё я спать, лучше завтра со свежей головой разберусь с этим. Ещё раз спасибо!
    UPD.2.(2:36) Понял в чём косяк, ваш код отказывается у меня работать, а именно сточка (ItemTmp.ItemData.Bitmap as IBitmapLink).SetResourceBitmap(BitmapCloud);, получилось с ItemTmp.ItemData.Bitmap.Assign.
  5. Like
    Andrey Efimov отреагировална Brovin Yaroslav в Как использовать иконки разного качества для экранов с разным DPI?   
    Что за ошибка? Можно использовать ItemTmp.ItemData.Bitmap.Assign вместо варианта с IBitmapLink Вопрос про дефолтный стиль оформите отдельной темой.
  6. Like
    Andrey Efimov отреагировална 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
  7. Like
    Andrey Efimov отреагировална Brovin Yaroslav в Есть ли в fmx класс TImageList?   
    На данный момент (до версии RAD Studio XE5) FireMonkey не имеет компонент TImageList.
    Однако, для хранения графических ресурсов отлично подходит TStyleBook. Общая идея сводится к добавлению именованных графических ресурсов в TStyleBook в контейнере TImage. Затем мы каждому TImage задаем имя через StyleName. И затем в нашем коде уже по строковому идентификатору достаем нужную картинку.
     
    Рассмотрим теперь это на практике.
    Создадим приложение, которое будет вытаскивать картинку по имени из TStyleBook и отображать его в контейнере TImage.
     
    1. Создаем TStyleBook. Перетаскиваем его палитры компонентов (Tool Palette) в дизайнере на форму. Так же на форме я разметил кнопку и TImage для отображения выбранного изображения.

     
    2. Открываем дизайнер стилей и добавляем компонент TImage, путем перетаскивания TImage в корень Structure Panel (панель с деревом компонентов формы).

     
    3. В TImage загружаем картинку и называем картинку через TImage.StyleName. В моем случае изображение андроида и название  - 'android'. 


     
    4. Обратите внимание, что RAD Studio XE5 поддерживает картинки разного dpi для четкой отображения на экранах с разными dpi и Экранным масштабом (Scale). На рисунке выше, я загрузил два разрешения картинки, для обычных экранов, и экранов с удвоенной плотностью пикселей. Это актуально для мобильных платформ и OSX с экранами ретина.
     
    5. Пишем метод, который вытащить картинку по имени:
    function TForm4.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; Result := Image.Bitmap; end else Result := nil; end; Каждый объект FireMonkey TFmxObject предоставляет способ для поиска среди дочерних объектов объект с указанными именем StyleLookup. Доступ к корню всех стилей в StyleBook  является свойство TStyleBook.Style. Далее ищем у корня стиль с нужным именем картинки. Если стиля нету, то метод вернет nil. Иначе проверяем, что стиль есть и он экземпляр контейнера TImage. Далее просто выбираем картинку через свойство Bitmap.
     
    6. Вытаскиваем картинку и отображаем ее в TImage на форме.
    procedure TForm4.Button1Click(Sender: TObject); var Bitmap: TBitmap; begin Bitmap := GetImage('android'); if Bitmap <> nil then Image1.Bitmap.Assign(Bitmap); end; Вот в принципе и вся идея. Эту идею можно обобщить, сделав отдельный компонент с быстрой загрузкой картинок. Но это уже практика.
     
    Пример можно скачать тут: ImageBook.zip
  8. Like
    Andrey Efimov отреагировална Brovin Yaroslav в Получаем разрешение экрана устройства, логические и физические размеры экрана в FireMonkey   
    Введение
    Появление экранов повышенной плотность физических точек, привело с одной стороны к проблеме адаптации графического интерфейса под разные разрешения экранов при их одинаковых физических размерах, с другой к увеличению четкости и качества картинки.
     
    Например, если раньше на iPhone 3 при размере экрана 3,5 дюйма позволял отобразить 320х480 точек, то на устройстве iPhone 4 при таком же физическом размере экрана, экран мог уже отображать 640х960 точек. Это хорошо видно на увеличенном изображении обычного экрана и ретина экрана на рисунке ниже (слева - не ретина, справа - ретина (2х)). Справа количество физических точек ровно в четыре раза больше, чем слева:

     
    Для разработчика это могло означать, что интерфейс привязанный к разрешению 320х480 на Retina экране будет занимать только четверть экрана. Естественно, что использование разрешения экрана в физических координатах не удобно с этой точки зрения. Именно по этому появились логические координаты, которые гарантируют, что тот же пользовательский интерфейс для iPhone 3, будет иметь такие же размеры (физические) и на экране с ретиной.
     
    FireMonkey работает в логических координатах. Это означает, что на iPhone 3 - 4 мы работаем с логическим разрешением 320x480 точек. Однако, при отображении интерфейса на iPhone 4 c (с двойной плотностью пикселей по сравнению с iPhone 3), интерфейс автоматически масштабируется на физическое разрешение 640х960 с коэффициентом масштабирования равным 2. 
     
    Практика
    Теперь посмотрим, как получить всю эту информацию. Вся информация об экране (логический размер и коэффициент масштабирования) находится в сервисе IFMXScreenService. 
    Чтобы получить физическое разрешение экрана, нужно логический размер умножить на коэффициент масштабирования.
     
    Код ниже показывает, как получить доступ к этому сервису и извлечь требуемые параметры:
    var ScreenService: IFMXScreenService; LogicScreenSize: TPoint; ScreenScale: Single; begin // Запрашиваем сервис экрана, для получения информации о размере и текущем коэффициенте масштабирования if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then begin LogicScreenSize := ScreenService.GetScreenSize.Round; ScreenScale := ScreenService.GetScreenScale; LabelLogicScreenSize.Text := Format('Логический размер: %d, %d', [LogicScreenSize.X, LogicScreenSize.Y]); LabelPhysicScreenSize.Text := Format('Физический размер: %f, %f', [LogicScreenSize.X * ScreenScale, LogicScreenSize.Y * ScreenScale]); LabelScreenScale.Text := Format('Коэффициент масштабирования: %f',[ScreenService.GetScreenScale]); end; end; Результат кода приведен на снимке экранов ниже для iPad устройств с ретиной экраном и без:

  9. Like
    Andrey Efimov получил реакцию от Brovin Yaroslav в Задаем отступ между картинкой и текстом в TListBoxItem   
    Вопрос решил! Не знаю, как я мог забыть про стили… Прошу прощения за такой простой вопрос(Мне стыдно   )
     
    Всем у кого появился подобный вопрос, загружаете через «TStyleBook» свой стиль, далее редактируете его, находим ListBox (listboxitemnodetail), открываем ветку и находим «area:Tlayout->Text», чтобы редактировать отступ, выберите свойство Margins и редактируйте.
     
    P.S. Тему наверно можно удалять или …

  10. Like
    Andrey Efimov отреагировална 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
  11. Like
    Andrey Efimov получил реакцию от Brovin Yaroslav в Автоматический переход на вторую строку TLabel   
    Если выставить:
    Label1.Align := alTop;  Label1.AutoSize := True;  Label1.WordWrap := True; то при компиляции под андроид, Label1.WordWrap := True; автоматически превращается в Label1.WordWrap := False; и перенос не работает.
  12. Like
    Andrey Efimov отреагировална 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 компоненты. 
×
×
  • Создать...