多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > A022-列表容器之ExpandableListView

A022-列表容器之ExpandableListView

來源:程序員人生   發布時間:2016-02-28 11:12:28 閱讀次數:2521次

概述

本節課介紹Android中可實現2級可展開收縮列表的ExpandableListView容器,筆者感覺它非常難用并且難理解,很多時候我們可能需要對控件進行擴大和定制,但是它不太方便擴大,它使用難點主要在數據結構上和對控件的事件監聽,其他的實現方式類似ListView,下面會提供筆者在實際開發中使用到的案例。

案例

ExpandableListView

上面實現的效果可展開的2級列表,每一個組項都可能有若干個子項,默許的ExpandableListView不太美觀,我們需要通過自定義布局類美化它,在使用進程中有1些需要我們去了解的點,會在實現進程提1下。

實現進程

源碼已上傳到Git@OSC,各位可以clone參考
http://git.oschina.net/devilwwj/AndroidDevelopCourse/tree/master/code?dir=1&filepath=code&oid=7961fb146029fb10776b101b918c59ff77fbd672&sha=e65897b0a246924292356f2b488d430c081081ff

布局分為:
- Activity布局
- 組項布局(layout_expand_group.xml)
- 子項布局(layout_expand_item.xml)

layout/activity_expandablelistview.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ExpandableListView android:id="@+id/expandablelistview" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@color/transparent" android:childDivider="@color/transparent" android:fastScrollEnabled="true" android:groupIndicator="@color/transparent" android:divider="@null" android:listSelector="@color/transparent" android:choiceMode="singleChoice" android:scrollbars="none" > ExpandableListView> LinearLayout>

layout/layout_expand_group.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/group_layout" android:layout_width="match_parent" android:layout_height="57dp" android:background="#ffffff" android:clickable="true" android:minHeight="?android:attr/listPreferredItemHeight" > <ImageView android:id="@+id/iv_group_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="18dp" android:background="@drawable/ic_leftnav_10" /> <TextView android:id="@+id/tv_group_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="59dp" android:text="時局" android:textColor="#333333" android:textSize="16sp" /> <View android:id="@+id/item_group_devider" android:layout_width="match_parent" android:layout_height="0.5dp" android:layout_alignLeft="@+id/tv_group_text" android:layout_alignParentBottom="true" android:background="@color/listview_divider" android:layout_marginRight="10dp" android:visibility="visible"/> <ImageView android:id="@+id/iv_expand" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="25dp" android:clickable="true" android:padding="5dp" android:src="@drawable/ic_leftnav_down" /> RelativeLayout>

layout/layout_expand_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="40dp" android:background="@drawable/slidingmenu_item_selector" android:minHeight="?android:attr/listPreferredItemHeight" > <TextView android:id="@+id/tv_item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="75dp" android:text="時局" android:textColor="@drawable/slidingmenu_item_text_selector" android:textSize="15sp" android:clickable="true" /> <View android:id="@+id/item_devider" android:layout_width="match_parent" android:layout_height="0.5dp" android:layout_alignParentBottom="true" android:layout_marginLeft="59dp" android:layout_marginRight="10dp" android:background="@color/listview_divider" android:visibility="visible" /> RelativeLayout>

自定義Adapter
- 繼承BaseExpandableListAdapter并實現以下方法
- getGroupCount(獲得組項的個數)
- getChildrenCount(獲得子項個數)
- getGroup(獲得組對象)
- getChild(獲得子對象)
- getGroupId(獲得組項id)
- getChildId(獲得子項id)
- hasStableIds(組和子元素是不是持有穩定的ID)
- getGroupView(獲得顯示指定組的視圖對象)
- getChildView(獲得顯示指定項的視圖對象)
- isChildSelectable(子項是不是可選中)
- 傳入組項列表(如:List)
- 傳入子項列表(如:List)

適配器代碼:
com.devilwwj.androiddevelopcourse.adapters.ExpandableListViewAdapter

package com.devilwwj.androiddevelopcourse.adapters; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.devilwwj.androiddevelopcourse.R; import com.devilwwj.androiddevelopcourse.domain.Category; import com.devilwwj.androiddevelopcourse.domain.GroupItem; import java.util.HashMap; import java.util.List; /** * 自定義可展開列表的適配器 */ public class ExpandableListViewAdapter extends BaseExpandableListAdapter { private Context mContext;// 上下文 private ExpandableListView expandableListView; // 可展開列表對象 private ListgroupList; // 組列表 private ListchildList; // 子項列表 private LayoutInflater inflater; // 自定義接口回調監聽器 private OnGroupExpandListener OnGroupExpandListener; private OnGroupClickListener onGroupClickListener; private OnChildItemClickListener onChildClickListener; private HashMap maps = new HashMap(); private boolean expandStateAtPosition = false; public OnGroupClickListener getOnGroupClickListener() { return onGroupClickListener; } public void setOnGroupClickListener( OnGroupClickListener onGroupClickListener) { this.onGroupClickListener = onGroupClickListener; } public OnGroupExpandListener getOnGroupExpandListener() { return OnGroupExpandListener; } public void setOnGroupExpandListener( OnGroupExpandListener onGroupExpandListener) { OnGroupExpandListener = onGroupExpandListener; } public OnChildItemClickListener getOnChildClickListener() { return onChildClickListener; } public void setOnChildClickListener( OnChildItemClickListener onChildClickListener) { this.onChildClickListener = onChildClickListener; } private int mExpandedGroupPosition; public int getExpandedGroupPosition() { return mExpandedGroupPosition; } public void setExpandedGroupPosition(int mExpandedGroupPosition) { this.mExpandedGroupPosition = mExpandedGroupPosition; } public ExpandableListViewAdapter(Context context, ExpandableListView expandableListView, ListgroupList, ListchildList) { super(); this.mContext = context; this.expandableListView = expandableListView; this.groupList = groupList; this.childList = childList; inflater = LayoutInflater.from(context); // 初始化列表展開狀態 for (int i = 0; i < groupList.size(); i++) { maps.put(i, false); } } private int mGroupPosition = 0; private int mChildPosition = 0; /** * 設置子項被選中方法 * * @param groupPosition * @param childPosition */ public void setItemChecked(int groupPosition, int childPosition) { if (expandableListView == null) { return; } this.mGroupPosition = groupPosition; this.mChildPosition = childPosition; int numberOfGroupThatIsOpened = 0; for (int i = 0; i < groupPosition; i++) { if (expandableListView.isGroupExpanded(i)) { numberOfGroupThatIsOpened += this.getChildrenCount(i); } } int position = numberOfGroupThatIsOpened + groupPosition + childPosition + 1; if (!expandableListView.isItemChecked(position)) { expandableListView.setItemChecked(position, true); } } @Override public int getGroupCount() { return groupList.size(); } @Override public int getChildrenCount(int groupPosition) { return childList.get(groupPosition).size(); } /* * 取得組項 (non-Javadoc) * * @see android.widget.ExpandableListAdapter#getGroup(int) */ @Override public GroupItem getGroup(int groupPosition) { return groupList.get(groupPosition); } @Override public Category getChild(int groupPosition, int childPosition) { return childList.get(groupPosition).get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { final GroupViewHolder groupViewHolder; if (convertView == null) { convertView = inflater.inflate(R.layout.layout_expand_group, parent, false); groupViewHolder = new GroupViewHolder(convertView); convertView.setTag(groupViewHolder); } else { groupViewHolder = (GroupViewHolder) convertView.getTag(); } GroupItem groupItem = groupList.get(groupPosition); groupViewHolder.itemGroupIcon.setBackgroundResource(groupItem .getDrawableId()); groupViewHolder.itemGroupText.setText(groupItem.getText()); // 如果該組沒有子項,則不顯示箭頭 if (childList.get(groupPosition).size() == 0) { groupViewHolder.itemArrow.setVisibility(View.GONE); groupViewHolder.itemGroupLayout .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onGroupClickListener.onGroupClick(groupPosition); } }); } else { groupViewHolder.itemArrow.setVisibility(View.VISIBLE); groupViewHolder.itemGroupLayout .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { OnGroupExpandListener.onGroupExpand(groupPosition); } }); } groupViewHolder.itemGroupText.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onGroupClickListener.onGroupClick(groupPosition); } }); groupViewHolder.itemArrow.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { OnGroupExpandListener.onGroupExpand(groupPosition); } }); // 判斷isExpanded就能夠控制按下還是關閉,同時更換圖片,這里使用屬性動畫來控制旋轉 if (isExpanded) { groupViewHolder.itemArrow .setImageResource(R.drawable.ic_leftnav_up); // 沒有孩子項就不隱藏分割線 if (childList.get(groupPosition).size() > 0) { groupViewHolder.itemDivider.setVisibility(View.INVISIBLE); } else { groupViewHolder.itemDivider.setVisibility(View.VISIBLE); } } else { groupViewHolder.itemArrow .setImageResource(R.drawable.ic_leftnav_down); groupViewHolder.itemDivider.setVisibility(View.VISIBLE); } return convertView; } @Override public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final ChildViewHolder childViewHolder; if (convertView == null) { convertView = inflater.inflate(R.layout.layout_expand_item, parent, false); childViewHolder = new ChildViewHolder(convertView); convertView.setTag(childViewHolder); } else { childViewHolder = (ChildViewHolder) convertView.getTag(); } String content = childList.get(groupPosition).get(childPosition) .getTitle(); // 設置內容 childViewHolder.itemChildText.setText(content); // 設置文本點擊事件 childViewHolder.itemChildText.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onChildClickListener.onChildItemClick(groupPosition, childPosition); } }); if (childPosition == childList.get(groupPosition).size() - 1) { childViewHolder.itemDivider.setVisibility(View.VISIBLE); } else { childViewHolder.itemDivider.setVisibility(View.GONE); } // 設置子項被選中的狀態 return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { // 設置孩子項可選中 return true; } private static class GroupViewHolder { RelativeLayout itemGroupLayout; ImageView itemGroupIcon; TextView itemGroupText; ImageView itemArrow; View itemDivider; public GroupViewHolder(View convertView) { itemGroupLayout = (RelativeLayout) convertView .findViewById(R.id.group_layout); itemGroupIcon = (ImageView) convertView .findViewById(R.id.iv_group_icon); itemGroupText = (TextView) convertView .findViewById(R.id.tv_group_text); itemArrow = (ImageView) convertView.findViewById(R.id.iv_expand); itemDivider = (View) convertView .findViewById(R.id.item_group_devider); } } private static class ChildViewHolder { TextView itemChildText; View itemDivider; public ChildViewHolder(View convertView) { itemChildText = (TextView) convertView .findViewById(R.id.tv_item_text); itemDivider = (View) convertView.findViewById(R.id.item_devider); } } public interface OnGroupExpandListener { void onGroupExpand(int position); } public interface OnGroupClickListener { void onGroupClick(int position); } public interface OnChildItemClickListener { void onChildItemClick(int groupPosition, int childPosition); } public boolean getExpandStateAtPosition(int groupPosition) { // 取得當前位置的展開狀態 expandStateAtPosition = maps.get(groupPosition).booleanValue(); return expandStateAtPosition; } public void setExpandStateAtPosition(int groupPosition, boolean expandStateAtPosition) { this.expandStateAtPosition = expandStateAtPosition; maps.put(groupPosition, expandStateAtPosition); } }

解析1下上面的代碼,我們可以看到ExpandableListView除1個組項,每一個組項下面有若干個子項,我們在使用的時候首先要肯定要展現的數據結構,組項有groupPosition來標識位置,但是子項需要根據groupPosition和ChildPosition來標識位置,我們設置數據的時候分別在getGroupView和getChildView方法來設置組視圖和子項視圖數據,最后返回填充數據的視圖對象,1些邏輯控制的代碼也是在這兩個方法中進行,比如控制組項的展開、組項的點擊、子項的點擊、子項被選中效果等等,這里筆者是自定義了回調接口來滿足業務的需求,Android API也提供的類似的方法,大家可以查看官方文檔。

Activity代碼
com.devilwwj.androiddevelopcourse.activities.ExpandableListViewTestActivity

package com.devilwwj.androiddevelopcourse.activities; import android.content.Context; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.widget.ExpandableListView; import com.devilwwj.androiddevelopcourse.R; import com.devilwwj.androiddevelopcourse.adapters.ExpandableListViewAdapter; import com.devilwwj.androiddevelopcourse.domain.Category; import com.devilwwj.androiddevelopcourse.domain.GroupItem; import com.devilwwj.androiddevelopcourse.utils.ResourceUtil; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; /** * A022-列表容器之ExpandableListView * * @author devilwwj */ public class ExpandableListViewTestActivity extends ActionBarActivity implements ExpandableListViewAdapter.OnGroupClickListener, ExpandableListViewAdapter.OnGroupExpandListener , ExpandableListViewAdapter.OnChildItemClickListener { private ExpandableListView expandableListView; private Context mContext; private ExpandableListViewAdapter expandAdapter; private ListgroupList; private ListchildList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_expandablelistview); mContext = ExpandableListViewTestActivity.this; expandableListView = (ExpandableListView) this.findViewById(R.id.expandablelistview); expandableListView.setGroupIndicator(null); // 去掉默許唆使器 // 設置展開列表數據 setExpandableListView(); } private void setExpandableListView() { try { // 這里分別摹擬組項和子項數據 groupList = new ArrayList(); childList = new ArrayList(); ResourceUtil resourceUtil = new ResourceUtil(this); // 從本地獲得目錄 String str = getString(R.string.categories); JSONObject jsonObject = new JSONObject(str); JSONObject categoryObj = jsonObject.optJSONObject("categories"); // 左側側邊欄 JSONArray jsonArray = categoryObj.optJSONArray("left"); for (int i = 0; i < jsonArray.length(); i++) { JSONArray groupArray = jsonArray.getJSONArray(i); GroupItem groupItem = new GroupItem(); groupItem.setDrawableId(resourceUtil.getResId("ic_leftnav_" + (i + 1), "drawable")); JSONObject groupObj = groupArray.optJSONObject(0); groupItem.setGroupId(groupObj.optString("cat_id")); // 設置組別的分類id groupItem.setText(groupObj.optString("title")); groupList.add(groupItem); Listcategories = new ArrayList(); if (groupArray.length() > 0) { // 如果多于1項分類 for (int index = 1; index < groupArray.length(); index++) { JSONObject itemObj = groupArray.optJSONObject(index); Category categorie = new Category(); categorie.setTitle(itemObj.optString("title")); categorie.setCat_id(itemObj.optString("cat_id")); categories.add(categorie); } } childList.add(categories); } // 實例化適配器 expandAdapter = new ExpandableListViewAdapter(this, expandableListView, groupList, childList); expandableListView.setAdapter(expandAdapter); // 設置ExpandableListView的相干事件監聽 // 子項選中、子項被點擊、組項展開、組項被點擊 // expandableListView.setOnItemSelectedListener(itemSelectedListener); expandableListView.setOnChildClickListener(mOnChildClickListener); // expandableListView.setOnGroupExpandListener(mOnGroupExpandListener); // expandableListView.setOnGroupClickListener(mOnGroupClickListener); expandAdapter.setOnGroupClickListener(this); expandAdapter.setOnGroupExpandListener(this); expandAdapter.setOnChildClickListener(this); } catch (JSONException e) { e.printStackTrace(); } } final private ExpandableListView.OnChildClickListener mOnChildClickListener = new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, final int groupPosition, final int childPosition, long id) { // 設置子項被選中的背景 // expandAdapter.setItemChecked(groupPosition, childPosition); // 返回true,列表不可展開 return false; } }; final private ExpandableListView.OnGroupExpandListener mOnGroupExpandListener = new ExpandableListView.OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { for (int i = 0, count = expandableListView .getExpandableListAdapter().getGroupCount(); i < count; i++) { expandAdapter.setExpandedGroupPosition(groupPosition); if (groupPosition != i) { // 關閉其他組 expandableListView.collapseGroup(i); } } } }; final private ExpandableListView.OnGroupClickListener mOnGroupClickListener = new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, final int groupPosition, long id) { return true; } }; @Override public void onGroupExpand(int position) { // 組項被展開時會回調這個方法 if (expandAdapter.getExpandStateAtPosition(position)) { // 收起 expandableListView.collapseGroup(position); expandAdapter.setExpandStateAtPosition(position, false); } else { expandableListView.expandGroup(position, true); expandAdapter.setExpandStateAtPosition(position, true); } } @Override public void onGroupClick(int position) { // 履行選中后的操作 } @Override public void onChildItemClick(int groupPosition, int childPosition) { // 子項被點擊會回調這個方法 } }

最后

實際開發中,我們可能會遇到其他UI上的需求,原生的效果是完全不能滿足我們的,這里提1點就是,熟練掌握API和解決問題能力很重要,不管UI怎樣變我們都有辦法去實現,可能只要我們找到對應的API設置1下或看看有無大神造好了輪子,終究我們還是可以找到解決方案,在Android開發當中我們常常打交道也最頭痛的是UI,多實踐和學習才能更好的完成工作,謝謝大家。

轉載請注明:IT_xiao小巫 http://blog.csdn.net/wwj_748

歡迎關注我的公眾號:wwjblog
wwjblog

版權聲明:本文為博主原創文章,未經博主允許不得轉載。

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 黄大片日本一级在线a | 直接在线观看的三级网址 | 国产色视频一区二区三区 | 亚洲v日本v欧美v综合v | 亚洲丝袜另类 | 亚洲国产日韩欧美一区二区三区 | 国产中文| 波多野结衣免费视频观看 | 国产精品一区二区三区四区 | 国产成人在线视频 | 亚洲高清视频在线观看 | 国产福利亚洲 | 午夜亚洲视频 | 亚洲国产一区二区三区最新 | 黄色大片aa| 2022国内精品免费福利视频 | 女人18一级特级毛片免费看 | 国产精品久久久久久 | 欧美俄罗斯一级毛片激情 | 黄色亚洲网站 | 亚洲欧美日韩综合在线一区二区三区 | 国产精品亚洲欧美日韩区 | 不卡精品国产_亚洲人成在线 | 在线不欧美 | 性欧美一级毛片在线播放 | 自由成熟的性色视频 | 精品欧美一区二区三区在线 | 日韩精品中文字幕一区三区 | 曰本www| 极品美女国产精品免费一区 | 久久亚洲国产精品五月天 | 一次性a爱片 | 香蕉蕉亚亚洲aav综合 | 欧美日韩高清观看一区二区 | 中文字幕日韩欧美一区二区三区 | 亚洲第一页在线播放 | 国产高清中文字幕 | 看黄免费网站 | 亚洲精品国产啊女成拍色拍 | 欧美一级视 | 亚洲欧美自拍视频 |