Android自己定義組件系列【5】——進階實踐(2)

來源:互聯網
上載者:User

標籤:widget   out   on()   方法   封裝   raw   ota   ttext   用兩個   

上一篇《Android自己定義組件系列【5】——進階實踐(1)》中對任老師的《可下拉的PinnedHeaderExpandableListView的實現》前一部分進行了實現,這一篇我們來看看ExpandableListView的使用並實現剩下的部分。

原文出處:http://blog.csdn.net/singwhatiwanna/article/details/25546871

一、ExpandableListView的使用方法

ExpandableListView是ListView的子類,它在普通ListView的基礎上進行了擴充,適配器為ExpandableListAdapter。


與Adapter相似的是。實現ExpandableListAdapter也有例如以下方式:

1、擴充BaseExpandableListAdapter實現ExpandableListAdapter

2、使用SimpleExpandableListAdapter將兩個List集合封裝成ExpandableListAdapter

3、使用SimpleCursorTreeAdapter將Cursor中的資料封裝成SimpleCursorTreeAdapter

接下來用第一種方式來做個小範例。來看看ExpandableListView的使用

ExpandableListAdapter adapter = new BaseExpandableListAdapter() {@Overridepublic boolean isChildSelectable(int arg0, int arg1) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean hasStableIds() {// TODO Auto-generated method stubreturn false;}@Overridepublic View getGroupView(int arg0, boolean arg1, View arg2, ViewGroup arg3) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getGroupId(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic int getGroupCount() {// TODO Auto-generated method stubreturn 0;}@Overridepublic Object getGroup(int arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic int getChildrenCount(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getChildView(int arg0, int arg1, boolean arg2, View arg3,ViewGroup arg4) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getChildId(int arg0, int arg1) {// TODO Auto-generated method stubreturn 0;}@Overridepublic Object getChild(int arg0, int arg1) {// TODO Auto-generated method stubreturn null;}};
能夠看到BaseExpandableListApdater中的方法非常多,主要方法介紹例如以下:

getGroupCount():返回組列表數量

getGroupView():返回的View作為組清單項目

getChildrenCount():返回子清單項目的數量

getChildView():返回的View作為特定組、特定位置的子清單項目

package com.example.expandablelistviewtest;import android.app.Activity;import android.os.Bundle;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseExpandableListAdapter;import android.widget.ExpandableListAdapter;import android.widget.ExpandableListView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ExpandableListAdapter adapter = new BaseExpandableListAdapter() {int[] logos = new int[] {R.drawable.ic_launcher,R.drawable.ic_launcher,R.drawable.ic_launcher};private String[] groupTypes = new String[]{"電腦語言", "人類語言", "動物語言"};private String[][] childTypes = new String[][] {{"Java", "C++", "C", "PHP"},{"漢語", "英語", "日語", "法語"},{"咕咕", "汪汪", "喵喵"}};// 擷取指定組位置、指定子清單項目處的子清單項目資料@Overridepublic Object getChild(int groupPosition, int childPosition) {return childTypes[groupPosition][childPosition];}@Overridepublic long getChildId(int groupPosition, int childPosition) {return childPosition;}@Overridepublic int getChildrenCount(int groupPosition) {return childTypes[groupPosition].length;}private TextView getTextView() {AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 64);TextView textView = new TextView(MainActivity.this);textView.setLayoutParams(lp);textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);textView.setPadding(36, 0, 0, 0);textView.setTextSize(20);return textView;}// 該方法決定每一個子選項的外觀@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {TextView textView = getTextView();textView.setText(getChild(groupPosition, childPosition).toString());return textView;}// 擷取指定組位置處的組資料@Overridepublic Object getGroup(int groupPosition) {return groupTypes[groupPosition];}@Overridepublic int getGroupCount() {return groupTypes.length;}@Overridepublic long getGroupId(int groupPosition) {return groupPosition;}// 該方法決定每一個組選項的外觀@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {LinearLayout ll = new LinearLayout(MainActivity.this);ll.setOrientation(0);ImageView logo = new ImageView(MainActivity.this);logo.setImageResource(logos[groupPosition]);ll.addView(logo);TextView textView = getTextView();textView.setText(getGroup(groupPosition).toString());ll.addView(textView);return ll;}@Overridepublic boolean isChildSelectable(int groupPosition,int childPosition) {return true;}@Overridepublic boolean hasStableIds() {return true;}};ExpandableListView expandListView = (ExpandableListView) findViewById(R.id.list);expandListView.setAdapter(adapter);}}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" ><ExpandableListView     android:id="@+id/list"    android:layout_width="match_parent"    android:layout_height="wrap_content"/></RelativeLayout>

二、程式碼分析

首先看onCreate方法:

    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        expandableListView = (PinnedHeaderExpandableListView) findViewById(R.id.expandablelist);        stickyLayout = (StickyLayout)findViewById(R.id.sticky_layout);        initData();        adapter = new MyexpandableListAdapter(this);        expandableListView.setAdapter(adapter);        // 展開全部group        for (int i = 0, count = expandableListView.getCount(); i < count; i++) {            expandableListView.expandGroup(i);        }        expandableListView.setOnHeaderUpdateListener(this);        expandableListView.setOnChildClickListener(this);        expandableListView.setOnGroupClickListener(this);        stickyLayout.setOnGiveUpTouchEventListener(this);    }
前面幾行非常easy。和上面的範例差點兒一樣。我們僅僅須要再關注一下initData()方法和以下的幾行監聽函數。

initData()中是類比的資料。例如以下:

    void initData() {        groupList = new ArrayList<Group>();        Group group = null;        for (int i = 0; i < 3; i++) {            group = new Group();            group.setTitle("group-" + i);            groupList.add(group);        }        childList = new ArrayList<List<People>>();        for (int i = 0; i < groupList.size(); i++) {            ArrayList<People> childTemp;            if (i == 0) {                childTemp = new ArrayList<People>();                for (int j = 0; j < 13; j++) {                    People people = new People();                    people.setName("yy-" + j);                    people.setAge(30);                    people.setAddress("sh-" + j);                    childTemp.add(people);                }            } else if (i == 1) {                childTemp = new ArrayList<People>();                for (int j = 0; j < 8; j++) {                    People people = new People();                    people.setName("ff-" + j);                    people.setAge(40);                    people.setAddress("sh-" + j);                    childTemp.add(people);                }            } else {                childTemp = new ArrayList<People>();                for (int j = 0; j < 23; j++) {                    People people = new People();                    people.setName("hh-" + j);                    people.setAge(20);                    people.setAddress("sh-" + j);                    childTemp.add(people);                }            }            childList.add(childTemp);        }    }
接下來我們看看監聽這幾個監聽函數

public class MainActivity extends Activity implements        ExpandableListView.OnChildClickListener,        ExpandableListView.OnGroupClickListener,        OnHeaderUpdateListener, OnGiveUpTouchEventListener {
從Activity的繼承關係上看。OnChildClickListener和OnGroupClickListener是ExpandableListView類的監聽函數。

    @Override    public boolean onGroupClick(final ExpandableListView parent, final View v,            int groupPosition, final long id) {        return false;    }    @Override    public boolean onChildClick(ExpandableListView parent, View v,            int groupPosition, int childPosition, long id) {        Toast.makeText(MainActivity.this,                childList.get(groupPosition).get(childPosition).getName(), 1)                .show();        return false;    }
再來看看OnHeaderUpdateListener,這個監聽函數實際上是在重寫(自己定義)的ExpandableListView中自己定義的監聽。

    public void setOnHeaderUpdateListener(OnHeaderUpdateListener listener) {        mHeaderUpdateListener = listener;        if (listener == null) {            return;        }        mHeaderView = listener.getPinnedHeader();        int firstVisiblePos = getFirstVisiblePosition();        int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos));        listener.updatePinnedHeader(firstVisibleGroupPos);        requestLayout();        postInvalidate();    }

getPinnedHeader()方法建立(得到)一個列表頭。然後通過updatePinnedHeader方法設定當前可見的子列表元素的組名稱。

requestLayout()方法的作用是當view確定自身已經不再適合現有的地區時,該view本身調用這種方法要求parent view又一次調用他的onMeasure onLayout來對又一次設定自己位置。特別的當view的layoutparameter發生改變,而且它的值還沒能應用到view上,這時候適合調用這種方法。

postInvalidate()方法的作用是實現介面重新整理。

   public interface OnHeaderUpdateListener {        /**         * 採用單例模式返回同一個view對象就可以         * 注意:view必須要有LayoutParams         */        public View getPinnedHeader();        public void updatePinnedHeader(int firstVisibleGroupPos);    }
從OnHeaderUpdateListener監聽函數的定義上看。當觸發監聽後會調用兩個方法的實現例如以下:

    @Override    public View getPinnedHeader() {        if (mHeaderView == null) {            mHeaderView = (ViewGroup) getLayoutInflater().inflate(R.layout.group, null);            mHeaderView.setLayoutParams(new LayoutParams(                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));        }        return mHeaderView;    }

    @Override    public void updatePinnedHeader(int firstVisibleGroupPos) {        Group firstVisibleGroup = (Group) adapter.getGroup(firstVisibleGroupPos);        TextView textView = (TextView) getPinnedHeader().findViewById(R.id.group);        textView.setText(firstVisibleGroup.getTitle());    }
接下來我們須要知道什麼情況下回觸發這個監聽函數。

   protected void refreshHeader() {        if (mHeaderView == null) {            return;        }        int firstVisiblePos = getFirstVisiblePosition();        int pos = firstVisiblePos + 1;        int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos));        int group = getPackedPositionGroup(getExpandableListPosition(pos));        if (group == firstVisibleGroupPos + 1) {            View view = getChildAt(1);            if (view.getTop() <= mHeaderHeight) {                int delta = mHeaderHeight - view.getTop();                mHeaderView.layout(0, -delta, mHeaderWidth, mHeaderHeight - delta);            }        } else {            mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight);        }        if (mHeaderUpdateListener != null) {            mHeaderUpdateListener.updatePinnedHeader(firstVisibleGroupPos);        }    }
能夠看到再調用refreshHeader()方法的時候會觸發updatePinnerHeader方法。

    @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount, int totalItemCount) {        if (totalItemCount > 0) {            refreshHeader();        }        if (mScrollListener != null) {            mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);        }    }
呵呵,這下最終恍然大悟了。在onScroll方法中調用了refreshHeader,這就是說在滑動螢幕的時候OnHeaderUpdateListener監聽會觸發。會不斷的推斷是否應該改變列名稱。

快淩晨1點鐘了,今天就分析到這吧。明天繼續。


再次聲明一下,本文是為了學習Android自己定義組件,對任老師部落格《可下拉的PinnedHeaderExpandableListView的實現》進行具體解讀。假設有問題希望指出。

原文出處:http://blog.csdn.net/singwhatiwanna/article/details/25546871













Android自己定義組件系列【5】——進階實踐(2)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.