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

Лидеры


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

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

  1. 14 баллов
    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. 10 баллов
    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. 10 баллов
    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.
  4. 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
  5. 9 баллов
    Brovin Yaroslav

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

    Хочу от всей души поздравить с днем рождения нашего модератора Андрея Ефимова @Andrey Efimov. Человек, на которого можно положиться и который всегда готов прийти на помощь. Из года в год помогает нашему форуму становиться лучше. С днем рождения! Успехов тебе в работе, в личных делах. И не забывать про Делфи!
  6. 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 Правда у меня только звук "чпок" на всех константах. Но мне он и был нужен )
  7. 8 баллов
    OnePeople

    Монополия

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

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

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

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

    Боролись как-то с артефактами отображения (мы их прозвали "крокодилами" из-за сходства на первом скриншоте с этим багом)... Могли отображаться также левые спрайты, или обрезки скролившихся контролов... Коллега выяснил что не надо трогать Form.Fill, из-за переключения в недрах FMX нативной и не нативной канвы: если нужен фон - брось Rect по контенту и в нем делай заливку...
  19. 5 баллов
    В конце концов получилось исправить. Для interlaced гифок проблема была вообще пустяковая. Одна строчка не в том месте. А вот для optimized все оказалось несколько сложней, но в итоге теперь все гифки отображаются правильно. Пользуйтесь на здоровье! FMX.GifUtils.zip
  20. 4 балла
    Все невизуальные компоненты, которые не используют код FMX прекрасно работают.
  21. 4 балла
    Уважаемый коллеги! Пришло время показывать результаты работы нового фреймворка FGX native в деле и в реальном приложении. В рамках XXVI РОССИЙСКОГО НАЦИОНАЛЬНОГО КОНГРЕССА «ЧЕЛОВЕК И ЛЕКАРСТВО» будет представлен доклад: «Контроль полипрагмазии «в кармане», мобильная разработка основанная на FGX Native» Будет представлена мобильная программа, написанная с использованием вышеназванного фреймворка для Андроида. Конечно конгресс для врачей, но если кому будет интересно, приходите послушать доклад 9-го апреля в ЦМТ ( Москва, Краснопресненская набережная, 12). С 16-00 до 20-00. Доклад последний, поэтому, думаю к 18-30 можно подтягиваться! Программа конгресса
  22. 4 балла
    В аттаче пример того как я себе представляю такую реализацию. Будем использовать в нашем проекте. Буду рад критике, предложениям, и все такое. TestWhatsNew.zip
  23. 4 балла
    по вопросам. 1) выбор на хостингах невелик - MySQL, Postgres. Я PG выбрал чисто в силу интереса и он вроде поближе к стандартам, и у него ХП и другие всякие штуки.... Сижу на SWEB.RU. Опять же просто потому что давно. Есть и masterhost и любой другой крупный провайдер подойдет. 2) не путаем хостинг с бэкенд-сервером (BAS). Типа Firebase или Amazon или еще туча. на хостинге у вас все свое. что написали то и работает. на BAS есть много приятных плюшек. Довольно платных ессно. Зато и push и email рассылки и админка... 3) MSSQL не вариант. Веб в основном на Linux. 4) обычно просто THttpClient. На нем нормально пишется клиентская часть API 5) обычная схема. просто с нуля некоторые вещи пилить. зато бесплатно. Практика показывает что иногда лучше заплатить и получить богатое приложение сразу. но иногда как написал Евгений, потом можно упереться в ограничения сервисов. Но можно решать проблемы по мере поступления...
  24. 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 - если готовы разбираться в нюансах его работы. Вот как то так.
  25. 4 балла
    krapotkin

    Переезд на 10.3 Rio

    научили конечно ))) все придумано до нас вот статья вот так в грубом приближении должно это быть p.s. Забыл удалить из ваших форм эти циклы, которых там быть не должно Форма - это интерфейс взаимодействия с пользователем. Данные должны жить отдельно. test10.3.zip
  26. 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 Что интересно, этот же код можно без изменений использовать под любой другой платформой. На других платформах приложение будет считать что ему выдали все права, и соответственно запускать все коллбеки без каких-либо вопросов.
  27. 4 балла
    Dev

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

    https://www.youtube.com/watch?v=YU7MlY58n9U&t=59s
  28. 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;
  29. 4 балла
    А можно для тех, кто не смог присутствовать, хотя бы кратко основные тезисы?
  30. 4 балла
    Ярослав, иду из-за тебя и сенчи. Давай там, зажги!
  31. 3 балла
    krapotkin

    Разбор JSON с мультизапросом

    вы просто без разделителей склеиваете три разных JSON-массива вам бы каждый из них описать отдельно. да и вообще принято логически законченные участки кода выделять в отдельные функции function GetValuesAsJson($query) { ..... } тогда будет например '{"Arr1":'. GetValuesAsJson($query1). ', "Arr2":'.GetValuesAsJson($query2).', "Arr3":'.GetValuesAsJson($query3).'}' ну и разбор полученного объекта например с помощью XSuperObject. Примеры есть на офсайте https://github.com/onryldz/x-superobject
  32. 3 балла
    Можно использовать rtl со всеми компонентами, которые там есть. Плюс есть возможность использовать AndroidAPI, если очень нужно. Это пока не реализовано. Но подобные сервисы будут реализованы по мере необходимости и запросов. Это есть и есть кроссплатформенная реализация. В самом FMX , кстати, ее нету. Можно будет настраивать статус бар в приложении. Положение формы относительно статус бара и простейшие операции по подкраске. Службы еще не тестировались, но в первой версии можно будет использовать построение сервисов, на базе тех, что есть в rtl. Перехваты и прочее - это уже особенности системы Андроид. В теории такое возможно, если делать приложение с несколькими Activity. Но на практике не думаю ,что это будет удобно с учетом того, как это можно сделать.
  33. 3 балла
    Демо проект с быстрым списком (его подготовил Андрей Зубов) FastSimpleList.apk
  34. 3 балла
    dnekrasov

    TImageList  в  TImage

    Хм... Я смотрю Help совсем популярностью у Вас не пользуется... TImageList.Bitmap(...) TImageList.BitmapExists(...) TImageList.BitmapItemByName(...)
  35. 3 балла
    Procedure TServerConnectionTH.RecieveData(); // сюда приходя данные со сканера //Data - это данные в виже TBytes //str - строка со считанным штрихкодом var Intent: JIntent; str:String; begin str:=TEncoding.UTF8.GetString(Data); Form1.DisplayR.Lines.Add(Str); Form1.DisplayR.GoToTextEnd; Intent := TJIntent.Create; Intent.setAction(StringToJString('com.google.android.c2dm.intent.RECEIVE')); Intent.putExtra(StringToJString('text'),StringToJString('1')); Intent.putExtra(StringToJString('title'),StringToJString('1C')); Intent.putExtra(StringToJString('data'),StringToJString(str)); TAndroidHelper.Context.sendBroadcast(Intent); end;
  36. 3 балла
    Тоже свой вариант по быстрому накидал, как пример WhatNew.rar
  37. 3 балла
    gonzales

    Переезд на 10.3 Rio

    Чего Вы привязались к прогрессбару, это никак не связано с потоками, я просто уточнял, нужно ли обращаться к форме, созданной в потоке через синхронизацию. Прочитайте посты выше, вроде как уже больше недели это обсуждаем. У вас очень странное представление о UI. Вы правда считаете, что я демонстрирую пользователю одновременно Сплэш, две формы, и повергающий его в экстаз прогрессбар??
  38. 3 балла
    Евгений Корепов

    Не работает onClose (Android)

    Для этого есть событие TForm.OnSaveState http://docwiki.embarcadero.com/Libraries/Rio/en/FMX.Forms.TForm.OnSaveState
  39. 3 балла
    Расписывать в деталях прям не буду https://gist.github.com/ashumkin/3e2e213d657162ae26d364a85c64b472
  40. 3 балла
    Да там всё Евгений Корепов сделал уже. Я только три копейки своих добавил... Вот конечный код: unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Net.HttpClient, System.Generics.Collections, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts, FMX.ListView; const ListViewItemImageEmpty = -1; ListViewItemImageLoading = 0; ListViewItemImageLoaded = 1; type TForm1 = class(TForm) ListView1: TListView; Layout1: TLayout; Button1: TButton; procedure Button1Click(Sender: TObject); procedure ListView1UpdatingObjects(const Sender: TObject; const AItem: TListViewItem; var AHandled: Boolean); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FListViewUpdating : Boolean; FHTTPClient : THTTPClient; FAsyncResultList : TList<IAsyncResult>; procedure LoadImage(const AItem: TListViewItem; const AListItemImage : TListItemImage); procedure ClearListViewAndCancelAsynchronousRequests(); public end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.FormCreate(Sender: TObject); begin listview1.ItemIndex := 0; listview1.ItemAppearance.ItemAppearance := 'Custom'; listview1.ItemAppearanceObjects.ItemObjects.Accessory.Visible := False; FHTTPClient := THTTPClient.Create; FAsyncResultList := TList<IAsyncResult>.Create; FListViewUpdating := False; end; procedure TForm1.FormDestroy(Sender: TObject); begin ClearListViewAndCancelAsynchronousRequests(); FListViewUpdating := True; FreeAndNil(FAsyncResultList); if Assigned(FHTTPClient) then FHTTPClient.Free; end; procedure TForm1.ClearListViewAndCancelAsynchronousRequests(); var I: Integer; begin FListViewUpdating := True; // Запрещаем продолжать загружать фотки (если ещё не успели загрузиться все) while FAsyncResultList.Count > 0 do // Дожидаемся окончания выполнения всех IAsyncResult.Cancel, несмотря на асинхронность begin for I := FAsyncResultList.Count - 1 downto 0 do if Assigned(FAsyncResultList.Items) and (not FAsyncResultList.Items.IsCompleted) then FAsyncResultList.Items.Cancel else FAsyncResultList.Delete(I); // Заодно удаляем отработанные элементы end; ListView1.Items.Clear; FListViewUpdating := False; end; procedure TForm1.Button1Click(Sender: TObject); var I: Integer; Item: TListViewItem; ARandom: Integer; begin ClearListViewAndCancelAsynchronousRequests(); //Формирование нового списка for I := 1 to 10000 do begin FAsyncResultList.Add(nil); FListViewUpdating := True; Item := listview1.Items.Add; Item.Height := 45; Randomize; ARandom := Random(6); case ARandom of 0 : Item.data['ImageURL'] := 'http://fire-monkey.ru/uploads/monthly_2017_06/me.thumb.jpg.966ddc17d5602ee14feb43479c1f6963.jpg'; 1 : Item.data['ImageURL'] := 'http://fire-monkey.ru/uploads/monthly_2018_05/B-IpGQmVgTM.thumb.jpg.2ebeb0bd766ab7cf19f10195d6ea2be9.jpg'; 2 : Item.data['ImageURL'] := 'http://fire-monkey.ru/uploads/monthly_2016_04/10.png.b9ab371e8fd38172fee96bcf75fb6699.thumb.png.b0685259b03bfff540903913845532a5.png'; 3 : Item.data['ImageURL'] := 'https://secure.gravatar.com/avatar/9942c50b1641a921c52d4b389bd718d6?d=http://fire-monkey.ru/uploads/monthly_2017_12/K_member_87.png'; 4 : Item.data['ImageURL'] := 'http://fire-monkey.ru/uploads/monthly_2016_11/photo-1529.png.7267be10b59f950b7c5bb3f34a60901e.thumb.png.22027ae85266216220310ed694d57628.png'; 5 : Item.data['ImageURL'] := 'http://fire-monkey.ru/uploads/profile/photo-thumb-115.jpg'; end; Item.Data['ImageState'] := ListViewItemImageEmpty; FListViewUpdating := False; Item.Adapter.ResetView(Item); end; end; procedure TForm1.LoadImage(const AItem: TListViewItem; const AListItemImage : TListItemImage); var K: Integer; // Анонимная процедура захватывает локальную переменную, а не обращается к AItem, которой уже может не быть в момент _окончания_ скачивания фотки AAsyncResult: IAsyncResult; begin if Not Assigned(AItem) or Not Assigned(AListItemImage) then Exit; if AItem.Data['ImageState'].AsInteger <> ListViewItemImageEmpty then Exit; if AItem.Data['ImageURL'].AsString.IsEmpty then Exit; AItem.Data['ImageState'] := ListViewItemImageLoading; K := AItem.Index; // Запоминаем индекс в локальную K, которая уйдёт в анонимку (время жизни K > времени жизни анонимки) FAsyncResultList.Items[K] := FHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse: IHTTPResponse; begin if ASyncResult.IsCancelled then Exit; try AHTTPResponse := THTTPClient.EndAsyncHTTP(ASyncResult); if Not Assigned(AHTTPResponse) then Exit; if AHTTPResponse.StatusCode <> 200 then Exit; except Exit; end; TThread.Synchronize(Nil, procedure begin if FListViewUpdating or ASyncResult.IsCancelled then // Выходим, так как внутри анонимной процедуры AItem или AListItemImage - не сброшены в nil, хотя их уже может и не быть Exit; if Not Assigned(AItem) or Not Assigned(AListItemImage) then Exit; AListItemImage.BeginUpdate; AListItemImage.Bitmap := TBitmap.Create; AListItemImage.Bitmap.LoadFromStream(AHTTPResponse.ContentStream); AListItemImage.EndUpdate; AItem.Data['ImageState'] := ListViewItemImageLoaded; FAsyncResultList.Items[K] := nil; end ); end, AItem.Data['ImageURL'].AsString ); end; procedure TForm1.ListView1UpdatingObjects(const Sender: TObject; const AItem: TListViewItem; var AHandled: Boolean); function SetupImageObject(const AName: String; AWidth, AHeight, X , Y: Single; AAlign, AVertAlign: TListItemAlign): TListItemImage; var LIT: TListItemText; begin Result := TListItemImage(AItem.View.FindDrawable(AName)); if Result = Nil then begin // Создаём картинку Result := TListItemImage.Create(AItem); Result.Name := AName; Result.Bitmap := nil; Result.OwnsBitmap := True; // Создаём надпись LIT := TListItemText.Create(AItem); LIT.Name := 'LIT-' + AItem.Index.ToString; LIT.Width := 100; LIT.Height := 22; LIT.PlaceOffset.X := X + AWidth + 10; LIT.PlaceOffset.Y := Y; LIT.Text := LIT.Name; LIT.Visible := True; end; Result.Width := AWidth; Result.Height := AHeight; Result.PlaceOffset.X := X; Result.PlaceOffset.Y := Y; Result.Align := AAlign; Result.VertAlign := AVertAlign; Result.ScalingMode := TImageScalingMode.StretchWithAspect; Result.Visible := True; end; Var AListItemImage: TListItemImage; begin if FListViewUpdating then Exit; AListItemImage := SetupImageObject('s_image', 35, 35, 0 , 0, TListitemalign.Leading, TListItemAlign.Center); LoadImage(AItem, AListItemImage); AHandled := True; end; end.
  41. 3 балла
    Может кому пригодится https://blog.andreamagni.eu/2019/02/how-to-add-android-app-shortcuts-to-a-fmx-application/
  42. 3 балла
    mmover

    ClientWidth и ClientHeight

    cw := Grid1.Content.Width; ch := Grid1.Content.Height;
  43. 3 балла
    Slym

    Отображение картинок в ListView

    Логика асинхронности принимает на вход анонимную процедуру для обработки результата, анонимная процедура захватывает переменные в зоне своего определения, а там хоть итем, хоть индекс, хоть блэкджек с простихоспаде чем попало...
  44. 3 балла
    Прошу прощения, я ввел вас в заблуждение (тестировал на одном своем проекте). Открытие подобных ссылок вы должны делать самостоятельно, обрабатывая событие браузера ShouldStartLoadWithRequest. Вот код: uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, {$IFDEF ANDROID} Androidapi.JNI.Net, Androidapi.JNI.GraphicsContentViewText, Androidapi.Helpers, {$ENDIF ANDROID} FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.WebBrowser, FMX.Controls.Presentation; ..... const ConstMainURL = 'http://www.docme.ru/contacts'; .... procedure THeaderFooterForm.WebBrowser1ShouldStartLoadWithRequest( ASender: TObject; const URL: string); begin if Not URL.StartsWith(ConstMainURL) then // Если ссылка перехода отличается от базовой, то открываем ее через активити begin WebBrowser1.Stop; OpenURL(URL); end; end; procedure THeaderFooterForm.OpenURL(const AUrl: string); {$IFDEF ANDROID} var Uri: Jnet_Uri; OpenLinkIntent: JIntent; {$ENDIF ANDROID} begin {$IFDEF MSWINDOWS} ShellExecute(0, 'open', PChar(AUrl), nil, nil, SW_SHOWNORMAL); {$ENDIF MSWINDOWS} {$IFDEF ANDROID} Uri := StrToJURI(AUrl); OpenLinkIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, Uri); TAndroidHelper.Activity.startActivity(OpenLinkIntent); {$ENDIF ANDROID} end; И прикрепляю ваш проект с моими изменениями WebPrj.zip
  45. 3 балла
    Возможно: рывок происходит от того, что при смене владельца контролы отрисовываются первый раз (первый, это важно) на табконтроле. В момент первой отрисовки (емнип) компоненту создается и присваивается стиль, что ессно занимает некоторое время. При повтороной отрисовке стиль уже создан, потому все происходит быстро. Повторюсь, это мои догадки. Чтобы побороть именно этот случай, нужно компонентам заранее присваивать стиль программно, до первой отрисовки, т.е. до того как вы меняете родителя. Либо (я так не пробовал, не знаю сработает ли) отрисовать компоненты куданить в буффер, или в скриншот (или прямо на текущем родителе). Не уверен что это хороший вариант, пусть коллеги меня напинают). Мы в своем проекте все эти контролы расположили прямо на табах главной формы. Немного дольше длится первая загрузка, а потом все работает довольно плавно.
  46. 3 балла
    dnekrasov

    Компонент для вывода текста

    TRectangle для цвета, TBevelEffect для утопленности и TText для текста. А можно сделать кастомный стиль для TLabel по тому же сценарию. Родителем. TText позволяет просто вывести текст, а TLabel, например, позволяет вывести текст с определённым стилем, указав StyleLookup.
  47. 3 балла
    jornada

    Доступ к Yandex.Disk

    Лучше поздно, чем никогда) Например так // RESTRequest1.AddFile(FileName); AStream := TMemoryStream.Create(); AStream.LoadFromFile('D:\1.mp4'); RESTRequest1.AddBody(AStream, ctVIDEO_MP4);
  48. 3 балла
    krapotkin

    Размеры TPanel

    во время FormCreate еще не определены размеры лучше в OnShow, или OnResize
  49. 3 балла
    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
  50. 3 балла
    1. для упрощения кода работы с JSON давно можно использовать сложные пути ABase64:=JSON.GetValue<string>('body.nextStep.pdf'); 2. ну нельзя так: AStreamSource.WriteBuffer(Pointer(ABase64)^, Length(ABase64) * 2); так безопасней AStreamSource:=TBytesStream.Create(TEncoding.UTF8.GetBytes(ABase64)); 3. И сохранять лучше сразу в TFileStream - меньше расход памяти 4. не забываем finally Free (их выше нету)... хоть оно и может AUTOREFCOUNT (а может и нет!), но правила хорошего тона никто не отменял
Эта таблица лидеров рассчитана в Москва/GMT+03:00
×
×
  • Создать...