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

Barbanel

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

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

  • Посещение

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

    36

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

  1. Like
    Barbanel получил реакцию от Dev в Runtime permissions in Delphi 10.3 Rio   
    В поставке 10.3 есть примеры работы с правами.
    Один из них можно найти по такому пути:
    C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\Multi-Device Samples\Media\PhotoEditorDemo
    Что интересно, этот же код можно без изменений использовать под любой другой платформой.
    На других платформах приложение будет считать что ему выдали все права, и соответственно запускать все коллбеки без каких-либо вопросов.
  2. Like
    Barbanel получил реакцию от Brovin Yaroslav в Runtime permissions in Delphi 10.3 Rio   
    В поставке 10.3 есть примеры работы с правами.
    Один из них можно найти по такому пути:
    C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\Multi-Device Samples\Media\PhotoEditorDemo
    Что интересно, этот же код можно без изменений использовать под любой другой платформой.
    На других платформах приложение будет считать что ему выдали все права, и соответственно запускать все коллбеки без каких-либо вопросов.
  3. Like
    Barbanel отреагировална Brovin Yaroslav в [Android] TAnimator.AnimateFloatWait как работает   
    Почему?
    Андроид не поддерживает конструкции типа:
    while Flag do Application.ProcessMessage; Поскольку Андроид не позволяет запускать внутреннюю петлю обработки сообщений и выполнять обработку сообщений из главной очереди. Именно по этому не используйте этот паттерн в принципе.
    Любая анимация вида AnimateXXXAndWait внутри себя использует этот шаблон. Поэтому банально анимация выполняется, но отрисовки не будет. Так как сообщение на отрисовку будет обработано уже в главной петле обработки сообщения после возврата управления (выхода из этого паттерна). 
    На что заменить?
    Не использовать синхронную анимацию в принципе! Заменить синхронный на асинхронный вариант с коллбеком завершения.
  4. Like
    Barbanel отреагировална Паршенко Виктор в Нативные сторонние SDK. Обновление встроенных SDK до версии 12.1   
    Нет, стянуть заново это
    - удалить SDK из списка
    - удалить данные файлы из папки что написал выше
    - добавить SDK в список, автоматически загрузит новые файлы
     UpdateLocalCache просто стянет файлы из указанных мест.
    удаление и добавление SDK с нуля подтягивает новые пути для загрузки.
  5. Like
    Barbanel отреагировална Евгений Корепов в Runtime permissions in Delphi 10.3 Rio   
    Для полноценной работы вам нужно добавить параметры в вызов (иначе вы не узнаете дал ли пользователь разрешение или нет)
    PermissionsService.RequestPermissions([FPermissionWrite, FPermissionRead], nil); Вот так:
    PermissionsService.RequestPermissions([FPermissionWrite, FPermissionRead], PermissionRequestResult, ExplainReason); PermissionRequestResult - это обработка ответа пользователя
    procedure TForm.PermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); begin if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then begin // Ура! Пользователь дал разрешение на оба наших запроса. Выставялем глобальные флаги (к примеру) которые сигнализируют что можно читать/писать карту памти end else TDialogService.ShowMessage('Не возможно продолжить работу, требуемые разрешения не получены') end; И ExplainReason - если пользователь сдуру не дал разрешение, то вам нужно объяснить ему что без этого приложение работать не будет.
    procedure TForm.ExplainReason(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc); begin TDialogService.ShowMessage('Приложению нужен доступ к карте памяти для таких то целей, иначе приложение не сможет работать. Зайдите в настроки Андроид и дайте разрешение на доступ', procedure(const AResult: TModalResult) begin APostRationaleProc; end) end;  
  6. Like
    Barbanel отреагировална Alex7wrt в Не получается запустить эмулятор   
    Чтобы не было красного крестика, нужно не только создать эмулятор в AVD менеджере, но и запустить его там же. В итоге на экране увидите окно, в котором запускается интерфейс Android. Когда он запустится, и появится рабочий стол Android, можно запускать установку приложения на эмулятор.
    Только учтите, что на относительно слабых системах эмулятор может запускаться довольно долго. Ну и Вообще для проверки работоспособности (работает/ не работает) легче воспользоваться установкой на реальный девайс. 
  7. Like
    Barbanel получил реакцию от Ingalime в [Android] TAnimator.AnimateFloatWait как работает   
    Версия, платформа?
    В Токио под Андроид действительно была похожая проблема, мы ее так и не решили.
    Под Виндовс и иОС все работало правильно.
    Смутно помню, что были сторонние исходники, решающие эту проблему. 
    Kastri Free если не ошибаюсь.
  8. Like
    Barbanel отреагировална yooSee в Runtime permissions in Delphi 10.3 Rio   
    Всем привет, вот и я решил внести свою лепту в жизнь форума и сегодня мы разберемся с разрешениями на Delphi Rio под Андроид. 
    Для примера мы будем использовать разрешения на чтение и запись с памяти устройства, для начала в нашем проекте выставим в Delphi>Project>Application>Uses Permissions галочки на Read External Storage и Write External Storage.
    в uses проекта добавьте следующее
    uses System.Permissions, Androidapi.Jni.Os, Androidapi.Helpers, далее  создадим переменные
    var Form: TForm; .... FPermissionWrite: string; FPermissionRead: string; в Form.Create добавим следующий код
    procedure TForm.FormCreate(Sender: TObject); begin FPermissionWrite := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE); //Значение на запись FPermissionRead := JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE); //Значение на чтение end; и теперь сам не посредственно запрос на подтверждение наших прав
    procedure TForm.Button1Click(Sender: TObject); begin PermissionsService.RequestPermissions ([FPermissionWrite, FPermissionRead], nil); end; //это вызовет окно с запросом разрешения прав ну и для проверки бросим на форму TMemo и пару TButton , в них реализуем сохранение и чтение из файла с памяти устройства
    procedure TForm.Button1Click(Sender: TObject); begin Memo1.Lines.LoadFromFile(TPath.Combine(TPath.GetSharedDocumentsPath, 'test.txt')); end; procedure TForm.Button2Click(Sender: TObject); begin Memo1.Lines.SaveToFile(TPath.Combine(TPath.GetSharedDocumentsPath, 'test.txt')); end; P.S. Напоминаю что для работы TPath нам понадобится подключить в Uses 
    uses System.system.ioutils; Надеюсь материал будет полезен! 
     
     
     

    video_2019-02-08_00-11-36.mp4 Permissions.zip
  9. Haha
    Barbanel отреагировална Slym в Отображение картинок в ListView   
    Логика асинхронности принимает на вход анонимную процедуру для обработки результата, анонимная процедура захватывает переменные в зоне своего определения, а там хоть итем, хоть индекс, хоть блэкджек с простихоспаде чем попало...
  10. Like
    Barbanel отреагировална Ry Koo в [Android] Как отключить клавиатуру в приложении?   
    у формы есть событие FormVirtualKeyboardShown, где можно в общем обработать событие показа\скрытия клавиатуры.
    там и флаг есть KeyboardVisible.
    а в частности, для конкретного поля показывать\скрывать вот так можно как вариант:
    procedure Tform1.Memo1Tap(Sender: TObject; const Point: TPointF);
    var
      KeyboardService: IFMXVirtualKeyboardService;
    begin
      if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(KeyboardService)) then   // Запрашиваем сервис виртуальной клавиатуры
        KeyboardService.HideVirtualKeyboard;
     //KeyboardService.ShowVirtualKeyboard(Memo1); для показа
    end;
  11. Haha
    Barbanel отреагировална Евгений Корепов в Подписание новых приложений в google play   
    Вот точно ничего не надо делать и тем более подключать. Эмбаркадера еще не дочитала новости гугля. Они пока еще за 2015 год переваривают ))))
  12. Like
    Barbanel отреагировална Andrey Yakovlev в Работа с файлами в macOS   
    Добрый день. А вы не пробовали указывать не только имя файла, но и путь к нему? Я недавно с FM познакомился, не самый большой специалист по Маку ), но я бы не полагался на указание файла без каталога. У меня сделано так, например:
    function GetAppPath(): string;
    begin
        Result := TPath.GetDirectoryName(ParamStr(0));
    end;
     
    function MakeSettingsFileName(aInsideApp: boolean): string;
    var
        lFileName: string;
    begin
        lFileName := TPath.GetFileNameWithoutExtension(ParamStr(0)) + '.ini';
        if (aInsideApp) then
            Result := GetAppPath()
        else
            Result := TPath.GetDocumentsPath();
        Result := TPath.Combine(Result, lFileName);
    end;
    Смысл такой: поскольку приложение в macOS распространяется через dmg-пакет, я включаю конфигурационный файл внутрь Program.app, как раз в папку Contents/MacOS/, чтобы программе было с чем запуститься в первый раз (всяческие настройки соединения с сервером, БД, ну вы понимаете). В самой программе, я сначала делаю проверку наличия конфигурационного файла, сформировав путь до него вызовом функции MakeSettingsFileName(false). В этом случае, конф. файл ищется в каталоге Документы. Это, на самом деле, не так и важно, где он может лежать снаружи, идея тут в том, что в процессе работы конф. файл меняется и при выходе из программы всегда сохраняется снаружи, чтобы иметь возможность пользоваться им после замены dmg-пакета и инсталляции новой версии программы, которая опять будет содержать внутри себя "пустой" конф. файл. Если файл снаружи не нашелся, формируем повторным вызовом MakeSettingsFileName(true) путь к нему "внутри". Надеюсь, что понятно объяснил.
  13. Like
    Barbanel отреагировална Andrey Yakovlev в Запуск приложения в iOS Simulator   
    Дополнение. Забегая вперед, скажу, что все заработало, но хотелось бы подтвердить или опровергнуть свои догадки. Ноутбук, на котором изначально все работало, имеет High Sierra в качестве ОС. Это последняя яблочная ось, которая без вопросов переваривает 32-битные приложения. МакПро, на который все переносилось и проблемы которого здесь описывались, имеет уже последнюю Mojave. Вчера взял третий чистый МакБук Про (описание выглядит, как будто тут склад продукции Аппл :)), который по случаю также все еще имел High Sierra, поставил xCode 9.4.1 и 9.2 (его выбрал в качестве Command Line Tools), создал пустой проект, подключил к нему имеющийся developer-акк, поставил PAServer20 и в Delphi Rio стала нормально появляться информация в закладке Provisioning. Как следствие, и приложение нормально долетело до телефона.
    Вопрос в следующем: у кого-нибудь есть успешный опыт эксплуатации такой цепочки в ОС Mojave 64 бит? В этом проблема у нас была и нужно ждать PAServer 64? Просто догадки, ибо никакого другого объяснения случившемуся у меня нет, все выглядит, как удачное стечение обстоятельств.
    Всем спасибо за ответы.
  14. Confused
    Barbanel отреагировална Andrey Yakovlev в Запуск приложения в iOS Simulator   
    Barbanel, видел описание вашего опыта в другой ветке форума. Я уже:
    - зашел в iCloud под AppleID, который мы завели для developer-аккаунта
    - удалил все сертификаты из связки ключей, которые хотя бы как-то указывали на другие мои аккаунты и импортировал в xCode - Pref - Accounts тот самый, который у нас developer
    - сходил в developer.apple.com и завел там сначала AppID, а затем provisioning profile, для которого явно указал свой iPhone
    - загрузил и импортировал этот profile в xCode, точно вижу, что он про мой телефон знает
    - переключил PAServer в verbose режим и вижу, что он пытается сканировать имеющиеся сертификаты и видит даже больше, чем один и все они, так или иначе, имеют отношение к нашему developer-аккаунту
    - открыл тестовое приложение в Delphi Rio (и ее уже поставил, хоть это и долго), прописал правильно bundle identifier в VersionInfo
    и... все равно, Provisioning упорно ничего не видит.
    Извиняюсь за излишне подробное описание. У нас есть первый ноут, на котором приобретался сертификат и там все работает. Но я не понимаю, в чем разница, если сам сертификат прошел процедуру импорта/экспорта, из Иксов все на телефон встает как надо. Тупик, который все больше склоняет к написанию софта прямо в xCode, чего не сильно хотелось бы, так как есть еще потребность в Андройде.
  15. Like
    Barbanel получил реакцию от Ingalime в Nox: в приложении произошла ошибка   
    Поясните плиз для тупых, что есть Nox?
  16. Like
    Barbanel получил реакцию от Tumaso в Запуск приложения в iOS Simulator   
    Я смутно припоминаю что где-то в аккаунте разработчика (у Эппла) нужно прописать серийники телефонов/планшетов на которых вы хотите отлаживать приложения.
    Без этого показывается тоже сообщение "Cannot connect to Mac".
    Вот здесь: https://developer.apple.com/account/ios/device/
    Также просмотрите здесь https://developer.apple.com/account/ios/profile/ все ли профайлы/сертификаты вы имеете.
    Также, после этого на новом маке вам нужно открыть xCode -> Preferences -> Accounts и загрузить эти профайлы/сертификаты на макбук. 
  17. Like
    Barbanel отреагировална Tumaso в Как собрать apk для android 8.1 не имея устройства с такой версией android?   
    Delphi Rio:
    1. Target Platform -> Android
    2. Project -> Build
    3. Project -> Deploy
    В итоге apk для android 5/6/7/8/8.1/9 создан
  18. Like
    Barbanel отреагировална Сергей Сергеев в Бегущая строка   
    Сделал так..
    TEdit положил внутри THorzScrollBox. Ширина TEdit больше чем Scroll, что не влезло справа, обрезалось. Спрятал ScrollBar, чтобы не портил вид.
    Положил на форму TrackBar c Value от 0 до 150.  Для значения Value добавил TFloatAnimaton с изменением Value от 0-150 по циклу и с реверсом.
    На событие OnChangeValue TrackBar повесил обработчик в котором, в зависимости от значения Track меняю у HorzscrollBox позицию ползунка ( .ScrollBy (dX,dY) - еле нашел!) 
    Результат на видео https://youtu.be/crtw-qQmjFc. Проект вечером прикреплю - может кому понадобится.
    "мозг" тут :
     
    var Form1: TForm1; currPos : integer=0; implementation {$R *.fmx} {$R *.LgXhdpiPh.fmx ANDROID} {$R *.Windows.fmx MSWINDOWS} procedure TForm1.TrackBar1Change(Sender: TObject); var cnt : integer; cp :integer ; begin lbT.Text := TrackBar1.Value.ToString; cp := Round(TrackBar1.Value) ; cnt := currPos - cp; currPos := cp; HorzScrollBox1.ScrollBy(cnt,0) ; end;  
    Test.rar
  19. Like
    Barbanel отреагировална RoschinSpb в Как убить кнопку кликнув на нее саму   
    Не ссоритесь девочки пож.
    Возвращаясь к сути вопроса. Основная сложность тут в том, что в Delphi нельзя разрушать экземпляр класса внутри метода этого класса за исключением тех случаев, когда метод использует только для разрушения Free, DisposeOf. Почему так, а не иначе, какие есть исключения и почему "уменяфсёработает" объяснять долго, поэтому в первом приближении предлагаю принять это за аксиому.
    Обработчики событий OnClick и пр. вызываются из методов классов, так что разрушать контрол внутри события нельзя от слова совсем. Кроме очевидных случаев типа Self.DisposeOf существуют более запутанные варианты, когда к примеру закрывает и разрушается форма, что приводит к разрушению всех дочерних контролов.
    Образно говоря, самоубийства строго запрещены, но не запрещено нанимать киллера и в качестве жертвы указывать себя. Т.е. должен быть некий другой (глобальный) объект который будет разрушать объекты, которые хотели бы самоубицо. Реализацию такого объекта можете придумать сами, или использовать TPurgatory (чистилище, в католическом учении — промежуточное место между раем и адом). Но чтобы убедиться в правильности работы можно создать своего наследника TButton в котором перекрыть деструктор и поставить в нем точку останова. При запуске в режиме отладки посмотрите стек вызова деструктора (надо быть внимательным, он может быть длиннющим), ни где в этом стеке не должно быть метода разрушаемого экземпляра. Если в Вы нашли метод разрушаемого объекта (за исключением вышеуказанных), то Ваш способ удаления работает не правильно и с некоторой долей вероятности будет приводить к AV и другим "неприятностям" которые почти невозможно отловить в режиме отладки.
  20. Like
    Barbanel отреагировална nassl в Координата в процессе свайпа   
    Отвечу сам себе, чтобы не потерять .
    Итак, хочется ловить жесты влево, вправо и после лонгтап считывать координаты точки касания. В частности изменяется размер TImage, который скрывается по окончании свайпа запуском анимации в которой Opacity меняется от 1 до 0}.
    TPointF P, OldP;
    void __fastcall TForm1::FormGesture(TObject *Sender, const TGestureEventInfo &EventInfo,
              bool &Handled)
    {
     if (EventInfo.Flags.Contains(TInteractiveGestureFlag::gfBegin))
     {  switch (EventInfo.GestureID)  { case igiLongTap: OldP.y=EventInfo.Location.y;   OldP.x=EventInfo.Location.x; }
     }
     else if(EventInfo.Flags.Contains(TInteractiveGestureFlag::gfEnd))
           {//Жест закончен - не убирать, иначе не сработает TTouchAction::Up   }
     else
      {switch (EventInfo.GestureID)
       {case sgiRight:  DosomethingRight(); break;
        case sgiLeft:     DosomethingLeft();   break;
        case igiPan:      P.y=EventInfo.Location.y;   P.x=EventInfo.Location.x;  break;
       }
     }
    }
     //---------------------------------------------------------------------------
    void __fastcall TForm1::FormTouch(TObject *Sender, const TTouches Touches, const TTouchAction Action)
    {if (Action==TTouchAction::Up)  //Палец убран
      {// Обработка концовки свайпа, например
       FloatAnimation1->Start(); 
      }
    }
    void __fastcall TForm1::FloatAnimation1Finish(TObject *Sender)
    { Image->Visible=false;Image->Opacity=1;}
    ...........................................................
    PS советы по улучшению кода приветствуются, но у меня получилось так.
     
     
  21. Like
    Barbanel отреагировална kami в Как убить кнопку кликнув на нее саму   
    Вы выискиваете какие-то обходные маневры, генерацию уникальных имен с привлечением guid, обнуление имени после создания...
    а на самом деле ничего из этих костылей не нужно.
  22. Like
    Barbanel получил реакцию от Ingalime в Как убить кнопку кликнув на нее саму   
    function CreateGUID(): string; var GUID: TGUID; begin if ( System.SysUtils.CreateGUID(GUID) <> 0 ) then Result := '' else Result := GUIDToString(GUID); end; ... begin ... lFrame.Name := CreateGUID(); end; Это чтобы уж совсем быть уверенным)))
    PS. В Delphi 7 - 100% можно создавать компоненты не присваивая ему имя, у нас так все справочники в CRM работали.
  23. Haha
    Barbanel отреагировална slav_z в Как убить кнопку кликнув на нее саму   
    теперь все понятно. спасибо.
  24. Like
    Barbanel отреагировална dnekrasov в [Windows] Запретить окну переход в прозрачный режим   
    Недавно решил одну проблемку, которая долго мучала - решил поделиться, может кому ещё пригодится.
    При работе с двумя мониторами или с монитором и проектором часто возникает необходимость запретить окну "исчезать" при наведении курсора мыши на миниатюру другого приложения в панели задач. Чтобы это сделать надо:
    uses ... Winapi.DwmApi ... TMainForm = class(TForm) ... protected procedure CreateHandle; override; ... end; ... procedure TMainForm.CreateHandle; var Val, Res: Integer; begin inherited CreateHandle; Val := 1; Res := DwmSetWindowAttribute(FormToHWND(Self), DWMWA_EXCLUDED_FROM_PEEK, @Val, SizeOf(Val)); {$IFDEF DEBUG} if Res <> S_OK then ShowMessage(SysErrorMessage(Res)); {$ENDIF} end; Спасибо @Alex7wrt за наводку
  25. Like
    Barbanel отреагировална slav_z в Работа с атрибутами текста   
    Как сделать текст с подобными атрибутами? Очень просто!
    (Цвет текста не работает в XE8) Вот весь код:
    unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.UIConsts, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects, FMX.TextLayout; type TForm1 = class(TForm) Button1: TButton; Text1: TText; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} type TTextAccess = class(TText); procedure ClearTextAttribute(Text: TText); begin TTextAccess(Text).Layout.ClearAttributes; end; procedure AddTextAttribute(Text: TText; Pos,Length: Integer; FontStyles: TFontStyles; FontColor: TAlphaColor); var Font: TFont; begin Font:=TFont.Create; Font.Assign(Text.Font); Font.Style:=FontStyles; TTextAccess(Text).Layout.AddAttribute( TTextRange.Create(Pos,Length), TTextAttribute.Create(Font,FontColor)); end; procedure TForm1.Button1Click(Sender: TObject); begin AddTextAttribute(Text1,10,17,[TFontStyle.fsBold],claRed); AddTextAttribute(Text1,34,8,[TFontStyle.fsUnderline],claBlue); AddTextAttribute(Text1,47,8,[TFontStyle.fsStrikeOut],claGreen); Text1.Repaint; end; end.  
×
×
  • Создать...