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

Brovin Yaroslav

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

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

  • Посещение

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

    390

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

  1. Пост Brovin Yaroslav - сообщение в Как добавить поддержку выделение TListBoxItem в своем стиле итема? был отмечен как ответ   
    Чтобы добавить в свой итем поддержку выделения, нужно в TListBox добавить объект, который будет использоваться для выделения:
    Добавляем TRectangle в стиль TStyleBox -> Background.  Для добавленного прямоугольника задаем название стиля: StyleName = 'selection' Указываем цвет заливки прямоугольника После запуска TListBox будет использовать этот объект для осуществления выделения своих итемов.
  2. Пост Brovin Yaroslav - сообщение в Как получить доступ к свойству объекта в стиле и как повесить свой обработчик на его события? был отмечен как ответ   
    Добрый день
    О том, как получить доступ к любому свойству через StylesData (в том числе к свойству text) частично описано тут:
    Как получить значение свойства объекта стиля, используя StylesData? Как получить объект стиля? Назначение обработчиков событий для элементов стиля через StylesData Допустим, что TSpinBox в стиле назван (StyleName), как 'spinbox', тогда
    Присваивание обработчика для SpinBox:
    ListBoxItem1.StylesData['spinbox.OnChange'] := TValue.From<TNotifyEvent>(SBCountChange); Доступ к свойству Text у TSpinBox:
    ListBoxItem1.StylesData['spinbox.Text'].ToString; Таким способом можно получить доступ к любому свойству и событию любого элемента стиля.
  3. Пост Brovin Yaroslav - сообщение в Как получить количество элементов стиля? был отмечен как ответ   
    Каждый стилевой объект является дочерним к корню TStyleBook. Поэтому получение количества стилевых объектов будет запрашиваться так:
    StyleBook1.Style.ChildrenCount
  4. Пост Brovin Yaroslav - сообщение в [Отклонение] При использовании AutoReverse не восстанавливается значение свойства Inverse был отмечен как ответ   
    Исправлено в XE10.
     
    Workaround для версий до XE8 (включительно)
    Перед вызовом анимации сбросить Inverse в False.
    Это косвенно обсуждалось в теме: Как сделать эффект вспышки для контрола, когда он подсвечивается на короткий диапазон времени?
  5. Пост Brovin Yaroslav - сообщение в У меня не получается обновить высоту своего класса итема для TListBox был отмечен как ответ   
    При добавлении своих итемов загрузите стиль принудительно:
    procedure TTabbedForm.AddItem; var Item: TCustomListBoxItem; begin Item:=TCustomListBoxItem.Create(ListBox1, 100); Item.AssignBitmap(ImageControl1.Bitmap); Item.MainText := DateToStr(Now); Item.DetailText := 'Note'; ListBox1.AddObject(Item); Item.ApplyStyleLookup; // <-- форсируем загрузку стиля end; Если стиль грузить не хотите, то можно принудительно вызывать метод для выравнивания всех итемов: 
    ListBox.RealignContent;  Но этот метод нужно вызвать после того, как стили всех видимых итемов были загружены.
     
    P.S. При создании своих итемов не вешайте внутри них на свои же события OnResize и OnApplyStyleLookup обработчики. При таком подходе любой пользователь вашего класса, повесив свой обработчик полностью сломает логику работы ваших итемов. Вместо этого используйте специальные виртуальные методы базового класса:
    procedure ApplyStyle; override; procedure Resize; override;
  6. Пост Brovin Yaroslav - сообщение в [TTreeView] При попытке создать дочерние итемы при разворачивании узла дерева, у меня возникает ошибка. В чем может быть проблема? был отмечен как ответ   
    У вас простая ошибка в реализации OnExpandAction:
    Вы вызываете 
    Item.DeleteChildren Этот метод удаляет все дочерние объекты. Но в FireMonkey в дочерние объекты так же входят объекты стиля. Поэтому вы по сути удалили все итемы и стиль этого элемента, хотя сами в OnClick (кнопки стиля узла дерева) еще находитесь в кнопке, которую разрушили.
     
    Правило: удалять нужно только подитемы. Очистить подитемы в узле дерева можно так:
    procedure RemoveSubNodes(ARoot: TTreeViewItem); var SubNode: TTreeViewItem; begin Assert(ARoot <> nil); while ARoot.Count > 0 do begin SubNode := ARoot.ItemByIndex(0); SubNode.Parent := nil; FreeAndNil(SubNode); end; end;
  7. Пост Brovin Yaroslav - сообщение в Как обнулить миллисекунды в TTimeEdit? был отмечен как ответ   
    Поняли правильно, системный диалог выбора времени на андроиде не дает возможности изменять секунды и миллисекунды.
     
    Чтобы заменить значение миллисекунд на свое вы можете воспользоваться функцией RecodeSecond или RecodeMilliSecond:
    #include "System.DateUtils.hpp" void __fastcall TForm1::TimeEdit1Change(TObject *Sender) { TimeEdit1->DateTime = RecodeSecond(TimeEdit1->DateTime, 0); }
  8. Пост Brovin Yaroslav - сообщение в Советы по созданию мобильного приложения Master-Detail был отмечен как ответ   
    Клик по итему
    Как уже предыдущие пользователи правильно заметили, нажатие на итем в списке самый интуитивно понятный способ на мобильных платформах. По скольку это полностью совпадает с правилами построения пользовательского интерфейса на мобильных платформах.
    Не надо придумывать свои способы, когда уже есть стандартные. Этим вы только запутаете пользователя, привыкшего к общему принципу работы с любым приложением. Если вам такой способ нужен, то лучше перепроектируйте ваш интерфейс, чтобы этого избежать (смотрите пункт 1.) Открытие нового вида
    На счет этого, если вы делаете приложение под андроид, то я бы не рекомендовал для этих целей использовать TTabControl. По одной самой главной причине:
     
    Потребление дополнительных ресурсов. Заставляет форму создавать все контролы на всех вкладках, даже на тех, что не видны. 
     
    Легко представить типичную ситуацию, когда ваше приложение довольно большое и содержит большое число форм ввода и редактирования данных. Теперь представьте, что все эти контролы создаются при запуске приложения и живут все время существования приложения. Это совсем не маленькие размеры памяти, особенно на Андроиде.
     
    Ресурсы мобильной платформа не равны ресурсам настольных платформ. И если на настольной системе вы можете особо не заморачиваться о размере потребляемой памяти, так как ее много. То на мобильнике это может привести к нехватке памяти и как следствие разрушение вашего приложения.
     
    Главная идея - это иметь в каждый момент времени только то, что нужно. Поэтому я бы лучше рассматривал либо создание отдельной формы, либо создание в рантайме специального слоя (вида), которые будет загружен по верх всего, а потом будет разрушен после окончания выполнения редактирования.
     
    Так же советую использовать фреймы для таких функционально законченных блоков (редакторы сущности):
    Позволяет быстро и удобно создавать в нужное время на мобильной платформе требуемый вид. Забирая от системы ресурсы только в тот момент, когда они действительно необходимы. Повторное использование в других местах приложения.
  9. Пост Brovin Yaroslav - сообщение в Как программно получать время в русском формате у TimeEdit? был отмечен как ответ   
    Конвертации вида:
    TTime <-> String TDate <-> String TDateTime <-> String являются базовыми операциями в RTL и не имеют отношения к компоненту TTimeEdit.
     
    Чтобы время перевести в строку с требуемым форматом, нужно использовать метод FormatString:
    TimeEdit1->Time.FormatString("hh:nn:ss"); По умолчанию все функции конвертации без параметров используют настройки формата из FormatSettings. Можете поменять стандартный формат в этой глобальной переменной, тогда все функции будут использовать ваш формат.
  10. Пост Brovin Yaroslav - сообщение в Как программно создаваемому TListBoxItem присвоить стиль? был отмечен как ответ   
    Лучше использовать для этих целей TMetropolisUIListBoxItem  и создавать итемы именно этого класса. Так как TMetropolisUIListBoxItem определяет логику по заданию данных в объекты стиля
    item = new TMetropolisUIListBoxItem(Owner); Стандартный стиль для TMetropolisUIListBoxItem - "collectionlistboxitem" P.S. Когда создаете объекты в RunTime нужно указывать в качестве владельца форму, а не родительский контрол.
  11. Пост Brovin Yaroslav - сообщение в Отслеживание ошибок на эмуляторе Андроид при использовании своего ява кода был отмечен как ответ   
    О вашей цели. Я уже не раз говорил вам, что не получится сделать то, что вы хотите. В частности нельзя просто так взять и поместить FireMonkey компонент в нативный. Это задача не тривиальная и требует глубокого понимания работы платформы FireMonkey под Android. Вы на это потратите кучу времени и с очень большой вероятностью не дойдете до финиша. Об отладке java кода. Stack Trace попадает в лог только если в коде выбрасывающим исключение явно написано выводить StackTrace.
    try { .... } catch (IOException e) { e.printStackTrace(); } В любом другом случае будет выведено только название исключение.
    Поэтому отлаживаться лучше через команды логирования Log.d, Log.e, Log.w
  12. Пост Brovin Yaroslav - сообщение в Как разместить программно TTimeEdit в ListView? был отмечен как ответ   
    Главные отличия TListView от TListBox в:
    TListBoxItem - контрол, TListViewItem - нет В TListBoxItem можно добавлять любые контролы, используя Parent. В TListVIewItem - нет. TListVIewItem хранит только данные для отображения TListVIewItem сам выполняет отрисовку хранимых данных через метод Render За счет собственно ручной отрисовки в TListVIewItem достигается прирост скорости и малое потребление памяти (хранение только актуальных данных) Чтобы создать свой вариант TListViewItem, нужно создать свой класс итема, в нем реализовать требуемые данные (например время) и создать in-place редактор для редактирования времени, зарегистрировать его и тд. P.S. В вашем случае, проще использовать Master-Detail подход. При котором по нажатию на итем, будет открываться вкладка для редактирования информации об итеме, в том числе время через TTimeEdit. Это будет быстрее и проще.
     
    P.S.P.S. Если же вы все-таки хотите создать свой итем, будьте готовы, что придется детально изучить, как это делается в самом TListVew.
  13. Пост Brovin Yaroslav - сообщение в Как загрузить иконку в итемы TListView, хранящиеся в TStyleBook? был отмечен как ответ   
    1. Устанавливаем отображение итемов в TListView с картинкой:

    2. Вытаскиваем по имени картинку из TStyleBook способом, описанным в этой теме: Есть ли в fmx класс TImageList?
    function GetImage(const AImageBook: TStyleBook; const AImageName: string): TBitmap; var StyleObject: TFmxObject; Image: TImage; begin StyleObject := AImageBook.Style.FindStyleResource(AImageName); if StyleObject is TImage then begin Image := StyleObject as TImage; Result := Image.Bitmap; end else Result := nil; end;  3. Код по установке картинки в итем:
    var ListItem: TListViewItem; begin ListItem := ListView1.Items.Add; ListItem.Bitmap.Assign(Image1.Bitmap); end; 4. Наблюдаем результат:

  14. Пост Brovin Yaroslav - сообщение в [Windows] Почему итемы у TListBox не отображают ItemData? был отмечен как ответ   
    Почему не добавляется иконка в TListBoxItem на платформе Windows? Так же поле Detail так же не поддерживается для TListBoxItem под Windows. Либо используйте свой стиль, либо TMetropolistUIListBoxItem 
    P.S. Лучше определить TTimeEdit в стиле. При создании TTImeEdit, привязке к итему и большом числе итемов могут наблюдаться большое потребление ресурсов. За счет того, что для 1000 итемов будет создано и не распущено 1000 TTimeEdit
  15. Пост Brovin Yaroslav - сообщение в [Android] баг: memo съедает буквы при использовании Swype был отмечен как ответ   
    Каждый производитель делает клавиатуру по своим принципах. К сожалению, андроид никак не регулирует принцип работы такой клавиатуры с точки зрения взаимодействия такой клавиатуры с другими приложениями.
     
    После вашего сообщения, мы проверили несколько Swype клавиатур и на всех все работает корректно.
     
    На указанной вами, действительно проблема есть. Но она связана с тем, что сама версия клавиатуры ведет себя абсолютно по своим принципам. Например, вместо посимвольного набора слова, она при добавлении нового символа почему-то очищает только что набранное слово и тд.
     
    В вашем случае проще решить это, поставив более новую версию (например 3.26.92.37556) этой клавиатуры: http://4pda.ru/forum/index.php?showtopic=150358&st=6500#entry10426659, которая видимо исправляет это поведение.
  16. Пост Brovin Yaroslav - сообщение в У меня не получается воспользоваться функцией IntersectRectF был отмечен как ответ   
    Очевидно, если прочитать документацию на функцию RectF, можно обнаружить, что третий и четвертый параметр это правая и нижняя граница, а не ширина и высота соответственно.
     
    В связи с нарушением контракта функции создания прямоугольника, функция вполне корректно говорит о том, что пересечений прямоугольников нет.
     
    Для правильного создания TRectF, вы можете воспользоваться любым из предложенных по ссылкам ниже способам:
    RectF - старым способом. TRectF.Create - новым способом
  17. Пост Brovin Yaroslav - сообщение в Вычисление высоты текста в TText при WordWrap = true был отмечен как ответ   
    Добрый день,
     
    Посмотрите на тему: Автоматический переход на вторую строку TLabel
    Там рассказывается, как вычислить высоту текста.
  18. Пост Brovin Yaroslav - сообщение в Как залить цветом область произвольной формы? был отмечен как ответ   
    Нет, 
     
    Как вариант, использовать заливку полигона или пути:
    procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin Canvas.Fill.Kind := TBrushKind.Solid; Canvas.Fill.Color := TAlphaColorRec.Red; Canvas.FillPolygon([TPointF.Create(0, 0), TPointF.Create(100, 0), TPointF.Create(100, 100)], 1); end;
  19. Пост Brovin Yaroslav - сообщение в Как убрать клавиатуру вызванную фокусом TEdit? был отмечен как ответ   
    Добрый день,
     
    Два варианта:
    Как я могу скрыть / показать клавиатуру под "Android"? Сбросить фокус
    Edit.ResetFocus
  20. Пост Brovin Yaroslav - сообщение в Какой способ лучше для информирования пользователя о выполнении долгой операции? был отмечен как ответ   
    Добрый день,
     
    Использование отдельного потока для длительной операции - хорошая практика. Вопрос о том, как вы будите информировать пользователя об этом ложится на ваши плечи. И зависит от того, чего вы хотите добиться.
     
    Способы индикации выполнения длительной операции
    В голову на первый взгляд мне приходят, например, такие способы:
     
    1. Модальное окно с индикацией хода выполнения операции

    Полностью блокирует работу с приложением, до тех пор, пока операция не закончится или пользователь не отменит ее выполнение.
     
    Достоинства:
    Хорошо применимо, когда в вашем приложении много окон и вам нужно разом заблокировать все. Если вы идете этим путем, то вы можете сделать свою модальную форму со своим дизайном и любыми вариантами индикации вашей задачи, так же как вы работаете с FireMonkey.  Такой подход будет кроссплатформенным и хорошо будет работать, как на Windows, так и на OSX. Недостатки:
    Если вы не используете специальные стили и хотите, чтобы ваше приложение выглядело на всех настольных версиях ОС, как родное, придется постараться, чтобы добиться полного соответствия с темой ОС.  
    2. Системное окно выполнения долгой операции

    Такой же способ, как и первый. Единственное отличие, что в этом способе вы используете диалоговое окно операционной системы.
     
    Достоинства:
    Такое диалоговое окно будет на всех версия ОС Windows выглядеть, как родное. Вам не надо будет заботиться о том, что оно будет выглядеть "не так" в какой-то версии Windows. Недостатки:
    Если вы используете свою стилизацию, отличную от системной. То вам придется изрядно попыхтеть, чтобы сделать нативный диалог в вашем стиле. Такое решение не кроссплатформенно. Вам придется отдельно реализовать такой диалог на разных платформах по разному. 3. Создание слоя, перекрывающего всю форму

    Заключается в размещении TLayout с TAniIndicator и TProgressDialog, перекрывающей все содержимое формы. 
     
    Достоинства:
    В случаях, когда ваше приложение состоит из одной формы (без Docked окон), такое решение будет эффектно и красиво выглядеть. Кроссплатформенно Недостатки:
    Не позволяет полностью блокировать интерфейс, если ваше приложение состоит из нескольких окон (не модальных). 4. Локальное отображение выполнения операции

    Если действие не должно блокировать весь интерфейс, то лучше сделать отображение индикации локальным. Например, в примере выше, при отправке заявки, пока заявка выполняется, отображается индикатор в самой кнопки. Кнопка при этом блокируется.
     
    P.S. Если речь идет об андроиде, то обратите свое внимание на готовые компоненты отображения диалогов:
    FGX. Индикация хода выполнения длительных операций, виртуальная клавиатура и ActionSheet
  21. Пост Brovin Yaroslav - сообщение в [Windows] Как можно сделать эффект "Липкие окошки" TForm? был отмечен как ответ   
    Добрый день,
     
    У FireMonkey нету готового решения из коробки. Но, можно реализовать вручную так:
    Получаем хендл окна формы: 
    uses FMX.Platform.Win; //...... var WinHandle: TWinWindowHandle; begin WinHandle := WindowHandleToPlatform(Handle); // WinHandle.Wnd < -- Хендл окна end Вешаем Hook на оконную процедуру, используя полученный хендл и функции установки хука: Hook Functions В перекрытой нами оконной процедуре перехватываем сообщение WM_WINDOWPOSCHANGING и корректируем позицию окна, используя информацию о границе экрана и других окнах на экране. Таким способом можно сделать прилипание не только к границе экрана, но и к другим окнам (так же как прилипают между собой окна виджетов).
  22. Пост Brovin Yaroslav - сообщение в Почему для моих объектов стиля сбрасываются данные при прокручивании TListBox? был отмечен как ответ   
    Это хороший вопрос. Я поясню. 
    TListBox может иметь большое число элементов (Items, например 1000). Однако, реально из них отображается только видимая часть (Например 50). Отсюда приходит мысль, что не следует грузить стиль всем элементам в лист боксе, поскольку это займет очень много ресурсов: как процессорного времени на загрузку, так и памяти на хранение.  При прокручивании TListBox, стили выгружаются с невидимых элементов, и загружаются для новых видимых. Каждый элемент TListBoxItem, хранит свои данные у себя (Text, IsChecked, Bitmap).  Когда стиль загружается, сам элемент TListBoxItem, устанавливает нужные данные в объекты стиля в соответствии с хранимыми данными (Text, IsChecked, Bitmap).  При выгрузке стиля установленные данные в объекты стиля, теряются. Если только они не были самостоятельно сохранены. Когда вы вручную самостоятельно добавляете свой объект в стиле, вы должны позаботиться о том, чтобы сохранить задаваемые данные для элементов и восстановить эти значения при очередной загрузке стиля. TStyledControl поддерживает встроенный механизм кэширования пользовательских данных через StylesData.  При использовании StylesData контрол автоматически сохраняет ваше значение в своем словаре и при смене стиля самостоятельно обновляет свойства объектов стиля в соответствии с хранимыми данными в словаре. О том, как работать с StylesData можно прочитать тут: Доступ к элементам стиля StylesData Когда вы стали использовать вариант с icon, то по сути сам TListBoxItem за вас восстановил иконку, поскольку это заложено в его базовое поведение  P.S. Используйте StylesData.
  23. Пост Brovin Yaroslav - сообщение в [Android] Как вызвать метод java объекта? был отмечен как ответ   
    Отвечу, но тему все равно создайте новую типа: "Как вызвать метод java объекта", чтобы другим тоже помогла.
     
    Как вы понимаете, в JAVA все объекты. Поэтому, чтобы вызвать какой-либо метод объекта, нужно вначале создать объект, если речь конечно не идет о статическом методе или методе класса (одно и тоже).
    Если у вас статический метод (в java помечен ключевым словом static)
    //Toast zxczx = Toast.makeText(context, "Привет", Toast.LENGTH_SHORT); var Toast: JToast; begin Toast := TJToast.JavaClass.makeText(SharedActivity, StringToJString('Привет'), TJToast.JavaClass.LENGTH_SHORT); Обратите внимание, что метод makeText статический! Значит он запрашивается через JavaClass, как и константы java-класса. Если у вас метод класса:
    var Animation: JAntareyAnimation; begin Animation := TJAntareyAnimation.Create; Animation.Rotate3D; end;
  24. Пост Brovin Yaroslav - сообщение в Как осуществить связь между Delphi интерфейсом и Java классом? был отмечен как ответ   
    Для версий выше, включая XE7
    Используйте специальную утилиту для автоматического получения pas файлов: "Утилита генерации pas файлов для AndroidAPI из jar файлов"
     
    Актуально для XE6 и ниже
    Связь происходит автоматически по атрибуту:
    [JavaSignature('android/widget/Toast')] Дополнительно советую зарегистрировать типы таким образом:
    procedure RegisterTypes; begin TRegTypes.RegisterType('com.antarey.AntareyAnimation', TypeInfo(<Название вашего юнита>.JAntareyAnimation)); end; initialization RegisterTypes; end. Базовый интефейс для вашего класса, например для Toast должен соответствовать базовому классу Toast в Android Api.
     
    Например, если Toast в Android API наследуется от java.lang.Object, то на стороне делфи обертка JToast должна расширять интерфейс JavaObject
    JToastClass = interface(JObjectClass) .... JToast = interface(JObject) Как у вас и написано в вопросе. Мост программно проверит классы помеченные атрибутом JavaSignature (JavaSignatureAttribute - классовая реализация атрибута). И для них сделает связь с нативным классом.
     
    Если вы неправильно укажите сигнатуру методов в интерфейсе JToast или неправильно определите базовый интерфейс, то будет ошибка при попытке вызова неправильного метода, а не на этапе компиляции, так как мост программный. При этом нужно знать:
    Что не обязательно транслировать в JToast все методы из Android Api, достаточно объявить только нужные вам.
  25. Пост Brovin Yaroslav - сообщение в [Android] Можно ли использовать нативную анимацию android.view для анимации TControl? был отмечен как ответ   
    Оставлю здесь только два факта:
    <TControl>!= <View> <TForm> = <View> Из которых следует, что использовать анимацию от нативного View не получится для анимации контрола.
    Максимум может получится для анимации самой формы, но тоже далеко не факт.
×
×
  • Создать...