您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
安卓用ExpandableListView二级列表代替listview嵌套實現二級列表
发布时间:2021-06-25 22:07:12编辑:雪饮阅读()
實際上在最開始的時候由於沒有接觸到ExpandableListView,那麽用的是listview,在這裏listview一般正常情況下使用是沒有問題的。
但是譬如實現二級列表時候可能會出現二級列表中多個item只顯示一個的情況,那麽還有另外一個情況就是比如二級列表item響應事件時候如果需要給獲取到當前二級item的position肯定是沒有問題的,但是此時如果想要獲取對應的一級列表中對應item的position就有點困難,或者本人太菜,目前還沒有找到這方面的方法,嘗試過tag的方式,但是失敗了。
那麽爲什麽要用ExpandableListView也是基於以上原因,起初群主介紹的,我抱著試試看的心態,確實這東西棒極了,基本沒有什麽bug的哦。
雖然只是二級,但是我想基本上沒有什麽特別恐怖的需求大於二級吧,就算有大於二級的,我想應該也還是有解決方案的吧。
用起來簡單的很,接下來我們來以實例進行分析:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_cut_library);
sdcardDir=Environment.getExternalStorageDirectory().toString();
scan_dir=new File(sdcardDir+File.separator+"penguinVideoEdit"+File.separator+"cut");
initialData();
ExpandableListView listview = (ExpandableListView) findViewById(R.id.expandablelistview);
adapter = new ActivityCutLibrary.MyExpandableListViewAdapter();
listview.setAdapter(adapter);
int groupCount = listview.getCount();
for (int i=0; i<groupCount; i++) {
listview.expandGroup(i);
};
}
提供數據支持
這裏initialData();爲了給這個二級列表提供數據支持。
這個數據支持其實現如:
private void initialData() {
scan_dir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
int video_num=countVideoNum(file.toString());
if(video_num>0){
ArrayList<VideoInfo> viList=new ArrayList<VideoInfo>();
getVideoFile(viList,file);
VideoList VideoList=new VideoList(file.toString(),viList);
VideoDirectoryList.add(VideoList);
return true;
}
}
return false;
}
});
}
這裏的結構其實就是一個嵌套集合ArrayList,外層每個對象又包含一個ArrayList集合。
這樣就形成了比如有n個目錄,每個目錄下有n個視頻文件的結構了,説白了外層集合主要作用就是遍歷這些目錄名。内層集合是遍歷每個目錄下的視頻文件。
獲取ExpandableListView實例
ExpandableListView listview = (ExpandableListView) findViewById(R.id.expandablelistview);
這裏從當前主佈局文件中定義的expandablelistview以id的形式獲取進來即可
當然這個主佈局中這個expandablelistview的實現如:
activity_main_cut_library.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".videocutlibrary.ActivityCutLibrary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ExpandableListView
android:groupIndicator="@null"
android:id="@+id/expandablelistview"
android:layout_margin="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
這個不僅文件中 android:groupIndicator="@null"是爲了防止二級列表中出現有下拉箭頭的,因爲這個ExpandableListView默認實現的二級列表是可以通過下拉箭頭進行摺叠或者展開的。而我這裏則是不需要此需求的。
創建並設置ExpandableListView的數據適配器
ExpandableListView listview = (ExpandableListView) findViewById(R.id.expandablelistview);
adapter = new ActivityCutLibrary.MyExpandableListViewAdapter();
listview.setAdapter(adapter);
這裏的數據適配器MyExpandableListViewAdapter,其實現如:
private MyExpandableListViewAdapter adapter;
private class MyExpandableListViewAdapter extends BaseExpandableListAdapter {
// 获得某个父项的某个子项
@Override
public Object getChild(int parentPos, int childPos) {
return VideoDirectoryList.get(parentPos).getVideoList().get(childPos);
}
// 获得父项的数量
@Override
public int getGroupCount() {
return VideoDirectoryList.size();
}
// 获得某个父项的子项数目
@Override
public int getChildrenCount(int parentPos) {
return VideoDirectoryList.get(parentPos).getVideoList().size();
}
// 获得某个父项
@Override
public Object getGroup(int parentPos) {
return VideoDirectoryList.get(parentPos);
}
// 获得某个父项的id
@Override
public long getGroupId(int parentPos) {
return parentPos;
}
// 获得某个父项的某个子项的id
@Override
public long getChildId(int parentPos, int childPos) {
return childPos;
}
// 按函数的名字来理解应该是是否具有稳定的id,这个方法目前一直都是返回false,没有去改动过
@Override
public boolean hasStableIds() {
return false;
}
// 获得父项显示的view
@Override
public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup) {
if (view == null) {
LayoutInflater inflater=LayoutInflater.from(ActivityCutLibrary.this);
view = inflater.inflate(R.layout.cut_library_parent_item, null);
}
TextView text = (TextView) view.findViewById(R.id.cut_from_name);
text.setText(VideoDirectoryList.get(parentPos).getAbsolutePath());
return view;
}
// 获得子项显示的view
@Override
public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup) {
VideoInfo videoInfo=VideoDirectoryList.get(parentPos).getVideoList().get(childPos);
if (view == null) {
LayoutInflater inflater=LayoutInflater.from(ActivityCutLibrary.this);
view = inflater.inflate(R.layout.cut_library_child_item, null);
}
ImageView iv=view.findViewById(R.id.iv);
loadCover(iv,videoInfo.getAbsolutePath(), ActivityCutLibrary.this);
TextView text = (TextView) view.findViewById(R.id.tv);
text.setText(videoInfo.getBrevityName());
Button delete_bt=view.findViewById(R.id.delete_bt);
View.OnClickListener listener=new View.OnClickListener(){
@Override
public void onClick(View v)
{
if(v==delete_bt){
Message msg = new Message();
String absolutePath=videoInfo.getAbsolutePath();
msg.obj=new CutLibraryVideoDeleteHandler(parentPos,childPos);
videoDeleteHandler.sendMessage(msg);
}
}
};
delete_bt.setOnClickListener(listener);
return view;
}
// 子项是否可选中,如果需要设置子项的点击事件,需要返回true
@Override
public boolean isChildSelectable(int i, int i1) {
return false;
}
}
可以看到這裏有一級目錄的getview還有二級目錄的getview,那麽其它事項都是和普通的listview差不多的。
使ExpandableListView二級列表默認展開
int groupCount = listview.getCount();
for (int i=0; i<groupCount; i++) {
listview.expandGroup(i);
};
ExpandableListView實現的二級列表默認情況下每個一級列表item的二級列表都是默認沒有展開的,要通過箭頭點擊之後才能展開。
但是這裏我們需求中是不用箭頭的,所以要通過代碼實現默認展開。
Item移除的處理
比起之前嵌套的listview的方式,ExpandableListView實現的二級列表中,某個二級item被移除時候的ui邏輯同步就更簡單了,比如我有一個邏輯是儅某個一級item中所有二級item被幹掉后,則該一級item也被幹掉,那麽基於我當前代碼環境其實現可以很簡單的就完成了,如:
public Handler videoDeleteHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
CutLibraryVideoDeleteHandler VH = (CutLibraryVideoDeleteHandler) msg.obj;
VideoInfo videoInfo=VideoDirectoryList.get(VH.getParentPos()).getVideoList().get(VH.getChildPos());
String absolutePath=videoInfo.getAbsolutePath();
File file = new File(absolutePath);
String parent=file.getParent();
if(file.delete()){
VideoDirectoryList.get(VH.getParentPos()).getVideoList().remove(VH.getChildPos());
if(VideoDirectoryList.get(VH.getParentPos()).getVideoList().size()==0){
VideoDirectoryList.remove(VH.getParentPos());
}
adapter.notifyDataSetChanged();
Toast.makeText(ActivityCutLibrary.this, "删除成功", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(ActivityCutLibrary.this, "删除失败", Toast.LENGTH_SHORT).show();
}
super.handleMessage(msg);
}
};
可以看到這裏我只通知了一次,因爲畢竟只有一個適配器
adapter.notifyDataSetChanged();
而數據列表則是同時操作刪除了兩個數據列表。
最後的效果如:
補充:上面忘了貼出一級列表對應的佈局文件和二級列表對應的佈局文件。 一級列表cut_library_parent_item.xml:<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/cut_from_name"
/>
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/videolist"
>
</ListView>
</LinearLayout> 二級列表:cut_library_child_item.xml:<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:id="@+id/iv"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="100dp"
>
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="20dp"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_alignParentBottom="true"
android:background="@color/teal_700"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
>
<Button
android:id="@+id/delete_bt"
android:tag="delete_bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
关键字词:ExpandableListView
相关文章
-
无相关信息