• 0
Andrew

TForm на планшетах Android

Вопрос

Для проведения опытов на Delphi XE8 использовал два планшета Android:

- Lenovo TAB S8-50LC на базе процессора Intel Atom Z3745: http://www.ixbt.com/portopc/lenovo-tab-s8-50lc.shtml. На нем установлен Android версии 4.4.2. Подключил к USB и, как не странно, тестовая программка "Hello World!" успешно запустилась, хотя думал, что с процессором Intel вообще ничего не получится;

- Prestigio Multipad PMT5777_3G с процессором ARM MediaTek MT8382. На нем установлен Android 4.2.2.

Затем на форму красного цвета бросил зеленый TRectangle, присвоил Align значение Client, а также добавил желтую рамку с помощью свойства Stroke (Thinkness=10). Запустил на Prestigio - выглядит нормально, если не считать не дорисованных уголков (см. красные квадраты). Кстати, на Windows уголки рамки отображаются нормально.

 

MainForm.Top = 25 - видимо, смещение от статус-бара.

 

prestigio_1.png

 

 

Затем запустил на Lenovo и результат получился не такой красивый. Как видим, верх формы почему-то "уехал" за статус-бар, а ее свойство Top равно 0:

 

lenovo_1.png

 

------------------------------------------------------------------------------------------------------------------------------------

 

Поворачиваем планшеты на 90 градусов. На Prestigio все выглядит нормально:

 

prestigio_2.png

 

 

На Lenovo произошло какое-то расстройство:

 

lenovo_2.png

 

 

Как я понял, на Lenovo возникают проблемы с получением высоты статус-бара и размеров экрана при повороте планшета, но с чем это связано - непонятно. Возможно решение где-то в FMX.Platform.Android или глубже. По крайней мере там переменная FStatusBarHeight равна нулю.

На моем примере ниже можно получить правильные размеры и позицию для формы (в т.ч. с учетом статус-бара):

NativeWin := SharedActivity.getWindow;
if NativeWin <> nil then
begin
ContentRect := TJRect.Create;
DecorView := NativeWin.getDecorView;
DecorView.getWindowVisibleDisplayFrame(ContentRect);
end;

Изменено пользователем Andrew

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

4 ответа на этот вопрос

  • 0

написано же что в данный момент не поддерживается прямая работа с процессорами intel. то что у вас работает то это через эммулятор арм команд а соответственно возможны любые глюки. в 9 версии в планах было что сделают а сделают или нет хз. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

В Magnum Labs опубликовали решение проблемы с отображением верхней части формы для Android-устройств с процессором Intel x86. Раньше она уезжала под статус бар. Как и предполагалось, требуется внести поправки в FMX.Platform.Android.

lenovo_2b.jpg

 

Для устранения проблемы необходимо:
==================================
1) скопировать файл FMX.Platform.Android.pas в папку с проектом;
2) внести заменить "родную" функцию
function TWindowManager.RetrieveContentRect: TRect; на приведенную ниже и перекомпилировать проект:

 

function TWindowManager.RetrieveContentRect: TRect;
var
Activity: JActivity;
NativeWin: JWindow;
DecorView: JView;
ContentRectVisible, ContentRect: JRect;
begin
Activity := SharedActivity;
if Activity <> nil then
begin
NativeWin := Activity.getWindow;
if NativeWin <> nil then
begin
FStatusBarHeight := FNewContentRect.Top;
ContentRect := TJRect.Create;
DecorView := NativeWin.getDecorView;
DecorView.getDrawingRect(ContentRect);
// Fix by Flying Wang &
CallInUIThread(
procedure
begin
if (not PlatformAndroid.GetFullScreen(nil)) and
(SharedActivity.getWindow.getAttributes.Flags and
TJWindowManager_LayoutParams.JavaClass.FLAG_FULLSCREEN <>
TJWindowManager_LayoutParams.JavaClass.FLAG_FULLSCREEN) then
begin
// http://www.2cto.com/kf/201307/227536.html
ContentRectVisible := TJRect.Create;
DecorView.getWindowVisibleDisplayFrame(ContentRectVisible);
if (ContentRect.Top < 1) or
(ContentRectVisible.Top < FStatusBarHeight) then
begin
ContentRect.Top := ContentRectVisible.Top;
FNewContentRect.Top := ContentRectVisible.Top;
FStatusBarHeight := FNewContentRect.Top;
end;
end;
end);
Result := TRect.Create(Round(FNewContentRect.Left / FScale),
Round(FNewContentRect.Top / FScale), Round(ContentRect.Right / FScale),
Round(ContentRect.Bottom / FScale));
end;
end;
end;

 

Ссылка на источник: https://magnumlabs.wordpress.com/2015/10/10/delphiandroid-misalignment-status-bar-on-intel-based-devices/

Изменено пользователем Andrew

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Нашел и устранил последнюю проблему планшета Lenovo TAB S8-50LC (CPU Intel Atom). Не исключаю, что подобная проблема возникает и на других устройствах.

 

При изменении ориентации устройства картинка поворачивается моментально. Возможно поэтому в 9 случаях из 10 программа не успевала на это правильно реагировать и форма в портретной ориентации отображалась как альбомная и наоборот. В общем, это выглядело крайне неприятно:

 

lenovo_2.jpg

 

Нужно в процедуре "TPlatformAndroid.HandleAndroidCmd(ACmd: Int32);" найти строки:

===============
APP_CMD_CONFIG_CHANGED:
begin
FContentRectMightHaveChanged := ContentRectChangeRefreshCount;  // <<---- !!!!
FOrientationMightHaveChanged := True;
Include(FAppCmdStates, TAndroidAppCmdState.ConfigChanged);
end;

===============

и в отмеченной строке умножить ContentRectChangeRefreshCount на 3 или 4: FContentRectMightHaveChanged := ContentRectChangeRefreshCount * 4;

 

После этой поправки и исправлений от "Magnum Labs" (см. выше) форма отображается правильно, сколько планшет не крути. На скорость работы приложения это никак не отразилось. Проверялось также на нескольких аппаратах Samsung.

 

lenovo_2c.jpg

 

Если будет интересно, в следующий раз расскажу как устранить проблему ненужного появления NavigationBar если кликнуть по TMediaPlayerControl или TWebBrowser, а также странной анимации появления/скрытия указанных компонент при изменении их свойства Visible. Проблема с NavigationBar касается устройств, у которых имеется SoftKey.

Изменено пользователем Andrew

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Похожие публикации

    • Автор: Рагим
      Доброго времени суток. Пишу мобильное приложение на Delphi Berlin. Добавил вибрацию при нажатии на кнопку. На Андроид 4.4.2 все работает нормально, на Андроид 6 при нажатии на кнопку приложение вылетает. Проблема точно в вибрации, так как при отсутствии вибрации все работает нормально. В качестве процедуры вибрации использую следующий код:
      procedure Vibr; //Процедура вибрации var   VibratorObj: JObject;   Vibrator: JVibrator; begin   VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);   Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);   if Vibrator.hasVibrator() then     Vibrator.vibrate(200); end;  
      Как по Вашему, в чем может быть причина?
    • Автор: rakhmet
      Что это (alert, message, notify, etc.)? И как этим можно воспользоваться на Android?

    • Автор: rakhmet
      Можно ли на Delphi определить, способно устройство звонить или нет? Понадобилось определить, чем является устройство - телефоном, планшетом, или каким-нибудь мутантом, чтобы автоматически скрывать кнопку "Набрать номер" на тех устройствах, которые не умеют звонить.
    • Автор: gresaggr
      Как избежать повторных нажатий/ закликиваний на кнопку?
      Имеется следующий код:
      procedure Tfm.ButtonPrevCardClick(Sender: TObject);
      begin
        ButtonPrevCard.Enabled := false;
        Application.ProcessMessages;

       // здесь код по смене карты + пауза в 2 секунды

        ButtonPrevCard.Enabled := true;
        Application.ProcessMessages;
      end;
      Под Windows повторных нажатий/закликиваний при этом не происходит.
      А под Андроид, если пользователь быстро подряд нажал несколько раз, то сработает также несколько раз.
       
    • Автор: Pax Beach
      Я использую принудительную ориентацию экрана на Android устройстве.
      Что это означает?
      Когда открывается приложение, экран переворачивается в то положение, которое я устанавливаю по умолчанию, или которое было установлено в настройках приложения (состояние читается при запуске приложения).
      Приведу пример кода, как я его написал. Здесь что-то лишнее, что-то может стоит доработать.
      Есть две проблемы в примере:
      1. Чтобы изменить ориентацию экрана, приходится закрывать (уничтожать) приложение, а потом открывать заново.
      2. Когда стоит режим ландшафт, то срабатывает автоматический переворот экрана по сенсору, когда поворачиваешь экран на 180 градусов. А когда стоит режим портрет, автоматически экран не переворачивается.
       
      В настройках проекта так:

       
      В Object inspector для главной формы так:

       
      В модуле проекта вот так:
      begin Application.Initialize; TAndroidHelper.Activity.getWindow.addFlags (TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON); Application.FormFactor.Orientations := [TFormOrientation.Portrait, TFormOrientation.InvertedPortrait, TFormOrientation.Landscape, TFormOrientation.InvertedLandscape]; Application.CreateForm(TDM, DM); Application.CreateForm(TfmMain, fmMain); VKAutoShowMode := TVKAutoShowMode.Always; Application.Run; end.  
      В модуле главной формы:
      procedure TfmMain.FormShow(Sender: TObject); begin if DM.setOrientation(TAndroidHelper.Activity) then Invalidate; end;  
      В дата-модуле вот так:
      function TDM.setOrientation(Activity: JActivity): boolean; var orient: Integer; begin result := False; if DM.GetSettingsBoolean('IsOrientationLandshaft', true) then orient := TJActivityInfo.JavaClass.SCREEN_ORIENTATION_SENSOR_LANDSCAPE else orient := TJActivityInfo.JavaClass.SCREEN_ORIENTATION_SENSOR_PORTRAIT; try if Activity.getRequestedOrientation <> orient then begin Activity.setRequestedOrientation(orient); result := true; end; except result := False; end; end;  
       
    • Автор: dmokrushin123
      На устройство с IOS сообщения приходят и через Kinvey и через FCM (Firebase Cloud Messaging).
      На Android возвращается Token, сами уведомления НЕ приходят. 
       
       
       
       
       
       
    • Автор: notricky
      Почему-то код, исправно работающий для WIN, не работает на ANDROID.
      procedure AssignEventToComponent(C: TComponent; MethodName: String; const Evt: TNotifyEvent; OnlyIfNil: boolean = true); var M: TMethod; begin M := GetMethodProp(C,MethodName); if not OnlyIfNil or (M.Code = nil) then begin TNotifyEvent(M) := Evt; SetMethodProp(C,MethodName,M); end; end; Есть какие-то особенности работы TMethod для ANDROID?
    • Автор: lala4a
      Доброе время суток .
      Я только начал знакомится с потоками , не судите строго .
      Вот код . Смысл которого через отдельный поток загружать изображение с сервера .
      unit Unit5; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,iduri,idhttp, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.Controls.Presentation, FMX.StdCtrls; type ThreadHTTP=class(TThread) private Stream:TMemoryStream; bmp:tbitmap; url:string; public constructor Create(abmp:tbitmap; aurl: String); procedure Execute;override; // procedure ShowResult; end; type TForm5 = class(TForm) Button1: TButton; Image1: TImage; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } procedure getpic(pic: string; img: Tbitmap); end; var Form5: TForm5; implementation {$R *.fmx} constructor ThreadHTTP.Create(abmp:tbitmap;aurl:string); begin inherited Create(false); bmp := abmp; url:=aurl; end; procedure ThreadHTTP.Execute; var j:integer; idhttp : TIdHTTP; ms:tmemorystream; png:tbitmap; begin ms := TMemoryStream.Create; IdHTTP := TIdHTTP.Create(nil); url:=TIdURI.URLEncode(url); try idhttp.Get(url,ms); ms.Position := 0; finally bmp.LoadFromStream(ms); idhttp.Free; ms.Free; end; end; procedure TForm5.Button1Click(Sender: TObject); begin getpic('krovat1',form5.Image1.Bitmap); end; procedure TForm5.getpic(pic: string; img: Tbitmap); var zapros:string; idhttp:tidhttp; MyHTTP:ThreadHTTP; begin zapros:='http://127.0.0.1/getimage_'+pic; MyHTTP:=ThreadHTTP.Create(img,zapros); MyHTTP.FreeOnTerminate := true; MyHTTP.resume; end; end. Код корявый , но работает в win32 .  В Android ничего не происходит .
      Помогите разобраться , пожалуйста .
       
    • Автор: ivadimos
      Пытаюсь опубликовать приложение в Гугл маркет.
      Присылают ответ на почту.

      OpenSSL
      The vulnerabilities were addressed in OpenSSL 1.02f/1.01r. To confirm your OpenSSL version, you can do a grep search for:
      $ unzip -p YourApp.apk | strings | grep "OpenSSL"
      You can find more information and next steps in this Google Help Center article.
      Но ведь я не использую никакой работы с сетью и т.д, только firedac и sqlite
    • Автор: Rusland
      Имеется форма с Edit, в котором набран IP-адрес 192.168.1.12
      Если попробовать долгим тапом выделить весь текст (для копирования), то выделяется только какая-то одна цифра. Весь текст никак не выделить. Тоже самое будет, если вместо точек поставить любые другие знаки препинания или пробел. Как решить эту проблему?
       
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу