ExpandableListView+Dialog實現彈出二級下拉列表選項。可自由用於Activity和Fragment中

話說今天剛是本人失業第二天。已經感覺有點無聊了。對於這次失業挺突然的。不過想通之後也沒啥可惋惜的。畢竟身懷技術走到哪都不怕找不到飯碗。作爲技術人員要做的首要就是不斷提高自身技術水平,以適應這個瞬息萬變的社會。
本人是15年下半年入行,喜歡這行也是興趣所向。喜歡那種解決問題後的成就感,完成一個功能後的喜悅感。但是覺得自己又比較矛盾,自己也確實很喜歡編程,但是卻對上班編程感覺不是那麼特別喜歡,原因是:雖然也是同樣的寫程序,上班是要根據公司領導的安排而去寫一些有時候自己不是很喜歡的代碼或者是沒有技術含量的代碼。而自己寫的話肯定是寫一些自己喜歡或者自己感興趣的方向去深究和鑽研。希望自己有一天實現經濟自由,可以隨意學習自己喜歡的技術吧。

 好了上面叨叨了很多,下來看今天的正題:
 一個ExpandableListView+Dialog實現的彈出二級下拉菜單選項的功能。直接老規矩先看效果圖:

這裏寫圖片描述

ExpandableListView相信大家從單詞上都能看出來,裏面有listview。沒錯,這裏給大家大概說一下有興趣的可以繼續查閱資料瞭解,ExpandableListView是繼承自ListView。這樣一說估計心裏都有個大概了。

下來看看具體實現:
這裏我們是在Activity裏面實現的
1.首先在 activity_main中添加基本的一些佈局,用於後面觸發事件和顯示結果數據

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="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"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="diaog.com.expandablelistviewdialog.MainActivity">
    <EditText
        android:id="@+id/editText_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:editable="false"
        android:textSize="22sp" />

    <EditText
        android:id="@+id/editText_child"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:editable="false"
        android:textSize="22sp" />


    <Button
        android:id="@+id/btnShowDialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Show"
        android:textSize="22sp" />
</LinearLayout>

這個佈局沒什麼可說的。
2. expandablelistview_item.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="match_parent" >

    <ExpandableListView
        android:id="@+id/ew_dialog"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="@android:color/white" />

</LinearLayout>

這裏說下它跟listview不同的是要自己獨立寫一個layout。下來是兩個xml佈局文件,一個顯示一級目錄一個顯示對應的二級目錄

group_item.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="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/group_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:padding="5dp"
        android:textSize="24sp" />

</LinearLayout>

child_item.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="match_parent" >

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_margin="5dp"
        android:layout_height="wrap_content"
        android:textSize="18sp" />

</LinearLayout>

3.下來是adapter,這裏是繼承自BaseExpandableListAdapter

 private Context context;
    private List<String> listGroup = new ArrayList<String>();
    private List<List<String>> listChild = new ArrayList<List<String>>();

    public MyExpandableListAdapter(Context context, List<String> listGroup,
                                   List<List<String>> listChild) {
        super();
        this.context = context;
        this.listGroup = listGroup;
        this.listChild = listChild;
    }

    @Override
    public int getGroupCount() {
        // TODO Auto-generated method stub
        return listGroup.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        // TODO Auto-generated method stub
        return listChild.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        // TODO Auto-generated method stub
        return listGroup.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return childPosition;
    }

    @Override
    public long getGroupId(int groupPosition) {
        // TODO Auto-generated method stub
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        convertView = LinearLayout.inflate(context, R.layout.group_item, null);
        TextView text_group = (TextView) convertView.findViewById(R.id.group_text);
        text_group.setText(listGroup.get(groupPosition));

        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        convertView = LinearLayout.inflate(context, R.layout.child_item, null);
        TextView text_child = (TextView) convertView.findViewById(R.id.text);
        text_child.setText(listChild.get(groupPosition).get(childPosition));

        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return true;
    }

基本跟listview的baseadapter很相似相當於兩個Basedapter。這裏要注意的就是getGroupView和getChildView方法。從方法名稱可以看到,一個是獲取一級目錄layout的一個是獲取其下的二級目錄的layout。這裏我都是引用了xml的layout的,之前在網上也看到很多人在這裏是直接寫一個getGenericView(String s)方法

public TextView getGenericView(String s) {
        // Layout parameters for the ExpandableListView
        AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,50);

        lp.height=36;
        TextView text = new TextView(activity);
        text.setLayoutParams(lp);
        text.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
        text.setPadding(36, 0, 0, 0);
        text.setTextColor(Color.BLACK);     
        text.setTextSize(22);
        text.setText(s);        
        return text;
    }

不過我本人還是習慣儘量講佈局和代碼分開,那樣感覺可拓展性比較好,例如將來的二級或者一級目錄不是一行文字而是一個複雜的佈局呢。

4.下來是爲了方便,對此功能做了一個封裝,創建一個utils類將彈出dialog和添加數據等方法進行封裝。

public class SecondaryMemuUtils {
    private Context context;
    private ExpandableListView expandableListView; // Layout expandablelist.xml
    private List<String> listGroup = new ArrayList<String>();
    private List<List<String>> listChild = new ArrayList<List<String>>();

    private String[] groupDate;//一級目錄數據

    private String[][] childDate;//對應的二級目錄數據



    public SecondaryMemuUtils(Context context,
                              ExpandableListView expandableListView, List<String> listGroup,
                              List<List<String>> listChild, String[] groupDate,
                              String[][] childDate) {
        super();
        this.context = context;
        this.expandableListView = expandableListView;
        this.listGroup = listGroup;
        this.listChild = listChild;
        this.groupDate = groupDate;
        this.childDate = childDate;
    }

    /**
     * 添加二級菜單數據
     *
     * @param groupDate
     */
    public void addDate(String[] groupDate) {
        // TODO Auto-generated method stub
        for (int i = 0; i < groupDate.length; i++) {
            String group_text = groupDate[i];// 獲取每一個一級菜單text
            listGroup.add(group_text);
            List<String> children = new ArrayList<String>();
            if (listGroup.get(i).equals(group_text)) {
                mforTwoArrays(children,childDate,i);
//              children.add("公路建設");
//              children.add("鐵路建設");
//              children.add("礦產開發");
//              children.add("旅遊開發");
            } else if (listGroup.get(i).equals(group_text)) {
                mforTwoArrays(children,childDate,i);
//              children.add("河湖養殖");
//              children.add("毀林草開墾");
            } else if (listGroup.get(i).equals(group_text)) {
                mforTwoArrays(children,childDate,i);
//              children.add("水污染");
//              children.add("大氣污染");
//              children.add("土壤污染");
//              children.add("固體廢棄物污染");
//              children.add("噪聲污染");
            } else {
                mforTwoArrays(children,childDate,i);
//              children.add("放牧");
//              children.add("砍伐");
//              children.add("捕撈");
//              children.add("狩獵");
//              children.add("道路交通等");
            }

            listChild.add(children);
        }

    }

    /**
     * 循環添加數據
     * @param children
     * @param arrs
     * @param j
     */
    private void mforTwoArrays(List<String> children,String[][] arrs, int j){
        String[] arr2 = arrs[j];
        for (int c = 0; c < arr2.length; c++) {
            children.add(arr2[c]);
        }
    }


    /**
     * 類型
     * @param editText_group
     * @param editText_child
     */
    public void createExpandableListViewDialog(final EditText editText_group,final EditText editText_child) {
        // 設給彈出窗口的view
        final Dialog dialog; // 彈出類似Spinner選擇項的窗口
        View viewList = ((Activity) context).getLayoutInflater().inflate(
                R.layout.expandablelistview_item, null);
        dialog = new Dialog(context);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);//取消dialog的標題欄
        dialog.show();
        dialog.setContentView(viewList);
        expandableListView = (ExpandableListView) viewList.findViewById(R.id.ew_dialog);
        // 綁定ExpandableListView的數據
        MyExpandableListAdapter mAdapter = new MyExpandableListAdapter(context,listGroup,listChild);
        expandableListView.setAdapter(mAdapter);

        /**
         * 1 單擊事件 返回 false表示不觸發單擊事件
         */
        expandableListView.setOnGroupClickListener(new OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                return false;
            }

        });

        /**
         * Child 單擊事件
         */
        expandableListView.setOnChildClickListener(new OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View view,
                                        int groupPosition, int childPosition, long id)
                    throws RuntimeException {
                Toast.makeText(context, listGroup.get(groupPosition)
                                + "--->>>"
                                + listChild.get(groupPosition)
                                .get(childPosition).toString(), Toast.LENGTH_SHORT)
                        .show();
                // editText1.setText(listGroup.get(groupPosition)
                // + "下的"
                // + listChild.get(groupPosition).get(childPosition)
                // .toString());
                editText_group.setText(listGroup.get(groupPosition));
                editText_child.setText(listChild.get(groupPosition)
                        .get(childPosition).toString());

                dialog.dismiss();
                return true;
            }
        });
    }

}

這裏爲了更好的封裝,寫了一個mforTwoArrays方法。將傳進來的數據自動循環添加進去。這樣我們就可以傳任意的string類型的二級目錄數組數據了。

private void mforTwoArrays(List<String> children,String[][] arrs, int j){
        String[] arr2 = arrs[j];
        for (int c = 0; c < arr2.length; c++) {
            children.add(arr2[c]);
        }
    }

對於一級目錄的數據添加則比較簡單

public void addDate(String[] groupDate) {
        // TODO Auto-generated method stub
        for (int i = 0; i < groupDate.length; i++) {
            String group_text = groupDate[i];// 獲取每一個一級菜單text
            listGroup.add(group_text);

就可以循環添加每一個一級目錄列表了。
至此算是大功告成,下來我們在測試一下吧。
在MainActivity中調用,首先我們得創建菜單二二級菜單的數據。和裝它們的集合list。然後調用我們寫好的工具類裏面的createExpandableListViewDialog和addDate方法。就是如此簡單:

public class MainActivity extends AppCompatActivity {
    private Button btnShowDialog;
    private ExpandableListView expandableListView; //
    private List<String> listGroup = new ArrayList<String>();
    private List<List<String>> listChild = new ArrayList<List<String>>();
    private String[] groupDate = { "開放建設", "農牧漁業活動", "環境污染", "其他" };
    private String[][] childDate = {
            { "房地產", "公路建設", "鐵路建設", "礦產開發", "旅遊開發", "管理建設及河道治理" },
            { "河湖養殖", "毀林草開墾" }, { "水污染", "大氣污染", "土壤污染", "固體廢棄物污染", "噪聲污染" },
            { "放牧", "砍伐", "採挖", "捕撈", "狩獵", "道路交通等" } };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText editText_child = (EditText) findViewById(R.id.editText_child);
        final EditText editText_group = (EditText) findViewById(R.id.editText_group);
        btnShowDialog = (Button) findViewById(R.id.btnShowDialog);
        btnShowDialog.setOnClickListener(new View.OnClickListener() {
            SecondaryMemuUtils secondaryMemuUtils = new SecondaryMemuUtils(
                    MainActivity.this, expandableListView, listGroup, listChild,
                    groupDate, childDate);
            @Override
            public void onClick(View view) {

                listChild.clear();
                listGroup.clear();
                secondaryMemuUtils.addDate(groupDate);// 添加二級菜單數據
                secondaryMemuUtils.createExpandableListViewDialog(editText_group,editText_child);

            }
        });


    }

    }

是不是感覺調用的代碼不多呢。最後在奉上

源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章