Python日常-正則表達式批量替換dimens.xml中的單位

事情起源

最近做的Android項目中出現了一個這樣的需求:不同寬度的設備上,控件的尺寸按比例縮放。也就是說,假如在360dp寬的設計稿上,某個Button的寬度為120dp,那么到了480dp寬的設備上,這個Button的寬度應該拉成160dp。一開始我想到了幾種思路:

  • 全部用layout_weight,但是這樣太麻煩了
  • 百分比布局,還是一樣,需要計算百分比,太麻煩
  • 鴻洋_推出的AutoLayout,但我一看Github上的issues,似乎很多坑的樣子,不敢試
  • 布局里面的寬高全部寫到dimens.xml中,然后為不同寬度的設備寫多套dimens.xml,這樣做比較麻煩,但現在看來是最有效的辦法

也就是說,我會把一個Button的布局代碼寫成這樣(所有長度單位全部寫到dimens.xml里):

<Button
        android:layout_marginTop="@dimen/login_button_margin_top"
        android:id="@+id/id_button_login"
        android:layout_width="@dimen/large_button_width"
        android:layout_height="@dimen/standard_widget_height"
        android:layout_gravity="center"
        android:textSize="@dimen/sp15"
        android:text="登錄"
        android:textColor="@color/white"
        android:gravity="center"
        />

然后在values/dimens.xml里面,定義這些單位:

<resources>

    <!-- Widget Width && Height -->
    <dimen name="toolbar_height">@dimen/standard_widget_height</dimen>
    <dimen name="large_button_width">270dp</dimen>
    <dimen name="standard_widget_height">42dp</dimen>

    <!--Margin && Padding-->
    <dimen name="login_button_margin_top">30dp</dimen>
   
</resources>

創建values-w480dp目錄,在里面的dimens.xml定義(如果設計稿的屏幕寬度是360dp,那么這里乘以一個三分之四):

<resources>

    <!-- Widget Width && Height -->
    <dimen name="toolbar_height">@dimen/standard_widget_height</dimen>
    <dimen name="large_button_width">360dp</dimen>
    <dimen name="standard_widget_height">56dp</dimen>

    <!--Margin && Padding-->
    <dimen name="login_button_margin_top">40dp</dimen>
   
</resources>

但是隨著項目布局文件的增多,dimens里面的標簽數量也會水漲船高,到時候難道為每一個寬度的布局都去算一遍寬高嗎?這顯然太費人力了

思路

于是我就想寫個腳本來自動化地做這件事,人生苦短,首選武器必然是Python。一下子思路就很簡單:找出所有xxdp的文本,把數值解析出來,乘以一個倍數,再寫回去

所以問題就變成了怎么把xxdp解析出來,一開始想到的是XML解析庫,網上看了一下,想用xml.dom.minidom這個包,后來發現解析出來后不知道咋把數值寫回去(肯定可以的,但我太懶了不想去看文檔),所以干脆就用正則表達式了。我用這樣一個表達式來把dimens.xml里面的單位給匹配出來:

> *(\w+)[sd]p *<

這里我假設單位都是整數,為了防止里面有空格加了個' *',這樣(\w+)所匹配出來的就是dp或sp的數值了。寫回去好辦,把匹配出來的數值改一改再替換回去就是了。

代碼

最后的代碼長這樣:

import re

def auto_transfrom_reg(res_path, new_res_path, t):
    value_file_360p_path = res_path + '//values//dimens.xml'
    new_value_file_path = res_path + new_res_path
    file_handler = open(value_file_360p_path)
    new_file_handler = open(new_value_file_path, 'w')
    line = file_handler.readline()
    while line:
        match_obj = re.search(r'> *(\w+)[sd]p *<', line)
        if match_obj:
            dp_str = match_obj.group(0)
            new_dp_str = ''
            if dp_str.find('d') >= 0:
                dp_value = int(dp_str[1:dp_str.find('d')])
                new_dp_value = dp_value * t
                new_dp_str = '>%.1fdp<' % new_dp_value
            else:
                dp_value = int(dp_str[1:dp_str.find('s')])
                new_dp_value = dp_value * t
                new_dp_str = '>%.1fsp<' % new_dp_value
                print new_dp_str
            new_line = re.sub(r'> *(\w+)[sd]p *<', new_dp_str, line)
            new_file_handler.write(new_line)
            print new_line
        else:
            new_file_handler.write(line)
        line = file_handler.readline()
    pass

if __name__ == '__main__':
    auto_transfrom_reg('E://XXX//YYYY//app//src//main//res',
                       '//values-w480dp//dimens.xml', 480.0/360)

效果自然是完美替換:

對比
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容