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

Fedor K

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

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

  • Посещение

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

    17

Весь контент Fedor K

  1. Как вариант в стиле вынести картинку с текстом в отдельный TLayout и добавить TFloatAnimation с триггером на IsSelected на свойство Opacity :
  2. Из приведенного выше кода ничего вручную удалять не нужно, кроме самого TListBoxItem, как и выполняется в примере выше (listbox1.Items.Delete(indexclick) или Form1.listbox1.Items.Delete(0)) . Все создаваемые дополнительные контролы (TGridPanelLayout, TRectangle, TText) создаются здесь с AOwner = TListBoxItem + задается Parent, который мы и удаляем, а при удалении родительского все дочерние удаляются вместе с ним. Можете убедиться в этом проверив утечку памяти: ReportMemoryLeaksOnShutdown := True; Sashar333 не используйте никогда .Name в качестве хранилища или идентификатора, это плохая практика. Для этих целей отлично подходят тэги (TagString или TagFloat), которые имеют все TFmxObject.
  3. elxanders скиньте пожалуйста пример своего проекта, я посмотрю в чем дело.
  4. Пожалуйста, внимательно посмотрите пример выше: cbbFiles: TComboBox; TComboBox содержит внутри себя TComboListBox с элементами списка, которые у вас автопереводятся. При помощи предоставленного выше примера автоперевод отключается. Если у Вас множество TComboBox, которым нужно запретить перевод, то можно воспользоваться таким способом: //Создаем helper для TComboBox type TComboBoxHelper = class helper for TComboBox public procedure SetAutoTranslate(AEnabled: Boolean = false); end; ... implementation ... { TComboBoxHelper } //Согласно примеру выше procedure TComboBoxHelper.SetAutoTranslate(AEnabled: Boolean); var i, count : integer; begin count := Self.Count - 1; for i := 0 to count do Self.ListBox.ListItems[i].AutoTranslate := AEnabled; end; ... //Пример использования helper в Вашем коде <Ваш TComboBox 1>.SetAutoTranslate; ... <Ваш TComboBox N>.SetAutoTranslate;
  5. Причина такого поведения довольно простая - java библиотеки FMX часто передают в Delphi только уведомление о событии, без непосредственного влияния на процесс. Открываем библиотеку fmx.jar и смотрим код класса WebClient (package com.embarcadero.firemonkey.webbrowser;): public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { super.onReceivedSslError(view, handler, error);// обработка ошибки происходит здесь по дефолту if (this.mListener != null) { this.mListener.onReceivedSslError(view, handler, error);//передача в Delphi лишь уведомления, что событие произошло } } Одно из решений*: 1. Заменяем** код на: public void onReceivedSslError(WebView paramWebView, SslErrorHandler paramSslErrorHandler, SslError paramSslError) { if (this.mListener != null) { this.mListener.onReceivedSslError(paramWebView, paramSslErrorHandler, paramSslError);//Delphi обработчик } else { super.onReceivedSslError(paramWebView, paramSslErrorHandler, paramSslError);//обработчик по умолчанию } } После манипуляций получаем свою версию библиотеки, мой пример здесь (Delphi Berlin). 2. Подключаем библиотеку к проекту (скриншот ниже). 3. Копируем unit FMX.WebBrowser.Android в папку своего проекта и меняем следующие строки: procedure TAndroidWebBrowserService.TWebBrowserListener.onReceivedSslError( P1: JWebView; P2: JSslErrorHandler; P3: JSslError); begin P2.proceed;//добавляем разрешение для истекших сертификатов FWBService.FailLoadingWithError;//стандартный обработчик OnDidFailLoadWithError end; *Если вариант изменения кода java библиотек совсем не подходит, можно реализовать все средствами Delphi. Для этого создаем свою реализация класса WebViewClient (или WebClient) и задаем его для JWebBrowser: //все тот же unit FMX.WebBrowser.Android; procedure TAndroidWebBrowserService.InitUIThread; var lClient : TWebBrowserCLientFix;//наш класс begin FJWebBrowser := TJWebBrowser.JavaClass.init(TAndroidHelper.Activity); FJWebBrowser.getSettings.setJavaScriptEnabled(True); lClient := TWebBrowserCLientFix.Create(Self); FJWebBrowser.setWebViewClient(lClient);//меняем на наш класс FListener := TWebBrowserListener.Create(Self); lClient.SetWebViewListener(FListener); //комментируем //FJWebBrowser.SetWebViewListener(FListener); **Замена кода происходит по тому же сценарию, как и создание своих собственных классов на java. Если кому потребуется помощь - пишите, я помогу ответами и примером.
  6. Для того, чтобы при нажатии на уведомление оно автоматически исчезало из StatusBar при его создании необходимо добавлять флаг: localBuilder.setAutoCancel(true); В библиотеке fmx.jar этот код отсутствует (package com.embarcadero.rtl.notifications, public class NotificationPublisher). У меня есть перекомпиленная библиотека для Seattle. Изменение библиотек выполняется таким же образом, как и создание своих всем известным методов через .bat файл.
  7. ENERGY Для получения всех активных уведомлений в Android существует метод: getActiveNotifications added in API level 23 StatusBarNotification[] getActiveNotifications () FMX (Berlin и ниже точно, Tokyo не смотрел) не предоставляет доступ к этому методу, в исходниках (Androidapi.JNI.App.pas) он закомментирован. Возможно при использовании своего wrapper для класса JNotificationManager или отсюда можно получить доступ к требуемому функционалу.
  8. Да, команда работает только на телефонам с root правами. Попробуйте эти команды (выполнить нужно обе по порядку): #adb root #adb remount
  9. Golovanyuk, такое случается, когда кабель не достаточно хорошего качества/расшатан разъем/кастомная прошивка + недостаточно прав на телефоне. Если приложение первый раз запускается - то проблема не в настройках IDE. Попробуйте сделать следующее: Подключите телефон по USB Перейдите в папку platform-tools, лежит в Android SDK. У меня например такой путь: F:\18.0\PlatformSDKs\android-sdk-windows\platform-tools. Откройте окно команд (зажимаете "Shift" + правая кнопка мыши -> "Открыть окно команд"). Выполните "adb devices" - отобразиться список подключенных устройств. Выполните "adb shell su 0 setenforce 0" - на телефоне может появится окно запроса прав.
  10. Ingalime этой настройкой нельзя управлять программно по политики безопасности системы. Из приложения программно можно лишь проверить эту галочку и предложить пользователю открыть эти настройки. Есть 2 решения: (самый простой способ) не отправлять уведомление с сервера. Т.к. у Вас устройства хранятся в таблице, то необходимо просто добавить туда новый столбец (например "PushEnabled") и изменить sql запрос, которым выбираете токены устройств с БД. PHP код в этом случае не затрагивается. (если править сервер невозможно или у вас нет доступа) запретить уведомления в BroadcastReceiver, который их обрабатывает и непосредственно создает уведомление в статус баре (приложение свернуто/закрыто) или передает обработку в код FMX (приложение открыто). 2-ой способ является не тривиальным, т.к. требуется изменить стандартную библиотеку FMX cloud-messaging.jar, либо написать свой собственный BroadcastReceiver и его использовать в проекте + придется использовать SharedPreferences, чтобы хранить флаг состояния уведомлений для BroadcastReceiver. Я рекомендую воспользоваться первым способом. Опишите логику "включения/отключения" пушей, по каким правилам и где изменяется эта настройка, чтобы легче было Вам помочь.
  11. Дело в том, что TComboBox лишь контейнер, вам нужно обращаться именно к списку элементов в ListBox. Чтобы запретить перевод можно поступить так: var i, count : integer; begin count := cbbFiles.Count - 1; for i := 0 to count do cbbFiles.ListBox.ListItems[i].AutoTranslate := False; end;
  12. У стандартного TListView уже все есть: //устанавливаем режим редактирования у списка либо в редакторе свойств выставляем ListView1.EditMode := True; //... //Получаем список всех выбранных элементов ListView1.Items.CheckedIndexes(true); //обращаться к свойству текущего элемента так: ListView1.Items.SetChecked(const Index: Integer; const Value: Boolean); ListView1.Items.GetChecked(const Index: Integer): Boolean;
  13. Для таких таблиц лучше ее рисовать на ListView. Пока не видел достойных гридов для Андроид. Пример реализации:
  14. Для открытия файла лучше пользоваться не: TNSURL.Wrap (TNSURL.OCClass.URLWithString (StrToNSStr (PChar (URL)))); а: TNSUrl.Wrap(TNSUrl.OCClass.fileURLWithPath(StrToNSStr(path)));
  15. Думаю для старта Вам хватит этого sample. Код писал на старой XE7 и сейчас требуются правки, но для понимания подойдет. Если будут вопросы - пишите.
  16. Да, Вы правы, у приложения и сервиса общий только Context, обмен инфой возможен только стандартными способами Android.
  17. 1. TMS iCL 2. DPF- смотрите в сторону TDPFQLPreviewController 3. Ручками, что-то вроде такого (документация apple): var controller : UIDocumentInteractionController; URL: NSURL; {$ENDIF} path : string; temp : Boolean; begin path := ExtractFilePath(ParamStr(0)) + '/Sample.pdf'; {$IFDEF IOS} URL := TNSUrl.Wrap(TNSUrl.OCClass.fileURLWithPath(StrToNSStr(path))); controller := TUIDocumentInteractionController.Wrap( TUIDocumentInteractionController.OCClass.interactionControllerWithURL(URL)); TNSUrl.Wrap(TNSUrl.OCClass.fileURLWithPath(StrToNSStr(path))); temp := controller.presentOpenInMenuFromRect( WindowHandleToPlatform(self.Handle).View.frame, WindowHandleToPlatform(self.Handle).View,true); {$ENDIF} end;
  18. 1. Возможно я где-то пропустил в теме, но зачем держать соединение в сервисе ? 2. Связать можно как и обычно, из вашего приложения доступен DM сервиса, на котором может находится TMemData. 3.Опишите пожалуйста более подробнее задачи, которые перед Вами стоят, тогда ответы будут более продуктивны. Данная тема скорей всего архитектурный вопрос, а не вопрос потребления памяти.
  19. Один из вариантов открытия одного приложения из другого - это использование URL schemes (Ярослав давал выше ссылку). Из приложение А: //отправка uses Macapi.Helpers, FMX.Helpers.iOS; //делаем намерение открыть URL (по сути тоже самое Intent в Android) SharedApplication.openURL(StrToNSUrl(Url)); Приложение Б (подробнее, хотя немного устарело): //подписываемся на события if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(aFMXApplicationEventService)) then aFMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent); //обработчик function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; var lURL : string; begin case AAppEvent of TApplicationEvent.OpenURL : begin lURL := (AContext as TiOSOpenApplicationContext).URL; //реализуем логику end; Как передать файлы я вижу несколько вариантов: - использовать буфер обмена (класс UIPasteboard - думаю не сложно его использовать в FMX, я им пользовался только в Xamarin, на FMX возможно (нужно проверить) можно использовать FMX.Platform.IFMXClipboardService). Перед открытием URL в "А" - сохраняем картинку/файл в буфер обмена, в "Б" при открытии считываем. - передавать в URL путь к файлу (это возможно только, если и "А" и "Б" являются приложением одной группы). пример с Object-C.
  20. Для Android достаточно в приложении "Дочка" обработать стартовый Intent: uses System.StartUpCopy, Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText; ... var Intent: JIntent; lStartIndex : Integer = -1; begin Application.Initialize; Intent := TAndroidHelper.Activity.getIntent; if (Intent <> nil) and (Intent.getExtras <> nil) and Intent.getExtras.containsKey(StringToJString('START_FORM')) then begin lStartIndex := Intent.getExtras.getInt(StringToJString('START_FORM')); end; //создание нужной формы в зависимости от lStartIndex Для мобильных платформ я бы советовал использовать TFrame, вместо TForm, оперирую лишь одной главной формой. Много форм оставьте для VCL.
  21. При реализации OAuth 2.0 при помощи TWebBrowser главное отследить Redirect. В случае успешной авторизации в URL будет содержаться необходимый токен. Посмотрите в сторону использования вот этих форм (находятся в ..\source\data\rest): {$IFDEF MSWINDOWS} REST.Authenticator.OAuth.WebForm.Win {$ELSE} REST.Authenticator.OAuth.WebForm.FMX {$ENDIF} У них есть событие: property OnAfterRedirect: TOAuth2WebFormRedirectEvent read FOnAfterRedirect write FOnAfterRedirect; TOAuth2WebFormRedirectEvent = procedure(const AURL: string; var DoCloseWebView : boolean) of object; Вот обработчик: procedure TframeAutch.AfterRedirect(const AURL: string; var DoCloseWebView: boolean); var i:integer; Str: string; Params: TStringList; begin i := pos('#access_token=',AURL); if (i>0) then begin Str := AURL; Delete(Str,1,i); Params:=TStringList.Create; try Params.Delimiter:='&'; Params.DelimitedText := Str; token := Params.Values['access_token']; DoCloseWebView := True; finally Params.Free; end; end; end; **Код выше из XE7, сейчас мб что-то изменилось. Использовал такой подход для авторизации в vk, facebook, google+. ***Если нужно, могу сделать демку, но это только на выходных.
  22. Общая схема такая: 1. Регистрация своего приложения в API соцсетей (facebook, vk). 2. Реализуете в своем приложении авторизацию через OAuth 2.0: - можно использовать легкий вариант через WebBrowser, т.о. образом сразу поддерживая Android/IOS. - можно сделать красиво, используя "Intent" и "startActivityForResult". - можно использовать SDK соцсетей, но это совсем другая история... 3. После регистрации сохраняем токен, при помощи которого мы можем через API автоматически постить сообщения. Учитываем здесь время действия токена, периодически его обновляя.
  23. 1. Перед подобными вызовами активностей с указанием пакета, всегда рекомендуется проверять наличие их в системе: //получаем список пакетов, которые могут обработать ваше намерение tempList := TAndroidHelper.Activity.getPackageManager. queryIntentActivities(Intent); //стартуем только в случае наличия пакета if tempList.size > 0 then TAndroidHelper.Activity.startActivity(Intent); 2. При отправке сторонним приложениям файлов (изображения в частности) всегда рекомендуется создавать копию изображения: а) с УНИКАЛЬНЫМ именем - необходимо для разрешения проблем с кешированием в других приложениях. Например Facebook кеширует по имени и при повторном вызове не обновляет; б) сохранять нужно в CacheDir, т.к. другим приложениям может попросту не быть доступа к файлу вашего приложения (использование Uri обязательно). 3. Т.к. у подобных приложений шарингом занимаются отдельные активности, то не забудьте про флаги NewTask | ClearTask у намерения. п.с. Не забудьте потом периодически удалять свой кеш.
  24. Необходимо использовать TJContext.JavaClass.NOTIFICATION_SERVICE вместо TJActivity.JavaClass.NOTIFICATION_SERVICE Для получения менеджера лучше использовать контекст (данный код работает на версии 4.4 и 5+): function GetNotificationService: JNotificationManager; var NotificationServiceNative: JObject; begin NotificationServiceNative := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.NOTIFICATION_SERVICE); Result := TJNotificationManager.Wrap((NotificationServiceNative as ILocalObject).GetObjectID); end;
×
×
  • Создать...