【深入篇】自定義ExpandableListView,實現二級列表效果


 先看效果圖:

上圖是我們要實現的效果,那么現在我們開始着手去做,主要分為以下幾步:

     一丶我們需要根據效果圖去思考該如何動手,從上圖分析看,我們可以用一個相對布局RelativeLayout來完成group(一級item)的布局設計,至於child(二級item)的布局,我們可以用一個TextView來完成,當然,如果如要更復雜的效果可以參照一級item的布局方式進行。

以下是main.xmlgroup.xmlchild.xml的布局:

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" >
  <ExpandableListView
    android:id="@+id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:cacheColorHint="#00000000"
    android:listSelector="#00000000"
  >
</ExpandableListView>
</LinearLayout>

 

group.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:id="@+id/group_layout">

  <ImageView
    android:id="@+id/group_logo"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_centerInParent="true"
    android:layout_marginLeft="10dp"
    android:contentDescription="@string/list_logo" />

  <TextView
    android:id="@+id/group_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_toRightOf="@id/group_logo"
    android:textColor="#130c0e"
    android:textSize="18sp" />

  <TextView
    android:id="@+id/group_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/group_title"
    android:layout_marginLeft="10dp"
    android:layout_toRightOf="@id/group_logo"
    android:textColor="#838B8B"
    android:textSize="15sp" />

<ImageView
    android:id="@+id/group_state"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerInParent="true"
    android:layout_marginRight="10dp"
    android:contentDescription="@string/list_state" />

</RelativeLayout>

 

child.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent" >

  <TextView
    android:id="@+id/child_text"
    android:layout_width="wrap_content"
    android:layout_height="20dp"
    android:layout_centerInParent="true"
    android:layout_marginTop="15dp"
    android:textColor="#130c0e"
    android:textSize="15sp" />

</RelativeLayout>

     二、布局文件設置好以后,我們開始着手去實現代碼,首先談談我在實現過程中遇到的問題:

         一:在剛開始為二級item(expandableListView.setOnChildClickListener)設置點擊事件時,自己思維進入了一個誤區,刷新代碼寫錯位置導致二級item不能實時表明選中狀態,實驗了一番發現自己腦子發抽,其實把代碼轉移到點擊事件中就OK了。

         二:為一級item設置點擊事件時,剛開始想套用二級Item點擊事件的方法去做,發現行不通后,自己實驗了一番,定義了一個整型數組來存放對應groupPosition的點擊次數,根據點擊次數來設置狀態圖標,功能雖然實現了,但是感覺自己的這個方法不大實用,如果是動態加入就有點問題了,這個還希望各位看官給點建議。

 好了,廢話不多說了,下面是實現的代碼,希望各位不吝指教:

 

/**
* 自定義ExpandableList列表類
*
* @author jgduan
*
*/
public class ExpandableList extends Activity {

 

  // 這個數組是用來存儲一級item的點擊次數的,根據點擊次數設置一級標簽的選中、為選中狀態
  private int[] group_checked = new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  // 用來標識是否設置二級item背景色為綠色,初始值為-1既為選中狀態
  private int child_groupId = -1;
  private int child_childId = -1;

 

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 隱藏標題
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    // 指定布局
    setContentView(R.layout.main);
    // 新建一個ExpandableListView
    ExpandableListView expandableListView = (ExpandableListView) findViewById(R.id.list);
    // 設置默認圖標為不顯示狀態
    expandableListView.setGroupIndicator(null);
    // 為列表綁定數據源
    expandableListView.setAdapter(adapter);
    // 設置一級item點擊的監聽器
    expandableListView.setOnGroupClickListener(new OnGroupClickListener() {

 

    @Override
    public boolean onGroupClick(ExpandableListView parent, View v,
    int groupPosition, long id) {
        group_checked[groupPosition] = group_checked[groupPosition]+1;
        // 刷新界面
        ((BaseExpandableListAdapter) adapter).notifyDataSetChanged();
        return false;
      }
    });

 

    // 設置二級item點擊的監聽器
    expandableListView.setOnChildClickListener(new OnChildClickListener() {

 

      @Override
      public boolean onChildClick(ExpandableListView parent, View v,
      int groupPosition, int childPosition, long id) {
        // 將被點擊的一丶二級標簽的位置記錄下來
        child_groupId = groupPosition;
        child_childId = childPosition;
        // 刷新界面
        ((BaseExpandableListAdapter) adapter).notifyDataSetChanged();
        return false;
      }
  });
}

 

final ExpandableListAdapter adapter = new BaseExpandableListAdapter() {
  // 一級標簽上的logo圖片數據源
  int[] group_logo_array = new int[] { R.drawable.map,
  R.drawable.message, R.drawable.music, R.drawable.children };
  // 一級標簽上的標題數據源
  private String[] group_title_arry = new String[] { "中醫常識", "中醫養生",
  "美容養顏", "育兒百科" };
  // 一級標簽的描述文本數據源
  private String[] group_text_array = new String[] { "四診法、穴位、經絡等",
  "葯膳食療,安神醒腦等", "減肥、明目等", "關注幼兒保健" };
  // 子視圖顯示文字
  private String[][] child_text_array = new String[][] {
  { "孕吐怎么辦", "新生兒黃疸的治療", "嬰兒吐奶怎么辦", "小兒感冒咳嗽怎么辦" },
  { "孕吐怎么辦", "新生兒黃疸的治療", "嬰兒吐奶怎么辦", "小兒感冒咳嗽怎么辦" },
  { "孕吐怎么辦", "新生兒黃疸的治療", "嬰兒吐奶怎么辦", "小兒感冒咳嗽怎么辦" },
  { "孕吐怎么辦", "新生兒黃疸的治療", "嬰兒吐奶怎么辦", "小兒感冒咳嗽怎么辦" } };
  // 一級標簽上的狀態圖片數據源
  int[] group_state_array = new int[] { R.drawable.group_down,
  R.drawable.group_up };

 

  // 重寫ExpandableListAdapter中的各個方法
  /**
  * 獲取一級標簽總數
  */
  @Override
  public int getGroupCount() {
    return group_text_array.length;
  }

 

  /**
  * 獲取一級標簽內容
  */
  @Override
  public Object getGroup(int groupPosition) {
    return group_text_array[groupPosition];
  }

 

  /**
  * 獲取一級標簽的ID
  */
  @Override
  public long getGroupId(int groupPosition) {
    return groupPosition;
  }

 

  /**
  * 獲取一級標簽下二級標簽的總數
  */
  @Override
  public int getChildrenCount(int groupPosition) {
    return child_text_array[groupPosition].length;
  }

 

  /**
  * 獲取一級標簽下二級標簽的內容
  */
  @Override
  public Object getChild(int groupPosition, int childPosition) {
    return child_text_array[groupPosition][childPosition];
  }

 

  /**
  * 獲取二級標簽的ID
  */
  @Override
  public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
  }

  /**
  * 指定位置相應的組視圖
  */
  @Override
  public boolean hasStableIds() {
    return true;
  }

 

  /**
  * 對一級標簽進行設置
  */
  @Override
  public View getGroupView(int groupPosition, boolean isExpanded,
  View convertView, ViewGroup parent) {
    // 為視圖對象指定布局
    convertView = (RelativeLayout) RelativeLayout.inflate(
    getBaseContext(), R.layout.group, null);
    /**
    * 聲明視圖上要顯示的控件
    */
    // 新建一個ImageView對象,用來顯示一級標簽上的logo圖片
    ImageView group_logo = (ImageView) convertView
    .findViewById(R.id.group_logo);
    // 新建一個TextView對象,用來顯示一級標簽上的標題信息
    TextView group_title = (TextView) convertView
    .findViewById(R.id.group_title);
    // 新建一個TextView對象,用來顯示一級標簽上的大體描述的信息
    TextView group_text = (TextView) convertView
    .findViewById(R.id.group_text);
    // 新建一個ImageView對象,根據用戶點擊來標識一級標簽的選中狀態
    ImageView group_state = (ImageView) convertView
    .findViewById(R.id.group_state);
    /**
    * 設置相應控件的內容
    */
    // 設置要顯示的圖片
    group_logo.setBackgroundResource(group_logo_array[groupPosition]);
    // 設置標題上的文本信息
    group_title.setText(group_title_arry[groupPosition]);
    // 設置整體描述上的文本信息
    group_text.setText(group_text_array[groupPosition]);

    if(group_checked[groupPosition] % 2 == 1){
      // 設置默認的圖片是選中狀態
      group_state.setBackgroundResource(group_state_array[1]);
    }else{
      for(int test : group_checked){
        if(test == 0 || test % 2 == 0){
          // 設置默認的圖片是未選中狀態
          group_state.setBackgroundResource(group_state_array[0]);
        }
      }
  }
  // 返回一個布局對象
  return convertView;
}

 

  /**
  * 對一級標簽下的二級標簽進行設置
  */
  @Override
  public View getChildView(int groupPosition, int childPosition,
  boolean isLastChild, View convertView, ViewGroup parent) {
    // 為視圖對象指定布局
    convertView = (RelativeLayout) RelativeLayout.inflate(
    getBaseContext(), R.layout.child, null);
    /**
    * 聲明視圖上要顯示的控件
    */
    // 新建一個TextView對象,用來顯示具體內容
    TextView child_text = (TextView) convertView
    .findViewById(R.id.child_text);
    /**
    * 設置相應控件的內容
    */
    // 設置要顯示的文本信息
    child_text.setText(child_text_array[groupPosition][childPosition]);
    // 判斷item的位置是否相同,如相同,則表示為選中狀態,更改其背景顏色,如不相同,則設置背景色為白色
    if (child_groupId == groupPosition
    && child_childId == childPosition) {
      // 設置背景色為綠色
      convertView.setBackgroundColor(Color.GREEN);
    } else {
      // 設置背景色為白色
      convertView.setBackgroundColor(Color.WHITE);
    }
  // 返回一個布局對象
  return convertView;
}

 

  /**
  * 當選擇子節點的時候,調用該方法
  */
   @Override
   public boolean isChildSelectable(int groupPosition, int childPosition) {
       return true;
    }

 

    };

  }

 

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM