編輯:關於android開發
一、知識點
1、ExpandableListView常用XML屬性
2.ExpandableListView繼承BaseExpandableListAdapter後重寫的各個函數詳解
3.ExpandableListView自定義下拉圖標
二、解析
2.1、ExpandableListView常用XML屬性
2.1.1 設置點擊item項後該item項的背景色
//當你選中某一個item項時,該item項的背景會變色,下面的值是將該背景色設置為透明 android:listSelector="#00000000"
2.1.2 設置item項的高度
//這個是用在item的布局文件裡 android:minHeight="50dp"
2.1.3 拖動時背景圖片問題
//在拖動的時候背景圖片消失變成黑色背景,等到拖動完畢我們自己的背景圖片才顯示出來 android:scrollingCache=”false” 或 android:cacheColorHint=”#00000000″
2.1.4 分割線高度
android:dividerHeight="1dp"
2.2ExpandableListView繼承BaseExpandableListAdapter後重寫的各個函數詳解
下面的代碼幾乎每條都給了注釋,就不再贅述了。
2.2.1 child.xml
<?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="50dp" android:orientation="horizontal" > <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" android:textSize="18dp" android:text="this" /> </LinearLayout>
2.2.2 group.xml
<?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="wrap_content" android:minHeight="50dp" android:orientation="horizontal" > <ImageView android:layout_marginLeft="10dp" android:layout_gravity="center_vertical" android:id="@+id/arrow" android:layout_width="25dp" android:layout_height="25dp" /> <TextView android:layout_marginLeft="10dp" android:id="@+id/logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:layout_gravity="center_vertical" /> </LinearLayout>
2.2.3 colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="gray">#BEBEBE</color> <color name="SeaGreen1">#54FF9F</color> </resources>
2.2.4 activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ExpandableListView android:id="@+id/expandlist" android:divider="@color/gray" android:childDivider="@color/SeaGreen1" android:layout_width="match_parent" android:layout_height="match_parent" android:groupIndicator="@null" android:listSelector="#00000000" android:dividerHeight="1dp" > </ExpandableListView> </LinearLayout>
2.2.5 MyExpandableListAdapter.java
package com.yds.example; import java.util.List; import java.util.Map; import android.content.Context; import android.database.DataSetObserver; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ImageView; import android.widget.TextView; public class MyExpandableListAdapter extends BaseExpandableListAdapter { //上下文 Context context; //聲明一個布局管理器對象 LayoutInflater inflater; //聲明一個組集合 List<Map<String, Object>>group; //聲明一個子元素集合 List<List<Map<String, Object>>>child; //聲明一個map對象 Map<String, Object>map; /** * 自定義適配器的構造函數 * @param context 上下文 * @param group 組集合 * @param child 子元素集合 */ public MyExpandableListAdapter(Context context,List<Map<String, Object>>group,List<List<Map<String, Object>>>child){ //初始化上下文 this.context = context; //初始化布局管理器對象 inflater = LayoutInflater.from(context); //初始化組集合 this.group = group; //初始化子元素集合 this.child = child; } /** * ExpandableListAdapter裡面的所有條目 * 都可用嗎?如果是yes,就意味著所有條目可以選擇和點擊了。 * 返回值:返回True表示所有條目均可用。 */ @Override public boolean areAllItemsEnabled() { // TODO Auto-generated method stub return true; } /** * 獲取指定組中的指定子元素數據。 */ @Override public Object getChild(int groupPosition, int childPosition) { // TODO Auto-generated method stub /*child.get(groupPosition)是得到groupPosition處的list對象,然後 * child.get(groupPosition).get(childPosition)得到child的map對象,然後 * child.get(groupPosition).get(childPosition).get("Child")是得到key值 * 為Child的值 * */ return child.get(groupPosition).get(childPosition).get("Child"); } /** * 獲取指定組中的指定子元素ID,這個ID在組裡一定是唯一的。聯合ID(getCombinedChildId(long, long))在所有條目(所有組和所有元素)中也是唯一的。 */ @Override public long getChildId(int groupPosition, int childPosition) { // TODO Auto-generated method stub /******子元素的位置********/ return childPosition; } /**獲取一個視圖對象,顯示指定組中的指定子元素數據。 * @param groupPosition 組位置(該組內部含有子元素) * @param childPosition 子元素位置(決定返回哪個視圖) * @param isLastChild 子元素是否處於組中的最後一個 * @param convertView 重用已經有的視圖對象,它是RecycleBin緩存機制調用getScrapView方法獲取廢棄已緩存的view. * @param parent 返回的視圖(View)對象始終依附於的視圖組。通俗的說是它的父視圖。 */ @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolderChild viewHolderChild; /*當convertView為空,也就是沒有廢棄已緩存 view時,將執行下面方法,調用layoutinflate的 * inflate()方法來加載一個view。 * 如有不懂,請點擊:http://blog.csdn.net/libmill/article/details/49644743 */ if(convertView==null){ //重新加載布局 convertView = inflater.inflate(R.layout.child, null); //初始化控件管理器(自己命名的) viewHolderChild = new ViewHolderChild(); //綁定控件id viewHolderChild.tv = (TextView) convertView.findViewById(R.id.tv); /*convertView的setTag將viewHolderChild設置到Tag中,以便系統第二次繪制 ExpandableListView時從Tag中取出 */ convertView.setTag(viewHolderChild); }else{ //當convertView不為空時,從Tag中取出viewHolderChild viewHolderChild = (ViewHolderChild) convertView.getTag(); } //給子元素的TextView設置值 viewHolderChild.tv.setText(getChild(groupPosition, childPosition).toString()); //返回視圖對象,這裡是childPostion處的視圖 return convertView; } /** * 獲取指定組中子元素的個數 */ @Override public int getChildrenCount(int groupPosition) { // TODO Auto-generated method stub return child.get(groupPosition).size(); } /** * 從列表所有項(組或子項)中獲得一個唯一的子ID號。可折疊列表要求每個元素(組或子項)在所有的子元素和組中 * 有一個唯一的ID。本方法負責根據所給的子ID號和組ID號返回唯一的ID。此外,若hasStableIds() * 是true,那麼必須要返回穩定的ID。 * @param groupId 包含該子元素的組ID * @param childId 子元素的ID * @return:列表所有項(組或子項)中唯一的(和可能穩定)的子元素ID號。(譯者注:ID理論上是穩定的, * 不會發生沖突的情況。也就是說,這個列表會有組、子元素,它們的ID都是唯一的。) */ @Override public long getCombinedChildId(long groupId , long childId ) { // TODO Auto-generated method stub return 0; } /** * 獲取組ID * @param groupId 組ID * @return :組ID */ @Override public long getCombinedGroupId(long groupId) { // TODO Auto-generated method stub return 0; } /** * 得到指定組的組數據 * @param groupPosition:指定的組的位置 * @return 返回指定組的組數據 */ @Override public Object getGroup(int groupPosition) { // TODO Auto-generated method stub /**group.get(groupPosition)獲取map對象 * group.get(groupPosition).get("Group")獲取key值為Group的數據 * **/ return group.get(groupPosition).get("Group"); } /** * 獲取組長 */ @Override public int getGroupCount() { // TODO Auto-generated method stub return group.size(); } /** * 獲取指定組的Id */ @Override public long getGroupId(int groupPosition) { // TODO Auto-generated method stub return groupPosition; } /** * 獲取指定組的視圖對象 * @param groupPosition:組位置(決定返回哪個視圖) * @param isExpanded:改組是展開狀態還是伸縮狀態 * @param convertView:重用已有的視圖對象 * @return 返回指定組的視圖對象 */ @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolderGroup viewHolder; //判斷convertView是否為空,convertView是RecycleBean調用getScrapView函數得到廢棄已緩存的view if(convertView==null){ //初始化控件管理器對象 viewHolder = new ViewHolderGroup(); //重新加載布局 convertView = inflater.inflate(R.layout.group, null); //給組元素綁定ID viewHolder.logo_tv = (TextView) convertView.findViewById(R.id.logo); //給組元素箭頭綁定ID viewHolder.arrow = (ImageView) convertView.findViewById(R.id.arrow); //convertView將viewHolder設置到Tag中,以便再次繪制ExpandableListView時從Tag中取出viewHolder; convertView.setTag(viewHolder); }else {//如果convertView不為空,即getScrapView得到廢棄已緩存的view //從Tag中取出之前存入的viewHolder viewHolder = (ViewHolderGroup) convertView.getTag(); } //設置組值 viewHolder.logo_tv.setText(getGroup(groupPosition).toString()); //如果組是展開狀態 if (isExpanded) { //箭頭向下 viewHolder.arrow.setImageResource(R.drawable.arrow_down); }else{//如果組是伸縮狀態 //箭頭向右 viewHolder.arrow.setImageResource(R.drawable.arrow); } //返回得到的指定組的視圖對象 return convertView; } /** * 組和子元素是否持有穩定的ID,也就是底層數據的改變不會影響到它們。 * @return 返回一個Boolean類型的值,如果為TRUE,意味著相同的ID永遠引用相同的對象 */ @Override public boolean hasStableIds() { // TODO Auto-generated method stub return false; } /** * 是否選中指定位置上的子元素。 */ @Override public boolean isChildSelectable(int arg0, int arg1) { // TODO Auto-generated method stub return true; } /** * 如果當前適配器不包含任何數據則返回True。經常用來決定一個空視圖是否應該被顯示。 * 一個典型的實現將返回表達式getCount() == 0的結果,但是由於getCount()包含了頭部和尾部,適配器可能需要不同的行為。 */ @Override public boolean isEmpty() { // TODO Auto-generated method stub return false; } /** * 當組收縮狀態的時候此方法被調用。 */ @Override public void onGroupCollapsed(int groupPosition) { // TODO Auto-generated method stub } /** * 當組展開狀態的時候此方法被調用。 */ @Override public void onGroupExpanded(int groupPosition) { // TODO Auto-generated method stub } /** * 注冊一個觀察者(observer),當此適配器數據修改時即調用此觀察者。 * @param observer:當數據修改時通知調用的對象 */ @Override public void registerDataSetObserver(DataSetObserver observer) { // TODO Auto-generated method stub } /** * 取消先前通過registerDataSetObserver(DataSetObserver)方式注冊進該適配器中的觀察者對象。 * @param observer 取消這個觀察者的注冊 */ @Override public void unregisterDataSetObserver(DataSetObserver observer) { // TODO Auto-generated method stub } /** * 組控件管理器 * @author Administrator * */ class ViewHolderGroup{ TextView logo_tv; ImageView arrow; } /** * 子控件管理器 * @author Administrator * */ class ViewHolderChild{ TextView tv; } }
2.2.6 MainActivity.java
package com.yds.example; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.widget.ExpandableListView; public class MainActivity extends Activity { //聲明一個可伸展的列表視圖對象 private ExpandableListView expandlist; //聲明並初始化一個組集合對象,該集合時一個一維數組 private List<Map<String, Object>>groupList = new ArrayList<Map<String,Object>>(); //聲明一個子元素集合對象,該集合是一個數組鏈表 private List<List<Map<String, Object>>>childList = new ArrayList<List<Map<String,Object>>>(); //聲明一個子元素集合對象 private List<Map<String, Object>>child; //聲明一個map對象 private Map<String, Object>map; //組元素值 private String[] armTypes = new String[]{ "WORD", "EXCEL", "EMAIL", "PPT" }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); //加載布局 setContentView(R.layout.activity_main); //給組賦值 for (int i = 0; i < armTypes.length; i++) { //每次都要初始化map對象 map = new HashMap<String, Object>(); //將組值放入key為Group的map中 map.put("Group", armTypes[i]); //將map添加到組集合中 groupList.add(map); } //給每組的子元素賦值 for (int j = 0; j < 4; j++) { //每次初始化子集合對象。該對象是一個一維數組 child = new ArrayList<Map<String,Object>>(); //每個組下面有25個子元素 for (int i = 0; i < 25; i++) { //初始化map對象 map = new HashMap<String, Object>(); //將子元素的值放入key值為Child的map中 map.put("Child", "this is "+i+" example"); //將map添加到一維數組中 child.add(map); } //將一維數組添加到集合中 childList.add(child); } //可伸展的列表視圖綁定ID expandlist = (ExpandableListView) findViewById(R.id.expandlist); //聲明並初始化一個adapter MyExpandableListAdapter adapter = new MyExpandableListAdapter(MainActivity.this,groupList,childList); //可伸展的列表視圖加載adapter expandlist.setAdapter(adapter); } }
三、結果截圖:
第三方開源框架的下拉刷新列表(QQ比較常用的)。,開源框架PullToRefreshListView是第三方開源框架下拉刷新列表,比較流行的QQ 微信等上面都在用。 下載
(轉)[原] Android 自定義View 密碼框 例子,androidview遵從准則 暴露您view中所有影響可見外觀的屬性或者行為。 通過XML添加和設置樣式
使用Vitamio打造自己的Android萬能播放器—— 手勢控制亮度、音量、縮放 使用Vitamio打造自己的Android萬能播放器(1)——
Android中Service的一個Demo例子 Android中Service的一個Demo例子 Service組件是Android系統重要的一部分,網上看了代碼,很簡