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

ENERGY

Пользователи
  • Постов

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

  • Посещение

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

    57

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

  1. Like
    ENERGY получил реакцию от AngryOwl в Размер компилируемого файла   
    Menkos1
    Это код для уменьшения размера exe под Windows. Добавляшь в Dpr файл (Project > View Source),  выбираешь Release в правой панели, затем Project  > Build. Размер еще уменьшиться.
    Правда потом нужно протестировать программу. На VCL с этими директивами у меня проблем никогда не было, - в смысле каких то багов в программе. На FMX не пробовал (я FMX пока только под моб. девайсы использую)
  2. Like
    ENERGY получил реакцию от AngryOwl в Размер компилируемого файла   
    Системе не навредит, просто смысла в этом нет. Лучше упаковать архиватором, или инсталлятором.
    Упакованные exe распаковываются целиком в память, и остаются там до конца, плюс дольше запускаются.
    Не упакованные exe загружаются по сегментам, частично, только то, что нужно. http://api.farmanager.com/ru/articles/packers.html
     
    Я такой обычно код вставляю в dpr файл, для Windows проектов.  
    uses  Windows; {$IFDEF RELEASE}     {$SETPEFlAGS IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_DEBUG_STRIPPED or          IMAGE_FILE_LINE_NUMS_STRIPPED}     {$WEAKLINKRTTI ON}     {$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])} {$ENDIF} Конечно же нужно выбрать Release в Build Configurations в правой панели.
    Есть смысл упаковывать вирусы итп, чтобы быстрее скачать, чтобы зашифровать и сменить сигнатуру. Или кеиген или что-то подобное.
  3. Like
    ENERGY получил реакцию от rareMax в [Отклонение] TFloatAnimation и TFrame   
    Столкнулся с такой же проблемой, если любой компонент (в моем случае TImage ) лежит на фрейме не работает TFloatAnimation вообще.
    Решение: 
    При создании фрейма нужно указывать Self формы, а не  nil.
    : MyFrame := TMyFrame.Create(Self);
  4. Like
    ENERGY получил реакцию от Ingalime в [Статья]Как создать простой Android Broadcast Receiver. How to implement simplest Android Broadcast Receiver in Delphi   
    Как создать простейший Android Broadcast Receiver.
    Создайте класс, для приема Intent уведомлений:
     
    uses Androidapi.JNIBridge, Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText; type TMyReceiver = class(TJavaLocal, JFMXBroadcastReceiverListener) public constructor Create; procedure onReceive(context: JContext; intent: JIntent); cdecl; end; uses Androidapi.Helpers, Androidapi.JNI.JavaTypes; { TMyReceiver } constructor TMyReceiver.Create; begin inherited; end; procedure TMyReceiver.onReceive(context: JContext; intent: JIntent); begin Log.d('Broadcast Received = ' + JStringToString(intent.getAction)); end;  
    Регистрируем тип уведомлений и приемник в событиях формы:
     
    type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { private } FMyListener: TMyReceiver; FBroadcastReceiver: JFMXBroadcastReceiver; public { public } end; procedure TForm1.FormCreate(Sender: TObject); var Filter: JIntentFilter; begin FMyListener := TMyReceiver.Create; FBroadcastReceiver := TJFMXBroadcastReceiver.JavaClass.init(FMyListener); Filter := TJIntentFilter.JavaClass.init; Filter.addAction(TJIntent.JavaClass.ACTION_SCREEN_OFF); Filter.addAction(TJIntent.JavaClass.ACTION_SCREEN_ON); TAndroidHelper.context.getApplicationContext.registerReceiver (FBroadcastReceiver, Filter); end; procedure TForm1.FormDestroy(Sender: TObject); begin TAndroidHelper.context.getApplicationContext.unregisterReceiver (FBroadcastReceiver); end; Все.
    Теперь когда вы запустите программу и выключите\включите экран, лог покажет :
    FMX: BroadcastSample: Broadcast Received = android.intent.action.SCREEN_OFF FMX: BroadcastSample: Broadcast Received = android.intent.action.SCREEN_ON Takashi Yamamoto
  5. Like
    ENERGY отреагировална Zyablik3000 в Компонент - наследник TPresentedScrollBox   
    Всем спасибо) Решение нашел сам.
    Прочитав http://yaroslavbrovin.ru/new-approach-of-development-of-firemonkey-control-control-model-presentation-part-1-ru/  и другие материалы с этой странички (к слову: жутко полезная информация) перекрыл в своем компоненте функцию
    function DefinePresentationName: string; override;
    function TScrBox.DefinePresentationName: string; begin Result:='PresentedScrollBox-style'; end; Дело оказалось в том, что не загружалась презентация для моего компонента (а модель создавалась), точнее пыталась загрузиться презентация 'ScrBox-style', прокси для которой не зарегистрирован. Ведь имя презентации формировалось как 'Имя класса' + '-style'
    Но этого оказалось недостаточно. Еще понадобилось задать свойство StyleLookup:='scrollboxstyle'; т.к. скроллбары и прочие контролы берутся из стиля TStyledCustomScrollBox'а, который описан в FMX.ScrollBox.Style.
    Надеюсь кому-то поможет, и этот кто-то не будет как я тратить на решение этой задачи три дня жизни.
     
    Test.7z
  6. Like
    ENERGY отреагировална qz5 в Публикация приложения на Google Play   
    вот инструкция на английском, с картинками - http://docwiki.embarcadero.com/RADStudio/Rio/en/Submitting_Your_Android_App_to_Google_Play
  7. Like
    ENERGY получил реакцию от Ingalime в [Android] Прозрачность формы в RIO и выше   
    В версиях студии после 10.1 (Berlin) прозрачность форм в Android сломалась.
    Баг находится здесь  https://quality.embarcadero.com/browse/RSP-22314
    Причина и одно из простых решений находятся в комментах.
    Починить можно так, проверено в 10.4: 
    Work around is to set your formstyle property of the form to "Popup". This will make the form transparent again. But this wil have the effect of the wsMaximized style not working properly. You can go around this by making the following code additions to your form:
    procedure TForm1.Adjustformsize; begin Width := Screen.Width; height := Screen.Height; Top := 0; left := 0; end; You should call this procedure before you show the form. Also you should anticipate a form resize when the device is rotated. You can use the following code for that:
    first add System.Messaging and fmx.Platforms to your uses clause. Then add the following code
    procedure TForm1.OrientationChangedHandler(const Sender: TObject; const Msg: TMessage); begin AdjustFormSize; end; //Add in the formcreate: TMessageManager.DefaultManager.SubscribeToMessage(TOrientationChangedMessage, OrientationChangedHandler); // add in the destroy: TMessageManager.DefaultManager.Unsubscribe(TOrientationChangedMessage, OrientationChangedHandler);  
  8. Like
    ENERGY отреагировална gonzales в поломались ПУШи в 10.4   
    Нашел причину,
    В недрах класса TPushService
    TPushService = class abstract public type TPropPair = TPair<string, string>; TPropArray = TArray<TPropPair>; // commonly used names TServiceNames = record public const GCM = 'gcm'; // deprecated 'Is not available anymore. Please use FCM instead'; // Google cloud messaging FCM = 'fcm'; // Google Firebase cloud messaging APS = 'aps'; // Apple end; Соответственно нужно исправить
    FPushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);
    на
    FPushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.FCM);
     
    Все работает
  9. Like
    ENERGY отреагировална gonzales в поломались ПУШи в 10.4   
    Не могу одолеть пуши при компиляции приложения в 10.4
    Вот стандартный код
    unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, System.PushNotification, System.JSON, System.Net.HTTPClient, System.Threading,REST.Types {$IFDEF ANDROID}, FMX.PushNotification.Android, FMX.Memo.Types{$ENDIF} {$IFDEF IOS}, FMX.PushNotification.IOS{$ENDIF}; type TForm1 = class(TForm) MemoLog: TMemo; procedure FormCreate(Sender: TObject); private FDeviceID: string; FDeviceToken: string; FPushService: TPushService; FPushServiceConnection: TPushServiceConnection; procedure OnReceiveNotificationEvent(Sender: TObject; const ANotification: TPushServiceNotification); procedure OnServiceConnectionChange(Sender: TObject; AChange: TPushService.TChanges); procedure PushServiceRegister; { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} const FAndroidServerKey = '13648316531'; procedure TForm1.OnReceiveNotificationEvent(Sender: TObject; const ANotification: TPushServiceNotification); const FCMSignature = 'gcm.notification.body'; GCMSignature = 'message'; APNsSignature = 'alert'; var aText: string; aObj: TJSONValue; begin // это событие срабатывает при открытом приложении {$IFDEF ANDROID} aObj := ANotification.DataObject.GetValue(GCMSignature); if aObj <> nil then aText := aObj.Value else aText := ANotification.DataObject.GetValue(FCMSignature).Value; {$ELSE} aObj := ANotification.DataObject.GetValue(APNsSignature); if aObj <> nil then aText := aObj.Value; {$ENDIF} ShowMessage(aText); end; procedure TForm1.OnServiceConnectionChange(Sender: TObject; AChange: TPushService.TChanges); begin if (TPushService.TChange.DeviceToken in AChange) and Assigned(FPushServiceConnection) then begin FDeviceID := FPushService.DeviceIDValue[TPushService.TDeviceIDNames.DeviceID]; FDeviceToken := FPushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken]; MemoLog.Lines.Add('DeviceID - '+ FDeviceID); MemoLog.Lines.Add('DeviceToken - '+ FDeviceToken); end; end; procedure TForm1.PushServiceRegister; begin FPushService := nil; FPushServiceConnection := nil; {$IF defined(ANDROID)} FPushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM); FPushService.AppProps[TPushService.TAppPropNames.GCMAppID] := FAndroidServerKey; {$ENDIF} {$IF defined(IOS) AND defined(CPUARM)} FPushService := TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.APS); {$ENDIF} if Assigned(FPushService) then begin FPushServiceConnection := TPushServiceConnection.Create(FPushService); FPushServiceConnection.OnChange := OnServiceConnectionChange; FPushServiceConnection.OnReceiveNotification := OnReceiveNotificationEvent; FPushServiceConnection.Active := true; FDeviceID := FPushService.DeviceIDValue[TPushService.TDeviceIDNames.DeviceID]; FDeviceToken := FPushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken]; MemoLog.Lines.Add('DeviceID - '+ FDeviceID); MemoLog.Lines.Add('DeviceToken - '+ FDeviceToken); end; end; procedure TForm1.FormCreate(Sender: TObject); begin PushServiceRegister; end; end. При регистрации пуш-сервиса строка FPushService.AppProps[TPushService.TAppPropNames.GCMAppID] := FAndroidServerKey; вызывает Segmentation Fault (11)
    В 10.3 тот же самый код работает, дебаг ничего не дает, проваливаюсь в процедуру
    procedure TPushService.SetAppProp(const AName, AValue: string); begin FAppProps.AddOrSetValue(AName, AValue); end; а внутрь AddOrSetValue уже не идет, сразу ошибка.
    Если кто сталкивался, помогите плиз
  10. Like
    ENERGY получил реакцию от Alexandr4444 в Как в программе определить физические размеры экрана устройства?   
    Android/iOS var    clientScreenScale   : Single;    clientScreenSize    : TSize;    clientScreenService : IFMXScreenService; begin   if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(clientScreenService)) then     clientScreenScale := clientScreenService.GetScreenScale   else     clientScreenScale := 1;   // The display device's width:   clientScreenSize.CX := Round(clientScreenService.GetScreenSize.X * clientScreenScale);   // The display device's height:   clientScreenSize.CY := Round(clientScreenService.GetScreenSize.Y * clientScreenScale); end;  
  11. Like
    ENERGY получил реакцию от AndrewKruchinin в [Статья] Как конвертировать растровую картинку в векторный TPath Firemonkey. How to convert a bitmap image (png, jpeg, bmp) into a Firemonkey vector TPath.   
    Как конвертировать растровую картинку в векторный TPath Firemonkey.
    How to convert a bitmap image (png, jpeg, bmp) into a Firemonkey vector TPath. Manual.

    Плюсы векторных изображений: 
    Можно изменять размер избражения в любую сторону, уменьшать и увеличивать, без потери качества. Картинка всегда будет с четкими краями, без размытия по краям и квадратиков. Можно легко изменять в RunTime цвет заливки и обводной рамки, изменяя цвета в полях Fill и Stroke компонента TPath. Заливка как правило одна - это цвет из свойства Fill Color. Но ... цвет может быть и градиентом из множества цветов, который можно указать в диспетчере объектов, там же можно загрузить и Bitmap как текстуру в качестве заливки.  Можно анимировать изображение, изменяя вышеуказанные свойства, а также направление градиента, размер, толщину обводной линии итд. Тоже можно менять и для Stroke свойства - обводной рамки.
    Минусы:
    Получаемое изображение упрощенное. Т.к. оно может содержать только один путь (Path) и одну плоскость.
    Возможно получиться скомбинировать множества TPath, положив их друг на друга с прозрачностью. 
    Векторное изображение вычисляется и рисуется "в живую", поэтому потребуется больше ресурсов, чем при отрисовке обычных растровых картинок png, jpg, bitmap.
    Что означает нагрузку на аппаратную часть, замедление работы программы и более быструю разрядку мобильного устройства.
    Поэтому если и использовать подобные векторные изображения, то в случае если нужно отобразить большие картинки-символы на разных экранах (не иконки) - например на маленьком экране телефона, и на большом планшете и на еще большем Desktop экране. 
    Хотя в примере \Samples\Object Pascal\Multi-Device Samples\User Interface\CustomListBox\CustomListBox.dproj используется векторная иконка\чекбокс очень простая. 
     
    Преимущества векторного изображения наглядно:

     
    Ингредиенты: 
    1. Векторный редактор, я взял бесплатный inkscape, который можно скачать здесь . 
    2. Картинка. Желательно чтобы картинка была с большим разрешением, от 300px и больше. Если взять изображение маленького размера, например 48x48 или 64x64, то контуры получатся не такими точными. И хотя inkscape все равно применит сглаживание контуров, и квадратиков вы не увидите, обводные линии могут получиться другой формы, к примеру более жирными или могут слиться с другими линиями.
    Исходное изображение лучше брать в формате PNG, т.к. JPEG оставляет артефакты в виде точек, в итоге программа при трассировке может захватить и их, что не желательно. Конечно же если другого исходника нету, то смысла конвертировать jpg в png нет - качество не улучшится.
    Основной метод конвертации - это трассировка изображения, - когда алгоритм ищет края и обводные линии, и на основе их рисует свои. Потому качественные результаты получаться если брать изображение с одной плоскостью, без теней, градиентов и деталей, в стиле Windows 8\10 или Android. Т.н. Flat (плоский) icon. 
    3. IDE RAD Studio Delphi или С++

    Приступим. 
    Запускаем incscape. 
    Размер исходной png картинки 668x720.

    1. Меню File > Open - указываем путь. Иконка загрузилась.
    2. Нажимаем левой кнопкой мыши на картинку, чтобы она выделилась.
    3. Меню Path > Trace Bitmap. Сразу выберите чекбокс Live Preview (см скриншот).
    Здесь есть разные методы, но нам нужна секция Single Scan: Creates a Path. Методы нужно подбирать визуально, "на глаз". 
    Можно также использовать и секцию Multiply Scans, а затем скомбинировать пути в один (Path > Combine), т.к. нам нужен один путь, и один набор. Путь (Path) это набор инструкций о том как и сколько рисовать линий-векторов. Для нашего конкретного случая, этой конкретной иконки, оптимальный вариант Color Quantization и количество цветов = 2.

     
    4. Нажимаем OK и закрываем окно. Появилось наше изображение залитое черным цветом - это и есть наша векторная картинка. 
    Стоит заметить что прямо под ним лежит наше исходного изображение. Чтобы его удалить нужно отодвинуть мышкой векторное изображение, выделить исходную картинку и удалить ее клавишей Delete.  
    5. Вы можете отредактировать пути, выбрав в левой панели инструмент Edit Paths By nodes (F2) или добавить фильтры\эффекты в меню Path > Path Effects. В данном примере я ничего не менял.
    6. File Save As > inkscape SVG .
    7. Открываем полученный SVG файл в блокноте или в Lister тотал коммандера. Ищем массив чисел, который обычно начинается со строчки "<path". Находим эту строчку, нам нужно набор символов, который идет после буквы "d=", к примеру d="m 397.33334,c -48.1 ...-0.326 -1.64129,-0.66405 z" и копируем все, что внутри кавычек в буфер.
    8. Далее в RAD IDE кидаем на форму TPath. В Object Inspector WrapMode устанавливаем в Fit, и в поле Data вставляем из буфера наш код.
    9. Меняем Fill и Stroke цвета на нужные нам значения (здесь я установил желтый цвет и увеличил толщину обводки (Stroke)). 

     
    Еще пару примеров. 
    Дерево - параметры Brightness Cutoff, Threshold 0.370 . Как видите здесь оптимальнее подходит метод Brightness Cutoff.  Здесь исходная png картинка - это дерево черного цвета, я ее распознал, и затем добавил в TPath, а в свойстве Fill указал градиент от черного до зеленого.
    Наушники - Edge Detection 0. Конечно конкретно в этом случае нужно подчищать изображение.

     

    Иногда бывает что при вставке пути в TPath, компонент его отображает некорректно, если снова зайти в DATA TPath, то окажется что часть данных потеряна. 
    Что исправить эту ситуацию, нужно путь упростить. Это значит что после шага 4, нужно выбрать в incscrape меню Path > Simplify, затем снова сохранить файл. 
    Правда Simplify в incscrape работает не очень хорошо, часто загругляет прямые участки. Лучше делать Simplify в Adobe Illustrator.
     
    Статья опубликована на сайте fire-monkey.ru и возможно будет изменяться и дополняться.
    Автор: ENRGY  
    24. 02. 17 
     
  12. Like
    ENERGY получил реакцию от Ingalime в Запрет потери активности приложения   
    {$IFDEF ANDROID}   procedure KeepScreenOn(aEnable: boolean);   var     vFlags: integer;   begin     vFlags := TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON;     if aEnable then     begin       CallInUIThread (   // uses FMX.Helpers.Android       procedure       begin         TAndroidHelper.Activity.getWindow.setFlags (vFlags, vFlags);       end );     end     else       CallInUIThread (       procedure       begin         TAndroidHelper.Activity.getWindow.clearFlags (vFlags);       end );   end;   {$ENDIF} Это для Berlin и ниже.
    При использовании Tokyo - вызов CallInUIThread не нужен, можно вызывать напрямую, т.к. теперь главный Delphi поток это Java  UIThread.
     
    iOS
    uses iOSapi.UIKit; {$R *.fmx} procedure TForm6.Button1Click(Sender: TObject); var UIApp : UIApplication; begin UIApp := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication); UIApp.setIdleTimerDisabled(True); end;
  13. Like
    ENERGY получил реакцию от Maximus в Неверная ширина текста из .Canvas.TextWidth   
    Оттого, что ширина текста определяется для шрифта и размера указанного в Canvas, а не для шрифта из компонента.
    Например, в TLabel.TextSettings.Font  и в его TLabel.Canvas.Font размер шрифта будет разный (в Canvas он дефолтный - 12).
    В FMX компонентах Canvas, кстати, общий и один и тот же - это Canvas формы.
    Если в OnResize чего-либо, сделать так: 
      Label.Canvas.Font.Size := Label.Font.Size; или Label.Canvas.Font.Assign(Label.Font); (чуть дольше)   lRealWidth := Label.Canvas.TextWidth(Label.Text);  То размер будет корректный.
  14. Like
    ENERGY получил реакцию от GASCHE в Что невозможно сделать на Delphi для Android?   
    Delphi хоронят уже лет 15, это все слова. Нет идеальных инструментов. У всех какие то косяки, втч и у нативных средств, ведь все это придумывают люди, люди не роботы.
    На деле Delphi отличное средство для мультиплатформенной разработки вполне сложных программ. Мне как фрилансеру вполне хватает. Производительность гораздо лучше чем у Angular\Ionic, которые по факту WebView - веб в браузере - очень тормозное решение и подходит только для формочки "логин\пароль".  Также по производительности и глюкам Delphi имхо лучше чем ReactJS, и Xamarin aka Mono. 
    Во фрилансе огромная конкуренция, в основном индусы, в этом плане с Delphi можно быстрее разработать ПО чем предлагают сроки остальные.
    Проблема Делфай в том что оно дорогое, и  не так распространено - (это взаимосвязанный фактор) - таким образом сложно найти команду и мало проектов на нем разрабатывается, меньше сообщество и меньше документации и библиотек с готовыми решения Поэтому для одиночек это больше подходит.
     
    Но конечно нужно смотреть на развитие - вот Токио получилась очень сырым продуктом, я до сих пор на Берлине пишу под 4 платформы, если следующая версия выйдет такой же ультраглючной, то следует задуматься.
    А вообще хороший программист - это тот кто знает несколько языков, не бойтесь учить новое - опыт ускорит разработку с любым инструментом.
  15. Like
    ENERGY получил реакцию от Ingalime в TListView: список в виде CheckBox в ListViewItem   
    Что то у Евгения много лишнего в коде. Также вариант AItem.Data['ShowPool']:=AShowPool; медленный (т.к. в списке строк (TDictionary) ищется строка 'ShowPool' прямым перебором от начала до конца всего массива строк ), в моем случае гораздо быстрее.
    Вот вариант с чекбоксами :
    lvDetails.ItemAppearanceName := TAppearanceNames.ImageListItem; // или свой тип станадртный TAppearanceNames.ListItem lvDetails.ItemAppearanceObjects.ItemObjects.Accessory.AccessoryType := TAccessoryType.Checkmark; Все. теперь создаете OnItemClick - который будет включаь\выключать чекбокс 
    procedure TfrmMain.lvDetailsItemClick(const Sender: TObject; const AItem: TListViewItem); begin   if aItem = nil then exit;   if AItem.Objects.AccessoryObject.AccessoryType = TAccessoryType.Checkmark then   begin     AItem.Objects.AccessoryObject.Visible := not AItem.Objects.AccessoryObject.Visible;     // When listview is resized because of rotation, accessory properties will be reset to default values // Save status to the Tag AItem.Tag := integer(AItem.Objects.AccessoryObject.Visible);   end; end;  
    Добавляем событие OnUpdateObjects, на случай если девайс поменял ориентацию (в этом случае accessory свойства не сохраняются).
    procedure TfrmMain.lvDetailsUpdateObjects(const Sender: TObject; const AItem: TListViewItem); begin   // In order for text to be truncated properly, shorten text object   AItem.Objects.TextObject.Width := AItem.Objects.TextObject.Width - (2 +                 AItem.Objects.AccessoryObject.Width);   // Restore checked state when device is rotated.   // When listview is resized because of rotation, accessory properties will be reset to default values   if AItem.Objects.AccessoryObject.AccessoryType = TAccessoryType.Checkmark then     AItem.Objects.AccessoryObject.Visible := Boolean(AItem.Tag); end;  
    Проверяем наличие чекбокса:  
    if ListView.Items[i].Objects.AccessoryObject.Visible then  
  16. Thanks
    ENERGY получил реакцию от MrSergei2017 в Неверная ширина текста из .Canvas.TextWidth   
    Оттого, что ширина текста определяется для шрифта и размера указанного в Canvas, а не для шрифта из компонента.
    Например, в TLabel.TextSettings.Font  и в его TLabel.Canvas.Font размер шрифта будет разный (в Canvas он дефолтный - 12).
    В FMX компонентах Canvas, кстати, общий и один и тот же - это Canvas формы.
    Если в OnResize чего-либо, сделать так: 
      Label.Canvas.Font.Size := Label.Font.Size; или Label.Canvas.Font.Assign(Label.Font); (чуть дольше)   lRealWidth := Label.Canvas.TextWidth(Label.Text);  То размер будет корректный.
  17. Thanks
    ENERGY получил реакцию от amok в [Статья][Android] AlarmManager - Автозапуск приложения в назначенное время   
    Фух. Наконец то проспался и понял как сделать.
    Нужно просто поставить Alarm еще раз, напр. чтобы выполнился через 3 секунды.  (неудобный, есть вероятность попасть на ошибку)
    просто вызвать его в Broadcast после Activity . (не всегда работает)
    Запустить Activity и в BroadcastReceiver подождать 8 секунд, а затем там же снять WakeLock. 
    Это вариант работает прекрасно.
    Также с этим кодом Alarm срабатывает если Activity уже запущено либо в фоне. Нужно перехватывать WillBecomeForeground, BecameActive и там включать экран. Процессор включается в WakeLock, но не на долго, вам нужно включить экран при помощи функции ниже, сделать работу затем отключить экран).
    В моем случае, в отдельном потоке крутиться самописный планировщик, для других задач, который возбуждает события, по нему я и включаю\отключаю экран.
     
    Итак выстраданный бесcонными ночами Java код, обратите внимание на  TestLauncher.putExtra("StartedFromAM", true), это чтобы знать из Activity что запустились из Broadcast (предложенный Blong'гом EXTRA_ALARM_COUNT с BroadcastReceiver всегда вернет ноль, он работает только если запускать напрямую Activity!) : 
    package com.TestReceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.os.Handler; public class AlarmReceiver extends BroadcastReceiver { private static PowerManager.WakeLock mWakeLock; @Override public void onReceive(Context context, Intent intent) { if (mWakeLock == null) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Delphi"); mWakeLock.acquire(); } Intent TestLauncher = new Intent(); TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity"); TestLauncher.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); // I TestLauncher.putExtra("StartedFromAM", true); context.startActivity(TestLauncher); // Handler h = new Handler(); h.postDelayed(new Runnable(){ public void run(){ mWakeLock.release(); mWakeLock = null; } }, 8000); //Toast.makeText(context, "Reelase! ("+mcounter.toString()+")", Toast.LENGTH_SHORT).show(); // For example } } PARTIAL_WAKE_LOCK означает что процессор во время выполнения этого кода, не будет уходить в спящий режим.
    Теперь в OnCreate нашей формы добавляем флаги чтобы включить экран, но при условии что  запустились мы из AlarmManager : 
    function StartedFromAlarmManager: boolean; begin {$IFDEF ANDROID}   Result := TAndroidHelper.Activity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false);   // this will work only if using Activity instead of Broadcast - TJPendingIntent.JavaClass.getActivity:   //  Result := TAndroidHelper.Activity.getIntent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT, 0); {$ELSE}   Result := false; {$ENDIF} end;  
    {$IFDEF ANDROID}   procedure TurnOnAndKeepScreenAndroid(aEnable: boolean);   var     vFlags: integer;   begin     vFlags := TJWindowManager_LayoutParams.JavaClass.FLAG_TURN_SCREEN_ON or         TJWindowManager_LayoutParams.JavaClass.FLAG_DISMISS_KEYGUARD or         TJWindowManager_LayoutParams.JavaClass.FLAG_SHOW_WHEN_LOCKED or         TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON;     if aEnable then     begin       CallInUIThread (   // uses FMX.Helpers.Android       procedure       begin         TAndroidHelper.Activity.getWindow.setFlags (vFlags, vFlags);       end );     end     else       CallInUIThread (       procedure       begin         TAndroidHelper.Activity.getWindow.clearFlags (vFlags);       end );   end;   {$ENDIF} И сразу же отключаем наш WakeLock устанавливая второй раз Alarmmanager на срабатывание через 3 сек (соответственно запуститься BroadcastReceiver и освободит WakeLock).   (уже отключается сам в Broadcast сразу после старта Activity)- т.к. во флагах окна, уже указан FLAG_KEEP_SCREEN - это будет держать экран и систему включенной. 
    Не забудьте  поставить разрешение WAKE LOCK = true!
     
     
     
     
  18. Like
    ENERGY отреагировална FeLDMARShaL в [iOS] Полноценная фоновая работа приложения   
    Расскажу о том как я добился нормальной фоновой работы приложения. В моем понимании нормальная фоновая работа приложения - это сохранять геокоординаты и систематически (по мере их накопления передавать на сервер). По сути у нас получился трекер. Те кто считают что iOS такое не умеет делать, и все что будет написано ниже это фейк лучше закройти эту тему. Итак начнем, по пунктам:
    1) Добавляем к проекту ключ NSLocationAlwaysAndWhenInUseUsageDescription - для новых иОС это обязательно, начиная с 11 или 12 версии уже не помню

    2) Сообщаем приложению о намерении что мы будем использовать геокоординаты в фоне (редактируем ключ UIBackgroundModes выставляя галочку напротив location)

    3) Далее  для того чтобы не поломать другие приложения которые используют геолокацию создаем специальную дерективу, которая будет сообщать о том что наше приложение будет использовать геолокацию в фоне, я ее назвал iOS_RequestAlwaysAuthorization

    4) Дальше намного сложнее, нам нужно исправить исходники самой Delphi, а именно System.iOS.Sensors. Изменять будем процедуру TiOSLocationSensor.DoStart, все что отличается от стандартного у меня в рамках описания моей директивы:
    function TiOSLocationSensor.DoStart: Boolean; var I: Integer; begin {$ifdef iOS_RequestAlwaysAuthorization} if TOSVersion.Check(8) and (FLocater <> nil) then FLocater.requestAlwaysAuthorization; {$else iOS_RequestAlwaysAuthorization} if TOSVersion.Check(8) and (FLocater <> nil) then FLocater.requestWhenInUseAuthorization; {$endif iOS_RequestAlwaysAuthorization} // check authorization if Authorized = TAuthorizationType.atUnauthorized then SensorError(SLocationServiceUnauthorized); // check if location sensor is enabled if not FLocater.locationServicesEnabled then SensorError(SLocationServiceDisabled); // start location updates if (LocationChange = TLocationChangeType.lctLarge) and CanUseSignifChangeNotifs then FLocater.startMonitoringSignificantLocationChanges else FLocater.startUpdatingLocation; // start heading updates if CanUseHeading then begin FLocater.startUpdatingHeading; end; // start monitoring regions if CanMonitorRegions then for I := 0 to Regions.Count - 1 do FLocater.startMonitoringForRegion(ConvLocationRegion(Regions[I])); Result := FLocater.locationServicesEnabled; if Result then Result := Authorized = TAuthorizationType.atAuthorized; {$ifdef iOS_RequestAlwaysAuthorization} FLocater.setAllowsBackgroundLocationUpdates(True); FLocater.setPausesLocationUpdatesAutomatically(False); {$endif iOS_RequestAlwaysAuthorization} end; Собственно усе, можно наслаждаться фоновой работой. Все это работает под Delphi 10.2.3. На телефоне iPhone 6s под управлением iOS 11. Как было сказано выше, работает как геолокация так и инет и вообще все остальные процессы внтури приложения, такие как TTimer
    Собственно вот результат данного трекера:

     
    Если приблизить то можно увидеть насколько точно и часто он обновляет координаты:

     
    И да, огромное спасибо человеку с ником Artyom Karapetyan, именно он натолкнул на мысль того как надо правильно все сделать
  19. Like
  20. Like
    ENERGY отреагировална Roma77751 в Gif File   
    ПРОБЛЕМА РЕШЕНА! Всем спасибо, отдельное спасибо dnekrasov и IVGSoft, натолкнули на верную мысль. Только менять переменные надо было тут 
     Begin
          Stream.Read(RGBEntry, SizeOf(RGBEntry));
          With APalette do
          begin
            B := RGBEntry.R or (RGBEntry.R shl 8);
            G := RGBEntry.G or (RGBEntry.G shl 8);
            R := RGBEntry.B or (RGBEntry.B shl 8);
            A := $FF;
          end;
     видимо китайцы что то напутали...? Прикрепляю исправленный исходник.
    FMX.GifUtils.rar


  21. Like
    ENERGY получил реакцию от Anatoliy в Gif File   
    Попробуйте этот же модуль, только с исправленными багами.
    http://fire-monkey.ru/topic/5029-обработка-анимированных-gif-по-рецепту-китайского-коллеги/  
  22. Like
    ENERGY отреагировална sinuke в [Android] Прозрачный StatusBar в RAD 10.3 Rio   
    Привет
    Вчера была выпущена финальная версия RAD Studio 10.3 Rio, в которой много нововведений для Андройд. Но вот про статусбар снова "забыли". Хотя не совсем, добавили файлик styles-v21.xml, который превносит новую материальную тему на устройствах под управлением Android 5.0 и выше вместо устаревшей Holo.
    Но все равно свойство формы SystemStatusBar так и не реализовали. Поэтому при запуске статус бар будет окрашен в унылый серый цвет (см. скриншот).

    Для того, чтобы сделать статусбар прозрачным и поместить под него содержимое формы, то достаточно сделать несколько несложных шагов:
    1. Убираем из деплоймента (Project -> Deployment) файл styles-v21.xml (можно просто снять галочку рядом с именем файла)

    2. Добавить в деплоймент проекта новый файл styles-v21.xml (styles-v21.zip) и прописать ему путь res\values-v21\

    3. В результате получится следующий вид

     
    P.S. В новом файле по сравнению со стандартным добавилась строчка <item name="android:windowTranslucentStatus">true</item>, которая и отвечает за прозрачный статусбар
    P.P.S. Чтобы определять размер статус бара, все также можно воспользоваться решеним ZuBy - http://blog.rzaripov.kz/2016/12/android-ios.html
    P.P.P.S. Тестовый проектик - StatusBar.zip
  23. Like
    ENERGY отреагировална FREEFAR в PUSH Notification не работает после публикации   
    Всем доброго времени суток. 
    Казалось бы. Во время разработки и перед тем как подписали приложение сертификатом Distribution, пуши приходили норм. Но после того как прошли аудит Apple пуши куда-то пропали. FCM возвращал ошибку InvalidRegistration.
    Оказалось все достаточно просто. На сервере с которого мы отправляем пуш, В php скрипте, который отправляет пуши надо выставить
    sandbox = false
    Ура! Всем удачи)
  24. Like
    ENERGY получил реакцию от Anatoliy в Приложение для получения информации о составе основных комплектующих, входимостей по моделям автобусов и троллейбусов МАЗ на смартфонах v.11.52.   
    Зайдите в гугл картинки и поищите что-то типа mobile UI design.
    Также у Delphi есть пакет премиум скинов - Firemonkey premium styles. 
  25. Like
    ENERGY получил реакцию от Anatoliy в TScrollBox или TPresentedScrollBox поворот на 180   
    А зачем скрол переворачивать то?
    TPresentedScrollBox  у него есть Content, установите Content высоту на размер больше, добавляйте вниз сообщение (в невидимую область ниже) и программно с анимацией прокручивайте вниз.   
×
×
  • Создать...