Android - N级树形结构实现

目前已经实现3级之内的任意级树形结构展示(如果想增加更多级,需要扩展排序算法),并支持单选和多选(使用不同的适配器)。

实现使用的控件:ListView

首先,最重要的应该是数据源的格式,支持树形结构的数据源,每条数据应该都要指明它的父级是谁,本文为parent_org,并把每条数据都存放在一个HashMap里面。这里使用的除了parent_org(父营业部),还有org_name(营业部名称),org_code(营业部编号)。

其次,对数据进行排序。因为只使用ListView实现,所以需要实现层次结构的树形结构,需要对数据按父级->2级->3级->父级->2级->父级->2级->父级->2级->3级这样的顺序排序。

接着,实现适配器,展现树形结构。

最后,调用适配器,并调用适配器里的方法获取选择结果。

排序算法:

/**
* 查询操作员营业部列表类
*
* @author xinyan
*
*/
public class QueryIntOrgListWork extends BaseWork implements Runnable { private static final String TAG = "QueryIntOrgListWork";
HashMap<String, String> params; public QueryIntOrgListWork(Context context, Map args) {
super(context, args); } public QueryIntOrgListWork(Context context, View layoutView, Map args) {
super(context, layoutView, args); } @Override
public void work() {
params = new HashMap<String, String>();
AppState appState = AppState.getState(); BrokerInfo brokerInfo = appState.getBrokerInfo();
// params.put("uuid", brokerInfo.getUuid());
Utils.putUuid(params);
params.put("funcno", "20017");
params.put("org_type", "0");
params.put("right_flag", "1");
try {
HttpFactory httpFactory = new HttpFactory();
byte[] bytes = httpFactory.send(
Configuration.getString("system.http"), params,
HttpFactory.POST); if (bytes == null) {
return;
} String result = new String(bytes,
Configuration.getString("system.charSet")); JSONObject jsonObject = new JSONObject(result); // 增加登录过期或账号已在其他地方登录的处理
try {
String strPrompt = jsonObject.getString("errorInfo");
String strErrorNo = jsonObject.getString("errorNo");
if (!StringHelper.isEmpty(strPrompt)) {
if (strPrompt.contains("未登")
|| strPrompt.contains("其它地方登陆")) {
sendMessage(new LoginExpiredUiWork(null));
return;
}
}
// 如果访问接口异常,提示信息
if (!strErrorNo.equals("0")) {
HashMap<String, String> param = new HashMap<String, String>();
if (null != strPrompt) {
param.put("errorInfo", "调用查询操作员机构列表接口:" + strPrompt);
} else {
param.put("errorInfo", "");
} sendMessage(new CallInterfaceExceptionUiWork(param));
if ("-111".equals(strErrorNo) || "-110".equals(strErrorNo)
|| "-2008000".equals(strErrorNo)) {
return;
}
}
} catch (Exception e) {
} String errorNo = jsonObject.getString("errorNo");
if (errorNo.equals("-1")) {
String errorInfo = jsonObject.getString("errorInfo");
Map<String, String> map = new HashMap<String, String>();
map.put("errorNo", "-1");
map.put("errorInfo", errorInfo);
} else if (errorNo.equals("-999")) { Intent intent = new Intent("com.thinkive.action.MAIN");
context.startActivity(intent); } else if (errorNo.equals("0")) {
JSONArray array = jsonObject.getJSONArray("results"); ArrayList<HashMap<String, Object>> dataList = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> dataItem = null; for (int i = 0; i < array.length(); i++) {
dataItem = new HashMap<String, Object>(); JSONObject item = array.getJSONObject(i);
String org_name = item.getString("org_name");
// String area_addr = item.getString("area_addr");
//
// String org_type = item.getString("org_type");
// String right_flag = item.getString("right_flag");
// String zip_code = item.getString("zip_code");
// String acct_len = item.getString("acct_len");
String org_code = item.getString("org_code");
// String acct_prefix = item.getString("acct_prefix"); // String org_full_name = item.getString("org_full_name");
String parent_org = item.getString("parent_org");
// String area_no = item.getString("area_no");
// String org_status = item.getString("org_status");
// String org_cls = item.getString("org_cls"); dataItem.put("org_name", org_name);
dataItem.put("org_code", org_code);
dataItem.put("parent_org", parent_org); dataList.add(dataItem);
}
AppState.getState().getBrokerInfo()
.setIntOrgs(regroupData(dataList));
} } catch (Exception e) {
e.printStackTrace();
} } /**
* 对数据根据子父级关系进行重组
*/
private List<HashMap<String, Object>> regroupData(
List<HashMap<String, Object>> dataList) {
HashMap<String, Object> item = null;
ArrayList<HashMap<String, Object>> regroupedDataList = null;
for (int i = 0; i < dataList.size(); i++) {
item = dataList.get(i); String strOrg = item.get("org_code").toString();
String strParentOrg = item.containsKey("parent_org") ? item.get(
"parent_org").toString() : ""; // 如果没有父营业部,遍历列表是否存在子营业部
if (StringHelper.isEmpty(strParentOrg)) {
HashMap<String, Object> item2 = null; ArrayList<HashMap<String, Object>> childList = null; // 遍历列表是否存在子营业部
for (int j = 0; j < dataList.size(); j++) {
if (i == j) {
continue;
} item2 = dataList.get(j); // 列表存在子营业部
if (strOrg.equals(item2.get("parent_org"))) {
childList = new ArrayList<HashMap<String, Object>>();
if (null != item2.get("child")) { // 如果该营业部的子营业部还存在子营业部,那么此营业部是1级,*
item2.put("org_level", "1");
} else { // 如果该营业部的子营业部不存在子营业部,那么将此营业部暂定为2级
item2.put("org_level", "2");
}
childList.add(item2);
}// end if
}// end for
item.put("child", childList); } else {// 如果有父营业部
HashMap<String, Object> parentOrgItem = null; boolean isParentOrgExist = false; // 首先检查列表是否存在父营业部
for (int j = 0; j < dataList.size(); j++) {
if (i == j) {
continue;
} parentOrgItem = dataList.get(j); // 列表存在父营业部
if (strParentOrg.equals(parentOrgItem.get("org_code"))) {
isParentOrgExist = true; // 加入当前营业部到该父营业部的子营业部列表,标记当前项为2级营业部
item.put("org_level", "2"); ArrayList<HashMap<String, Object>> childList = null;
if (null != parentOrgItem.get("child")) {
childList = (ArrayList<HashMap<String, Object>>) parentOrgItem
.get("child");
} else {
childList = new ArrayList<HashMap<String, Object>>();
} // 检查子营业部列表是否已经存在该营业部
boolean isOrgExist = false;
if (childList.size() > 0) {
HashMap<String, Object> childItem = null; for (int k = 0; k < childList.size(); k++) {
childItem = (HashMap<String, Object>) childList
.get(k); if (childItem.get("org_code").toString()
.equals(item.get("org_code"))) {
isOrgExist = true;
}
}
}
if (!isOrgExist) {
childList.add(item);
parentOrgItem.put("child", childList);
} break;
}// end if
}// end for // 检查完了是否存在父营业部之后,再检查列表是否存在该营业部的子营业部
HashMap<String, Object> childOrgItem = null; ArrayList<HashMap<String, Object>> childList = new ArrayList<HashMap<String, Object>>(); // 遍历列表是否存在子营业部
for (int k = 0; k < dataList.size(); k++) {
if (i == k) {
continue;
} childOrgItem = dataList.get(k); // 列表存在子营业部
if (strOrg.equals(childOrgItem.get("parent_org"))) { if (null != childOrgItem.get("child")) { // 如果该营业部的子营业部还存在子营业部,那么此营业部是1级,*
childOrgItem.put("org_level", "1");
} else { // 如果该营业部的子营业部不存在子营业部,那么将此营业部暂定为2级
childOrgItem.put("org_level", "2");
}
childList.add(childOrgItem);
}// end if
}// end for if (childList.size() > 0) {
item.put("child", childList); // 如果当前营业部存在父营业部和子营业部,那么就是2级
if (isParentOrgExist) {
item.put("org_level", "2");
} else { // 不存在父营业部,那么是1级
item.put("org_level", "1");
}
} else { // 不存在子营业部
if (isParentOrgExist) { // 不存在子营业部,但存在父营业部,那么是2级
item.put("org_level", "2");
} else { // 不存在子营业部和父营业部,那么是1级
item.put("org_level", "1");
}
}
}// end else
}// end for // 当数据按数学结构组织好之后,按顺序排列为列表,以便在listview里显示
regroupedDataList = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> tempItem = null;
for (int i = 0; i < dataList.size(); i++) {
tempItem = dataList.get(i); if ("1".equals(tempItem.get("org_level").toString())) {
regroupedDataList.add(tempItem); // 把子营业部加入到重组后的列表
if (tempItem.containsKey("child")) {
ArrayList<HashMap<String, Object>> childList = (ArrayList<HashMap<String, Object>>) tempItem
.get("child");
HashMap<String, Object> childItem = null;
if (childList.size() > 0) {
for (int j = 0; j < childList.size(); j++) {
childItem = (HashMap<String, Object>) childList
.get(j);
regroupedDataList.add(childItem); // 检查子营业部是否还有子营业部
if (childItem.containsKey("child")) {
ArrayList<HashMap<String, Object>> childList2 = (ArrayList<HashMap<String, Object>>) childItem
.get("child");
HashMap<String, Object> childItem2 = null;
if (childList2.size() > 0) {
for (int k = 0; k < childList2.size(); k++) {
childItem2 = (HashMap<String, Object>) childList2
.get(k);
regroupedDataList.add(childItem2);
}// end for
}// end if
}// end if
}// end for
}// end if
}// end if
}// end if
}// end for for (int i = 0; i < regroupedDataList.size(); i++) {
if (regroupedDataList.get(i).containsKey("child")) {
regroupedDataList.get(i).remove("child");
}
} // 父级、子级都得排序
Log.i(TAG, "重组前的营业部数据" + dataList);
Log.i(TAG, "重组后的营业部数据" + regroupedDataList); return regroupedDataList;
} @Override
public void run() {
work();
} }
多选营业部树形列表适配器:
/**
* 多选营业部树形列表适配器
*
* @author xinyan
* @date 2013-5-27
*/
public class MultiCheckIntOrgListAdapter extends BaseAdapter {
public static final String TAG = "MultiCheckIntOrgListAdapter"; public static final String CHECKED_TRUE = "1";
public static final String CHECKED_FALSE = "0";
public static final String IS_CHECKED = "IS_CHECKED"; private List<HashMap<String, Object>> mDataList; private LayoutInflater mInflater; public MultiCheckIntOrgListAdapter(Context context,
List<HashMap<String, Object>> dataList) {
this.mInflater = LayoutInflater.from(context);
mDataList = dataList;
setDefaultChecked();
} @Override
public int getCount() {
return mDataList.size();
} @Override
public Object getItem(int position) {
return mDataList.get(position);
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final HashMap<String, Object> dataItem = mDataList.get(position);
if (null == convertView) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.lv_item_tree_structure,
null); holder.cb = (CheckBox) convertView
.findViewById(R.id.lv_item_tree_structure_cb);
holder.text = (TextView) convertView
.findViewById(R.id.lv_item_tree_structure_text);
holder.joinBottom = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_join_bottom);
holder.leaf = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_leaf);
holder.joinBottom2 = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_join_bottom2);
holder.leaf2 = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_leaf2);
holder.tree = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_tree); convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tree.setVisibility(View.GONE);
holder.joinBottom.setVisibility(View.GONE);
holder.leaf.setVisibility(View.GONE);
holder.joinBottom2.setVisibility(View.GONE);
holder.leaf2.setVisibility(View.GONE); // 如果是父级
if ("1".equals(dataItem.get("org_level"))) {
holder.tree.setVisibility(View.VISIBLE);
holder.joinBottom.setVisibility(View.GONE);
holder.leaf.setVisibility(View.GONE);
holder.joinBottom2.setVisibility(View.GONE);
holder.leaf2.setVisibility(View.GONE); } else if ("2".equals(dataItem.get("org_level"))) {// 如果是子级
holder.joinBottom2.setVisibility(View.GONE);
holder.leaf2.setVisibility(View.GONE);
holder.tree.setVisibility(View.GONE); holder.joinBottom.setVisibility(View.VISIBLE);
holder.leaf.setVisibility(View.VISIBLE);
} else { // 3级
holder.tree.setVisibility(View.GONE); holder.joinBottom2.setVisibility(View.VISIBLE);
holder.leaf2.setVisibility(View.VISIBLE);
holder.joinBottom.setVisibility(View.VISIBLE);
holder.leaf.setVisibility(View.VISIBLE);
} try {
holder.text.setText(dataItem.get("org_code").toString() + " "
+ dataItem.get("org_name").toString());
} catch (Exception e) {
} final CheckBox cb = holder.cb; if (CHECKED_TRUE.equals(dataItem.get(IS_CHECKED))) {
cb.setChecked(true);
} else {
cb.setChecked(false);
} convertView.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
if (cb.isChecked()) {
cb.setChecked(false);
dataItem.put(IS_CHECKED, CHECKED_FALSE);
} else {
cb.setChecked(true);
dataItem.put(IS_CHECKED, CHECKED_TRUE);
} if ("1".equals(dataItem.get("org_level").toString())) {
// 遍历子营业部
HashMap<String, Object> item = null;
for (int i = position + 1; i < mDataList.size(); i++) {
item = mDataList.get(i); if ("2".equals(item.get("org_level"))
|| "3".equals(item.get("org_level"))) {
if (cb.isChecked()) {
item.put(IS_CHECKED, CHECKED_TRUE);
} else {
item.put(IS_CHECKED, CHECKED_FALSE);
}
} else if ("1".equals(item.get("org_level"))) {
break;
}// end else if
}// end for
notifyDataSetChanged();
}// end if
else if ("2".equals(dataItem.get("org_level").toString())) {
// 遍历子营业部
HashMap<String, Object> item = null;
for (int i = position + 1; i < mDataList.size(); i++) {
item = mDataList.get(i); if ("3".equals(item.get("org_level"))) {
if (cb.isChecked()) {
item.put(IS_CHECKED, CHECKED_TRUE);
} else {
item.put(IS_CHECKED, CHECKED_FALSE);
}
} else if ("1".equals(item.get("org_level"))) {
break;
}// end else if
}// end for
notifyDataSetChanged();
}// end else if return true;
}
return false;
}
}); return convertView;
} /**
* 拿到已选择营业部的代码字符串,代码之间逗号分隔
*
* @return
*/
public String getSelectedOrgCodes() {
StringBuilder sbOrgCodes = new StringBuilder();
for (int i = 0; i < mDataList.size(); i++) {
if (mDataList.get(i).get(IS_CHECKED).equals(CHECKED_TRUE)) {
if (sbOrgCodes.length() <= 2) {
sbOrgCodes.append(mDataList.get(i).get("org_code")
.toString());
} else {
sbOrgCodes.append(","
+ mDataList.get(i).get("org_code").toString());
}// end else
}// end if
}// end for Log.i(TAG, "getSelectedOrgCodes: " + sbOrgCodes.toString()); return sbOrgCodes.toString();
} /**
* 拿到已选择的营业部(org_code+org_name)
*
* @return
*/
public String getSelectedOrg() {
StringBuilder sbOrg = new StringBuilder();
for (int i = 0; i < mDataList.size(); i++) {
if (mDataList.get(i).get(IS_CHECKED).equals(CHECKED_TRUE)) {
String strText = mDataList.get(i).get("org_code").toString()
+ " " + mDataList.get(i).get("org_name").toString();
if (sbOrg.length() <= 2) {
sbOrg.append(strText);
} else {
sbOrg.append("," + strText);
}// end else
}// end if
}// end for Log.i(TAG, "getSelectedOrg: " + sbOrg.toString()); return sbOrg.toString();
} /**
* 默认全部选中
*/
private void setDefaultChecked() {
for (int i = 0; i < mDataList.size(); i++) {
mDataList.get(i).put(IS_CHECKED, CHECKED_TRUE);
}
} class ViewHolder {
TextView text;
CheckBox cb;
ImageView tree;// 树形图
ImageView joinBottom;// 连接线
ImageView leaf;// 子节点图
ImageView joinBottom2;// 3级连接线
ImageView leaf2;// 3级子节点图
} }

 单选营业部树形列表适配器

/**
* 单选营业部树形列表适配器
*
* @author xinyan
* @date 2013-5-27
*/
public class SingleChoiceIntOrgListAdapter extends BaseAdapter {
public static final String TAG = "SingleChoiceIntOrgListAdapter"; public static final String CHECKED_TRUE = "1";
public static final String CHECKED_FALSE = "0";
public static final String IS_CHECKED = "IS_CHECKED"; private List<HashMap<String, Object>> mDataList; private LayoutInflater mInflater; public SingleChoiceIntOrgListAdapter(Context context,
List<HashMap<String, Object>> dataList) {
this.mInflater = LayoutInflater.from(context);
mDataList = dataList;
} @Override
public int getCount() {
return mDataList.size();
} @Override
public Object getItem(int position) {
return mDataList.get(position);
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final HashMap<String, Object> dataItem = mDataList.get(position);
if (null == convertView) {
holder = new ViewHolder();
convertView = mInflater.inflate(
R.layout.lv_item_tree_structure_single_choice, null); holder.cb = (CheckBox) convertView
.findViewById(R.id.lv_item_tree_structure_cb);
holder.text = (TextView) convertView
.findViewById(R.id.lv_item_tree_structure_text);
holder.joinBottom = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_join_bottom);
holder.leaf = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_leaf);
holder.joinBottom2 = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_join_bottom2);
holder.leaf2 = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_leaf2);
holder.tree = (ImageView) convertView
.findViewById(R.id.lv_item_tree_structure_tree); convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tree.setVisibility(View.GONE);
holder.joinBottom.setVisibility(View.GONE);
holder.leaf.setVisibility(View.GONE);
holder.joinBottom2.setVisibility(View.GONE);
holder.leaf2.setVisibility(View.GONE); // 如果是父级
if ("1".equals(dataItem.get("org_level"))) {
holder.tree.setVisibility(View.VISIBLE);
holder.joinBottom.setVisibility(View.GONE);
holder.leaf.setVisibility(View.GONE);
holder.joinBottom2.setVisibility(View.GONE);
holder.leaf2.setVisibility(View.GONE); } else if ("2".equals(dataItem.get("org_level"))) {// 如果是子级
holder.joinBottom2.setVisibility(View.GONE);
holder.leaf2.setVisibility(View.GONE);
holder.tree.setVisibility(View.GONE); holder.joinBottom.setVisibility(View.VISIBLE);
holder.leaf.setVisibility(View.VISIBLE);
} else { // 3级
holder.tree.setVisibility(View.GONE); holder.joinBottom2.setVisibility(View.VISIBLE);
holder.leaf2.setVisibility(View.VISIBLE);
holder.joinBottom.setVisibility(View.VISIBLE);
holder.leaf.setVisibility(View.VISIBLE);
} try {
holder.text.setText(dataItem.get("org_code").toString() + " "
+ dataItem.get("org_name").toString());
} catch (Exception e) {
} convertView.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
dataItem.put(IS_CHECKED, CHECKED_TRUE); // 把其它的营业部设置为false
for (int i = 0; i < mDataList.size(); i++) {
if (i == position) {
continue;
} else {
mDataList.get(i).put(IS_CHECKED, CHECKED_FALSE);
}
}
}
return false;
}
}); return convertView;
} /**
* 拿到已选择营业部的代码字符串,代码之间逗号分隔
*
* @return
*/
public String getSelectedOrgCodes() {
StringBuilder sbOrgCodes = new StringBuilder();
for (int i = 0; i < mDataList.size(); i++) {
if (mDataList.get(i).get(IS_CHECKED).equals(CHECKED_TRUE)) {
if (sbOrgCodes.length() <= 2) {
sbOrgCodes.append(mDataList.get(i).get("org_code")
.toString());
} else {
sbOrgCodes.append(","
+ mDataList.get(i).get("org_code").toString());
}// end else
}// end if
}// end for Log.i(TAG, "getSelectedOrgCodes: " + sbOrgCodes.toString()); return sbOrgCodes.toString();
} /**
* 拿到已选择的营业部(org_code+org_name)
*
* @return
*/
public String getSelectedOrg() {
StringBuilder sbOrg = new StringBuilder();
for (int i = 0; i < mDataList.size(); i++) {
if (mDataList.get(i).get(IS_CHECKED).equals(CHECKED_TRUE)) {
String strText = mDataList.get(i).get("org_code").toString()
+ " " + mDataList.get(i).get("org_name").toString();
if (sbOrg.length() <= 2) {
sbOrg.append(strText);
} else {
sbOrg.append("," + strText);
}// end else
}// end if
}// end for Log.i(TAG, "getSelectedOrg: " + sbOrg.toString()); return sbOrg.toString();
} /**
* 默认全部选中
*/
private void setDefaultChecked() {
for (int i = 0; i < mDataList.size(); i++) {
mDataList.get(i).put(IS_CHECKED, CHECKED_TRUE);
}
} /**
* 设置默认选中的营业部
*
* @param orgCode
*/
public void setDefaultChecked(String orgCode) {
for (int i = 0; i < mDataList.size(); i++) {
if (orgCode.contains(mDataList.get(i).get("org_code").toString())) {
mDataList.get(i).put(IS_CHECKED, CHECKED_TRUE);
} else { // 因为查询框里使用的多选营业部框跟这里使用的一个数据源,
// 为了避免其它地方对这造成的影响,所以全部初始化好
mDataList.get(i).put(IS_CHECKED, CHECKED_FALSE);
}
}
} class ViewHolder {
TextView text;
CheckBox cb;
ImageView tree;// 树形图
ImageView joinBottom;// 连接线
ImageView leaf;// 子节点图
ImageView joinBottom2;// 3级连接线
ImageView leaf2;// 3级子节点图
} }

ListView的item布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/lv_item_tree_structure_tree"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:scaleType="fitXY"
android:src="@drawable/customer_account_mgr"
android:visibility="gone" />
<ImageView
android:id="@+id/lv_item_tree_structure_join_bottom"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:scaleType="fitXY"
android:src="@drawable/joinbottom"
android:visibility="gone" />
<ImageView
android:id="@+id/lv_item_tree_structure_leaf"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:scaleType="fitXY"
android:src="@drawable/leaf"
android:visibility="gone" />
<ImageView
android:id="@+id/lv_item_tree_structure_join_bottom2"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:scaleType="fitXY"
android:src="@drawable/joinbottom"
android:visibility="gone" />
<ImageView
android:id="@+id/lv_item_tree_structure_leaf2"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:scaleType="fitXY"
android:src="@drawable/leaf"
android:visibility="gone" />
<CheckBox
android:id="@+id/lv_item_tree_structure_cb"
style="@style/custom_checkbox"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:clickable="false" />
<TextView
android:id="@+id/lv_item_tree_structure_text"
android:layout_width="400dp"
android:layout_height="40dp"
android:gravity="center_vertical"
android:paddingLeft="10dp"
android:textColor="@color/black"
android:textSize="20sp" />
</LinearLayout>

Android - N级树形结构实现父级标志图


Android - N级树形结构实现子级标志图

Android - N级树形结构实现父级和子级的连接线

上一篇:MySQL sql语言的笔记


下一篇:怎样注册uber司机 如何注册uber司机 最新详细攻略