问题来源:自己做了一个应用,UI发过来交互文档中的尺寸单位都是px,而google推荐dp,同时为了适配不同屏幕,需要从新计算,为了减少重复性工作,该脚本孕育而生。
实现方案:就是dimens.xml文件中写入UI交互文档大小,此时单位为px。通过遍历该文件,如果单位为px,就进行换算,如果是其他单位,如dp,就保持原来数值。关键就是px 与dp 换算,换算公式很简单,但是如何获取手机dpi 和文件夹命名就需要思考。本人采用adb 获取屏幕大小和dpi 信息,这样只要插入手机执行该脚本就能自动生成适配的values-xxx/dimens.xml文件,值得注意的地方是adb 获取屏幕大小,需要调换生成文件夹名。
注意:cmd 执行时,保存路径不要有中文
效果图:
GenerateDimensFile.py
#coding=utf-8
#author=ao.deng
import os
import subprocess
from xml.dom.minidom import Document
import xml.dom.minidom
import collections
import re
class GenerateDimensFile:
def __init__(self):
self.xmlStringdict = collections.OrderedDict() # xml存储
self.displaysSizeInfo=''
self.nDipInfo=0
def getCmdEexcuteResult(self,cmd):
ps = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
data =ps.stdout.readlines()
return data
def getInfoByADB(self):
cmd ="adb shell dumpsys window displays"
data =self.getCmdEexcuteResult(cmd)
row=0;
for item in data:
item = item.decode("utf-8").strip(" ").strip("\r\n")
if item=='Display: mDisplayId=0':
break
row+=1
needData=data[row+1]
dataList=needData.decode("utf-8").split(" ")
print(dataList)
self.nDipInfo=int(dataList[5].replace("dpi",""))
sizeInfo=dataList[6].replace("cur=","").split("x")
self.displaysSizeInfo=sizeInfo[1]+"x"+sizeInfo[0]
def px2dp(slef,px):
dp=int(px/(slef.nDipInfo/160))
return dp
def dp2px(slef,dp):
px=int(dp*(slef.nDipInfo/160))
return px
def getXmlNodeValue(self, childNodes):
value = ''
for childNode in childNodes:
if childNode.nodeName == '#text':
value = value + childNode.wholeText
# return childNode.wholeText
value_key = ''
if childNode.nodeName != '#text' and childNode.nodeName != '#comment':
attributeDict = childNode._attrs
if attributeDict != None:
for k, v in attributeDict.items():
value_key = value_key + ' %s="%s" ' % (k, childNode.getAttribute(k))
text = self.getXmlNodeValue(childNode.childNodes)
# print (text)
value = value + "<%s%s>%s</%s>" % (childNode.nodeName, value_key, text, childNode.nodeName)
# print(value)
return value
def parse_xml_file(self, xml_fname):
try:
DOMTree = xml.dom.minidom.parse(xml_fname)
collection = DOMTree.documentElement
stringList = collection.getElementsByTagName("dimen")
for string in stringList:
if string.hasAttribute("name"):
key = string.getAttribute("name")
print("name: %s" % key)
value = self.getXmlNodeValue(string.childNodes)
print("value: %s" % value)
self.xmlStringdict[key] = value
return True
except Exception as e:
print(e)
return False
def build_xml_file(self,saveRootPath):
if not os.path.exists(saveRootPath):
os.mkdir(saveRootPath)
if not os.path.exists(saveRootPath+"/"+"values-" + self.displaysSizeInfo):
os.mkdir(saveRootPath+"/"+"values-" + self.displaysSizeInfo)
try:
impl = xml.dom.minidom.getDOMImplementation()
doc = impl.createDocument(None, 'resources', None)
resources = doc.documentElement
for key, value in self.xmlStringdict.items():
if value[-2:]=="px":
nValue=self.px2dp(int(value[:-2]))
sVvalue ="%ddp"%nValue #屏幕匹配
else:
sVvalue=value
stringele = doc.createElement("dimen")
stringele.setAttribute("name", key)
text = doc.createTextNode(sVvalue)
stringele.appendChild(text)
resources.appendChild(stringele)
uglyXml = doc.toprettyxml(indent=' ', encoding='utf-8')
uglyXml = str(uglyXml, encoding="utf8")
if uglyXml:
uglyXml = uglyXml.replace("&", "&").replace("<", "<"). \
replace(""", "\"").replace(">", ">")
text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
prettyXml = text_re.sub('>\g<1></', uglyXml)
print(prettyXml)
self.xmlfd = open(os.path.join(saveRootPath+"/"+"values-" + self.displaysSizeInfo,"dimens.xml"), 'w', encoding='utf-8')
# doc.writexml(self.xmlfd,addindent=' ',newl='\n',encoding="utf-8")
self.xmlfd.write(prettyXml)
self.xmlfd.close()
print("xml生成成功")
return "xml生成成功"
except Exception as e:
print(str(e))
return "xml生成失败"
if __name__=="__main__":
mGenerateDimensFileHelper = GenerateDimensFile()
mGenerateDimensFileHelper.getInfoByADB()
mGenerateDimensFileHelper.parse_xml_file(r"E:\python_work\GenerateDimensFile\values\dimens.xml")
mGenerateDimensFileHelper.build_xml_file(r"E:\python_work\GenerateDimensFile\values")