您的位置:首页 > 编程语言 > Python开发

Python实现的用于从布局文件的id生成成员变量声明和findViewById语句的Android开发小工具

2017-02-09 11:16 996 查看
辛苦堆砌,转载请注明出处,谢谢!

软件开发中,我们有不少重复性的工作,这些工作,我们可以自己编写一些小程序来实现自动化,还可以按照自己的编程习惯做简单的定制,还是比较方便的。Android开发中,一项重复性的工作就是声明一个成员变量,比如

private Button mTestButton;
然后,我们最常做的工作就是在onCreate中再调用findViewById实现从布局文件到Java变量的映射

mTestButton = (Button) findViewById(R.id.test_button);
如果布局文件比较大,而且id比较多,我们要手动敲很多代码,然后还要注意强制类型转换。

之前为了减少自己敲击代码的工作量,利用python制做了一个小工具,大家可以试着用用,也可以在此基础上做一些修改,方便自己使用,程序员要利用自己的能力,减轻自己的工作才好。当然我们也可以使用Android Studio的代码模板做类似的事情,但是还是避免不了我要修改模板中的一些内容,利用我自己的这个小工具,至少对我来说,符合自己的变量定义习惯和代码风格,而且只需要复制到对应的Java文件即可。下面给出代码

#coding=utf-8
from xml.etree.ElementTree import parse
import os

class AndroidLayoutFileParser:

#android:id
android_id = "{http://schemas.android.com/apk/res/android}id"

android_id_add = "@+id/"

#成员变量声明格式串
declare = "private %s %s;\n"

#findViewById格式串
find_view_by_id = "%s = (%s) findViewById(R.id.%s);\n"

def __init__(self, input_filename, need_open_file=True):
self.result_list = []
self.output_filename = input_filename.replace(".xml", ".txt")
self.need_open_file = need_open_file
self.root_node = parse(input_filename).getroot()

def start(self):
self.__parse_tree__(self.root_node)

def open_result_file(self):
os.system('notepad %s' % self.output_filename)

def __parse_tree__(self, node):
if node is None:
return

#分析根节点
if self.root_node == node:
self.__parse_node__(node)

#递归分析子节点
for child in node:
self.__parse_node__(child)
self.__parse_tree__(child)

self.__print_result_file__()

def __parse_node__(self, node):
try:
element_id = node.attrib[self.android_id]
if element_id.find(self.android_id_add) != -1:
#[[Android布局或者视图控件类型(如LinearLayout,Button等), id],]
self.result_list.append([node.tag, element_id[len(self.android_id_add):]])
except KeyError:
pass

def __form_var_name__(self, id):
var_name = "m"
name_fragments = id.split("_")
if len(name_fragments) != 1:
#如果id是用下划线分割的字符串命名id,则生成变量名修正为驼峰式
#如id为test_button,则mTestButton
for name_fragment in name_fragments:
var_name += name_fragment.capitalize()
else:
#如果id是一个单词,如testButton,则生成mTestButton
var_name += id.capitalize()
return var_name

def __print_result_file__(self):
if len(self.result_list) != 0:
output = open(self.output_filename, "w")
output.write("================声明===================\n")
for result in self.result_list:
type, id = result
output.write(self.declare % (type, self.__form_var_name__(id)))

output.write("\n")
output.write("================findViewById===================\n")
for result in self.result_list:
type, id = result
output.write(self.find_view_by_id % (self.__form_var_name__(id), type, id))

output.close()

if __name__ == "__main__":
layout_files = []
files = os.listdir(os.curdir)
for file in files:
if file.endswith(".xml"):
layout_files.append(file)

for file in layout_files:
parser = AndroidLayoutFileParser(file)
parser.start()
parser.open_result_file()

我使用时一般将该脚本放置在一个单独的目录,然后复制想要生成代码的布局文件到该目录下,执行Python脚本,例如,我将该脚本命名为android_findViewById.py,然后有一个测试的layout文件fragment_login.xml,这个是我从之前项目中摘取的一些控件,真正关注的是android:id,其他的没有太大的意义。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:oritation="vertical">

<ImageView
android:id="@+id/login_title_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/login_icon_logo1" />

<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="40dp" />

<Button
android:id="@+id/login_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登陆" />

</LinearLayout>
然后执行脚本,生成一个fragment_login.txt并自动打开,结果如图:



可以看到,正确生成了对应的代码,效果还是不错的XD。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐