Android PopupWindow使用之地區、學校選擇二級聯動


  最近在做一個社交類APP時,希望用戶在注冊時根據地區來選擇自己所在的學校,由於用戶手動輸入學校,可能會出現各種問題,不利於后面對用戶信息的統計。於是決定在客戶端做好設置,用戶只要根據地區來選擇就好。第一想法就是使用PopupWindow,用彈框的方式讓用戶來選擇。讓實現的效果如下:

下面就來講一下是如何實現的(數據是從網絡獲取的,JSON解析使用的是Gson,網絡庫用的是Volley)

工程結構:

1、創建一個布局文件:view_select_province_list.xml,主要包括一個TextView(用來顯示標題)和兩個ListView(默認顯示地區ListView,隱藏SchoolListView)

<?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/list_title"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#3b3b3b"
        android:gravity="center"
        android:text="選擇地區"
        android:textColor="#ffffff"
        android:textSize="16sp"/>

    <ListView
        android:id="@+id/province"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#e4e4e4"
        android:divider="#aeaeae"
        android:dividerHeight="1dp"></ListView>

    <ListView
        android:id="@+id/school"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#e4e4e4"
        android:divider="#aeaeae"
        android:dividerHeight="1dp"></ListView>
</LinearLayout>

2、初始化PopupWindow

private void initPopView() {
        parent = this.getWindow().getDecorView();
        View popView = View.inflate(this, R.layout.view_select_province_list, null);
        mTitle = (TextView) popView.findViewById(R.id.list_title);
        mProvinceListView = (ListView) popView.findViewById(R.id.province);
        mSchoolListView = (ListView) popView.findViewById(R.id.school);
        mProvinceListView.setOnItemClickListener(itemListener);
        mSchoolListView.setOnItemClickListener(itemListener);

        mProvinceAdapter = new ProvinceAdapter(this);
        mProvinceListView.setAdapter(mProvinceAdapter);
        mSchoolAdapter = new SchoolAdapter(this);
        mSchoolListView.setAdapter(mSchoolAdapter);

        int width = getResources().getDisplayMetrics().widthPixels * 3 / 4;
        int height = getResources().getDisplayMetrics().heightPixels * 3 / 5;
        mPopWindow = new PopupWindow(popView, width, height);
        ColorDrawable dw = new ColorDrawable(0x30000000);
        mPopWindow.setBackgroundDrawable(dw);
        mPopWindow.setFocusable(true);
        mPopWindow.setTouchable(true);
        mPopWindow.setOutsideTouchable(true);//允許在外側點擊取消

        loadProvince();

        mPopWindow.setOnDismissListener(listener);
    }

其中,要想使PopupWindow點擊空白區域取消,必須設置

ColorDrawable dw = new ColorDrawable(0x30000000);

mPopWindow.setBackgroundDrawable(dw);

mPopWindow.setOutsideTouchable(true);

3、顯示PopupWindow

private void showPopWindow() 
{ mPopWindow.showAtLocation(parent, Gravity.CENTER, 0, 0);}

4、下載地區和學校數據(這里用的是volley和gson解析數據)

private void loadProvince() {
        mRequestQueue = Volley.newRequestQueue(this);
        GsonRequest<Province> request = new GsonRequest<Province>(Request.Method.POST, Config.PROVINCE_URL,
                Province.class, new Response.Listener<Province>() {
            @Override
            public void onResponse(Province response) {
                if (response.getData() != null && response.getError_code() == 0) {
                    mProvinceAdapter.setList(response.getData());
                    mProvinceAdapter.notifyDataSetChanged();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
            }
        }, this);
        mRequestQueue.add(request);
    }

    private void loadSchool() {
        mRequestQueue = Volley.newRequestQueue(this);
        GsonRequest<School> request = new GsonRequest<>(Request.Method.POST, Config.SCHOOL_URL + provinceId, School.class,
                new Response.Listener<School>() {
                    @Override
                    public void onResponse(School response) {
                        if (response.getData() != null && response.getError_code() == 0){
                            mSchoolAdapter.setList(response.getData());
                            mSchoolAdapter.notifyDataSetChanged();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        }, this);
        mRequestQueue.add(request);
    }

5、設置ListView 的Item點擊事件

/**
     * ListView Item點擊事件
     */
    AdapterView.OnItemClickListener itemListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (parent == mProvinceListView) {
                ProvinceList provinceName = (ProvinceList) mProvinceListView.getItemAtPosition(position);
                provinceId = provinceName.getProvince_id();
                mTitle.setText("選擇學校");
                mProvinceListView.setVisibility(View.GONE);//隱藏地區
                mSchoolListView.setVisibility(View.VISIBLE);//顯示學校
                loadSchool();
            } else if (parent == mSchoolListView) {
                SchoolList schoolName = (SchoolList) mSchoolListView.getItemAtPosition(position);
                mSelectSchool.setText(schoolName.getSchool_name());
                mPopWindow.dismiss();
            }
        }
    };

6、PopupWindow設置OnDismissListener,目的是為了再次進入選擇的時候,直接進入學校而不是地區的選擇

/**
     * popWindow消失監聽事件
     */
    PopupWindow.OnDismissListener listener = new PopupWindow.OnDismissListener() {
        @Override
        public void onDismiss() {
            mTitle.setText("選擇地區");
            mProvinceListView.setVisibility(View.VISIBLE);//顯示地區
            mSchoolAdapter.setList(new ArrayList<SchoolList>());//設置一個空的List,避免再次選擇學校后彈出的還是剛才的地區對應的學校
            mSchoolAdapter.notifyDataSetChanged();
            mSchoolListView.setVisibility(View.GONE);//隱藏學校
        }
    };

7、好了,這樣一個基於PopupWindow的二級聯動彈框選擇就完成了,其中,還有ListView的Adapter在這里我就沒有貼出來了,寫法和我們平常用的適配器一樣。我已經把代碼開源到我的GitHub上了,有需要的可以下載看看。

GitHub地址:https://github.com/tonycheng93/PopWindow

 

 

 


免責聲明!

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



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