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

Brovin Yaroslav

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

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

  • Посещение

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

    390

Весь контент Brovin Yaroslav

  1. Скиньте, пожалуйста, ссылки на баги в QC. P.S. XE2 вышла в 2012 году
  2. Нужно указать: Версию RAD Studio Версию операционной системы Используется ли виртуальная машина? Желательно понять, какая канва используется: GDI+ или Direct2D. Как определить текущую канву можно тут: Как определить, какая канва сейчас используется? После этого можно будет точнее диагностировать вашу ситуацию.
  3. Как определить, какая канва используется в текущий момент?
  4. Этот способ, как и в Windows подразумевает встраивание ресурсов прямо в исполняемый файл приложения. Поэтому при установки на устройство, как вы понимаете, ресурс останется в исполняемом файле. Чтобы ресурс распаковался в виде файла, нужно использовать способ с Deployment Manager по этому руководству: Включение своих файлов в приложение Без распаковки отдельным файлом стандартными средствами никак. Если это и возможно, то только при помощи низкоуровневого кодирования с использованием Android API. Поскольку, судя по описанию используемого JMediaPlayer в Android API (MediaPlayer), он не умеет читать из кастомного потока. Если же вопрос встраивания медиа ресурсов в приложение важно для вас, то либо распаковка файла либо долгие и мучительные поиски решения. Поскольку так в большинстве случаев не делают. Поскольку сам формат андроид приложения подразумеваем хранение всех ресурсов отдельно.
  5. Ничего не могу вам ответить. Поживем, увидим.
  6. Хороший вопрос. Не все знают, что в RAD Studio XE5 входит дизайнер растровых стилей для VCL (BitmapStyleDesigner), который также позволяет автоматически создавать стили для FireMonkey. Этот дизайнер находится в папке Bin/bitmapStyleDesigner.exe и содержит внутри себя автоматическую конвертацию любого VCL стиля в FireMonkey. Этот дизайнер также предназначен для внесения правок в стандартные системные стили андроида и йос. Чтобы получить системный стиль Android Dark, Android Light, iOS, iOS 7 нужно: 1. Выбрать дефолтный требуемый стиль: 2. Сохранить стиль как стиль FireMonkey: А дальше использовать файл стиля в своих приложениях.
  7. Завтра все равно попробую с IBitmapLink. Так как это работает намного быстрее, при таком подходе картинка существует в одном экземпляре и используется во всех итемах.
  8. Что за ошибка? Можно использовать ItemTmp.ItemData.Bitmap.Assign вместо варианта с IBitmapLink Вопрос про дефолтный стиль оформите отдельной темой.
  9. Здесь есть много решений. Но я приведу на мой взгляд самый оптимальный вариант по простоте и производительности с использованием 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
  10. Добрый день, FireMonkey вводит специальный метод TFmxObject.Clone, позволяющий выполнить копирование объекта (без внутреннего состояния) и всех его дочерних объектов путем сериализации/десериализации объекта в памяти. Соответственно, чтобы получить копию объекта нужно использовать метод: function TFmxObject.Clone(const AOwner: TComponent): TFmxObject; У этого метода есть важные особенности: Этот метод не копирует родителя Parent у копируемого объекта. Этот метод не копирует обработчики событий. Этот метод не копирует внутреннее состояние объекта. Только если это состояние сериализуется самим объектом. ​Поэтому после выполнения копирования, вы должны задать вручную родителя для копии и требуемые обработчики событий. Так сделано, поскольку в большинстве случаев после копирования для копии задается другой родитель, поэтому чтобы уменьшить количество не нужных операций по выравниванию контролов и тд, задание родителя отводится пользователю.
  11. Автор: Павел Литвинко Обзорная статья: http://blogs.embarcadero.com/vsevolodleonov/2014/01/31/appfactory1/ Видео обзор (Rus): http://www.youtube.com/watch?v=6Tahytk_QUM Видео обзор (En): http://www.youtube.com/watch?v=xVUhMAJquw8 Ссылки на приложения: AppFactory, AppProducts
  12. Надо при перемещении одного контрола проверять пересечение с остальными. Другого способа нет. Проверять в каждом не нужно. Достаточно проверить только перемещаемый контрол со всеми остальными. Определение пересечения двух контролов лучше делать по описанным мною способом: Как определить пересекаются ли два контрола или нет? Определение пересечения контрола с границей формы, проще сделать другим способом. Берем у контрола абсолютные координаты его позиции AbsoluteRect, а затем просто проверяем вхождение региона контрола в регион формы. Если форма полностью содержит контрол, значит он не пересекает границу, иначе - пересекает или полностью вне границы. Form1.ClientRect.Contains(Control1.AbsoluteRect)
  13. Проще всего определить имеют ли два контрола точки пересечения или нет, используя функцию 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 имеет в себе два подхода.
  14. Как лучше определить пересекаются ли два контрола или нет (Поворот контролов не учитывается)?
  15. Используйте тогда явную конвертацию вектора в точку: DraggableImage.Position.Point := DraggableImage.Position.Point + MoveVector.ToPointF; P.S. В приведенном мною коде, нету неиспользуемых переменных MouseDownPoint, Moving2 и Splitting. P.S.S. Текст ошибки все-таки не привели, что именно говорит компилятор.
  16. В 2D приложения третья ось не учитывается, поэтому можете в конструкторе указать, что она равна 0. MoveVector := TVector.Create(X - FStartPos.X, Y - FStartPos.Y, 0); Либо вместо TVector использовать TPointF. В этом случае нужно будет заменить вызовы: DraggableImage.LocalToAbsoluteVector(MoveVector); DraggableImage.ParentControl.AbsoluteToLocalVector(MoveVector); на DraggableImage.LocalToAbsolute(MovePoint); DraggableImage.ParentControl.AbsoluteToLocal(MovePoint); Где MovePoint: TPointF;
  17. Нужно создать профиль 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
  18. Самый простой способ, это спросить ip адрес сервера у PAServer. Запускаем PAServer сервер В консоле PAServer вводим команду "i" и нажимаем Enter. Сервер выдаст детальную информацию о используемом IP адресе (смотрите снимок экрана) Второй способ, посмотреть IP адрес в настройках сети OSX. Системные настройки -> Сеть -> Ethernet или Wi-Fi (В зависимости от того, что вы используете). На странице адаптера будет написано, что вы используете такой-то адрес (смотрите изображение ниже). + никто не отменял стандартные средства получения адреса компьютера из командной строки в системе Unix/Linux.
  19. Нужно использовать TLightMaterialSource вместо TColorMaterialSource. Еще обратите свое внимание на статью на документации: Creating the User Interface (FireMonkey 3D Tutorial)
  20. Не за что. Если задаете текст вручную, то нужно вызывать перерасчет высоты. Поскольку я привел код для варианта при условии не изменяемости текста.
  21. Да, согласен. На 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. 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. Какими доступными средствами можно осуществлять логирования под Андроид?
  24. Чтобы определить установлено ли нужное приложение или нет, нужно воспользовать следующим кодом: 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;
×
×
  • Создать...