您好,登錄后才能下訂單哦!
android中怎么自定義樹(shù)形,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。
TreeView.java代碼:
package com.tbx.android.widget; import java.util.ArrayList; public class TreeView extends ListView implements OnItemClickListener { private static String TAG = "TreeView"; List<TreeElement> treeElements = null;// 所有節(jié)點(diǎn)集合 List<TreeElement> currentElements = null;// 當(dāng)前顯示的節(jié)點(diǎn)集合 List<TreeElement> tempElements = null;// 用于臨時(shí)存儲(chǔ) HashMap<String, List<TreeElement>> deleteMap = new HashMap<String, List<TreeElement>>(); //用于存儲(chǔ)要?jiǎng)h除的子節(jié)點(diǎn),以及間接子節(jié)點(diǎn)。 TreeViewAdapter adapter = null;// 用于數(shù)據(jù)填充 LastLevelItemClickListener itemClickCallBack;// 用戶點(diǎn)擊事件回調(diào) public TreeView(final Context context, AttributeSet attrs) { super(context, attrs); Log.d(TAG, "create with TreeView(Context context, AttributeSet attrs)"); treeElements = new ArrayList<TreeElement>(); currentElements = new ArrayList<TreeElement>(); adapter = new TreeViewAdapter(context, currentElements); this.setAdapter(adapter); itemClickCallBack = new LastLevelItemClickListener() { @Override public void onLastLevelItemClick(int position,TreeViewAdapter adapter) { Log.d(TAG, "last level element " + currentElements.get(position).getTitle() + " is clicked"); } }; this.setOnItemClickListener(this); } public void initData(Context context, List<TreeElement> treeElements) { this.treeElements = treeElements; getFirstLevelElements(context); adapter.notifyDataSetChanged(); } /** * 設(shè)置點(diǎn)擊事件回調(diào)接口 * * @param itemClickCallBack */ public void setLastLevelItemClickCallBack(LastLevelItemClickListener itemClickCallBack) { this.itemClickCallBack = itemClickCallBack; } /** * 初始化樹(shù)形結(jié)構(gòu)列表數(shù)據(jù),把第一層級(jí)的數(shù)據(jù)添加到currentElements中 */ public void getFirstLevelElements(Context context) { Log.d(TAG, "initCurrentElements"); int size = treeElements.size(); Log.d(TAG, "tree elements num is: " + size); if (currentElements == null) { currentElements = new ArrayList<TreeElement>(); } currentElements.clear(); for (int i = 0; i < size; i++) { if (treeElements.get(i).getLevel() == 1) { currentElements.add(treeElements.get(i)); Log.d(TAG, "find a first level element: " + treeElements.get(i)); } } } /** * 從所有節(jié)點(diǎn)集合中獲取某父節(jié)點(diǎn)的子節(jié)點(diǎn)集合 * * @param parentId * @return */ private List<TreeElement> getChildElementsFromAllById(String parentId) { tempElements = new ArrayList<TreeElement>(); int size = treeElements.size(); for (int i = 0; i < size; i++) { String temptParentId = treeElements.get(i).getParentId() ; if(temptParentId != null){ if (temptParentId.equalsIgnoreCase(parentId)) { tempElements.add(treeElements.get(i)); Log.d(TAG, "find a child element: " + treeElements.get(i)); } } } return tempElements; } /** * 從當(dāng)前顯示的節(jié)點(diǎn)集合中 , 獲取某父節(jié)點(diǎn)的子節(jié)點(diǎn)集合 * @param parentId * @return */ private List<TreeElement> getChildElementsFromCurrentById(String parentId) { Log.d(TAG, "getChildElementsFromCurrentById parentId: " + parentId); if (tempElements == null) { tempElements = new ArrayList<TreeElement>(); } else { tempElements.clear(); } int size = currentElements.size(); if(size > 0){ for(TreeElement treeElement : currentElements){ String temp = treeElement.getParentId(); if(temp != null){ if (temp.equalsIgnoreCase(parentId)) { tempElements.add(treeElement); Log.d(TAG, "find a child element to delete: " +treeElement); } } } } return tempElements; } /** * 刪除某父節(jié)點(diǎn)的所有子節(jié)點(diǎn)集合(包括直接節(jié)點(diǎn)和間接節(jié)點(diǎn)) * @param parentId * @return */ private synchronized boolean delAllChildElementsByParentId(String parentId) { Log.e(TAG, "delAllChildElementsByParentId: " + parentId); List<TreeElement> childElments = getChildElementsFromCurrentById(parentId); List<TreeElement> treeElementsToDel = deleteMap.get(parentId); if (treeElementsToDel == null) { treeElementsToDel = new ArrayList<TreeElement>(); deleteMap.put(parentId, treeElementsToDel); } else { treeElementsToDel.clear(); } int size = childElments.size(); Log.e(TAG, "childElments size : " + size); TreeElement childElement = null; for (int i = 0; i < size; i++) { childElement = childElments.get(i); //尋找間接節(jié)點(diǎn) if (childElement.hasChild && childElement.fold) { treeElementsToDel.add(childElement); } } size = treeElementsToDel.size(); Log.e(TAG, "treeElementsToDel size : " + size); if(size > 0){ //刪除間接節(jié)點(diǎn) List<TreeElement> deleteTreeElement = treeElementsToDel; for(TreeElement element : deleteTreeElement){ delAllChildElementsByParentId(element.getId()); } } //刪除直接節(jié)點(diǎn) delDirectChildElementsByParentId(parentId); return true; } /** * 刪除某父節(jié)點(diǎn)的直接子節(jié)點(diǎn)集合 * * @param parentId * @return */ private synchronized boolean delDirectChildElementsByParentId( String parentId) { Log.d(TAG, "delDirectChildElementsByParentId(): " + parentId); boolean success = false; if (currentElements == null || currentElements.size() == 0) { Log.d(TAG, "delChildElementsById() failed,currentElements is null or it's size is 0"); return success; } synchronized (currentElements) { int size = currentElements.size(); Log.d(TAG, "begin delete"); for (int i = size - 1; i >= 0; i--) { String temp = currentElements.get(i).getParentId(); if(temp != null && temp.equalsIgnoreCase(parentId)){ currentElements.get(i).fold = false;// 記得隱藏子節(jié)點(diǎn)時(shí)把展開(kāi)狀態(tài)設(shè)為false currentElements.remove(i); } } } success = true; return success; } /** * 根據(jù)id查下標(biāo) * * @param id * @return */ @SuppressWarnings("unused") private int getElementIndexById(String id) { int num = currentElements.size(); for (int i = 0; i < num; i++) { if (currentElements.get(i).getId().equalsIgnoreCase(id)) { return i; } } return -1; } @SuppressWarnings("unused") private TreeElement getElementById(String id){ int num = currentElements.size(); if( num > 0){ for (int i = 0; i < num; i++) { if (currentElements.get(i).getId().equalsIgnoreCase(id)) { return currentElements.get(i); } } } return null; } @Override public void onItemClick(AdapterView<?> arg0, View convertView, int position, long id) { TreeElement element = currentElements.get(position); if (element.isHasChild()) {// 當(dāng)前節(jié)點(diǎn)有子節(jié)點(diǎn)時(shí)只進(jìn)行數(shù)據(jù)顯示或隱藏等操作 if (!element.isFold()) {// 當(dāng)前父節(jié)點(diǎn)為未展開(kāi)狀態(tài) currentElements.addAll(position + 1,this.getChildElementsFromAllById(element.getId())); } else if (element.fold) {// 當(dāng)前父節(jié)點(diǎn)為展開(kāi)狀態(tài) boolean success = this.delAllChildElementsByParentId(element.getId()); Log.d(TAG, "delete child state: " + success); if (!success) { return; } } element.setFold(!element.isFold());// 設(shè)置反狀態(tài) adapter.notifyDataSetChanged();// 刷新數(shù)據(jù)顯示 } else {// 當(dāng)前節(jié)點(diǎn)有子節(jié)點(diǎn)時(shí)只進(jìn)行用戶自定義操作 itemClickCallBack.onLastLevelItemClick(position,adapter); } } /** * 自定義內(nèi)部接口,用于用戶點(diǎn)擊最終節(jié)點(diǎn)時(shí)的事件回調(diào) */ public interface LastLevelItemClickListener { public void onLastLevelItemClick(int position,TreeViewAdapter adapter); } }
TreeElement.java代碼:
/** * 類(lèi)名:TreeElement.java * 類(lèi)描述:樹(shù)形結(jié)構(gòu)節(jié)點(diǎn)類(lèi) * 創(chuàng)建時(shí)間:2012-11-23 16:32 */ public class TreeElement { String id = null;// 當(dāng)前節(jié)點(diǎn)id String title = null;// 當(dāng)前節(jié)點(diǎn)文字 boolean hasParent = false;// 當(dāng)前節(jié)點(diǎn)是否有父節(jié)點(diǎn) boolean hasChild = false;// 當(dāng)前節(jié)點(diǎn)是否有子節(jié)點(diǎn) boolean childShow = false;// 如果子節(jié)點(diǎn),字節(jié)當(dāng)當(dāng)前是否已顯示 String parentId = null;// 父節(jié)點(diǎn)id int level = -1;// 當(dāng)前界面層級(jí) boolean fold = false;// 是否處于展開(kāi)狀態(tài) ... }
TreeViewAdapter.java
package com.tbx.android.adapter; import java.util.List; /** * 類(lèi)名:TreeViewAdapter.java * 類(lèi)描述:用于填充數(shù)據(jù)的類(lèi) * 創(chuàng)建時(shí)間:2012-11-23 16:32 */ public class TreeViewAdapter extends BaseAdapter { class ViewHolder { ImageView icon; TextView title; } Context context; ViewHolder holder; LayoutInflater inflater; List<TreeElement> elements; public TreeViewAdapter(Context context, List<TreeElement> elements) { this.context = context; this.elements = elements; } @Override public int getCount() { return elements.size(); } @Override public Object getItem(int position) { return elements.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { /** * ---------------------- get holder------------------------ */ if (convertView == null) { if (inflater == null) { inflater = LayoutInflater.from(context); } holder = new ViewHolder(); convertView = inflater .inflate(R.layout.tree_view_item, null); holder.icon = (ImageView) convertView .findViewById(R.id.tree_view_item_icon); holder.title = (TextView) convertView .findViewById(R.id.tree_view_item_title); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } /** * ---------------------- set holder-------------------------- */ if (elements.get(position).isHasChild()) {// 有子節(jié)點(diǎn),要顯示圖標(biāo) if (elements.get(position).isFold()) { holder.icon.setImageResource(R.drawable.tree_view_icon_open); } else if (!elements.get(position).isFold()) { holder.icon.setImageResource(R.drawable.tree_view_icon_close); } holder.icon.setVisibility(View.VISIBLE); } else {// 沒(méi)有子節(jié)點(diǎn),要隱藏圖標(biāo) holder.icon.setImageResource(R.drawable.tree_view_icon_close); holder.icon.setVisibility(View.INVISIBLE); } holder.icon.setPadding(25 * (elements.get(position).getLevel()), 0, 0, 0);// 根據(jù)層級(jí)設(shè)置縮進(jìn) holder.title.setText(elements.get(position).getTitle()); holder.title.setTextSize(35 - elements.get(position).getLevel() * 5); // 根據(jù)層級(jí)設(shè)置字體大小 return convertView; } }
MainActivity.java
public class MainActivity extends Activity { private TreeView lvAddress; //通訊錄列表 private List<TreeElement> lvAddressData = new ArrayList<TreeElement>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lvAddress = (TreeView) findViewById(R.id.frame_listview_address); LastLevelItemClickListener itemClickCallBack = new LastLevelItemClickListener() { // 創(chuàng)建節(jié)點(diǎn)點(diǎn)擊事件監(jiān)聽(tīng) @Override public void onLastLevelItemClick(int position, TreeViewAdapter adapter) { TreeElement element = (TreeElement) adapter.getItem(position); //然后自己處理 } }; //初始化數(shù)據(jù) initData(); lvAddress.initData(this, lvAddressData);// 初始化數(shù)據(jù) lvAddress.setLastLevelItemClickCallBack(itemClickCallBack);// 設(shè)置節(jié)點(diǎn)點(diǎn)擊事件監(jiān)聽(tīng) } private void initData() {//測(cè)試數(shù)據(jù) TreeElement root = new TreeElement(); root.setId("01"); root.setLevel(1); root.setTitle("好友"); root.setFold(false); root.setHasChild(true); root.setHasParent(false); root.setParentId(null); lvAddressData.add(root); TreeElement twoLevel = new TreeElement(); twoLevel.setId("0101"); twoLevel.setLevel(2); twoLevel.setTitle("初中同學(xué)"); twoLevel.setFold(false); twoLevel.setHasChild(true); twoLevel.setHasParent(true); twoLevel.setParentId("01"); lvAddressData.add(twoLevel); TreeElement threeLevel = new TreeElement(); threeLevel.setId("010101"); threeLevel.setLevel(3); threeLevel.setTitle("發(fā)財(cái)"); threeLevel.setFold(false); threeLevel.setHasChild(false); threeLevel.setHasParent(true); threeLevel.setParentId("0101"); lvAddressData.add(threeLevel); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
tree_view_item.xml布局內(nèi)容
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_vertical" android:orientation="horizontal" > <ImageView android:id="@+id/tree_view_item_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tree_view_item_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="15dip" /> </LinearLayout>
關(guān)于android中怎么自定義樹(shù)形問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。