Перейти к содержанию
  • Регистрация

Лидеры


Популярный контент

Показан контент с высокой репутацией за 03.11.2018 во всех областях

  1. 15 баллов
    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
  2. 12 баллов
    krapotkin

    Фреймворк для стандартного ListView

    Всем привет! После долгого творческого запоя я запилил альфу либы, которая позволяет юзать обычный, не-генномодифицированный ListView. Данные подаются в виде модели данных, описание раскладки итема лежит в JSON. Для работы пишется примитивный наследник класса-адаптера, который биндит данные модели на элементы из JSON. Я решил, что руками делать это дешевле чем через RTTI { TMyAdapter } procedure TMyAdapter.SetupDrawableContent(const ADrawable: TListItemDrawable; const AData: TMyData); begin if SameText( ADrawable.Name, 'text') then begin (ADrawable as TListItemText).Text := AData.Text; end else if SameText( ADrawable.Name, 'detail') then begin (ADrawable as TListItemText).Text := AData.Detail; end else if SameText( ADrawable.Name, 'balance') then begin (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Balance); end else if SameText( ADrawable.Name, 'reserved') then begin (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Reserved); end end; Главная хитрость и отличие от стандартного DynamicAppearance+LiveBinding - переменная высота итемов ListView и использование арифметики в описании раскладки. Можно указать Detail.Y = Text.Bottom + 5, ItemHeight = Detail.Bottom + 10, Detail.W = ItemWidth/2 - X {"Kind":"rect","Name":"BonusRect","Value":"", "Place":{"X":"itemwidth*3/4","Y":"Text.Y","W":"ItemWidth/4-5","H":"50"}, "BorderColor":"#FF005500", "Color":"lime", "LineWidth":3}, {"TextHAlign":2,"TextVAlign":1,"Kind":"text","Name":"Balance","Value":"", "Place":{"X":"BonusRect.x+5","Y":"Text.Y","W":"BonusRect.w-10","H":"50"}, "WordWrap":true, "Color" :"Black", "Font":{"Size":18,"Style":""}} ], "ItemHeight":"detail.bottom+10", Это дает довольно гибкую систему. Не на все случаи жизни, но все, что нужно, можно после автоматической раскладки дополнительно приписать в OnUpdateObjects Код для работы примерно такой procedure TForm1.FormCreate(Sender: TObject); begin data:= TMyDataList.CreateFromFile(ExePath()+'data.json'); // загрузка в модель данных Adapter := TMyAdapter.Create(lvWallets, data.Items, ExePath()+'pattern.json'); // создание адаптера и загрузка шаблона Adapter.Pattern.SetupListView(lvWallets); // задать отступы и разную мелочь Adapter.ResetView(); // здесь в цикле из модели данных создается нужное количество итемов ListView end; procedure TForm1.lvWalletsUpdatingObjects(const Sender: TObject; const AItem: TListViewItem; var AHandled: Boolean); begin Adapter.SetupContent(AItem); // загрузить текст, картинки и другое содержимое в элементы итема Adapter.Pattern.DoLayout(AItem); // поправить раскладку в соответствии с содержимым элементов итема end; Для использования кроме стандартных - текст, картинка, кнопка - создано несколько дополнительных элементов итема - прямоугольник, круг, уголок, линия. Отличие от ModernLV - , 1) все происходит без правки системных файлов 2) пока нет колонок и других особых изысков. На результат работы смотреть тут. Исходники пока не причесаны, будут чуть позже ListViewFramework.7z
  3. 11 баллов
    Расскажу о том как я добился нормальной фоновой работы приложения. В моем понимании нормальная фоновая работа приложения - это сохранять геокоординаты и систематически (по мере их накопления передавать на сервер). По сути у нас получился трекер. Те кто считают что 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, именно он натолкнул на мысль того как надо правильно все сделать
  4. 11 баллов
    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.
  5. 9 баллов
    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
  6. 9 баллов
    Brovin Yaroslav

    С днем рождения Андрей Ефимов ???

    Хочу от всей души поздравить с днем рождения нашего модератора Андрея Ефимова @Andrey Efimov. Человек, на которого можно положиться и который всегда готов прийти на помощь. Из года в год помогает нашему форуму становиться лучше. С днем рождения! Успехов тебе в работе, в личных делах. И не забывать про Делфи!
  7. 9 баллов
    Задался вопросом, нашел ответ, может кому пригодится. uses Androidapi.JNI.Media, Androidapi.Helpers, Androidapi.JNIBridge, AndroidApi.Jni.JavaTypes, Androidapi.JNI.GraphicsContentViewText; .... procedure TFormMain.PlaySoundEffects(const ASoundID : Integer; AVolume : Single = 1.0); var AudioObj: JObject; Audio: JAudioManager; begin AudioObj:= TAndroidHelper.Context.getSystemService(TJContext.JavaClass.AUDIO_SERVICE); Audio:= TJAudioManager.Wrap((AudioObj as ILocalObject).GetObjectID); Audio.loadSoundEffects; Audio.playSoundEffect(ASoundID, AVolume); end; Константы звуковых эффектов тут https://developer.android.com/reference/android/view/SoundEffectConstants Правда у меня только звук "чпок" на всех константах. Но мне он и был нужен )
  8. 8 баллов
    OnePeople

    Монополия

    Делал чисто для себя! И только для своего удовольствия! Возможны ошибки!*(вернее точно есть))) Графика не окончательная! Скриншоты сервер: Скриншоты клиент: Сервер на комп, клиент Android (должны находиться в одной сети) P/S И так как все устройства у меня Full HD, проверял только на них( Monopoly.rar
  9. 8 баллов
  10. 8 баллов
    Тема: "Сравнение возможностей кроссплатформенных мобильных библиотек нативных приложений FMX и FGX Native" Дата и время: 20 декабря 2018 года в 12:00 (по московскому времени) Участники: @Brovin Yaroslav, Андрей Совцов Регистрация: ссылка Ссылка на официальный телеграмм канал: https://t.me/fgx_native Участие бесплатное Под конец уходящего нового года сравним текущие возможности кроссплатформенной библиотеки мобильной разработки FGX Native и FMX. Поговорим о перспективах развития и ознакомимся с ближайшим планом до выпуска публичной бета версии. Посмотрим в живую на новый функционал библиотеки, разработанный за последнее время. У вас будет возможность задать любые вопросы автору. Не пропусти эту возможность!
  11. 7 баллов
    krapotkin

    Переезд на 10.3 Rio

    сколько бед принесла уже стрельба в ногу под названием ProcessMessages как хорошо, что в Андроиде наконец всех отучат от этого крайне вредного трюка давайте формально все что там у вас "высоконагруженное" выносите в потоки и пусть они работают. Ваши "потоки" пасутся в главном (Synchronize) и никакого толка нет концепцию надо поменять. запустили поток и занимайтесь своим делом. например покажите Splash а вернется поток - вот по возвращению и сделаете то, что этот Splash закроет. и уж точно потоки не должны ничего общего иметь с формами я писал статью про потоки, там про сплеши тоже есть в блоге и про ProcessMessages отдельная боль... http://www.cyberforum.ru/blogs/469693/blog4875.html
  12. 7 баллов
    Евгений Корепов

    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;
  13. 7 баллов
    Недавно решил одну проблемку, которая долго мучала - решил поделиться, может кому ещё пригодится. При работе с двумя мониторами или с монитором и проектором часто возникает необходимость запретить окну "исчезать" при наведении курсора мыши на миниатюру другого приложения в панели задач. Чтобы это сделать надо: 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 за наводку
  14. 6 баллов
    Это приложение для OS Windows выполняет: 1.Расчёт сцепления: -расчёт и подбор геометрических параметров нажимного и ведомого дисков, муфты выключения; -проверка параметров по теплонагруженности пар трения; -расчёт всех наиболее нагруженных деталей сцепления (пружины, пластины, подшипник). 2.Расчёт пневмогидравлического привода сцелпения: -подбор и проверка управляющего и исполнительного органов; -объём жидкости. 3.Возможность вноса и редактирования исходных данных и результатов в БД. 4.Распечатку всего расчёта с исходными данными, формулами, графиками, используемой литературой и результатами в MS Word. 5.Просмотр и изучение нажимного, ведомого дисков и муфты выключения в 3D. Изначально для работы в приложении необходимы некоторые знания конструкции сцепления и теории расчёта. Автор: Олег Киреев-ведущий инженер-конструктор, kireevoleg1966@gmail.com, +375 29 676 13 84 БЕЛАРУСЬ, г.Минск. Приму Ваши замечания и предложения. По совету Равиля Зарипова РАЗМЕСТИЛ на файлообменнике 12.08.2019г по этой: https://mega.dp.ua/a27WmeXKwY ссылке. На этом ресурсе обещают хранить 90 дней. Интересно услышать Ваши отзывы.
  15. 6 баллов
    dnekrasov

    Перехват сообщений в Windows

    Делаем как обычно, если надо переопределить какое-то событие окна interface uses {$IFDEF MSWINDOWS} Winapi.Windows, Winapi.Messages, FMX.Platform.Win, {$ENDIF} System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs; type TMainForm = class(TForm) private procedure CreateHandle; override; {$IFDEF MSWINDOWS} procedure WMIMENotify(var Msg: TMessage); message WM_IME_NOTIFY; {$ENDIF} public end; var MainForm: TMainForm; implementation {$R *.fmx} {$IFDEF MSWINDOWS} var OldWndProc: Pointer = nil; function NewWndProc(Wnd: HWND; Msg: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall; var Mess : TMessage; begin case Msg of WM_IME_NOTIFY: begin Mess.Msg := Msg; Mess.WParam := wParam; Mess.lParam := lParam; Mess.Result := 0; MainForm.Dispatch(Mess); Result := Mess.Result; end; else Result := CallWindowProc(OldWndProc, Wnd, Msg, WParam, LParam); end; end; {$ENDIF} { TMainForm } procedure TMainForm.CreateHandle; begin inherited CreateHandle; {$IFDEF MSWINDOWS} OldWndProc:= Pointer(SetWindowLong(WindowHandleToPlatform(Handle).Wnd, GWL_WNDPROC, Integer(@NewWndProc))); {$ENDIF} end; {$IFDEF MSWINDOWS} procedure TMainForm.WMIMENotify(var Msg: TMessage); begin {что-то делаем} end; {$ENDIF}
  16. 5 баллов
    сделано на Datasnap - 3х звенка MsSql- Сервис Https - Клиент ( Андроид, Ios, Win, Mac) Личный кабинет пациента клиники (www.familydoctor.ru) открывает зарегистрированным пользователям доступ к медицинской карте (результаты лабораторных исследований и функциональной диагностики, описание приемов врачей, направления и рекомендации, истории посещений клиники (дата, время, специалист), программам медицинского наблюдения (перечень, период прикрепления), информации о движении средств по депозитам. Для пересылки выписок (файлов) из медицинской карты используется электронная почта (в системе должен быть настроенный Майл Агент на отправку почты).Полной версией приложения могут воспользоваться только пациенты, подключившие услугу "Личный кабинет" в регистратуре любого корпуса клиники "Семейный доктор".В новой версии изменен дизайн, появились новые функции и разделы:вход по номеру медкарты или ФИО;запрос нового пароля;заявка на онлайн запись;отмена приема;прейскурант услуг клиники;справочник адресов клиники. сервис оплаты услуг клиники через приложение.В ближайшем будущем функционал личного кабинета будет дополнен онлайн расписанием специалистов, возможностью электронной записи на приём. в гугл плее https://play.google.com/store/apps/details?id=com.familydoctor.FD Есть тестовый вход, обращайтесь.
  17. 5 баллов
    Хочу поделиться с вами знаковой новостью для развития библиотеки FGX Native. Официально выпущено первое Андроид приложение в Google Play Market. Это приложение разработано Станиславом(@sinuke) для учащихся лицея по специальности "Почтовая связь". Оно одновременно является и полным конспектом, который всегда под рукой, и системой проверки своих знаний. Полностью разработано на Delphi и стандартных компонентах альфа версии FGX Native 0.9.7.0 в Delphi 10.3 Community Edition. Быстрые списки, гибкая разметка, продвинутая навигация, анимации переходов, поддержка тем и многое другое. Это лишь малая часть того, что было задействовано из текущих возможностей библиотеки. Приложение опубликовано в Google Play Market. Вы можете уже прямо сейчас скачать и протестировать приложение самостоятельно, загрузив его по ссылке (https://play.google.com/store/apps/details?id=com.sinukeapps.post). Оставляйте свои комментарии и предложения. Они помогут сделать приложение лучше, а FGX Native еще удобнее и стабильнее. Релиз первого приложения с использование библиотеки FGX Native - это результат огромной работы, проделанной за эти годы. В тоже время, это сигнал того, что библиотека обладает достаточным минимумом для создания типовых Андроид приложений. Ну, и пожалуй самое приятное, это то, что библиотека готова к бета тестированию, которое откроется в ближайшее время. О начале закрытого бета тестирования будет сообщено позже. Отдельное спасибо участникам закрытого альфа тестирования за поддержку, тестирование и идеи по улучшению библиотеки. В настоящее время участниками тестирования ведутся и другие интересные проекты на базе FGX Native, о которых я расскажу позже. Следите за новостями. Приложение: https://play.google.com/store/apps/details?id=com.sinukeapps.post Автор: Станислав Игнатович @sinuke Минимальные системные требования: Android 5.0 и arm v7
  18. 5 баллов
    Пока тестировал хелпер в боевом проекте он потихоньку оброс исрпавлениями/улучшениями: Загрузка из потока сделана через TBitmapSurface - это позволяет избежать множества глюков. LoadFromStream вынесен из Synchronize (основного потока) в поток HTTPClient - по результатам бенчмарка операция оказалась самая жручая. После исправления интерфейс перестал залипать совсем. Добавлен overload вариант с передачей в процедуру TListItemImage - для использования в TListView и корректной перерисовки подгруженных картинок через AListItemImage.Invalidate. unit BitmapAsyncLoader; interface uses FMX.Graphics, FMX.Surfaces, System.Net.HttpClient, System.Types, System.Classes, FMX.ListView.Types, FMX.ListView.Appearances; type TBitmapAsyncLoader = class helper for TBitmap procedure LoadFromURLAsync(const AUrl : String); overload; procedure LoadFromURLAsync(const AUrl : String; const AListItemImage : TListItemImage); overload; end; implementation var AHTTPClient : THTTPClient; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then TThread.Synchronize(Nil, procedure begin if Assigned(Self)then Assign(ABitmapSurface); ABitmapSurface.Free; end ) else ABitmapSurface.Free; end; end, AURL ); except end; end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then TThread.Synchronize(Nil, procedure begin if Assigned(Self) and Assigned(AListItemImage) then begin AListItemImage.BeginUpdate; Assign(ABitmapSurface); AListItemImage.Invalidate; AListItemImage.EndUpdate; end; ABitmapSurface.Free; end ) else ABitmapSurface.Free; end; end, AURL ); except end; end; initialization AHTTPClient:=THTTPClient.Create; finalization if Assigned(AHTTPClient) then AHTTPClient.DisposeOf; end. Тестовый проект, на этот раз с ListView (по кнопке добавляется 100 итемов) прилагаю. BitmapAsyncLoaderListView.7z
  19. 5 баллов
    Веб.бинар показал, что проделано огромная работа. Очень понравилось.
  20. 5 баллов
    В общем удалось решить проблему с кнопками пульта. Теперь приложение распознает все кнопки с пульта. Если кому-то нужно, прикрепил архив. (Delphi 10.3.1 Rio) fmx_androidkey_fix.zip
  21. 5 баллов
    Протокол SNTP Помимо NTP, существует упрощенная версия этого протокола - SNTP (Simple Network Time Protocol). Он реализован для синхронизации времени конечным клиентом, поскольку все преимущества протокола NTP проявляются именно в сети серверов, а для получения показаний конечным пользователем NTP излишне сложен. Поэтому для синхронизации времени конечными компьютерами и серверами был предложен протокол SNTP (SNTPv3: 1992 г., RFC1361 и 1995 г., RFC1769; SNTPv4 включён как подпротокол в NTPv4). На самом деле SNTP - это не новый протокол, а способ использования NTP-пакетов и NTP-серверов в приложениях, где не требуется высокоточное время, либо оно недостижимо. В этом случае клиент использует только часть информации UDP-пакета NTP-сервера. SNTP-клиент может работать с любыми версиями NTP-серверов, и кроме них - с особыми SNTP-серверами, которые в откликах заполняют только необходимые данные UDP-пакета. Таким образом, "облегченный" SNTP образует не сеть синхронизирующихся серверов, а пары "клиент-сервер". Любой NTP-сервер является одновременно SNTP-сервером. Клиент, который не передаёт полученное время дальше, может работать как NTP- или SNTP-клиент, в зависимости от условий. Для SNTP, как и для NTP, зарезервирован 123-й UDP-порт. Uses IdSNTP, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient; .... procedure TForm1.Button2Click(Sender: TObject); Var IdSNTP: TIdSNTP; begin IdSNTP:=TIdSNTP.Create(Self); IdSNTP.Host := 'ntp1.stratum2.ru'; ShowMessage(DateTimeToStr(IdSNTP.DateTime)); IdSNTP.Free; end;
  22. 5 баллов
    RoschinSpb

    Как убить кнопку кликнув на нее саму

    Не ссоритесь девочки пож. Возвращаясь к сути вопроса. Основная сложность тут в том, что в Delphi нельзя разрушать экземпляр класса внутри метода этого класса за исключением тех случаев, когда метод использует только для разрушения Free, DisposeOf. Почему так, а не иначе, какие есть исключения и почему "уменяфсёработает" объяснять долго, поэтому в первом приближении предлагаю принять это за аксиому. Обработчики событий OnClick и пр. вызываются из методов классов, так что разрушать контрол внутри события нельзя от слова совсем. Кроме очевидных случаев типа Self.DisposeOf существуют более запутанные варианты, когда к примеру закрывает и разрушается форма, что приводит к разрушению всех дочерних контролов. Образно говоря, самоубийства строго запрещены, но не запрещено нанимать киллера и в качестве жертвы указывать себя. Т.е. должен быть некий другой (глобальный) объект который будет разрушать объекты, которые хотели бы самоубицо. Реализацию такого объекта можете придумать сами, или использовать TPurgatory (чистилище, в католическом учении — промежуточное место между раем и адом). Но чтобы убедиться в правильности работы можно создать своего наследника TButton в котором перекрыть деструктор и поставить в нем точку останова. При запуске в режиме отладки посмотрите стек вызова деструктора (надо быть внимательным, он может быть длиннющим), ни где в этом стеке не должно быть метода разрушаемого экземпляра. Если в Вы нашли метод разрушаемого объекта (за исключением вышеуказанных), то Ваш способ удаления работает не правильно и с некоторой долей вероятности будет приводить к AV и другим "неприятностям" которые почти невозможно отловить в режиме отладки.
  23. 5 баллов
    Slym

    Артефакты на экране (Android)

    Боролись как-то с артефактами отображения (мы их прозвали "крокодилами" из-за сходства на первом скриншоте с этим багом)... Могли отображаться также левые спрайты, или обрезки скролившихся контролов... Коллега выяснил что не надо трогать Form.Fill, из-за переключения в недрах FMX нативной и не нативной канвы: если нужен фон - брось Rect по контенту и в нем делай заливку...
  24. 5 баллов
    В конце концов получилось исправить. Для interlaced гифок проблема была вообще пустяковая. Одна строчка не в том месте. А вот для optimized все оказалось несколько сложней, но в итоге теперь все гифки отображаются правильно. Пользуйтесь на здоровье! FMX.GifUtils.zip
  25. 4 балла
    Владимир Б.

    TInstructor - Step-By-Step инструкция

    Собственно понадобился подобный компонент для FMX, но готового решения найти не смог - пришлось ваять свой. Использовать проще простого: var scenaries: TDictionary<TFmxObject, string>; begin scenaries := TDictionary<TFmxObject, string>.Create; scenaries.Add(btn_1, '1 Button'); scenaries.Add(btn_2, '2 Button'); scenaries.Add(btn_3, '3 Button'); scenaries.Add(rctngl, 'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'#13#10'Rectangle'); scenaries.Add(pnl_1, 'Panel Panel Panel Panel Panel Panel Panel Panel Panel Panel'#13#10'Panel'); scenaries.Add(nil, 'Msg without target control!'); try instructor.LoadSteps(scenaries); finally FreeAndNil(scenaries); end; Репозиторий GitHub: https://github.com/ange007/TInstructor/
  26. 4 балла
    Да, у меня. Я только не знаю, с чем это связано. Запрос именно на это приложение я отправлял вчера и ответа еще не получил. Но неделю назад отправлял на другие приложения (ответ я в какой-то теме публиковал). Но вчера на старые мои запросы пришли письма о том, решилась ли моя проблема. И вот я там еще раз написал о том, что хотелось бы получить продление, что у делфи нет компилятора андройд-64, что будет он только осенью или зимой и что выпущу обновление в течение 2-х недель после появления компилятора. Утром пришел формальный ответ, что мол передадим в техническую группу и чуть что - сообщим
  27. 4 балла
    Окончательный вариант. Долго бился с изменением размера картинки внутри потока (к примеру что бы в ListView не грузить картинки больше чем нужно). Средствами TBitmap это оказалось сделать невозможно (именно в потоке), чтение форумов, issue Эмбаркадеро, привело к туманному выводу что проблема в архитектуре FMX. В Токио, TBitmap стал потокобезопасным - это означает что никогда не пытайтесь использовать Bitmap в потоке, рано или поздно получите артефакты и глюки. Я решил проблему отказавшись от работы с TBitmap в потоке, и использовав для этого TBitmapSurface (загрузка из stream, изменение размеров). Что умеет хелпер: 1. Загрузка картинки в Bitmap и подгонкой размера (размер можно и не менять - не передавайте параметр ASize) procedure LoadFromURLAsync(const AURL : String; const ASize : TControlSize = nil); overload; 2. Загрузка картинки в TListItemImage ListView. После Окончания загрузки хелпер выполнит AListItemImage.Invalidate в основном потоке приложения для отрисовки картинки. procedure LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); overload; 3. Создание картинки. Тоже самое что и предыдущие, но можно сэкономить строчку кода ABitmap:=TBitmap.Create constructor CreateFromUrlAsync(const AURL : String; const AListItemImage : TListItemImage = nil); По картинкам в ListView - можете на свой страх и риск грузить 100500 картинок, но лучше использовать загрузку только для видимой части (+- еще сколько то итемов). Хелпер тупо грузит картинки и не обеспечивает механизм оптимальной загрузки. Протестировано на Windows и Android. Ответы на вопросы которые мне задавали: Почему не создавать отдельный поток для каждой картинки, в нем создавать THTTPClient и делать запрос - пробовал этот вариант, он медленнее на порядок, даже под виндой это чертовски медленно. AHTTPClient.BeginGet и так создает отдельный поток на каждый запрос. Почему AHTTPClient глобальный для юнита - в хелпере нельзя вводить свои переменные, а создавать AHTTPClient внутри функции не выйдет - он убьется до завершения потока. И текущий вариант быстрее. Код хелпера и архив с тестовым проектом: unit BitmapAsyncLoader; interface uses System.Net.HttpClient, System.Net.URLClient, System.SysUtils, System.Types, System.Classes, FMX.Graphics, FMX.Surfaces, FMX.Types, FMX.ListView.Types; type TBitmapAsyncLoader = class helper for TBitmap private function ResizeBitmapSurface(const ABitmapSurface : TBitmapSurface; const AWidth, AHeight : Integer) : TBitmapSurface; procedure SynchronizeAssignFromBitmapSurface(const ABitmapSurface : TBitmapSurface; const AListItemImage : TListItemImage = nil); procedure StartHTTPThread(const AURL : String; const AWidth, AHeight : Integer; const AListItemImage : TListItemImage = nil); public procedure LoadFromURLAsync(const AURL : String; const ASize : TControlSize = nil); overload; procedure LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); overload; constructor CreateFromUrlAsync(const AURL : String; const AListItemImage : TListItemImage = nil); end; implementation type THTTPClientListener = class class procedure HTTPClientValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest; const Certificate: TCertificate; var Accepted: Boolean); end; var AHTTPClient : THTTPClient; constructor TBitmapAsyncLoader.CreateFromUrlAsync(const AURL : String; const AListItemImage : TListItemImage = nil); begin Create; LoadFromURLAsync(AURL, AListItemImage); end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); var AWidth, AHeight : Integer; begin if Assigned(AListItemImage) then begin AWidth:=Round(AListItemImage.Width); AHeight:=Round(AListItemImage.Height); end else begin AWidth:=-1; AHeight:=-1; end; StartHTTPThread(AURL, AWidth, AHeight, AListItemImage); end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const ASize : TControlSize = nil); var AWidth, AHeight : Integer; begin if Assigned(ASize) then begin AWidth:=Round(ASize.Width); AHeight:=Round(ASize.Height); end else begin AWidth:=-1; AHeight:=-1; end; StartHTTPThread(AURL, AWidth, AHeight); end; function TBitmapAsyncLoader.ResizeBitmapSurface(const ABitmapSurface : TBitmapSurface; const AWidth, AHeight : Integer) : TBitmapSurface; begin if (AWidth <> -1) and (AHeight <> -1) then begin try Result:=TBitmapSurface.Create; Result.StretchFrom(ABitmapSurface, AWidth, AHeight, ABitmapSurface.PixelFormat); finally ABitmapSurface.Free; end; end else Result:=ABitmapSurface; end; procedure TBitmapAsyncLoader.SynchronizeAssignFromBitmapSurface(const ABitmapSurface : TBitmapSurface; const AListItemImage : TListItemImage = nil); begin TThread.Synchronize(Nil, procedure begin Assign(ABitmapSurface); ABitmapSurface.Free; if Assigned(AListItemImage) then AListItemImage.Invalidate; end ); end; procedure TBitmapAsyncLoader.StartHTTPThread(const AURL : String; const AWidth, AHeight : Integer; const AListItemImage : TListItemImage = nil); begin AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except exit; end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, Self.CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then begin ABitmapSurface:=ResizeBitmapSurface(ABitmapSurface, AWidth, AHeight); SynchronizeAssignFromBitmapSurface(ABitmapSurface, AListItemImage); end; end; end, AURL ); end; class procedure THTTPClientListener.HTTPClientValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest; const Certificate: TCertificate; var Accepted: Boolean); begin Accepted:=True; end; initialization AHTTPClient:=THTTPClient.Create; AHTTPClient.OnValidateServerCertificate:=THTTPClientListener.HTTPClientValidateServerCertificate; finalization if Assigned(AHTTPClient) then AHTTPClient.DisposeOf; end. BitmapAsyncLoader.7z
  28. 4 балла
    Ingalime

    переход к x64?

    https://community.idera.com/developer-tools/b/blog/posts/google-play-store-android-32-bit-extension-for-delphi-and-c-builder-customers
  29. 4 балла
  30. 4 балла
    Одной из распространенных проблем, с которыми сталкивается разработчик в ходе разработки мобильных приложений, является построение UI. На вебинаре мы рассмотрим реализацию некоторых типовых шаблонов мобильных приложений в контексте библиотеки FGX Native, сравним подходы, используемые для реализации одинакового функционала в FMX и FGX, а также познакомимся с уникальными ключевыми особенностями FGX Native, которые раскрывают все достоинства нативной разработки. В вебинаре принимает участие создатель FGX – Ярослав Бровин. Дата: 11 июля 2019 12:00 МСК. Ссылка на регистрацию: http://forms.embarcadero.com/FGXNative
  31. 4 балла
    qz5

    Версия андроид

    Я разбавлю своим вариантом: Leagoo Power 2. У него цена около 3000 рублей, из коробки идет Андроид 8.1, но можно поставить Андроид 9 и даже... Android 10!!! С одной стороны у меня среди родственников есть смарты от 4ой до 9-ой версии Андроид, да и моя прога сейчас на всех работает (пока она простая). Но с другой стороны решил поискать дешевый смарт, на который можно несколько разных версий Андроид поставить, но: 1. чтобы это было легко, без всяких разблокировок и т.п. (у новых Xiaomi, Huawei как раз проблемы с заблокированным загрузчиком) 2. чтобы был максимально дешевый 3. чтобы можно было поставить Андроид 8.1 и Андроид 9, причем разные сборки 4. чтобы не надо было ставить всякие Flash Tools и т.п. - искал, чтобы прошивка была простой и максимально без лишних программ Оказалось, что Leagoo Power 2 Pro: 1. Поддерживает GSI-прошивки от Project Treble (Андроид 8.1, Андроид 9 и Android 10) 2. стоит около 3000 рублей 3. Для прошивки не нужно никаких лишних программ! Достаточно ADB, а он и так уже идет вместе с Delphi (можно и самому ADB ставить на комп, если Delphi нет например) Взял на будущее, чтобы было дешевое устройство, на котором можно экспериментировать с прошивками Правда сам пока не пробовал - телефон получил, всё работает, но пока закинул его в коробочку, тестирую на смартфоне с Андроид 7 (он всё равно постоянно на столе и там нужные мне программы). Как прошить ТВРП: https://4pda.ru/forum/index.php?showtopic=928803&st=120#entry81458052 Другие версии Андроид брать здесь: https://4pda.ru/forum/index.php?showtopic=892755 Где купить: решайте сами, многие покупают на Пандао, но я почитал отзывы - Пандао какой-то странный магазин, ничего там не покупал и не стал из-за 200 рублей рисковать. Я взял там, где советует официальный производитель: https://vk.com/wall-148943419_19677 Доставила почта Сингапура за 20 дней. p.s. я кучу разных вариантов пересмотрел и остановился именно на нем. Самая легкая перепрошивка из всех, недорогой смарт, есть запчасти, возможность ставить разные кастомы. может кому пригодится
  32. 4 балла
    mazayhin

    Как узнать Device Name на Андроиде?

    Это будет имя Bluetooth-адаптера. //uses System.Bluetooth; TBluetoothManager.Current.CurrentAdapter.AdapterName
  33. 4 балла
    Все невизуальные компоненты, которые не используют код FMX прекрасно работают.
  34. 4 балла
    Уважаемый коллеги! Пришло время показывать результаты работы нового фреймворка FGX native в деле и в реальном приложении. В рамках XXVI РОССИЙСКОГО НАЦИОНАЛЬНОГО КОНГРЕССА «ЧЕЛОВЕК И ЛЕКАРСТВО» будет представлен доклад: «Контроль полипрагмазии «в кармане», мобильная разработка основанная на FGX Native» Будет представлена мобильная программа, написанная с использованием вышеназванного фреймворка для Андроида. Конечно конгресс для врачей, но если кому будет интересно, приходите послушать доклад 9-го апреля в ЦМТ ( Москва, Краснопресненская набережная, 12). С 16-00 до 20-00. Доклад последний, поэтому, думаю к 18-30 можно подтягиваться! Программа конгресса
  35. 4 балла
    В аттаче пример того как я себе представляю такую реализацию. Будем использовать в нашем проекте. Буду рад критике, предложениям, и все такое. TestWhatsNew.zip
  36. 4 балла
    по вопросам. 1) выбор на хостингах невелик - MySQL, Postgres. Я PG выбрал чисто в силу интереса и он вроде поближе к стандартам, и у него ХП и другие всякие штуки.... Сижу на SWEB.RU. Опять же просто потому что давно. Есть и masterhost и любой другой крупный провайдер подойдет. 2) не путаем хостинг с бэкенд-сервером (BAS). Типа Firebase или Amazon или еще туча. на хостинге у вас все свое. что написали то и работает. на BAS есть много приятных плюшек. Довольно платных ессно. Зато и push и email рассылки и админка... 3) MSSQL не вариант. Веб в основном на Linux. 4) обычно просто THttpClient. На нем нормально пишется клиентская часть API 5) обычная схема. просто с нуля некоторые вещи пилить. зато бесплатно. Практика показывает что иногда лучше заплатить и получить богатое приложение сразу. но иногда как написал Евгений, потом можно упереться в ограничения сервисов. Но можно решать проблемы по мере поступления...
  37. 4 балла
    1. Хостинг рекомендую https://masterhost.ru/service/hosting/individual/ , это один из старейших и надежнейших хостеров России, там вы получите сразу все вам необходимое - MySQL, PHP любимой версии, если проект попрет, то сможете добавлять процессоры, память и т.д. Так же сможете зарегить домен под это дело, и при надобности получить SSL сертификат на этот домен. Все остальные хостинги игнорируйте, по крайней мере Российские. За почти 20 лет использования, мастерхост ни разу не подвел, а только радовал новыми плюшками. Реализация в вашем случае примерно такая: 1. MySQL на хостере - обеспечит вам работу и 10 миллионов активных пользователей. Но важно правильно спланировать структуру базы, структуру таблиц и структуру индексов таблиц. Если вы в этом не профи, то лучше нанять профи - ибо это фундамент, который потом очень сложно будет изменить. 2. PHP на хостере - прокладка между базой и запросами/ответами приложения. Рекомендую использовать самую свежую версию PHP, чтоб потом не пришлось перекраивать код удаляя deprecated функции и конструкции. 3. Протокол обмена - REST. Не вздумайте погружаться в теорию, читать про RESTful и пытаться реализовывать, этим занимаются только люди под тяжелыми наркотиками и обычно без единого законченного реального проекта. Достаточно того что приложение будет отправлять на сервер GET запросы получать JSON ответы. Можете подогнать протокол под существующие в Delphi компоненты TRESTClient, а можете и сами на стороне приложения разгребать JSON и получать нужные данные. Это совсем не сложно. 4. Приложение - посылает на сервер HTTP GET (ну или POST) запросы посредством THTTPClient, получает ответы в виде JSON, парсит их и так далее. Все содержимое предыдущего предложения - в отдельном потоке. Ну или используйте готовый TRESTClient - если готовы разбираться в нюансах его работы. Вот как то так.
  38. 4 балла
    krapotkin

    Переезд на 10.3 Rio

    научили конечно ))) все придумано до нас вот статья вот так в грубом приближении должно это быть p.s. Забыл удалить из ваших форм эти циклы, которых там быть не должно Форма - это интерфейс взаимодействия с пользователем. Данные должны жить отдельно. test10.3.zip
  39. 4 балла
    krapotkin

    Фреймворк для стандартного ListView

    Вот и картинки подвезли. Идиотский Deployment отказывается переписывать старые файлы на новые.... Пока полностью не удалил приложение, файл-описание раскладки был старый, без картинок Как видно из заголовка 3000+ итемов с авторасчетом высоты. 6 секунд Крутится плавно... ListViewTest.apk.rar
  40. 4 балла
    Barbanel

    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 Что интересно, этот же код можно без изменений использовать под любой другой платформой. На других платформах приложение будет считать что ему выдали все права, и соответственно запускать все коллбеки без каких-либо вопросов.
  41. 4 балла
    Dev

    Анимированная смена форм

    https://www.youtube.com/watch?v=YU7MlY58n9U&t=59s
  42. 4 балла
    beeoz

    TExpander глюки при при isExpanded=False

    Проблема сохранилась и в IDE Delphi Rio 10.3 . Причиной оказалось то, что в модуле FMX.StdCtrls в процедуре TExpander.UpdateControlSize указана переменная FContentHeight вместо FContent.Height procedure TExpander.UpdateControlSize(const ChangingState: Boolean); begin FChangingState := ChangingState; try if FIsExpanded then begin FContent.Visible := FIsExpanded; if FButton <> nil then Height := FButton.Height + FContent.Height; // здесь заменил FContentHeight на FContent.Height и заработало Repaint; end else begin Repaint; FContent.Visible := FIsExpanded; if FButton <> nil then Height := FButton.Height; end; finally FChangingState := False; end; end;
  43. 4 балла
    krapotkin

    Размеры TPanel

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

    Затирание bitmap canvas при map-unmap

    Я разобрался в чем дело: Вместо TMapAccess.Write используйте TMapAccess.ReadWrite. TMapAccess.Write по какой то причине затирает если не все, то некоторые последние изменения канваса. В доке http://docwiki.embarcadero.com/Libraries/Rio/en/FMX.Graphics.TBitmap.Map не нашел упоминания о таком поведении.
  48. 3 балла
    Vladimir PRO

    Узнать размер видеопамяти

    Обновлённая ссылка на DEMO: http://gofile.me/2Zesj/fbsharing-C0f3wb1o Последняя версия в папке: OpenCL_Demo2018 Barrier and Local_Memory REDUCT Delphi Tokyo 10.2.2 !! LAST !!
  49. 3 балла
    OnePeople

    рисование на Image1

    По быстрому) Paint.rar
  50. 3 балла
    1. Проверь AndroidManifest.template.xml, параметры minSdkVersion и targetSdkVersion 2. Перекомпилируй в Rio (предварительно сделав Revert System Files to Default у узла Target Platforms->Android->Libraries)
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...