Android完美适配dimens.xml脚本
Posted 先知丨先觉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android完美适配dimens.xml脚本相关的知识,希望对你有一定的参考价值。
相信大家都有适配的经历,而且面对大千世界千奇百怪的安卓手机,适配起来那叫一个蛋疼。所以本人决定研究一下自动化适配的方法,于是乎从dimens文件入手。
什么是dimens文件这里就不详细阐述了,相信大家都知道,不知道的童鞋可以问度娘。
这里我先帮大家再巩固一下像素密度相关知识:
像素密度
屏幕像素密度指单位长度屏幕显示的像素,即常说的dpi (dots per inch),每英寸点数。密度越高显示画面就越清晰。
android把像素密度按区间分成几种:
分类 | dpi |
---|---|
ldpi | 低密度 |
mdpi | 中密度 |
hdpi | 高密度 |
xhdpi | 超高密度 |
xxhdpi | 超超高密度 |
xxxhdpi | 超超超高密度 |
在Android将mdpi即中密度作为基准线,即1dp= 1px;
不同像素密度,系统给定了其对应比例和倍数如下:
分类目录 | ldpi | mdpi | hdpi | xhdpi | xxhdpi | xxxhdpi |
---|---|---|---|---|---|---|
密度(dpi) | ~120 | ~160 | ~240 | ~360 | ~480 | ~640 |
图片比例 | 1.5 | 2 | 3 | 4 | 6 | 8 |
倍数 | 0.75x | 1x | 1.5x | 2x | 3x | 4x |
除了系统给定的像素密度还有一些并不是规范的屏幕,所以就需要我们自己去计算倍数。那么首先要得到像素密度:
公式:根号下(长的平方+高的平方)➗屏幕尺寸
例如:
600*1024的8寸屏幕 | 720*1280的8寸屏幕 |
---|---|
他们之间的倍数关系是0.8倍。后面我们需要根据这个数值来进行适配。
ok到这里,像素密度基本知识回顾的差不多了那么进入今天的正题。
说了那么多无非就是用到最后的像素密度直接的倍数关系,那么今天要走的就是解放双手,不需要你手动去一个一个挨着计算dimens文件中的数值,而是采用脚本,帮你秒秒中完成。
Python脚本
这里提供两个方案:
第一种是通过ElementTree获取节点,根据Key去改变value;
第二种方案是通过/> 和< 符号来获取中间的数值,是因为dimens文件非常简单里面只有除了根节点外的dimen节点
<dimen name="dp_10">10dp</dimen>
第一种方案
本方案需要使用到ElementTree,代码中注视已经详细介绍了使用方法,如果有想要详细了解的童鞋可以自行查看API,ElementTree API
思路就是通过ElementTree获取到dimen节点,然后遍历得到对应的key和value,将value乘以设置好的倍数,然后再通过key写进去。
⚠️:这里用到了四舍五入,因为dimen文件不识别小数,会默认转成int,如果不使用四舍五入,假如计算后是1.9 ,那么写入dimens,会默认读到1,并不是1.9,所以应该四舍五入成2。
代码
# encoding=utf-8
from xml.etree import ElementTree as ET
import re
# 转换倍数
multiple = 0.9
# 文件名
fileName = "dimens.xml"
'''''判断某个节点是否包含所有传入参数属性
node: 节点
kv_map: 属性及属性值组成的map'''
def if_match(node, kv_map):
for key in kv_map:
if node.get(key) != kv_map.get(key):
return False
return True
def get_node_by_keyvalue(nodelist, kv_map):
'''''根据属性及属性值定位符合的节点,返回节点
nodelist: 节点列表
kv_map: 匹配属性及属性值map'''
result_nodes = []
for node in nodelist:
if if_match(node, kv_map):
result_nodes.append(node)
return result_nodes
def change_node_text(nodelist, text, is_add=False, is_delete=False):
'''''改变/增加/删除一个节点的文本
nodelist:节点列表
text : 更新后的文本'''
for node in nodelist:
if is_add:
node.text += text
elif is_delete:
node.text = ""
else:
node.text = text
# 新数据写入文件
def writeValue(key,result,tree):
nodes = tree.findall('dimen')
result_nodes = get_node_by_keyvalue(nodes, "name": key)
change_node_text(result_nodes, str(result))
tree.write(fileName)
# 正则获取数字
def showNumber(value_s):
value = re.findall("\\d+",value_s)
return value[0]
# 获取新数值
def calculate(key,value,tree):
''' 获取原始数值'''
value_org = showNumber(value)
'''乘倍数'''
result_cau = float(int(value_org) * float(multiple))
''' 四舍五入'''
result_count = round(result_cau)
''' 正则替换原数据数值'''
result = re.sub("\\d+", str(result_count), value)
writeValue(key,result,tree)
# 遍历得到key--value
def getValue(tree,root):
for dimen in root.iter('dimen'):
key = dimen.get('name')
value = dimen.text
calculate(key,value,tree)
''' 读取XML'''
def readXml():
tree = ET.parse('dimens.xml')
root = tree.getroot()
getValue(tree,root)
if __name__ == "__main__":
readXml()
使用方法
将dimens文件和python放在同一个目录下,更改你想要缩放的倍数,然后直接运行python文件就可以。
第二种方案
本方案是直接通过获取(’>’)和(’</’)中间的数值进行计算得到的,因为dimens没那么多复杂节点,除了根节点就是<dimen ></>
这里没有使用四舍五入公式,而是在计算后的结果中加0.5转int,效果是一样的。
start_i = s.find('>')
end_i = s.find('</')#代码
下面直接看代码
import sys
import io
fileName = sys.argv[1]
scale = sys.argv[2]
result = ''
def foo(s):
start_i = s.find('>')
end_i = s.find('</')
value = int(int(s[start_i + 1: end_i - 2]) * float(scale) + 0.5)
return "%s%d%s" % (s[: start_i + 1], value, s[end_i - 2:])
with io.open(fileName, 'r', encoding='utf8') as file:
for line in file:
if '<dimen name="' not in line:
result += line
else:
result += foo(line)
with io.open("dimens_output.xml", 'w', encoding='utf8') as file:
file.write(result)
使用方法
终端直接执行:
python python文件 dimens.xml 所放的倍数
python dimens.py dimens.xml 0.8
总结
这里只是给大家提供个思路和工具类,你也可以自己去用脚本实现。
这里只要大家会使用就好了,脚本代码已经上传,童鞋们可以自行下载:
http://download.csdn.net/detail/github_33304260/9915517
python不懂的小伙伴可以自己找度娘学一学,或者自己使用其他脚本语言实现也可以,后期将推出AndroidStudio的插件,小伙伴可以敬请期待。
扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~
公众号回复“资料获取”,获取更多干货哦~
有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码
以上是关于Android完美适配dimens.xml脚本的主要内容,如果未能解决你的问题,请参考以下文章
Android 屏幕适配屏幕适配通用解决方案 ① ( 定义 dimens.xml 方案 | 使用 ScreenMatch 插件生成不同屏幕分辨率的 dimens.xml 配置 )
Android 屏幕适配屏幕适配通用解决方案 ① ( 定义 dimens.xml 方案 | 使用 ScreenMatch 插件生成不同屏幕分辨率的 dimens.xml 配置 )