android ListView 實現3級節點 (可拓展N級)
ListView實現二級節點想必大家都知道可以用ExpandableListView 就可以輕鬆實現,但是要實現3級甚至多級選單怎麼實現呢? 再利用ExpandableListView 就會十分繁瑣,今天我們來探究另一種實現方式來實現。
思路:每次點選展開子選單 ,可以理解為 listView的一次重繪(資料更新<增加子節點資料>),而收起子選單就是移除當前節點下的子資料,這是資料更新。對於介面每一個itemView的實現可以在adapter裡面實現,根據沒個子元素的級別,是否含有子節點,是否已經展開來配置不同的介面顯示效果。首先來看實現的效果:
1:首先看子元素bean
package com.example.androidexpandablelistview; import java.util.ArrayList; import java.util.List; /** * 元素 可根據需要新增新的屬性 * @author jrh * */ public class TreeElement { /** * 各個元素的層級標識 */ private int parentLevel; /** * 節點顯示標題 */ private String noteName; /** * 子節點元素集合 */ private ArrayList<TreeElement> dataList = new ArrayList<TreeElement>(); /** * 是否已擴充套件 */ private boolean isExpandAble; /** * 是否有子節點元素 */ private boolean isHasChild; /** * 當前節點位置 */ private int position; /** * * @param parentLevel 各個元素的層級標識 * @param noteName 節點顯示標題 * @param dataList 子節點元素集合 * @param isExpandAble 是否已擴充套件 * @param isHasChild 是否有子節點元素 * @param position 當前節點位置 */ public TreeElement(int parentLevel, String noteName, ArrayList<TreeElement> dataList, boolean isExpandAble, boolean isHasChild, int position) { super(); this.parentLevel = parentLevel; this.noteName = noteName; this.dataList = dataList; this.isExpandAble = isExpandAble; this.isHasChild = isHasChild; this.position = position; } public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } public boolean isHasChild() { return isHasChild; } public void setHasChild(boolean isHasChild) { this.isHasChild = isHasChild; } public int getParentLevel() { return parentLevel; } public void setParentLevel(int parentLevel) { this.parentLevel = parentLevel; } public String getNoteName() { return noteName; } public void setNoteName(String noteName) { this.noteName = noteName; } public ArrayList<TreeElement> getDataList() { return dataList; } public void setDataList(ArrayList<TreeElement> dataList) { this.dataList = dataList; } public boolean isExpandAble() { return isExpandAble; } public void setExpandAble(boolean isExpandAble) { this.isExpandAble = isExpandAble; } }
2:資料更新adapter
package com.example.androidexpandablelistview; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; /** * 處理點選 資料更新 通用 * @author jrh * */ public class TreeAdapter extends BaseAdapter { private List<TreeElement> mParentList; private Context context; public TreeAdapter(List<TreeElement> parentList, Context context) { super(); this.mParentList = parentList; this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return mParentList == null ? 0 : mParentList.size(); } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return mParentList == null ? null : mParentList.get(arg0); } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { // TODO Auto-generated method stub return null; } public void onExpandClick(int position) { // 父節點沒有子元素直接返回 if (!mParentList.get(position).isHasChild()) { return; } // 父節點已經擴充套件 if (mParentList.get(position).isExpandAble()) { mParentList.get(position).setExpandAble(false); TreeElement element = mParentList.get(position); // 遍歷已擴充套件的元素,刪除 ArrayList<TreeElement> temp = new ArrayList<TreeElement>(); // 從當前點的下一個元素開始隱藏 for (int i = position + 1; i < mParentList.size(); i++) { if (element.getParentLevel() >= mParentList.get(i) .getParentLevel()) { break; } temp.add(mParentList.get(i)); } mParentList.removeAll(temp); for (int i = position + 1; i < mParentList.size(); i++) { mParentList.get(i).setPosition(i); } notifyDataSetChanged(); } else { // 父節點為點開 TreeElement objElement = mParentList.get(position); objElement.setExpandAble(true); int level = objElement.getParentLevel(); int nextLevel = level + 1; ArrayList<TreeElement> tempList = objElement.getDataList(); //擴充父類集合 for (int i = 0; i < tempList.size(); i++) { TreeElement element = tempList.get(i); element.setParentLevel(nextLevel); element.setExpandAble(false); mParentList.add(position+1,element); } for (int i = position+1; i <mParentList.size(); i++) { mParentList.get(i).setPosition(i); } notifyDataSetChanged(); } } }
3:具體適配adapter
package com.example.androidexpandablelistview;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.LayerDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* 具體子adapter 可根據不同的要求自定義
* @author jrh
*
*/
public class DetaiTreeAdapter extends TreeAdapter {
private LayoutInflater inflater;
private List<TreeElement> mParentList;
public DetaiTreeAdapter(List<TreeElement> parentList, Context context) {
super(parentList, context);
inflater = LayoutInflater.from(context);
mParentList = parentList;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return super.getCount();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return super.getItem(arg0);
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return super.getItemId(arg0);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
// hodler 需為區域性變數
ViewHodler hodler = new ViewHodler();
TreeElement treeElement = mParentList.get(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.itemview, null);
hodler.icon = (ImageView) convertView.findViewById(R.id.ic_img);
hodler.title = (TextView) convertView.findViewById(R.id.title_tv);
hodler.connection = (RelativeLayout) convertView
.findViewById(R.id.layout_treeview_connection);
convertView.setTag(hodler);
} else {
hodler = (ViewHodler) convertView.getTag();
}
// "-"; "+";圖示處理
if (treeElement.isHasChild()) {
if (treeElement.isExpandAble()) {
if (treeElement.getParentLevel() == 0) {
hodler.icon
.setImageResource(R.drawable.knowledgetree_rootexpanded);
} else {
hodler.icon
.setImageResource(R.drawable.knowledgetree_expanded);
}
} else {
if (treeElement.getParentLevel() == 0) {
hodler.icon
.setImageResource(R.drawable.knowledgetree_rootunexpanded);
} else {
hodler.icon
.setImageResource(R.drawable.knowledgetree_unexpanded);
}
}
} else {
hodler.icon.setImageResource(R.drawable.knowledgetree_leaf);
}
// 設定 展開 時,“-”、“+”間的連線
if (treeElement.getParentLevel() == 0) {
if (position + 1 < getCount()
&& mParentList.get(position + 1).getParentLevel() == 0) {
hodler.connection.setBackgroundResource(0);
} else if (position + 1 == getCount()) {
hodler.connection.setBackgroundResource(0);
} else {
hodler.connection
.setBackgroundResource(R.drawable.knowledgetree_halfconnection_root);
}
} else {
if (position + 1 < getCount()
&& mParentList.get(position + 1).getParentLevel() == 0) {
hodler.connection
.setBackgroundResource(R.drawable.knowledgetree_halfconnection_leaf);
} else if (position == getCount() - 1)
hodler.connection
.setBackgroundResource(R.drawable.knowledgetree_halfconnection_leaf);
else
hodler.connection
.setBackgroundResource(R.drawable.knowledgetree_connection);
}
// 標題背景設定
if (treeElement.getParentLevel() == 0) {
hodler.title.setBackgroundColor(Color.BLUE);
hodler.title.setPadding(8, 8, 8, 8);
} else if (treeElement.getParentLevel() == 1) {
hodler.title.setBackgroundColor(Color.RED);
hodler.title.setPadding(38, 8, 8, 8);
} else if (treeElement.getParentLevel() == 2) {
hodler.title.setPadding(78, 8, 8, 8);
hodler.title.setBackgroundColor(Color.GRAY);
}
hodler.title.setTextColor(Color.WHITE);
hodler.title.setText(treeElement.getNoteName());
return convertView;
}
@Override
public void onExpandClick(int position) {
super.onExpandClick(position);
}
class ViewHodler {
ImageView icon;
TextView title;
RelativeLayout connection;
}
}
4:主介面
package com.example.androidexpandablelistview;
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView mLv;
private DetaiTreeAdapter adapter;
private ArrayList<TreeElement> dataList;
private ArrayList<TreeElement> seconddataList;
private ArrayList<TreeElement> thirddataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initData();
initEvent();
}
/**
* 事件處理
*/
private void initEvent() {
mLv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
adapter.onExpandClick(arg2);
}
});
}
/**
* 資料載入
*/
private void initData() {
dataList = new ArrayList<TreeElement>();
seconddataList = new ArrayList<TreeElement>();
thirddataList = new ArrayList<TreeElement>();
adapter = new DetaiTreeAdapter(dataList, MainActivity.this);
mLv.setAdapter(adapter);
//模擬三級節點資料
for (int i = Data.thridTitle.length-1; i >=0; i--) {
TreeElement element = new TreeElement(2, Data.thridTitle[i], new ArrayList<TreeElement>(),
false, false, i);
thirddataList.add(element);
}
//模擬二級節點資料
for (int i = Data.secondTitle.length-1; i >=0; i--) {
TreeElement element = new TreeElement(1, Data.secondTitle[i],
i == 0 ? thirddataList : null, false,
i == 0 ? true : false, i);
seconddataList.add(element);
}
//模擬一級節點資料
for (int i = 0; i < Data.title.length; i++) {
TreeElement element = new TreeElement(0, Data.title[i],
i == 0 ? seconddataList : null, false, i == 0 ? true
: false, i);
dataList.add(element);
}
adapter.notifyDataSetChanged();
}
private void initView() {
mLv = (ListView) findViewById(R.id.lv);
}
}
5:模擬資料
package com.example.androidexpandablelistview;
/**
* 模擬資料
* @author jrh
*
*/
public class Data {
public static String title[] = {"常識判斷","言語理解","數量關係","判斷推理","資料分析"};
public static String secondTitle[]={"政治","經濟","法律","歷史","人文"};
public static String thridTitle[] ={"時政","馬克思主義哲學","中共黨史","中國特色社會主義體系"};
}
6:介面佈局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
7:itemView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|left"
android:orientation="horizontal"
android:paddingLeft="8dp" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
<RelativeLayout
android:id="@+id/layout_treeview_connection"
android:layout_width="wrap_content"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/img_treeview_ico"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:scaleType="fitXY"
android:contentDescription="@string/app_name" />
</RelativeLayout>
<ImageView
android:id="@+id/ic_img"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:textSize="18sp" />
</LinearLayout>
相關推薦
android ListView 實現3級節點 (可拓展N級)
ListView實現二級節點想必大家都知道可以用ExpandableListView 就可以輕鬆實現,但是要實現3級甚至多級選單怎麼實現呢? 再利用ExpandableListView 就會十分繁瑣,今天我們來探究另一種實現方式來實現。
Android ListView分兩列顯示(不用自定義Adapter)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_pa
Socket實現仿QQ聊天(可部署於廣域網)附原始碼(2)-伺服器搭建
1.前言 這是本系列的第二篇文章,第一篇文章得到了很多朋友們的支援,在這裡表示非常的感謝。對於這一系列文章需要補充的是這只是一篇入門級別的Socket通訊文章,對於專業人員來說完全可以跳過。本文只介紹一些基本TCP通訊技術並使用該技術實現聊天功能。本篇文章實現聊
XML(可拓展標記語言)
tle odin 對齊 cda 必須 style 結構 有一個 name 一、XML文檔基本結構 1.XML聲明(一般位於文檔的第一句話) <?xml version="1.0" encoding="utf-8"?> 2.每個XML文檔都有且僅有一個根元
QML ListView實現樹形二級列表(類似 android ExpandableListView控制元件)
前言 QML 中沒有直接提供類似 android 的ExpandableListView二級列表控制元件,treeView,但是用 treeView 實在是有些不方便,並且達不到想要的效果,所以乾脆用 ListView 來擴充套件一個,這其中也參考了網上一些用法
Android自動化之adb模擬操作(可實現按鍵精靈和手機輸入法)
最近因為工作需要,需要實現某一應用自動操作android手機的業務場景。網上查了下,發現按鍵精靈早就有了Android版本,於是研究了下它。 我們知道,手機連線電腦,在電腦上輸入adb命令是可以實現安裝應用、解除安裝應用、monkey等事件的,甚至可以指定點選
C++工作筆記-3種方法對資料型別進行拆分(可用於各種協議)
比如用Long Long存3個數據的內容。 這裡要知道大小端的知識點。 方法一是用位運算; 方法二是用指標; 方法三是結構體(本質上也是指標); 執行截圖如下: 原始碼如下: main.cpp #include <iostream> using
Android 自定義橫向進度條(可動態設定最大值)
自定義橫向進度條 主佈局檔案中包 含 <LinearLayout android:id="@+id/linearlayout" android:layout_width="match_parent" androi
一種高效的android雙擊退出(可擴充套件多擊)
參考Google,安卓手機中在檢視安卓系統版本的地方,三擊或者多擊會出現彩蛋,可以借鑑其原始碼進行實現。 //利用陣列來儲存時間 long[] mHits = new long[3]; @Override pub
基於Qt的OpenGL程式設計(3.x以上GLSL可程式設計管線版)---(十九)模板測試
(Vries的教程是我看過的最好的可程式設計管線OpenGL教程,沒有之一,其原地址如下,https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/02%20Stencil%20testing/ 關於模板測試的詳細知識瞭解
基於Qt的OpenGL程式設計(3.x以上GLSL可程式設計管線版)---(二十二)幀緩衝
Vries的教程是我看過的最好的可程式設計管線OpenGL教程,沒有之一,其原地址如下,https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/05%20Framebuffers/關於幀緩衝的詳細知識瞭解請看原教程,本
ztree實現checkbox樹形選單,並且父級節點不可選中(只有父級和子級選單);如何獲取選中子節點儲存到資料庫
1.使用ztree首先要匯入ztree的引入檔案(具體看自己需求,需要用ztree拓展功能的需要匯入拓展的js)、及樣式、圖片 注:ztree的樣式檔案必須和圖片檔案在同一級資料夾下 2.檔案引入之後,建立html頁面,樹形結構底層是套,如下圖所示即可
(三) arcgis runtime for android 100.3開發學習(載入影像切片服務)
今天我們來學關於arcgis影像切片服務,注意這個例子的demo比較簡單。我們主要看一下ArcGISMapImageLayer類的UML圖。程式碼是非常簡單的。 來看一下原始碼,非常簡單。 package com.esri.arcgisruntime.sample
(四) arcgis runtime for android 100.3開發學習(載入切片地圖服務)
今天我們來學習關於arcgis for android載入切片地圖服務相關知識。使用的是新版本的arcgis runtime for android100.3,我們來看下載入切片地圖服務的類ArcGISTiledLayer,該類繼承了ImageTiledLayer類,其中Ar
android:TextView實現文字走馬燈效果(欺騙系統獲取持久的焦點)
通常情況下我們想實現文字的走馬燈效果需要在xml檔案中這樣設定 <TextView android:layout_width="wrap_content"
Taurus.MVC 2.2.3.4 :WebAPI 實現許可權控制認證(及功能增強說明)
前言: 前兩天,當我還在老家收拾行旅,準備回廣州,為IT連的創業再戰365天時, 有網友扣上問:Taurus.MVC中如何實現認證和許可權控制,最好能做個小例子。 我一不小心回了句:等回廣州我再寫篇文章...... 然後,今天就來補文章了〜〜〜〜 Taurus.MVC Nuget 更新: 寫文之前
Android ListView 實現分批載入
ListView 想必大家都很熟悉了,當有大量資料需要顯示時,通常不會一次性把資料全部載入顯示出來,而是會先載入一部分,當用戶滑動螢幕滑到最後一條資料時,再載入下一部分資料。也就是分批載入。 這篇部落格將講解如何實現 ListView 的分批載入資料。
virtualbox中linux設定NAT和Host-Only上網(實現雙機互通同時可上外網)
關於虛擬機器中幾種網路連線方式請參考其他教程。平常,我們安裝好虛機,用橋接方式也就夠了。畢竟它能上內網和外網。但是有個問題,如果你的網路環境發生變化,虛機的Ip也會隨之改變(橋接的Ip和主機ip必須是同一網段)。為了解決此問題,喜歡折騰的我選擇了NAT網路+Host-Only
Android——ListView實現簡單列表
最近做一個black ant的溫控系統專案,裡面有很多列表項,但是用的時候,感覺封裝的已經挺好的了,自己拿過來改改程式碼就行了,所以用過之後也沒什麼感覺。現在趁著閒暇時間整理下簡
android api 中setVisibility( )的用法(可顯示或隱藏佈局或控制元件...)
View預設為可見的,在應用可以通過setVisibility 修改View的可見性,View可用性可以有如下三種狀態: View.VISIBLE View可見 View.INVISIBLE View不可以見,但仍然佔據可見時的大小和位置。 View.GONE View不可