DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: laidabin
今日帖子: 3
在线用户: 28
导航: 论坛 -> 移动应用开发 斑竹:flyers,iamdream  
作者:
男 bamboocaep (bamboocaep) ★☆☆☆☆ -
普通会员
2014/7/18 15:40:37
标题:
FireMonkey下android系统设置屏幕缩放比例失效的原因及解决方法 浏览:3161
加入我的收藏
楼主:
BambooCaep原创,转载请注明。

目前许多手机的屏幕分辨率大小不一,可以相差两三倍,但是屏幕尺寸并不会同比增加。为了使得显示出的界面能够适应不同的分辨率,英巴在FMX平台使用了

TWindowManager.Scale这个属性来进行屏幕缩放调整。

在FMX.Platform.Android.pas文件里,是使用SetScreenScaleOverrideHook来更改屏幕缩放比例的。

type
  TScreenScaleOverrideHook = procedure(const UserContext: Pointer; const DensityScale, DensityDPI: Single;
    var ScreenScale: Single);

procedure SetScreenScaleOverrideHook(const UserContext: Pointer; const Hook: TScreenScaleOverrideHook);
begin
  ScreenScaleOverrideHook := Hook;
  ScreenScaleOverrideHookContext := UserContext;
end;

function TPlatformAndroid.GetScreenScale: Single;
const
// Default values taken from Android SDK reference:
//   http://developer.android.com/reference/android/util/DisplayMetrics.html#density
  DefaultDensityScale = 1;
  DefaultDensityDPI = 160;
var
  Metrics: JDisplayMetrics;
  DensityScale, DensityDPI: Single;
begin
  if SameValue(FScreenScale, 0, TEpsilon.Scale) then
  begin
    Metrics := GetJDisplayMetrics;
    if Assigned(Metrics) then
    begin
      DensityScale := Metrics.density; // API level 1
      DensityDPI := Metrics.densityDpi; // API level 4
    end
    else
    begin
      DensityScale := DefaultDensityScale;
      DensityDPI := DefaultDensityDPI;
    end;

    FScreenScale := DensityScale;

    if Assigned(ScreenScaleOverrideHook) then
    begin
      ScreenScaleOverrideHook(ScreenScaleOverrideHookContext, DensityScale, DensityDPI, FScreenScale);

      if FScreenScale < 1 then
        FScreenScale := 1
      else if FScreenScale > 3 then
        FScreenScale := 3;
    end;
  end;

  Result := FScreenScale;
end;


constructor TWindowManager.Create;
begin
  ......
  FScale := PlatformAndroid.GetScreenScale;
  ......
end;


看起来相当美好。然而下述代码并不能生效,引用该单元后屏幕缩放比例并未改变。

unit TestScreenScale;

uses
  FMX.Platform.Android;

implementation

procedure MyHook(const UserContext: Pointer; const DensityScale, DensityDPI: Single;
    var ScreenScale: Single);
begin
  ScreenScale := ScreenScale / 2;
end;

initialization

SetScreenScaleOverrideHook(nil, MyHook);

end.

原因就在于,调用SetScreenScaleOverrideHook必须引用FMX.Platform.Android。而FMX.Platform.Android引用了FMX.Platform,但是FMX.Platform在初始化时调用了

RegisterCorePlatformServices方法,在Android系统下就是调用FMX.Platform.Android里面的RegisterCorePlatformServices方法。
于是,在我们SetScreenScaleOverrideHook之前,PlatformAndroid实例已经被创建了。

constructor TPlatformAndroid.Create;
begin
  ......
  PlatformAndroid := Self;
  TWindowManager.Current;
  ......
end;

于是,TWindowManager也有了实例,不会再创建。

结果就是:在我们SetScreenScaleOverrideHook之前,就已经注定不会再使用到这个Hook了!


解决方法倒是简单:
procedure SetScreenScaleOverrideHook(const UserContext: Pointer; const Hook: TScreenScaleOverrideHook);
begin
  ScreenScaleOverrideHook := Hook;
  ScreenScaleOverrideHookContext := UserContext;
  PlatformAndroid.FScreenScale := 0; //保证GetScreenScale时会重新计算
  TWindowManager.Current.FScale := PlatformAndroid.GetScreenScale; //重新获取Hook后的Scale。
end;
----------------------------------------------
-
作者:
男 wang_80919 (Flying Wang) ★☆☆☆☆ -
普通会员
2014/7/18 17:03:07
1楼: bug 修复的不错。谢谢。
----------------------------------------------
(C)(P)Flying Wang
作者:
男 tintin1943 (零输好) ★☆☆☆☆ -
盒子活跃会员
2014/7/18 19:04:39
2楼: 感谢共享!
----------------------------------------------
不喧哗 自有声 心静 思远 志行千里
作者:
男 happyhills (老妖) ▲▲▲▲△ -
普通会员
2014/7/21 18:36:57
3楼: 英巴公司已经决定聘用你们了(楼上)。赶快拨打电话4008000000
----------------------------------------------
-文科男,程序员。
作者:
男 fky1989 (fky1989) ▲▲▲▲▲ -
普通会员
2014/9/30 9:03:40
4楼: 感谢!
----------------------------------------------
-
作者:
男 changson (changson) ▲▲▲▲△ -
普通会员
2014/10/1 18:33:47
5楼: 楼主的发见
谢分享~
----------------------------------------------
-
作者:
男 dreamskr (凌风) ★☆☆☆☆ -
普通会员
2015/4/7 11:25:40
6楼: 还是不会用
----------------------------------------------
-
作者:
男 bamboocaep (bamboocaep) ★☆☆☆☆ -
普通会员
2015/4/7 11:28:43
7楼: procedure Hook_Scale(const UserContext: Pointer; const DensityScale, DensityDPI: Single; var ScreenScale: Single);
begin
  ScreenScale := 1;
end;

initialization

SetScreenScaleOverrideHook(nil, Hook_Scale);
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行60.54688毫秒 RSS