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

Равиль Зарипов (ZuBy)

Модераторы
  • Постов

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

  • Посещение

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

    264

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

  1. Like
    Равиль Зарипов (ZuBy) отреагировална Rusland в "Общение" сервиса и приложения через intent   
    Для ищущих ответа:
    Есть стандартное demo Object Pascal\Mobile Snippets\AndroidIntents\AndroidIntentsGroup.groupproj, в котором показано как из одного приложения передавать данные другому. С помощью этого примера удалось передавать данные из сервиса в основное приложение.
    В юните основного приложения пишем:
    uses FMX.Platform, FMX.Platform.Android, Androidapi.JNI.JavaTypes, Androidapi.JNI.Net, Androidapi.JNI.Os, Androidapi.Helpers, System.Messaging, Androidapi.JNI.GraphicsContentViewText; private { Private declarations } function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; procedure HandleActivityMessage(const Sender: TObject; const M: TMessage); function HandleIntentAction(const Data: JIntent): Boolean; procedure TForm1.FormCreate(Sender: TObject); var AppEventService: IFMXApplicationEventService; begin ... if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, AppEventService) then AppEventService.SetApplicationEventHandler(HandleAppEvent); // Register the type of intent action that we want to be able to receive. // Note: A corresponding <action> tag must also exist in the <intent-filter> section of AndroidManifest.template.xml. MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_VIEW); TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage); end; procedure TForm1.HandleActivityMessage(const Sender: TObject; const M: TMessage); begin if M is TMessageReceivedNotification then HandleIntentAction(TMessageReceivedNotification(M).Value); end; function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; var StartupIntent: JIntent; begin Result := False; if AAppEvent = TApplicationEvent.BecameActive then begin StartupIntent := MainActivity.getIntent; if StartupIntent <> nil then HandleIntentAction(StartupIntent); end; end; function TForm1.HandleIntentAction(const Data: JIntent): Boolean; var Extras: JBundle; begin Result := False; if Data <> nil then begin Memo1.ClearContent; // записываем в Memo пришедшее сообщение Extras := Data.getExtras; if Extras <> nil then Memo1.Text := JStringToString(Extras.getString(TJIntent.JavaClass.EXTRA_TEXT)); Invalidate; end; end; в AndroidManifest.template.xml добавляем 
    <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:mimeType="text/pas" /> Отправка сообщения из сервиса делается так:
    SendTextViaIntent('Hello from service'); procedure TAndroidServiceDM.SendTextViaIntent(const AText: string); var   Intent: JIntent; begin   Intent := TJIntent.Create;   Intent.setType(StringToJString('text/pas'));   Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);   Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // добавил такой флаг, без  него сервис затыкался   Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(AText));   if  TJContextWrapper.Wrap(System.JavaContext).getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then      TJContextWrapper.Wrap(System.JavaContext).startActivity(Intent); // заменил MainActivity на TJContextWrapper.Wrap(System.JavaContext), т.к. это сервис end; Работает исправно, хоть 100%-ую правильность кода не гарантирую  Но как передать сообщение из основной программы обратно в сервис я пока не знаю. Также делать хендл внутри сервиса? 
    Попытался просто добавить FMX.Platform, в результате получаю ошибку в FMX.Platform.Android вываливается ошибка об использовании Activity внутри сервиса.
  2. Like
    Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в [Android] Как изменить цвет системного статус бара и разместить контролы под ним?   
    Поскольку тема вызывает не поддельный интерес у пользователей. Я расскажу, как это делал я для одной демо программы, которую я готовил для выступления в ИТМО. Сразу приложу скриншот, как это будет выглядеть:

     
    Сразу скажу, что это решение временное и имеет ряд определенных нюансов, которые появятся после его использования. О том, как исправить эти нюансы указано в самом конце.
    Теперь к делу. Андроид позволяет сделать статус бар прозрачным с наложением белого цвета с альфа каналом. Это значит, если мы разместим под статус баром зеленый цвет, то статус бар станет соответствующего темно зеленого цвета. Этим и воспользуемся. Основная идея такая:
    Говорим Андроиду, что хотим прозрачный статус бар. Указываем андроиду, что хотим размещать форму под статус баром. Размещаем под статус баром TRectangle нужного цвета, в тон TToolBar (если используете) Теперь по шагам:
     
    1. Говорим Андроиду, что хотим прозрачный статус бар. Указываем андроиду, что хотим размещать форму под статус баром.
    Создаем файл style.xml со стилем для нашего приложения.
    <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="AppTheme" parent="@android:style/Theme.Holo.Light"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> <item name="android:windowBackground">@drawable/splash_image_def</item> <item name="android:windowNoTitle">true</item> </style> </resources> В стиле указываем, что мы хотим использовать прозрачный статус бар.
     
    Открываем Менеджер развертывания Menu->Project->Deployment Manager и добавляем наш файл стиля в проект только для андроид конфигураций:

    Remote Path: "res\values\" Remote Name: "styles.xml" Теперь при запуске программы, андроид будет считать, что:
      Приложение будет развернуто на весь экран Статус бар будет прозрачного цвета. 3. Размещаем под статус баром TRectangle нужного цвета, в том TToolBar (если используете)
    Я разместил вверху формы TRectangle, который залил требуемым цветом, в тон тул бару:

    Высота статус бара у андроида равна 24.
     
    Если вы делаете кроссплатформенный проект и для ios тоже, то по умолчанию скрываем этот прямоугольник и добавляем код по его отображению в конструктор формы только на андроиде
    constructor TFormMain.Create(AOwner: TComponent); begin inherited Create(AOwner); {$IFDEF ANDROID} SystemStatusBarBackground.Visible := True; {$ENDIF} end; В принципе все готово.
     
    Побочные эффекты
     
    По скольку это решение сделано сбоку, то пара моментов, которые придется в вашей программе следить:
    Нативные контролы распологаются по старому, полагая, что форма располагается под статус баром, а не под формой. Поэтому для нативных контролов таких, как TMapView, нужно корректировать позицию или отступы. {$IFDEF ANDROID} MapView.Margins.Top := -SystemStatusBarBackground.Height; {$ENDIF} Формы располагается так же и под нижними программными кнопками: Назад, домой и меню. Поэтому нужно так же иметь в виду, что расположенные снизу контролы, не будут кликабельны. Так как перекрываются нижней панелью с кнопками. Решение - это разместить TLayout под нижней панелью, чтобы сдвинуть ваши контролы к верху.
  3. Like
    Равиль Зарипов (ZuBy) отреагировална FeLDMARShaL в Режим звонка   
    В обычном режиме приложение выглядит хорошо и правильно. Однако если кто топозвонить, и пользователь свернет звонок и вернется в приложение, то можно наблдать следующий баг.
                                
  4. Like
    Равиль Зарипов (ZuBy) отреагировална zairkz в Режим звонка   
    Такое же поведение наблюдается если включить на Iphone режим модема, и к Iphone подключить хотя бы одно устройство. Но пока понятия не имею что с этим сделать. 
  5. Like
    Равиль Зарипов (ZuBy) получил реакцию от Axbor в [TidHTTP] Почему IdHttp1.Get может выдавать 404 ошибку, файл не найден?   
    function idHttpGet(const aURL: string): string; // uses System.Net.HttpClient, System.Net.HttpClientComponent, System.Net.URLClient; var Resp: TStringStream; Return: IHTTPResponse; begin Result := ''; with TNetHTTPClient.Create(nil) do begin Resp := TStringStream.Create('', TEncoding.ANSI); Return := Get( { TURI.URLEncode } (aURL), Resp); Result := Resp.DataString; Resp.Free; Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(idHttpGet('http://airnav.tj/ru/online/utdd')); end; Держи
  6. Like
    Равиль Зарипов (ZuBy) получил реакцию от Vitaldj в [TidHTTP] Почему IdHttp1.Get может выдавать 404 ошибку, файл не найден?   
    function idHttpGet(const aURL: string): string; // uses System.Net.HttpClient, System.Net.HttpClientComponent, System.Net.URLClient; var Resp: TStringStream; Return: IHTTPResponse; begin Result := ''; with TNetHTTPClient.Create(nil) do begin Resp := TStringStream.Create('', TEncoding.ANSI); Return := Get( { TURI.URLEncode } (aURL), Resp); Result := Resp.DataString; Resp.Free; Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(idHttpGet('http://airnav.tj/ru/online/utdd')); end; Держи
  7. Like
    Равиль Зарипов (ZuBy) получил реакцию от R.is в Как реализовать это?   
    Да пожалуйста, пользуйтесь.
    У Itema же есть Bitmap. Если нужно через инет, то нужно через хелпер тут не раз выкладывали
    Есть тема от меня в разделе TListView про динамическую загрузку картинок, посмотрите там.
  8. Like
    Равиль Зарипов (ZuBy) получил реакцию от Tom1984 в Динамическая подгрузка картинок в ListView   
    Привет Всем!
    Как принято в современных приложениях, догружать контент(обычно это картинки) при скролинге.
    я взял картинки пользователей этого форума

    Seattle LVdynamicLoadBitmap.zip
    Berlin LVdynamicLoadBitmap(Berlin).zip
  9. Like
    Равиль Зарипов (ZuBy) получил реакцию от DimArt в Как реализовать это?   
    что-то типа этого?

    demoLV.zip
  10. Like
    Равиль Зарипов (ZuBy) получил реакцию от HyperZen в Запрос на закрытие приложения при нажатии кнопки Назад   
    Если внимательно смотреть, то не бывает диалогов с одной кнопкой Yes, всегда OK
    case AResult of    mrOk: Close; end;
  11. Like
    Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в Как узнать поддерживаемый максимально допустимый размер изображения в TBitmap?   
    В FireMonkey TBitmap имеет верхнее ограничение на размеры хранимого изображения, ограниченные максимально допустимым размером текстур в текущей платформе. Узнать максимальную ширину и высоту можно так:
    var MaxWidthHeight: Integer; begin MaxWidthHeight := TCanvasManager.DefaultCanvas.GetAttribute(TCanvasAttribute.MaxBitmapSize); end;
  12. Like
    Равиль Зарипов (ZuBy) отреагировална krapotkin в Прочитать item'ы из listView   
    но лучше - не хранить данные в элементах интерфейса
  13. Like
    Равиль Зарипов (ZuBy) получил реакцию от zairkz в Поменять цвет статус бара Delphi [XE7] - Android   
    Возможно это работает также как и для IOS...
     
    У меня получилось


     
    Код не изменился, изменения были в форме...
    Нужно задать цвет
    Form1.Fill.Color := TAlphaColorRec.Red; Посередине я поставил Rectangle, чтобы цвет контента не был равен цвету форме.
    и снизу стоит Rectangle с черным цветом, т.к. у меня наэкранные кнопки.
    если убрать нижняя панель тоже покрасится.
     
    И теперь вопрос, кто знает как определить высоту наэкранных кнопок и их существование?
     
    P.S. Кривяков Виталий спасибо за модуль
  14. Like
    Равиль Зарипов (ZuBy) получил реакцию от Kitty в Поменять цвет статус бара Delphi [XE7] - Android   
    Возможно это работает также как и для IOS...
     
    У меня получилось


     
    Код не изменился, изменения были в форме...
    Нужно задать цвет
    Form1.Fill.Color := TAlphaColorRec.Red; Посередине я поставил Rectangle, чтобы цвет контента не был равен цвету форме.
    и снизу стоит Rectangle с черным цветом, т.к. у меня наэкранные кнопки.
    если убрать нижняя панель тоже покрасится.
     
    И теперь вопрос, кто знает как определить высоту наэкранных кнопок и их существование?
     
    P.S. Кривяков Виталий спасибо за модуль
  15. Like
    Равиль Зарипов (ZuBy) отреагировална Кривяков Виталий в Поменять цвет статус бара Delphi [XE7] - Android   
    Да, тоже столкнулся с тем, что цвет становиться белым и не меняется.
    Вот версия без необходимости менять исходники.
    SystemBar.zip
  16. Like
    Равиль Зарипов (ZuBy) отреагировална zairkz в Поменять цвет статус бара Delphi [XE7] - Android   
    Может Ярослав подключится на досуге, всем надо бы такую штуку)
  17. Like
    Равиль Зарипов (ZuBy) отреагировална zairkz в показать 9-patch в TstyleObject   
    Сохраните ваш стиль, откройте блокнотом найдите нужный вам итем стиля, добавьте отступы например:
     
    SourceLink = <         item           CapInsets.Left = 8.000000000000000000           CapInsets.Top = 8.000000000000000000           CapInsets.Right = 8.000000000000000000           CapInsets.Bottom = 8.000000000000000000           SourceRect.Left = 208.000000000000000000           SourceRect.Top = 249.000000000000000000           SourceRect.Right = 248.000000000000000000           SourceRect.Bottom = 293.000000000000000000         end   после чего у вас дизайнере появиться дополнительная область выделения, по ней и настраивайте область для растягивания 
  18. Like
    Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в [TfgRichEdit]- компонент редактирования текста с поддержкой форматирования   
    Пока не знаю. Недавно оптимизировал скорость отрисовки. Теперь у меня документ занимает в ~2 раз меньше узлов дерева, чем до оптимизации. Сейчас работаю над оптимизацией плавной прокрутки на мобильных платформах. 
  19. Like
    Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в показать 9-patch в TstyleObject   
    Там же, в коллекции линка есть и отступы, они как раз и отвечают за размеры боковых и угловых областей, которые не растягиваются.
  20. Like
    Равиль Зарипов (ZuBy) отреагировална Antonyan в Можно ли у TListViewItem при добавлении его в TListView установить свойство Accessory в None?   
    Как вариант, можно просто скрыть его
     
    Procedure XXX;
    Var
         LItem : TListViewItem;
     
    begin
     
              LItem := YourListView.Items.Add;
              LItem.Objects.AccessoryObject.Visible:=false;
     
    end;
  21. Like
    Равиль Зарипов (ZuBy) получил реакцию от zairkz в Как правильно рисовать на канве?   
    спец) он один из разработчиков Firemonkey
  22. Like
    Равиль Зарипов (ZuBy) отреагировална Andrey Efimov в TListViewHorz   
    Axbor
    Всё нормально скачивается, на всякий случай сделал 30 дневное зеркало: http://rghost.ru/7KvGrv9K6
  23. Like
    Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в Как сделать вывод текста в верхнем/нижнем регистре для отображения математической степени или индекса?   
    Добрый день,

    Пока, к сожалению, нету поддержки стиля верхнего и нижнего регистров для текста. Поэтому вместо жонглирования TText, я бы сделал свой компонент. В нем достаточно будет только определить метод Paint для отрисовки текста. Дальше просто:
    TTextLayout используем для измерения размеров текста. Потом согласно расчетам, просто выводим в нужные позиции текст. Для вдохновения можно сделать по образу и подобию TText.

    Расчет размеров текста:
    ATextLayout.BeginUpdate; try ATextLayout.Text := Text; ATextLayout.WordWrap := False; ATextLayout.MaxSize := TSizeF.Create(1000, 1000); finally ATextLayout.EndUpdate; end; Result := ATextLayout.TextRect.Size; Вывод текста:
    либо так:
    AContext.Canvas.FillText(Bounds, Text, False, 1, [], TTextAlign.Leading); Либо через TTextLayout:
    ATextLayout.Render; Вам остается только добавить логику по вычислению позиции верхнего или нижнего регистра относительно основного текста.
  24. Like
    Равиль Зарипов (ZuBy) получил реакцию от МихаилЪ чайковЪ в TListViewHorz   
    Давно не хватало TListView в горизонтальной ориентации, например чтобы сделать вот такую картинку

     
    zairkz сделал стиль с применением 9-patch png "технологии"
     
    С помощью жестов показано как сделать "сквозной скрол"
    как писал dreamix
     
     
    P.S. по компоненту TListViewHorz, не успел все протестить как следует со всеми параметрами
    не правильно будет отображаться Header'ы и Поиск, основной функционал сохранен
    UPDATE:  LVStyledhorz.7z
  25. Like
    Равиль Зарипов (ZuBy) получил реакцию от Alisson R Oliveira в SuperObject vs JSON   
    Привет Всем!
     
    Решил поделится впечатлениями по работе с SuperObject'ом и родным JSON'ом
     
    тест был файла с 2000+ объектами в JSON файле
    структура файла была такая
    { "status":"OK", "last_id":"711", "objects":[ { "obj_id":"1", "obj_acc_id":"1", "obj_cat_id":"24", "obj_title":"13 магистраль", "obj_descr":"ЖК представляет собой комфортный дом, состоящий из 14 блок-секций (подъездов). Расположен в перспективном развивающемся районе по 13 Магистрали с удобным выездом как на левый берег, так и в старую часть города. Вблизи Жилого комплекса распологается новая школа, парк отдыха и культуры.", "obj_address":"ул. Мамышулы - 104, д. 16\/1", "obj_address2":null, "obj_url":"3fa07dd73be072b049529c80c7d74732", "obj_planet":"1", "obj_country":"1", "obj_region":"1", "obj_city":"292", "obj_lat":"51.141", "obj_lon":"71.4835", "obj_insert_dt":null, "obj_update_dt":null, "obj_editted":"0", "obj_updated":"0", "obj_deleted":"0", "obj_showed":"1", "obj_rating":"0", "obj_pro_top":"0", "obj_pro_selected":"0", "obj_pro_unix_dt":"0", "obj_partner":"0", "obj_parent_id":"0", "obj_has_child":"0", "obj_currency":"0" }, // тут далее 2000+ объектов ] } SuperObject  Время выполнения:  ~01:393
    JSON родной Время выполнения: ~01:690
     
    разница не особо ощутима, тем более если будет меньше объектов
     
    JSON родной
    function JSONParse(const aJSONData: string; const aMemo: TMemo): boolean; var aJSValue: TJSONValue; aJSObject, aJSObjArr: TJSONObject; aJSArray: TJSONArray; I: integer; begin Result := false; aJSValue := TJSONObject.ParseJSONValue(aJSONData) as TJSONValue; if Assigned(aJSValue) then begin aJSObject := aJSValue as TJSONObject; aMemo.Lines.Add('status: ' + aJSObject.GetValue('status').Value); if aJSObject.GetValue('status').Value = 'OK' then begin Result := true; if Assigned(aJSObject) then begin aJSArray := aJSObject.GetValue('objects') as TJSONArray; if Assigned(aJSArray) then begin Result := true; aMemo.Lines.Add('last_id: ' + aJSObject.GetValue('last_id').Value); aMemo.Lines.Add('count: ' + aJSArray.Count.ToString); for I := 0 to aJSArray.Count - 1 do begin aJSObjArr := aJSArray.Items[I] as TJSONObject; if Assigned(aJSObjArr) then begin aMemo.Lines.Add(aJSObjArr.GetValue('obj_id').Value + ',' + aJSObjArr.GetValue('obj_acc_id').Value + ',' + aJSObjArr.GetValue('obj_cat_id').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_title').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_descr').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_address').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_url').Value); end; end; end; end; end; aJSValue.Free; end; end; SuperObject
    function JSONSOParse(const aJSONData: string; const aMemo: TMemo): boolean; var xObject: ISuperObject; xCount, I: integer; sfmt: string; begin Result := false; xObject := SO(aJSONData); aMemo.Lines.Add('status: ' + xObject['status'].AsString); if xObject['status'].AsString = 'OK' then begin Result := true; xCount := xObject['objects'].AsArray.Length; aMemo.Lines.Add('count: ' + xCount.ToString); aMemo.Lines.Add('last_id: ' + xObject['last_id'].AsInteger.ToString); for I := 0 to xCount - 1 do begin aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_id"'].AsInteger.ToString + ',' + xObject['objects[' + I.ToString + ']."obj_acc_id"'].AsInteger.ToString + ',' + xObject['objects[' + I.ToString + ']."obj_cat_id"'].AsInteger.ToString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_title"'].AsString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_descr"'].AsString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_address"'].AsString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_url"'].AsString); end; end; end; Разница ощутима когда пишешь код, SO намного легче читать
     
    Подробней почитать и скачать SO
×
×
  • Создать...