Android完美適配dimens.xml指令碼

相信大家都有適配的經歷,而且面對大千世界千奇百怪的安卓手機,適配起來那叫一個蛋疼。所以本人決定研究一下自動化適配的方法,於是乎從dimens檔案入手。
什麼是dimens檔案這裡就不詳細闡述了,相信大家都知道,不知道的童鞋可以問度娘。
這裡我先幫大家再鞏固一下畫素密度相關知識:

畫素密度

螢幕畫素密度指單位長度螢幕顯示的畫素,即常說的dpi (dots per inch),每英寸點數。密度越高顯示畫面就越清晰。

Android把畫素密度按區間分成幾種:

分類dpi
ldpi低密度
mdpi中密度
hdpi高密度
xhdpi超高密度
xxhdpi超超高密度
xxxhdpi超超超高密度

在Android將mdpi即中密度作為基準線,即1dp= 1px;
不同畫素密度,系統給定了其對應比例和倍數如下:

分類目錄ldpimdpihdpixhdpixxhdpixxxhdpi
密度(dpi)~160~240~320~480~640~960
圖片比例1.523468
倍數0.75x1x1.5x2x3x4x

除了系統給定的畫素密度還有一些並不是規範的螢幕,所以就需要我們自己去計算倍數。那麼首先要得到畫素密度:
公式:根號下(長的平方 高的平方)➗螢幕尺寸
這裡寫圖片描述

例如:

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檔案就可以。

第二種方案

本方案是直接通過獲取(‘>’)和(‘

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的外掛,小夥伴可以敬請期待。

掃碼關注公眾號“偉大程式猿的誕生“,更多幹貨等著你~
掃碼關注公眾號“偉大程式猿的誕生“,更多幹貨等著你~
掃碼關注公眾號“偉大程式猿的誕生“,更多幹貨等著你~

公眾號回覆“資料獲取”,獲取更多幹貨哦~