使用软导航栏正确检测屏幕尺寸(Detecting screensize correctly with soft navigation bar)
我正在使用Xamarin在C#中开发一个应用程序。 我使用以下代码来检测设备屏幕大小:
var metrics = Resources.DisplayMetrics; int widthInDp = metrics.WidthPixels / Resources.DisplayMetrics.Density; int heightInDp = metrics.HeightPixels / Resources.DisplayMetrics.Density;
在具有物理导航按钮且没有软导航栏的设备(Samsung SM-E7000)上,此方法返回预期结果:
360dp x 640dp in portrait mode 640dp x 360dp in landscape mode
但是,在没有物理导航按钮但具有软导航栏(Nexus 4)的设备上,此方法会返回意外(对我而言)结果:
384dp x 592dp in portrait mode 598dp x 384dp in landscape mode
对于Nexus来说,结果在纵向模式下允许48dp用于软导航栏,在横向模式下允许42dp。
我想使用全屏 - 如果设备有一个软导航栏我想隐藏它并使用空间。 我可以隐藏软导航栏,但我需要能够检测实际的屏幕尺寸(例如Nexus 4的384dp x 640dp),或者设备是否有软导航栏(最好是它的大小),所以我可以调整隐藏时可用的额外空间。
我已经看到几个针对Java的stackoverflow问题,其代码类似于:
public boolean hasNavBar (Resources resources) { int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); return id > 0 && resources.getBoolean(id); }
但我找不到C#/ Xamarin的等价物。
任何帮助赞赏。
I am developing an app in C# using Xamarin. I use the following code to detect the device screensize:
var metrics = Resources.DisplayMetrics; int widthInDp = metrics.WidthPixels / Resources.DisplayMetrics.Density; int heightInDp = metrics.HeightPixels / Resources.DisplayMetrics.Density;
On a device that has physical navigation buttons, and no soft navigation bar, (Samsung SM-E7000), this method returns expected results:
360dp x 640dp in portrait mode 640dp x 360dp in landscape mode
However, on a device that does not have physical navigation buttons, but has the soft navigation bar, (Nexus 4), this method returns unexpected (to me) results:
384dp x 592dp in portrait mode 598dp x 384dp in landscape mode
It seems for the Nexus the results allow 48dp for the soft navigation bar in portrait mode, and 42dp in landscape mode.
I want to use the fullscreen - if the device has a soft navigation bar I want to hide it and use the space. I can hide the soft navigation bar, but I need to be able to detect either the actual screen size (e.g. 384dp x 640dp for the Nexus 4), or whether the device has a soft navigation bar (and preferably its size), so I can adjust for the extra space available when it is hidden.
I have seen several stackoverflow questions answered for Java with code similar to:
public boolean hasNavBar (Resources resources) { int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); return id > 0 && resources.getBoolean(id); }
but I can't find the C#/Xamarin equivalent.
Any help appreciated.
原文:https://stackoverflow.com/questions/39096192
最满意答案
错误是告诉你到底发生了什么问题; 你用太多的参数调用构造函数。 为了明白我的意思,请看看在
makeRecord
的默认实现中通常如何构建日志记录:def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): """ A factory method which can be overridden in subclasses to create specialized LogRecords. """ rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func) if extra is not None: for key in extra: if (key in ["message", "asctime"]) or (key in rv.__dict__): raise KeyError("Attempt to overwrite %r in LogRecord" % key) rv.__dict__[key] = extra[key] return rv
请注意makeRecord如何使用一个
extra
参数,它不直接传递给LogRecord
? 另一方面,你直接将它传递给LogRecord.__init__
,这会导致错误。从这里,你有两个选择; 您可以提供更完整的
makeRecord
实现,或者您可以尝试使用LoggerAdapter
类,它应该可以帮助您用较少的代码实现相同的目标。这是一个例子:
# Common log info to be added to all logs reported with `log_adapter` context = {'host': 'localhost'} log = logging.getLogger('testing') log.addHandler(logging.StreamHandler()) d = {'host': '192.168.0.1'} log_adapter = logging.LoggerAdapter(log, context) log_adapter.warning('Hi', d)
如果您需要在每次记录日志时计算“主机”的值(例如),则可以使
context
成为类似字典的类的实例。 像这样:class LogContext(object): def __getitem__(self, key): if key == 'host': return 'localhost' raise KeyError(key) def __iter__(self): return iter(['host']) log_adapter = logging.LoggerAdapter(log, LogContext()) log_adapter.warning('Hi', d)
有一点需要注意
LoggingAdapter
,它显然没有将所有便捷的快捷函数定义为普通的Logger类。 这就是为什么我已经调用了warning
方法,而不是像上面那样warn
。有关
LoggingAdapter
和添加上下文到日志的更多信息可以在python文档中找到。注 - 我的示例中没有包含
MyLogHandler
,MyLogFormatter
或MongoLogger
,因为它们与问题/错误无关。The error is telling you exactly what's wrong; you are calling the constructor with too many arguments. To see what I mean, take a look at how log-records are ordinarily constructed in the default implementation of
makeRecord
:def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): """ A factory method which can be overridden in subclasses to create specialized LogRecords. """ rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func) if extra is not None: for key in extra: if (key in ["message", "asctime"]) or (key in rv.__dict__): raise KeyError("Attempt to overwrite %r in LogRecord" % key) rv.__dict__[key] = extra[key] return rv
Notice how makeRecord takes an
extra
param that it doesn't pass directly toLogRecord
? You, on the other hand, are passing that directly toLogRecord.__init__
, which is causing the error.From here, you've got two options; you could provide a more complete implementation of
makeRecord
, or you could try using theLoggerAdapter
class which should help you achieve the same goal with less code.Here's an example:
# Common log info to be added to all logs reported with `log_adapter` context = {'host': 'localhost'} log = logging.getLogger('testing') log.addHandler(logging.StreamHandler()) d = {'host': '192.168.0.1'} log_adapter = logging.LoggerAdapter(log, context) log_adapter.warning('Hi', d)
If you need to calculate the value of 'host' (for example) each time something is logged, you could make
context
an instance of a class that looks like a dictionary. Like so:class LogContext(object): def __getitem__(self, key): if key == 'host': return 'localhost' raise KeyError(key) def __iter__(self): return iter(['host']) log_adapter = logging.LoggerAdapter(log, LogContext()) log_adapter.warning('Hi', d)
One thing to note about
LoggingAdapter
, it apparently doesn't define all of the handy shortcut functions as the ordinary Logger class. That's why I've called thewarning
method instead ofwarn
as you did above.More info on
LoggingAdapter
and adding context to your logs can be found in the python docs.NOTE - I didn't include
MyLogHandler
,MyLogFormatter
, orMongoLogger
in my examples as they were not relevant to the issue/error.
相关问答
更多-
在调用self.format(record)之前, Formatter负责设置asctime和message ,这些属性是未定义的。 从format方法的doc: 记录的属性字典用作字符串格式化操作的操作数。 返回结果字符串。 在格式化字典之前,执行几个准备步骤。 使用msg%args计算记录的message属性。 如果格式化字符串包含'(asctime)',则调用formatTime()以格式化事件时间。 由于您的示例代码不调用 self.format(record) ,因此预期这些属性未定义的行为。 要 ...
-
在myapp()您将处理程序添加到名为'myapp'的记录器中。 由于testme()获取名为'testme'的记录器,因此它没有处理程序,因为它是日志记录层次结构的不同部分。 如果您在myapp()只有logger = logger.getLogger() ,那么它将起作用,因为您将处理程序添加到层次结构的根目录。 查看python日志记录文档。 In myapp() you are adding the handler to the logger named 'myapp'. Since testme( ...
-
如何在python中开始自定义错误日志功能[关闭](How to Begin with a Custom Error log function in python [closed])[2021-08-11]
import logging logging.basicConfig(...) try: do.something() except Exception: logging.exception("aiii!") 最终你想要离开basicConfig 。 import logging logging.basicConfig(...) try: do.something() except Exception: logging.exception("aiii!") Event ... -
正如您在编辑中所述,如果您使用logger.error(err)更正logging.error(err) , logger.error(err)得到正确的输出__main__ - ERROR - It was a good attempt though 。 在记录文档中解释了root出现在您的消息中的原因。 在该文档中,您可以找到有关更改显示消息格式的信息 。 由于您确实使用了logging.error(err)您没有调用已指定所需格式的logger 。 因此出现了root词。 您应该还注意到,在使用log ...
-
在Python的logging.config模块中使用自定义格式器类(Using custom formatter classes with Python's logging.config module)[2022-08-04]
在使用Python 2.7时,可以使用dictConfig()使用基于字典的配置:这比fileConfig()更灵活,因为它允许使用任意fileConfig()作为工厂返回,例如处理程序,格式化程序或过滤器。 如果必须使用fileConfig() ,则必须构造一个可调用的对象,该对象使用format和datefmt字符串值并返回您的类的一个实例。 class值只需要解析为可调用的类,而不是实际的类。 下面是一个custfmt.py的设置:在这个要点中 ,我有一个包含格式化程序定义的文件custfmt.py ... -
python logging:自定义Python LogRecord抛出一个错误(python logging: Custom Python LogRecord Throwing an error)[2022-06-30]
错误是告诉你到底发生了什么问题; 你用太多的参数调用构造函数。 为了明白我的意思,请看看在makeRecord的默认实现中通常如何构建日志记录: def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None): """ A factory method which can be overridden in subclasses to create specialized Lo ... -
您可以创建一个logging.Filter对象来检查LogRecord并确定是否应该记录它。 在此代码中,您还可以执行其他逻辑: https : //docs.python.org/3/library/logging.html#filter-objects 。 You could create a logging.Filter object that reviews the LogRecord and decides whether or not it should be logged. In this c ...
-
record是LogRecord的一个实例: >>> import logging >>> rec = logging.LogRecord('bob', 1, 'foo', 23, 'ciao', (), False) 你的方法可以访问感兴趣的属性(我正在拆分dir的结果以便于阅读): >>> dir(rec) ['__doc__', '__init__', '__module__', '__str__', 'args', 'created', 'exc_info', 'exc_text', 'file ...
-
登录python(logging in python)[2023-05-14]
您需要配置多个处理程序以将不同级别的日志输出到不同的文件。 例如,您希望将INFO级别日志记录到info.log,您可以使用INFO filer定义fileHandler class MyFilter(logging.Filter): def filter(self, rec): return rec.levelno == logging.INFO class MyHandler(logging.FileHandler): def __init__(self, *arg, ... -
您可以使用自定义LogRecord类来实现此目的,只要您可以明确地识别文本中的键。 例如: import logging import re KEY = 'PK_SOME_PUBLIC_KEY' SECRET_KEY = 'SK_SOME_PRIVATE_KEY' class StrippingLogRecord(logging.LogRecord): pattern = re.compile(r'\b[PS]K_\w+\b', re.I) def getMessage(self): ...