這篇文章主要介紹支持多項(xiàng)選擇的ExpandableListView怎么用,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
金平網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),金平網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為金平上1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的金平做網(wǎng)站的公司定做!
目標(biāo)(需求):
1. 創(chuàng)建一個(gè)可展開(kāi)可收縮的列表;
2. 其列表項(xiàng)包含多個(gè)checkable的部件,當(dāng)選擇某一行時(shí),該行包含的checkable的部件需要作出相應(yīng)的變化;
3. 可以選擇多個(gè)列表項(xiàng),并且這些列表項(xiàng)可被讀出
結(jié)果圖:
.jpg)
實(shí)現(xiàn):
1. 創(chuàng)建主layout用于規(guī)劃列表顯示。對(duì)于具體的列表項(xiàng),為了實(shí)現(xiàn)的方便我們也創(chuàng)建一個(gè)layout文件。
<?xml version="1.0" encoding="utf-8"?> <com.home.mymultichecklistview.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <com.home.mymultichecklistview.CheckableTextView android:id="@+id/item" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="6dip" android:layout_weight="1" /> <com.home.mymultichecklistview.InertCheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:maxWidth="40dp" android:maxHeight="40dp" android:focusable="false" android:layout_gravity="right" android:button="@drawable/checkbox" /> </com.home.mymultichecklistview.CheckableLinearLayout>
2. 類(lèi)似ListView,ExpandableListView也是通過(guò)Adapter來(lái)管理其包含的各種元素和操作,這里我們創(chuàng)建一個(gè)擴(kuò)展自BaseExpandableListAdapter的Adapter。與ListView不同的是,ExpandableListAdapter要渲染實(shí)現(xiàn)兩級(jí)View(Group級(jí)和列表項(xiàng)級(jí))的操作。它通過(guò)getGroupView()渲染Group項(xiàng),通過(guò)getChildView()渲染列表子項(xiàng)。
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
View groupView = convertView;
if (groupView == null) {
groupView = new TextView(context);
((TextView)groupView).setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
groupView.setPadding(50,0,0,0);
}
((TextView)groupView).setText(groupData[groupPosition]);
((TextView)groupView).setTextColor(context.getResources().getColor(R.color.fgcolor));
return groupView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
View itemView = convertView;
final ViewHolder vh;
if (itemView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = inflater.inflate(R.layout.item_view, null);
vh = new ViewHolder();
vh.layout = (CheckableLinearLayout)itemView.findViewById(R.id.layout);
vh.item = (TextView)itemView.findViewById(R.id.item);
itemView.setTag(vh);
} else {
vh = (ViewHolder)itemView.getTag();
}
vh.item.setText(itemData[groupPosition][childPosition]);
final ExpandableListView listView = ((ExpandableListView)((MainActivity)context).findViewById(R.id.list));
final int position = listView.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
listView.setItemChecked(position, checkedState[groupPosition][childPosition]);
vh.layout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((CheckableLinearLayout)v).toggle();
checkedState[groupPosition][childPosition] = !checkedState[groupPosition][childPosition];
listView.setItemChecked(position, ((CheckableLinearLayout)v).isChecked());
}
});
return itemView;
}3. 為每一列表子項(xiàng)容器創(chuàng)建OnClickListener監(jiān)聽(tīng)鼠標(biāo)的點(diǎn)擊事件。在這里要注意,由于列表子項(xiàng)包含了CheckBox,所以為了使點(diǎn)擊事件不要被CheckBox捕獲,我們需要?jiǎng)?chuàng)建一個(gè)擴(kuò)展自CheckBox的類(lèi)來(lái)屏蔽鼠標(biāo)和鍵盤(pán)事件。同時(shí),需要在這個(gè)容器里搜索其包含的checkable的部件并將check操作傳給這些部件。
Adapter中的方法getChildView()需要實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊監(jiān)聽(tīng)器:
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
View itemView = convertView;
final ViewHolder vh;
...
final int position = listView.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
listView.setItemChecked(position, checkedState[groupPosition][childPosition]);
vh.layout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((CheckableLinearLayout)v).toggle();
checkedState[groupPosition][childPosition] = !checkedState[groupPosition][childPosition];
listView.setItemChecked(position, ((CheckableLinearLayout)v).isChecked());
}
});
return itemView;
}擴(kuò)展自CheckBox的InertCheckBox需要屏蔽鍵盤(pán)和鼠標(biāo)事件
public class InertCheckBox extends CheckBox {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//直接返回false
return false;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
//直接返回false
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//直接返回false
return false;
}
@Override
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
//直接返回false
return false;
...
}列表項(xiàng)容器需要實(shí)現(xiàn)Checkable接口并且把check操作傳遞給其checkable的子部件
public class CheckableLinearLayout extends LinearLayout implements Checkable {
...
@Override
public void setChecked(boolean checked) {
this.isChecked = checked;
for (Checkable view : checkableViews) {
view.setChecked(checked);
}
}
@Override
public boolean isChecked() {
return this.isChecked;
}
@Override
public void toggle() {
isChecked = !isChecked;
for (Checkable view : checkableViews) {
view.toggle();
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
for (int i=0; i<this.getChildCount(); i++) {
findCheckableChild(this.getChildAt(i));
}
}
private void findCheckableChild(View child) {
if (child instanceof Checkable) {
checkableViews.add((Checkable)child);
}
if (child instanceof ViewGroup) {
for (int i=0; i<((ViewGroup)child).getChildCount(); i++) {
findCheckableChild(((ViewGroup) child).getChildAt(i));
}
}
}
...
}開(kāi)發(fā)中遇到的問(wèn)題:
1. 渲染后的child view類(lèi)似于放在一個(gè)cache中,下一次再通過(guò)convertView取時(shí),由于Group的收縮或擴(kuò)展操作會(huì)隱藏/顯示一些child view,導(dǎo)致某一child View的flat position發(fā)生變化,獲取到的convertView不是原來(lái)希望獲取的view。所以,每次獲取到view后都需要對(duì)其內(nèi)容重新設(shè)置(比如設(shè)置正確文本,設(shè)置監(jiān)聽(tīng)器等)
2. check的狀態(tài)設(shè)置很tricky。我開(kāi)始認(rèn)為直接在監(jiān)聽(tīng)器中調(diào)用容器的toggle()方法即可。結(jié)果發(fā)現(xiàn)一旦某個(gè)group做了expand或collapse操作后,所有列表項(xiàng)的check狀態(tài)全沒(méi)了。后來(lái)發(fā)現(xiàn)原來(lái)group做了expand/collapse操作后,ListView會(huì)對(duì)其所有子項(xiàng)重新設(shè)置check狀態(tài),而check狀態(tài)的值是存在ListView的一個(gè)SparseBooleanArray表里(mCheckStates)。由于沒(méi)有對(duì)這個(gè)表進(jìn)行設(shè)置,所以一刷新check狀態(tài)就全丟了。并且由于這個(gè)表的key是基于拉平后所有可見(jiàn)的列表項(xiàng)的位置定的,當(dāng)group擴(kuò)展或收縮后,同一個(gè)列表項(xiàng),它拉平后的位置還會(huì)變化。所以,為了解決這個(gè)問(wèn)題,我在adapter里增加了一個(gè)二維表用于記錄每一列表項(xiàng)的check狀態(tài)。在執(zhí)行 listView的setItemChecked函數(shù)時(shí),其check狀態(tài)是從這個(gè)自己創(chuàng)建的表中讀出的,不能通過(guò)ListView的mCheckStates來(lái)讀。這個(gè)我認(rèn)為是ExpandableListView的一個(gè)缺陷。
遺留的已知問(wèn)題:
我使用了@drawable/checkbox 來(lái)定義checkbox check 和uncheck時(shí)的圖片,但當(dāng)checkbox被check上時(shí),這個(gè)checked的圖片沒(méi)有生效。不知道為什么,還需要進(jìn)一步debug.
以上是“支持多項(xiàng)選擇的ExpandableListView怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
當(dāng)前題目:支持多項(xiàng)選擇的ExpandableListView怎么用
本文鏈接:http://chinadenli.net/article48/jgjcep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、小程序開(kāi)發(fā)、虛擬主機(jī)、自適應(yīng)網(wǎng)站、手機(jī)網(wǎng)站建設(shè)、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)