android 地址选择器

2018-08-31 15:36:38 u012556114 阅读数 4834

     android开发中时间、日期、地址等滚轮选择器很常见,很多App会使用这种效果,收集了一下资料,于是自己做了一个简单封装,方便使用,感谢各位大佬的资料,效果如图:

使用方法代码如下:

public class MainActivity extends AppCompatActivity {
    private Dialog dateDialog, timeDialog, chooseDialog;
    private TextView mTextView;
    private List<String> list = new ArrayList<>();
    private ChooseAddressWheel chooseAddressWheel;
    private String address;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initWheel();
        initData();
    }
/**
 * 初始化控件
 */
private void initView() {
    mTextView = findViewById(R.id.textView);
    String[] data = getResources().getStringArray(R.array.list);
    list.addAll(Arrays.asList(data));
}

/**
 * 初始化地址
 */
private void initWheel() {
    chooseAddressWheel = new ChooseAddressWheel(this);
    chooseAddressWheel.setOnAddressChangeListener(new OnAddressChangeListener() {
        @Override
        public void onAddressChange(String province, String city, String district) {
            address = (province + " " + city + " " + district);
            mTextView.setText(address);
        }
    });
}

/**
 * 初始化数据
 */
private void initData() {
    String address = Utils.readAssert(this, "address.txt");
    AddressModel model = JsonUtil.parseJson(address, AddressModel.class);
    if (model != null) {
        AddressDetailsEntity data = model.Result;
        if (data == null) return;
        if (data.ProvinceItems != null && data.ProvinceItems.Province != null) {
            chooseAddressWheel.setProvince(data.ProvinceItems.Province);
            chooseAddressWheel.defaultValue(data.Province, data.City, data.Area);
        }
    }
}

 

/**
 * 选择其他
 * @param view
 */
public void btnOther(View view) {
    showChooseDialog(list);
}

/**
 * 选择时间
 * @param view
 */
public void btnTime(View view) {
    showTimePick();
}

/**
 * 选择日期
 * @param view
 */
public void btnDate(View view) {
    showDateDialog(DateUtil.getDateForString("2000-02-14"));
}

/**
 * 选择地址
 * @param view
 */
public void btnAddress(View view) {
    chooseAddressWheel.show(view);
}

/**
 * 显示其他列表
 */
private void showChooseDialog(List<String> mlist) {
    DataPickerDialog.Builder builder = new DataPickerDialog.Builder(this);
    chooseDialog = builder.setData(mlist).setSelection(1).setTitle("取消")
            .setOnDataSelectedListener(new DataPickerDialog.OnDataSelectedListener() {
                @Override
                public void onDataSelected(String itemValue, int position) {
                    mTextView.setText(itemValue);
                }

                @Override
                public void onCancel() {

                }
            }).create();
    chooseDialog.show();
}


/**
 * 显示日期
 * @param date
 */
private void showDateDialog(List<Integer> date) {
    DatePickerDialog.Builder builder = new DatePickerDialog.Builder(this);
    builder.setOnDateSelectedListener(new DatePickerDialog.OnDateSelectedListener() {
        @Override
        public void onDateSelected(int[] dates) {
            mTextView.setText(String.format("%d-%s-%s", dates[0], dates[1] > 9 ? dates[1] : ("0" + dates[1]), dates[2] > 9 ? dates[2] : ("0" + dates[2])));
        }

        @Override
        public void onCancel() {

        }
    })
            .setSelectYear(date.get(0) - 1)
            .setSelectMonth(date.get(1) - 1)
            .setSelectDay(date.get(2) - 1);
    builder.setMaxYear(DateUtil.getYear());
    builder.setMaxMonth(DateUtil.getDateForString(DateUtil.getToday()).get(1));
    builder.setMaxDay(DateUtil.getDateForString(DateUtil.getToday()).get(2));
    dateDialog = builder.create();
    dateDialog.show();
}

/**
 * 显示时间
 */
private void showTimePick() {
    if (timeDialog == null) {
        TimePickerDialog.Builder builder = new TimePickerDialog.Builder(this);
        timeDialog = builder.setOnTimeSelectedListener(new TimePickerDialog.OnTimeSelectedListener() {
            @Override
            public void onTimeSelected(int[] times) {
                mTextView.setText(String.format("%d:%d", times[0], times[1]));
            }
        }).create();
    }
    timeDialog.show();
}

 

布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:padding="16dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        app:layout_constraintTop_toTopOf="parent"
        android:text="显示选择内容"
        android:textSize="18sp"
        android:textColor="@color/white"
        android:gravity="center"
        android:background="@drawable/shape_bg"/>

    <Button
        android:id="@+id/btn_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/time"
        app:layout_constraintTop_toBottomOf="@id/textView"
        android:layout_marginTop="10dp"
        android:textSize="18sp"
        android:textColor="@color/white"
        android:background="@drawable/shape_bg"
        android:onClick="btnTime"/>

    <Button
        android:id="@+id/btn_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/date"
        android:textSize="18sp"
        android:textColor="@color/white"
        android:background="@drawable/shape_bg"
        app:layout_constraintTop_toBottomOf="@id/btn_time"
        android:layout_marginTop="10dp"
        android:onClick="btnDate"/>

    <Button
        android:id="@+id/btn_address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/address"
        android:textSize="18sp"
        android:textColor="@color/white"
        android:background="@drawable/shape_bg"
        app:layout_constraintTop_toBottomOf="@id/btn_date"
        android:layout_marginTop="10dp"
        android:onClick="btnAddress"/>

    <Button
        android:id="@+id/btn_other"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/other"
        android:textSize="18sp"
        android:textColor="@color/white"
        android:background="@drawable/shape_bg"
        app:layout_constraintTop_toBottomOf="@id/btn_address"
        android:layout_marginTop="10dp"
        android:onClick="btnOther"/>

项目地址:https://gitee.com/jackning_admin/WheelPickerDemo
小菜鸡写得不好,欢迎大家给出指导意见

 

2017-12-04 23:12:15 QianNiYouShouZuo 阅读数 17096

首先反省一下,为什么一年多没写博客了,因为懒吗???。。。。。。

先贴地址和依赖方法,用起来很简单,github 项目地址 

https://github.com/ywp0919/AddressPickerLib

直接依赖在项目中的方法

在project的build.gradle里面这么写   

maven { url 'https://jitpack.io' }

然后在app 的build.gradle      

compile 'com.github.ywp0919:AddressPickerLib:1.0.1'

不多说了,各位先看下效果图不是你们需要的吧,需要的话再继续看下去

咳,最近项目里面UI设计了一个地址选择的界面跟京东的地址选择器非常像,做出来的效果是这样子的








这个向上弹出的加点动画啥的就行了,我这就没有弄gif图了


接下来我微讲一下实现的思路吧,因为只有一个View,大家想用的可以去把源码下载下来copy一下,或者不想下的直接依赖一下就OK了,地址在最上面有

这个选择器View其实就是一个TabLayout 与 一个 RecyclerView组成,没有什么花哨的东西,主要是逻辑上控制。

加载本地的json省市区的数据,也开放了方法用来在外部传入最新的省市区数据。

用法就行简单了,不管是用在popwindow上还是在activity或者fragment里面,都只要直接就在xml文件里面这么用就行了

<com.ywp.addresspickerlib.AddressPickerView
    android:id="@+id/apvAddress"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</com.ywp.addresspickerlib.AddressPickerView>
然后再设置一下回调就行了,如下

addressView.setOnAddressPickerSure(new AddressPickerView.OnAddressPickerSureListener() {
    @Override
    public void onSureClick(String address, String provinceCode, String cityCode, String districtCode) {
        mTvAddress.setText(address);
    }
});

确定 就会回调这个方法

这个address 是 省 市 区的字符串,其他三个对应相应的code

嗯完了,用起来就这么简单,有需要的朋友去看一下吧,github 项目地址 

https://github.com/ywp0919/AddressPickerLib

直接依赖在项目中的方法

在project的build.gradle里面这么写  

 maven { url 'https://jitpack.io' }



然后在app 的build.gradle     

 compile  'com.github.ywp0919:AddressPickerLib:1.0.1'




然后就直接在项目里面用就行了。

好了,结束了









2019-05-05 20:17:31 mp624183768 阅读数 618

è¿éåå¾çæè¿°

原来的git地址 https://github.com/Bigkoo/Android-PickerView

 

好吧,我们只能做一些摸索了,还好留下了demo,这个控件堪称完美,兄弟们可以一起去用用,大家交流体验。做那种滚动选项选择的不在话下,用了这个,就可以跟ios的大兄弟同步了,当然我不再介绍这里的时间选择器,数据固定已经封装。弱水三千,我取一瓢饮。我这里只拿选项选择器来进行地址滚动选择器(省、市、区三级联动)的用法。主要是数据不统一性,我不改动pickerView已封装好的控件,只在使用上下个道道。 
欲哭无泪的是,我这边的后台数据接口需要我这边修改地址选择提交的是id,就像ERP系统的下拉框一样,展示的时候显示键(name),实际提交的时候是提交值(id),有点点恶心,但是恶心也有个恶心的做法。然后我这边的数据库只做查询操作,所以直接生成后,放在assert文件下读取使用了,当然你还会发现更好的做法,大兄弟,你可以带带我~~

一、首先是添加依赖
 

 compile 'com.bigkoo:pickerview:2.1.1'

二、然后你就可以欢快地去使用了,网上有可以直接读取assert文件夹下数据库的方法,稍微封装了下。还有几个bean实体类,用于存储城市编码,省份id,等字段(最重要的是要存储id做后续修改提交的参数)。

1、读取assert下的sqlite数据库

package db;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/** 
 * This is a Assets Database Manager 
 * Use it, you can use a assets database file in you application 
 * It will copy the database file to "/data/data/[your application package name]/database" when you first time you use it 
 * Then you can get a SQLiteDatabase object by the assets database file  
 * @author RobinTang 
 * @time 2012-09-20 
 *  
 *  
 * How to use: 
 * 1. Initialize AssetsDatabaseManager 
 * 2. Get AssetsDatabaseManager 
 * 3. Get a SQLiteDatabase object through database file 
 * 4. Use this database object 
 *  
 * Using example: 
 * AssetsDatabaseManager.initManager(getApplication()); // this method is only need call one time 
 * AssetsDatabaseManager mg = AssetsDatabaseManager.getManager();   // get a AssetsDatabaseManager object 
 * SQLiteDatabase db1 = mg.getDatabase("db1.db");   // get SQLiteDatabase object, db1.db is a file in assets folder 
 * db1.???  // every operate by you want 
 * Of cause, you can use AssetsDatabaseManager.getManager().getDatabase("xx") to get a database when you need use a database 
 */  
public class AssetsDatabaseManager {  
    private static String tag = "AssetsDatabase"; // for LogCat  
    private static String databasepath = "/data/data/%s/databases"; // %s is packageName  


    // A mapping from assets database file to SQLiteDatabase object  
    private Map<String, SQLiteDatabase> databases = new HashMap<String, SQLiteDatabase>();  

    // Context of application  
    private Context context = null;

    // Singleton Pattern  
    private static AssetsDatabaseManager mInstance = null;

    /** 
     * Initialize AssetsDatabaseManager 
     * @param context, context of application 
     */  
    public static void initManager(Context context){  
        if(mInstance == null){  
            mInstance = new AssetsDatabaseManager(context);  
        }  
    }  

    /** 
     * Get a AssetsDatabaseManager object 
     * @return, if success return a AssetsDatabaseManager object, else return null 
     */  
    public static AssetsDatabaseManager getManager(){  
        return mInstance;  
    }  

    private AssetsDatabaseManager(Context context){  
        this.context = context;  
    }  

    /** 
     * Get a assets database, if this database is opened this method is only return a copy of the opened database 
     * @param dbfile, the assets file which will be opened for a database 
     * @return, if success it return a SQLiteDatabase object else return null 
     */  
    public SQLiteDatabase getDatabase(String dbfile) {  
        if(databases.get(dbfile) != null){  
            Log.i(tag, String.format("Return a database copy of %s", dbfile));  
            return (SQLiteDatabase) databases.get(dbfile);  
        }  
        if(context==null)  
            return null;  

        Log.i(tag, String.format("Create database %s", dbfile));  
        String spath = getDatabaseFilepath();  
        String sfile = getDatabaseFile(dbfile);  

        File file = new File(sfile);  
        SharedPreferences dbs = context.getSharedPreferences(AssetsDatabaseManager.class.toString(), 0);  
        boolean flag = dbs.getBoolean(dbfile, false); // Get Database file flag, if true means this database file was copied and valid  
        if(!flag || !file.exists()){  
            file = new File(spath);  
            if(!file.exists() && !file.mkdirs()){  
                Log.i(tag, "Create \""+spath+"\" fail!");  
                return null;  
            }  
            if(!copyAssetsToFilesystem(dbfile, sfile)){  
                Log.i(tag, String.format("Copy %s to %s fail!", dbfile, sfile));  
                return null;  
            }  

            dbs.edit().putBoolean(dbfile, true).commit();  
        }  

        SQLiteDatabase db = SQLiteDatabase.openDatabase(sfile, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);  
        if(db != null){  
            databases.put(dbfile, db);  
        }  
        return db;  
    }  

    private String getDatabaseFilepath(){  
        return String.format(databasepath, context.getApplicationInfo().packageName);  
    }  

    private String getDatabaseFile(String dbfile){  
        return getDatabaseFilepath()+"/"+dbfile;  
    }  

    private boolean copyAssetsToFilesystem(String assetsSrc, String des){  
        Log.i(tag, "Copy "+assetsSrc+" to "+des);  
        InputStream istream = null;  
        OutputStream ostream = null;  
        try{  
            AssetManager am = context.getAssets();  
            istream = am.open(assetsSrc);  
            ostream = new FileOutputStream(des);  
            byte[] buffer = new byte[1024];  
            int length;  
            while ((length = istream.read(buffer))>0){  
                ostream.write(buffer, 0, length);  
            }  
            istream.close();  
            ostream.close();  
        }  
        catch(Exception e){  
            e.printStackTrace();  
            try{  
                if(istream!=null)  
                    istream.close();  
                if(ostream!=null)  
                    ostream.close();  
            }  
            catch(Exception ee){  
                ee.printStackTrace();  
            }  
            return false;  
        }  
        return true;  
    }  

    /** 
     * Close assets database 
     * @param dbfile, the assets file which will be closed soon 
     * @return, the status of this operating 
     */  
    public boolean closeDatabase(String dbfile){  
        if(databases.get(dbfile) != null){  
            SQLiteDatabase db = (SQLiteDatabase) databases.get(dbfile);  
            db.close();  
            databases.remove(dbfile);  
            return true;  
        }  
        return false;  
    }  

    /** 
     * Close all assets database 
     */  
    static public void closeAllDatabase(){  
        Log.i(tag, "closeAllDatabase");  
        if(mInstance != null){  
            for(int i=0; i<mInstance.databases.size(); ++i){  
                if(mInstance.databases.get(i)!=null){  
                    mInstance.databases.get(i).close();  
                }  
            }  
            mInstance.databases.clear();  
        }  
    }  
}  

 

2、这里的数据提取需要注意要严格区分层级关系。其实就是你要模拟占位你的父级元素的个数,因为后面是通过ArrayList的position提取的。这个作者没讲清楚,我也没时间做进一步封装,因为主体源码都是作者的,不好意思提炼出来做二次封装。我debug模式下,贴几张图,给大伙感受下:

如果你报了这个错误,就好好用心感受下,这7张图。。。血的教训 
ArrayList数组越界
 

java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1

1、3个数据最外层的size必须一致

2、省份就一层数据 
 
3、城市需要先外部嵌套一层省份

 
4、第二层list中的才是每个省份所对应的城市 
 
5、区域最外层(跟省份size一致) 
 
6、区域第二层(跟对应省份的对应城市的size一致) 
 
7、区域第三层(跟对应省份的对应城市的对应区域的size) 


8、主要原因是因为,提取显示的时候是严格按照list下的position来获取的,所以一切都清楚了

 //返回的分别是三个级别的选中位置

                String tx = options1Items.get(options1).getPro_name()
                        + options2Items.get(options1).get(option2).getName()
                        + options3Items.get(options1).get(option2).get(options3).getName();



3、初始化OptionsPickerView,并使用
 

MainActivity.java

package com.pickerview.pickerviewdemo;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.bigkoo.pickerview.OptionsPickerView;

import java.util.ArrayList;

import db.AreaBean;
import db.CityBean;
import db.DBManager;
import db.ProvinceBean;

public class MainActivity extends AppCompatActivity {

    private TextView tvTitle;
    private OptionsPickerView pvOptions;//地址选择器
    private ArrayList<ProvinceBean> options1Items = new ArrayList<>();//省
    private ArrayList<ArrayList<CityBean>> options2Items = new ArrayList<>();//市
    private ArrayList<ArrayList<ArrayList<AreaBean>>> options3Items = new ArrayList<>();//区
    private ArrayList<String> Provincestr = new ArrayList<>();//省
    private ArrayList<ArrayList<String>> Citystr = new ArrayList<>();//市
    private ArrayList<ArrayList<ArrayList<String>>> Areastr = new ArrayList<>();//区

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        initEvent();
    }

    private void initView() {
        tvTitle = (TextView) findViewById(R.id.tvTitle);
    }

    private void initData() {
        //选项选择器
        pvOptions = new OptionsPickerView(this);
        // 获取数据库
        SQLiteDatabase db = DBManager.getdb(getApplication());
        //省
        Cursor cursor = db.query("province", null, null, null, null, null,
                null);
        while (cursor.moveToNext()) {
            int pro_id = cursor.getInt(0);
            String pro_code = cursor.getString(1);
            String pro_name = cursor.getString(2);
            String pro_name2 = cursor.getString(3);
            ProvinceBean provinceBean = new ProvinceBean(pro_id, pro_code, pro_name, pro_name2);
            options1Items.add(provinceBean);//添加一级目录
            Provincestr.add(cursor.getString(2));
            //查询二级目录,市区
            Cursor cursor1 = db.query("city", null, "province_id=?", new String[]{pro_id + ""}, null, null,
                    null);
            ArrayList<CityBean> cityBeanList = new ArrayList<>();
            ArrayList<String> cityStr = new ArrayList<>();
            //地区集合的集合(注意这里要的是当前省份下面,当前所有城市的地区集合我去)
            ArrayList<ArrayList<AreaBean>> options3Items_03 = new ArrayList<>();
            ArrayList<ArrayList<String>> options3Items_str = new ArrayList<>();
            while (cursor1.moveToNext()) {
                int cityid = cursor1.getInt(0);
                int province_id = cursor1.getInt(1);
                String code = cursor1.getString(2);
                String name = cursor1.getString(3);
                String provincecode = cursor1.getString(4);
                CityBean cityBean = new CityBean(cityid, province_id, code, name, provincecode);
                //添加二级目录
                cityBeanList.add(cityBean);
                cityStr.add(cursor1.getString(3));
                //查询三级目录
                Cursor cursor2 = db.query("area", null, "city_id=?", new String[]{cityid + ""}, null, null,
                        null);
                ArrayList<AreaBean> areaBeanList = new ArrayList<>();
                ArrayList<String> areaBeanstr = new ArrayList<>();
                while (cursor2.moveToNext()) {
                    int areaid = cursor2.getInt(0);
                    int city_id = cursor2.getInt(1);
//                    String code0=cursor2.getString(2);
                    String areaname = cursor2.getString(3);
                    String citycode = cursor2.getString(4);
                    AreaBean areaBean = new AreaBean(areaid, city_id, areaname, citycode);
                    areaBeanList.add(areaBean);
                    areaBeanstr.add(cursor2.getString(3));
                }
                options3Items_str.add(areaBeanstr);//本次查询的存储内容
                options3Items_03.add(areaBeanList);
            }
            options2Items.add(cityBeanList);//增加二级目录数据
            Citystr.add(cityStr);
            options3Items.add(options3Items_03);//添加三级目录
            Areastr.add(options3Items_str);
        }
        //设置三级联动效果
        pvOptions.setPicker(Provincestr, Citystr, Areastr, true);
        //设置选择的三级单位
//        pvOptions.setLabels("省", "市", "区");
        pvOptions.setTitle("选择城市");
        //设置是否循环滚动
        pvOptions.setCyclic(false, false, false);
        //设置默认选中的三级项目
        //监听确定选择按钮
        pvOptions.setSelectOptions(0, 0, 0);
        pvOptions.setOnoptionsSelectListener(new OptionsPickerView.OnOptionsSelectListener() {
            @Override
            public void onOptionsSelect(int options1, int option2, int options3) {
                //返回的分别是三个级别的选中位置
                String tx = options1Items.get(options1).getPro_name()
                        + options2Items.get(options1).get(option2).getName()
                        + options3Items.get(options1).get(option2).get(options3).getName();
                tvTitle.setText(tx);
            }
        });
    }

    private void initEvent() {
        tvTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pvOptions.show();
            }
        });
    }
}

4、xml文件就不贴了,就是一个Hellow World的标签

看下这个demo的运行效果图: 
这里写图片描述

 

5、github地址:https://github.com/TrebleZ/Pickerviewdemo

6、下载地址:http://download.csdn.net/detail/z_zt_t/9717228

2019-05-12 23:27:03 longxuanzhigu 阅读数 1420

最近在做地址管理的功能,新建地址的时候,需要根据后台提供的省市区的数据,让用户进行地址的选择,最近项目比较赶,本来想网上找一个的,可是找了很久都没找到我想要的效果,所以就根据后台提供的数据,弄了一个。

1.先看实现的效果图

在这里插入图片描述
本来数据是根据请求后台接口返回的数据,我这里就不请求后台数据了,直接把请求成功后的数据写死,可是把全国省市区的数据太多,导致报错:字符串数据太长,所以我这里只获取了北京的数据。

2.自定义收货地址选择器


public class AddressSelector extends LinearLayout implements View.OnClickListener{
    private int TextSelectedColor = Color.parseColor("#D5A872");
    private int TextEmptyColor = Color.parseColor("#333333");
    //顶部的tab集合
    private ArrayList<Tab> tabs;
    //列表的适配器
    private AddressAdapter addressAdapter;
    private ArrayList<CityInterface> cities;
    private OnItemClickListener onItemClickListener;
    private OnTabSelectedListener onTabSelectedListener;
    private RecyclerView list;
    //tabs的外层layout
    private LinearLayout tabs_layout;
    //会移动的横线布局
    private Line line;
    private Context mContext;
    //总共tab的数量
    private int tabAmount = 3;
    //当前tab的位置
    private int tabIndex = 0;
    //分隔线
    private View grayLine;
    //列表文字大小
    private int listTextSize = -1;
    //列表文字颜色
    private int listTextNormalColor = Color.parseColor("#333333");
    //列表文字选中的颜色
    private int listTextSelectedColor = Color.parseColor("#D5A872");
    //列表icon资源
    private int listItemIcon = -1;
    public AddressSelector(Context context) {
        super(context);
        init(context);
    }

    public AddressSelector(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public AddressSelector(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private void init(Context context){
        removeAllViews();
        this.mContext = context;
        setOrientation(VERTICAL);
        tabs_layout = new LinearLayout(mContext);
        tabs_layout.setWeightSum(tabAmount);
        tabs_layout.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT));
        tabs_layout.setOrientation(HORIZONTAL);
        addView(tabs_layout);
        tabs = new ArrayList<>();
        Tab tab = newTab("请选择",true);
        tabs_layout.addView(tab);
        tabs.add(tab);
        for(int i = 1;i<tabAmount;i++){
            Tab _tab = newTab("",false);
            _tab.setIndex(i);
            tabs_layout.addView(_tab);
            tabs.add(_tab);
        }
        line = new Line(mContext);
        line.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,6));
        line.setSum(tabAmount);
        addView(line);
        grayLine = new View(mContext);
        grayLine.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,2));
        grayLine.setBackgroundColor(mContext.getResources().getColor(R.color.line_DDDDDD));
        addView(grayLine);
        list = new RecyclerView(mContext);
        list.setLayoutParams(new ViewGroup.LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        list.setLayoutManager(new LinearLayoutManager(mContext));
        addView(list);
    }
    /**
     * 得到一个新的tab对象
     * */
    private Tab newTab(CharSequence text, boolean isSelected){
        Tab tab = new Tab(mContext);
        tab.setLayoutParams(new LayoutParams(0,LayoutParams.WRAP_CONTENT,1));
        tab.setGravity(Gravity.CENTER);
        tab.setPadding(0,5,0,5);
        tab.setSelected(isSelected);
        tab.setText(text);
        tab.setTextEmptyColor(TextEmptyColor);
        tab.setTextSelectedColor(TextSelectedColor);
        tab.setOnClickListener(this);
        return tab;
    }
    /**
     * 设置tab的数量,默认3个,不小于2个
     * @param tabAmount tab的数量
     * */
    public void setTabAmount(int tabAmount) {
        if(tabAmount >= 2){
            this.tabAmount = tabAmount;
            init(mContext);
        }
        else
            throw new RuntimeException("AddressSelector tabAmount can not less-than 2 !");
    }
    /**
     * 设置列表的点击事件回调接口
     * */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }
    /**
     * 设置列表的数据源,设置后立即生效
     * */
    public void setCities(ArrayList cities) {
        if(cities == null||cities.size() <= 0)
            return;
        if(cities.get(0) instanceof CityInterface){
            this.cities = cities;
            if(addressAdapter == null){
                addressAdapter = new AddressAdapter();
                list.setAdapter(addressAdapter);
            }
            addressAdapter.notifyDataSetChanged();
        }else{
            throw new RuntimeException("AddressSelector cities must implements CityInterface");
        }
    }
    /**
     * 设置顶部tab的点击事件回调
     * */
    public void setOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
        this.onTabSelectedListener = onTabSelectedListener;
    }

    @Override
    public void onClick(View v) {
        Tab tab = (Tab) v;
        //如果点击的tab大于index则直接跳出
        if(tab.index > tabIndex)
            return;
        tabIndex = tab.index;
        if(onTabSelectedListener != null){
            if(tab.isSelected)
                onTabSelectedListener.onTabReselected(AddressSelector.this,tab);
            else
                onTabSelectedListener.onTabSelected(AddressSelector.this,tab);
        }
        resetAllTabs(tabIndex);
        line.setIndex(tabIndex);
        tab.setSelected(true);
    }

    private void resetAllTabs(int tabIndex){
        if(tabs != null)
        for(int i =0;i<tabs.size();i++){
            tabs.get(i).resetState();
            if(i > tabIndex){
                tabs.get(i).setText("");
            }
        }
    }
    /**
     * 设置Tab文字选中的颜色
     * */
    public void setTextSelectedColor(int textSelectedColor) {
        TextSelectedColor = textSelectedColor;
    }
    /**
     * 设置Tab文字默认颜色
     * */
    public void setTextEmptyColor(int textEmptyColor) {
        TextEmptyColor = textEmptyColor;
    }
    /**
     * 设置Tab横线的颜色
     * */
    public void setLineColor(int lineColor) {
        line.setSelectedColor(lineColor);
    }
    /**
     * 设置tab下方分隔线的颜色
     * */
    public void setGrayLineColor(int grayLineColor) {
        grayLine.setBackgroundColor(grayLineColor);
    }
    /**
     * 设置列表文字大小
     * */
    public void setListTextSize(int listTextSize) {
        this.listTextSize = listTextSize;
    }
    /**
     * 设置列表文字颜色
     * */
    public void setListTextNormalColor(int listTextNormalColor) {
        this.listTextNormalColor = listTextNormalColor;
    }
    /**
     * 设置列表选中文字颜色
     * */
    public void setListTextSelectedColor(int listTextSelectedColor) {
        this.listTextSelectedColor = listTextSelectedColor;
    }
    /**
     * 设置列表icon资源
     * */
    public void setListItemIcon(int listItemIcon) {
        this.listItemIcon = listItemIcon;
    }

    /**
     * 标签控件
     * */
    @SuppressLint("AppCompatCustomView")
    public class Tab extends TextView {
        private int index = 0;
        private int TextSelectedColor = Color.parseColor("#D5A872");
        private int TextEmptyColor = Color.parseColor("#333333");
        /**
         * 是否选中状态
         * */
        private boolean isSelected = false;
        public Tab(Context context) {
            super(context);
            init();
        }

        public Tab(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public Tab(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
        private void init(){
            setTextSize(15);
        }
        @Override
        public void setText(CharSequence text, BufferType type) {
            if(isSelected)
                setTextColor(TextSelectedColor);
            else
                setTextColor(TextEmptyColor);
            super.setText(text, type);
        }

        @Override
        public void setSelected(boolean selected) {
            isSelected = selected;
            setText(getText());
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }
        public void resetState(){
            isSelected = false;
            setText(getText());
        }

        public void setTextSelectedColor(int textSelectedColor) {
            TextSelectedColor = textSelectedColor;
        }

        public void setTextEmptyColor(int textEmptyColor) {
            TextEmptyColor = textEmptyColor;
        }
    }
    /**
     * 横线控件
     * */
    private class Line extends LinearLayout {
        private int sum = 3;
        private int oldIndex = 0;
        private int nowIndex = 0;
        private View indicator;
        private int SelectedColor = Color.parseColor("#D5A872");
        public Line(Context context) {
            super(context);
            init(context);
        }

        public Line(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }

        public Line(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
        private void init(Context context){
            setOrientation(HORIZONTAL);
            setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT,6));
            setWeightSum(tabAmount);
            indicator= new View(context);
            indicator.setLayoutParams(new LayoutParams(0,LayoutParams.MATCH_PARENT,1));
            indicator.setBackgroundColor(SelectedColor);
            addView(indicator);
        }
        public void setIndex(int index){
            int onceWidth = getWidth()/sum;
            this.nowIndex = index;
            ObjectAnimator animator = ObjectAnimator.ofFloat(indicator, "translationX", indicator.getTranslationX(), (nowIndex-oldIndex)*onceWidth);
            animator.setDuration(300);
            animator.start();
        }

        public void setSum(int sum) {
            this.sum = sum;
        }

        public void setSelectedColor(int selectedColor) {
            SelectedColor = selectedColor;
        }
    }
    private class AddressAdapter extends RecyclerView.Adapter<AddressAdapter.MyViewHolder>{
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            MyViewHolder viewHolder =
                    new MyViewHolder(LayoutInflater.from(mContext).inflate(
                            R.layout.item_address,parent,false));
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, final int position) {
            if(listItemIcon != -1)
                holder.img.setImageResource(listItemIcon);
            if(listTextSize != -1)
                holder.tv.setTextSize(listTextSize);
            if(TextUtils.equals(tabs.get(tabIndex).getText(),cities.get(position).getCityName())){
                holder.img.setVisibility(View.VISIBLE);
                holder.tv.setTextColor(listTextSelectedColor);
            }else{
                holder.img.setVisibility(View.INVISIBLE);
                holder.tv.setTextColor(listTextNormalColor);
            }
            holder.tv.setText(cities.get(position).getCityName());
            holder.itemView.setTag(cities.get(position));
            holder.itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(onItemClickListener != null){
                        onItemClickListener.itemClick(AddressSelector.this,(CityInterface) v.getTag(),tabIndex,position);
                        tabs.get(tabIndex).setText(((CityInterface) v.getTag()).getCityName());
                        tabs.get(tabIndex).setTag(v.getTag());
                        if(tabIndex+1 < tabs.size()){
                            tabIndex ++;
                            resetAllTabs(tabIndex);
                            line.setIndex(tabIndex);
                            tabs.get(tabIndex).setText("请选择");
                            tabs.get(tabIndex).setSelected(true);
                        }
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return cities.size();
        }
        class MyViewHolder extends RecyclerView.ViewHolder{
            public TextView tv;
            public ImageView img;
            public View itemView;
            public MyViewHolder(View itemView) {
                super(itemView);
                this.itemView = itemView;
                tv = (TextView) itemView.findViewById(R.id.item_address_tv);
                img = (ImageView) itemView.findViewById(R.id.item_address_img);
            }
        }
    }
    public interface OnTabSelectedListener {
        void onTabSelected(AddressSelector addressSelector, Tab tab);
        void onTabReselected(AddressSelector addressSelector, Tab tab);
    }
}

3.Demo中设置点击按钮打开PopWindow进行地址选择

/**
     * 设置弹出PopWindow
     * @param v
     */
    private void setAddressSelectorPopup(View v) {
        int screenHeigh = getResources().getDisplayMetrics().heightPixels;

        CommonPopWindow.newBuilder()
                .setView(R.layout.pop_address_selector_bottom)
                .setAnimationStyle(R.style.AnimUp)
                .setBackgroundDrawable(new BitmapDrawable())
                .setSize(ViewGroup.LayoutParams.MATCH_PARENT, Math.round(screenHeigh * 0.6f))
                .setViewOnClickListener(this)
                .setBackgroundDarkEnable(true)
                .setBackgroundAlpha(0.7f)
                .setBackgroundDrawable(new ColorDrawable(999999))
                .build(this)
                .showAsBottom(v);
    }

    @Override
    public void getChildView(final PopupWindow mPopupWindow, View view, int mLayoutResId) {
        switch (mLayoutResId) {
            case R.layout.pop_address_selector_bottom:
                ImageView imageBtn = view.findViewById(R.id.img_guanbi);
                AddressSelector addressSelector = view.findViewById(R.id.address);

                //数据解析
                AddressSelectorReq addressSelectorReq = new Gson().fromJson(String.valueOf(response), AddressSelectorReq.class);
                //设置默认选择数据
                dealWithAddressSelector(addressSelector, addressSelectorReq.getDatas(), mPopupWindow);

                imageBtn.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mPopupWindow.dismiss();
                    }
                });
                break;
        }
    }

4.设置选择器默认数据

 private void dealWithAddressSelector(AddressSelector addressSelector, final List<AddressSelectorReq.DatasBean> 
            addressSelectorList, final PopupWindow mPopupWindow) {
        final String[] sheng = new String[3];

        final ArrayList<ItemAddressReq> itemAddressReqs = getItemAddressSheng(addressSelectorList);
        addressSelector.setTabAmount(3);
        //设置数据
        addressSelector.setCities(itemAddressReqs);
        //设置Tab横线的颜色
        addressSelector.setLineColor(Color.parseColor("#D5A872"));
        //设置Tab文字默认颜色
        addressSelector.setTextEmptyColor(Color.parseColor("#000000"));
        //设置列表选中文字颜色
        addressSelector.setListTextSelectedColor(Color.parseColor("#D5A872"));
        //设置Tab文字选中的颜色
        addressSelector.setTextSelectedColor(Color.parseColor("#D5A872"));

        //设置列表的点击事件回调接口
        addressSelector.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void itemClick(AddressSelector addressSelector, CityInterface city, int tabPosition, int selecePos) {
                switch (tabPosition) {
                    case 0:
                        //设置省列表数据
                        sheng[0] = city.getCityName();
                        saveId[0] = addressSelectorList.get(selecePos).getDb_id();
                        childrenBeanXList = addressSelectorList.get(selecePos).getDb_children();
                        addressSelector.setCities(getItemAddressShi(childrenBeanXList));
                        break;
                    case 1:
                        //设置市列表数据
                        sheng[1] = city.getCityName();
                        saveId[1] = childrenBeanXList.get(selecePos).getCb_id();
                        childrenBeans = childrenBeanXList.get(selecePos).getCb_children();
                        addressSelector.setCities(getItemAddressQu(childrenBeans));
                        break;
                    case 2:
                        //设置区列表数据
                        sheng[2] = city.getCityName();
                        saveId[2] = childrenBeans.get(selecePos).getId();
                        text_suozaidiqu.setText(sheng[0] + sheng[1] + sheng[2]);
                        mPopupWindow.dismiss();
                        break;
                }
            }
        });


        //设置顶部tab的点击事件回调
        addressSelector.setOnTabSelectedListener(new AddressSelector.OnTabSelectedListener() {
            @Override
            public void onTabSelected(AddressSelector addressSelector, AddressSelector.Tab tab) {
                switch (tab.getIndex()) {
                    case 0:
                        addressSelector.setCities(itemAddressReqs);
                        break;
                    case 1:
                        addressSelector.setCities(getItemAddressShi(childrenBeanXList));
                        break;
                    case 2:
                        addressSelector.setCities(getItemAddressQu(childrenBeans));
                        break;
                }
            }

            @Override
            public void onTabReselected(AddressSelector addressSelector, AddressSelector.Tab tab) {

            }
        });
    }

5.将获取的省市区的数据进行分类

  /**
     * 获取省的数据
     *
     * @param addressSelectorList
     * @return
     */
    @NonNull
    private ArrayList<ItemAddressReq> getItemAddressSheng(List<AddressSelectorReq.DatasBean> addressSelectorList) {
        final ArrayList<ItemAddressReq> itemAddressReqs = new ArrayList<>();
        for (int i = 0; i < addressSelectorList.size(); i++) {
            ItemAddressReq itemAddressReq = new ItemAddressReq();
            itemAddressReq.setAreaAbbName(addressSelectorList.get(i).getDb_areaAbbName());
            itemAddressReq.setAreaCode(addressSelectorList.get(i).getDb_areaCode());
            itemAddressReq.setAreaEnName(addressSelectorList.get(i).getDb_areaEnName());
            itemAddressReq.setAreaType(addressSelectorList.get(i).getDb_areaType());
            itemAddressReq.setAreaZip(addressSelectorList.get(i).getDb_areaZip());
            itemAddressReq.setAreaName(addressSelectorList.get(i).getDb_areaName());
            itemAddressReq.setId(addressSelectorList.get(i).getDb_id());
            itemAddressReq.setParentId(addressSelectorList.get(i).getDb_parentId());
            itemAddressReqs.add(itemAddressReq);
        }
        return itemAddressReqs;
    }


    /**
     * 获取市的数据
     *
     * @return
     */
    @NonNull
    private ArrayList<ItemAddressReq> getItemAddressShi(List<AddressSelectorReq.DatasBean.ChildrenBeanX> datas) {
        final ArrayList<ItemAddressReq> itemAddressReqs = new ArrayList<>();
        for (int i = 0; i < datas.size(); i++) {
            ItemAddressReq itemAddressReq = new ItemAddressReq();
            itemAddressReq.setAreaAbbName(datas.get(i).getCb_areaAbbName());
            itemAddressReq.setAreaCode(datas.get(i).getCb_areaCode());
            itemAddressReq.setAreaEnName(datas.get(i).getCb_areaEnName());
            itemAddressReq.setAreaType(datas.get(i).getCb_areaType());
            itemAddressReq.setAreaZip(datas.get(i).getCb_areaZip());
            itemAddressReq.setAreaName(datas.get(i).getCb_areaName());
            itemAddressReq.setId(datas.get(i).getCb_id());
            itemAddressReq.setParentId(datas.get(i).getCb_parentId());
            itemAddressReqs.add(itemAddressReq);
        }
        return itemAddressReqs;
    }

    /**
     * 获取区的数据
     *
     * @param addressSelectorList
     * @return
     */
    @NonNull
    private ArrayList<ItemAddressReq> getItemAddressQu(List<AddressSelectorReq.DatasBean.ChildrenBeanX.ChildrenBean> addressSelectorList) {
        final ArrayList<ItemAddressReq> itemAddressReqs = new ArrayList<>();
        for (int i = 0; i < addressSelectorList.size(); i++) {
            ItemAddressReq itemAddressReq = new ItemAddressReq();
            itemAddressReq.setAreaAbbName(addressSelectorList.get(i).getAreaAbbName());
            itemAddressReq.setAreaCode(addressSelectorList.get(i).getAreaCode());
            itemAddressReq.setAreaEnName(addressSelectorList.get(i).getAreaEnName());
            itemAddressReq.setAreaType(addressSelectorList.get(i).getAreaType());
            itemAddressReq.setAreaZip(addressSelectorList.get(i).getAreaZip());
            itemAddressReq.setAreaName(addressSelectorList.get(i).getAreaName());
            itemAddressReq.setId(addressSelectorList.get(i).getId());
            itemAddressReq.setParentId(addressSelectorList.get(i).getParentId());
            itemAddressReqs.add(itemAddressReq);
        }
        return itemAddressReqs;
    }

6.设置地址选择器的布局文件

<?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="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="#fff"
    android:orientation="vertical"
    android:padding="1dp">

    <ImageView
        android:id="@+id/img_guanbi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginTop="15dp"
        android:layout_marginRight="15dp"
        android:src="@drawable/guanbi" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:text="所在区域"
        android:textColor="#777777"
        android:textSize="16sp" />

    <com.showly.ylin.addressselectdemo.addressselector.AddressSelector
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="70dp" />
</RelativeLayout>

6.总结
到这里就实现了地址选择器的功能,因为后台提供的地址数据可能不一样,所以这里就不把全部数据拿出来了,需要完整数据的也可以Q我。
需要Demo的童鞋可以在公众号回复 “地址选择器”


以下是个人公众号(longxuanzhigu),之后发布的文章会同步到该公众号,方便交流学习Android知识及分享个人爱好文章:
在这里插入图片描述

2016-05-25 10:15:29 hubeiqiyuan 阅读数 19810

最近项目里面用到了一个地址选择器,实现现在主流的WheelView滑动选择,整理了下,做了个Demo.废话不多说,直接上代码:

主布局:

<?xml version="1.0" encoding="utf-8"?>
<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="com.example.user.myapplication.MainActivity">

    <TextView
        android:id="@+id/select_address_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="15sp"
        android:text="选择地址" />
</RelativeLayout>
MainActivity:

package com.example.user.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private TextView select_address_tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        select_address_tv= (TextView) findViewById(R.id.select_address_tv);
        select_address_tv   .setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ChangeAddressPopwindow mChangeAddressPopwindow = new ChangeAddressPopwindow(MainActivity.this);
                mChangeAddressPopwindow.setAddress("广东", "深圳", "福田区");
                mChangeAddressPopwindow.showAtLocation(select_address_tv, Gravity.BOTTOM, 0, 0);
                mChangeAddressPopwindow
                        .setAddresskListener(new ChangeAddressPopwindow.OnAddressCListener() {

                            @Override
                            public void onClick(String province, String city, String area) {
                                // TODO Auto-generated method stub
                                Toast.makeText(MainActivity.this,
                                        province + "-" + city + "-" + area,
                                        Toast.LENGTH_LONG).show();
                                select_address_tv.setText(province + city + area);
                            }
                        });
            }
        });
    }
}
主要的类:
package com.example.user.myapplication;

import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import android.widget.TextView;

import com.example.user.myapplication.wheelview.OnWheelChangedListener;
import com.example.user.myapplication.wheelview.OnWheelScrollListener;
import com.example.user.myapplication.wheelview.WheelView;
import com.example.user.myapplication.wheelview.adapter.AbstractWheelTextAdapter1;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class ChangeAddressPopwindow extends PopupWindow implements View.OnClickListener {

	private WheelView wvProvince;
	private WheelView wvCitys;
	private WheelView wvArea;
	private View lyChangeAddress;
	private View lyChangeAddressChild;
	private TextView btnSure;
	private TextView btnCancel;

	private Context context;
	private JSONObject mJsonObj;
	/**
	 * 所有省
	 */
	private String[] mProvinceDatas;
	/**
	 * key - 省 value - 市s
	 */
	private Map<String, String[]> mCitisDatasMap = new HashMap<String, String[]>();
	/**
	 * key - 市 values - 区s
	 */
	private Map<String, String[]> mAreaDatasMap = new HashMap<String, String[]>();


	private ArrayList<String> arrProvinces = new ArrayList<String>();
	private ArrayList<String> arrCitys = new ArrayList<String>();
	private ArrayList<String> arrAreas = new ArrayList<String>();
	private AddressTextAdapter provinceAdapter;
	private AddressTextAdapter cityAdapter;
	private AddressTextAdapter areaAdapter;

	private String strProvince = "广东";
	private String strCity = "深圳";
	private String strArea = "福田区";
	private OnAddressCListener onAddressCListener;

	private int maxsize = 14;
	private int minsize = 12;

	public ChangeAddressPopwindow(final Context context) {
		super(context);
		this.context = context;
		View view=View.inflate(context,R.layout.edit_changeaddress_pop_layout,null);

		wvProvince = (WheelView) view.findViewById(R.id.wv_address_province);
		wvCitys = (WheelView) view.findViewById(R.id.wv_address_city);
		wvArea = (WheelView)view. findViewById(R.id.wv_address_area);
		lyChangeAddress = view.findViewById(R.id.ly_myinfo_changeaddress);
		lyChangeAddressChild = view.findViewById(R.id.ly_myinfo_changeaddress_child);
		btnSure = (TextView) view.findViewById(R.id.btn_myinfo_sure);
		btnCancel = (TextView)view. findViewById(R.id.btn_myinfo_cancel);


		//设置SelectPicPopupWindow的View
		this.setContentView(view);
		//设置SelectPicPopupWindow弹出窗体的宽
		this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
		//设置SelectPicPopupWindow弹出窗体的高
		this.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
		//设置SelectPicPopupWindow弹出窗体可点击
		this.setFocusable(true);
		//设置SelectPicPopupWindow弹出窗体动画效果
//		this.setAnimationStyle(R.style.AnimBottom);
		//实例化一个ColorDrawable颜色为半透明
		ColorDrawable dw = new ColorDrawable(0xb0000000);
		//设置SelectPicPopupWindow弹出窗体的背景
		this.setBackgroundDrawable(dw);

		lyChangeAddressChild.setOnClickListener(this);
		btnSure.setOnClickListener(this);
		btnCancel.setOnClickListener(this);

		initJsonData();
		initDatas();


		initProvinces();
		provinceAdapter = new AddressTextAdapter(context, arrProvinces, getProvinceItem(strProvince), maxsize, minsize);
		wvProvince.setVisibleItems(5);
		wvProvince.setViewAdapter(provinceAdapter);
		wvProvince.setCurrentItem(getProvinceItem(strProvince));

		initCitys(mCitisDatasMap.get(strProvince));
		cityAdapter = new AddressTextAdapter(context, arrCitys, getCityItem(strCity), maxsize, minsize);
		wvCitys.setVisibleItems(5);
		wvCitys.setViewAdapter(cityAdapter);
		wvCitys.setCurrentItem(getCityItem(strCity));

		initAreas(mAreaDatasMap.get(strCity));
		areaAdapter = new AddressTextAdapter(context, arrAreas, getAreaItem(strArea), maxsize, minsize);
		wvArea.setVisibleItems(5);
		wvArea.setViewAdapter(areaAdapter);
		wvArea.setCurrentItem(getAreaItem(strArea));

		wvProvince.addChangingListener(new OnWheelChangedListener() {

			@Override
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				// TODO Auto-generated method stub
				String currentText = (String) provinceAdapter.getItemText(wheel.getCurrentItem());
				strProvince = currentText;
				setTextviewSize(currentText, provinceAdapter);

				String[] citys = mCitisDatasMap.get(currentText);
				initCitys(citys);
				cityAdapter = new AddressTextAdapter(context, arrCitys, 0, maxsize, minsize);
				wvCitys.setVisibleItems(5);
				wvCitys.setViewAdapter(cityAdapter);
				wvCitys.setCurrentItem(0);
				setTextviewSize("0", cityAdapter);

				//根据市,地区联动
				String[] areas = mAreaDatasMap.get(citys[0]);
				initAreas(areas);
				areaAdapter = new AddressTextAdapter(context, arrAreas, 0, maxsize, minsize);
				wvArea.setVisibleItems(5);
				wvArea.setViewAdapter(areaAdapter);
				wvArea.setCurrentItem(0);
				setTextviewSize("0", areaAdapter);
			}
		});

		wvProvince.addScrollingListener(new OnWheelScrollListener() {

			@Override
			public void onScrollingStarted(WheelView wheel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScrollingFinished(WheelView wheel) {
				// TODO Auto-generated method stub
				String currentText = (String) provinceAdapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, provinceAdapter);
			}
		});

		wvCitys.addChangingListener(new OnWheelChangedListener() {

			@Override
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				// TODO Auto-generated method stub
				String currentText = (String) cityAdapter.getItemText(wheel.getCurrentItem());
				strCity = currentText;
				setTextviewSize(currentText, cityAdapter);

				//根据市,地区联动
				String[] areas = mAreaDatasMap.get(currentText);
				initAreas(areas);
				areaAdapter = new AddressTextAdapter(context, arrAreas, 0, maxsize, minsize);
				wvArea.setVisibleItems(5);
				wvArea.setViewAdapter(areaAdapter);
				wvArea.setCurrentItem(0);
				setTextviewSize("0", areaAdapter);


			}
		});

		wvCitys.addScrollingListener(new OnWheelScrollListener() {

			@Override
			public void onScrollingStarted(WheelView wheel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScrollingFinished(WheelView wheel) {
				// TODO Auto-generated method stub
				String currentText = (String) cityAdapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, cityAdapter);
			}
		});

		wvArea.addChangingListener(new OnWheelChangedListener() {

			@Override
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				// TODO Auto-generated method stub
				String currentText = (String) areaAdapter.getItemText(wheel.getCurrentItem());
				strArea = currentText;
				setTextviewSize(currentText, cityAdapter);
			}
		});

		wvArea.addScrollingListener(new OnWheelScrollListener() {

			@Override
			public void onScrollingStarted(WheelView wheel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScrollingFinished(WheelView wheel) {
				// TODO Auto-generated method stub
				String currentText = (String) areaAdapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, areaAdapter);
			}
		});


	}


	private class AddressTextAdapter extends AbstractWheelTextAdapter1 {
		ArrayList<String> list;

		protected AddressTextAdapter(Context context, ArrayList<String> list, int currentItem, int maxsize, int minsize) {
			super(context, R.layout.item_birth_year, NO_RESOURCE, currentItem, maxsize, minsize);
			this.list = list;
			setItemTextResource(R.id.tempValue);
		}

		@Override
		public View getItem(int index, View cachedView, ViewGroup parent) {
			View view = super.getItem(index, cachedView, parent);
			return view;
		}

		@Override
		public int getItemsCount() {
			return list.size();
		}

		@Override
		protected CharSequence getItemText(int index) {
			return list.get(index) + "";
		}
	}

	/**
	 * 设置字体大小
	 * 
	 * @param curriteItemText
	 * @param adapter
	 */
	public void setTextviewSize(String curriteItemText, AddressTextAdapter adapter) {
		ArrayList<View> arrayList = adapter.getTestViews();
		int size = arrayList.size();
		String currentText;
		for (int i = 0; i < size; i++) {
			TextView textvew = (TextView) arrayList.get(i);
			currentText = textvew.getText().toString();
			if (curriteItemText.equals(currentText)) {
				textvew.setTextSize(14);
			} else {
				textvew.setTextSize(12);
			}
		}
	}

	public void setAddresskListener(OnAddressCListener onAddressCListener) {
		this.onAddressCListener = onAddressCListener;
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		if (v == btnSure) {
			if (onAddressCListener != null) {
				onAddressCListener.onClick(strProvince, strCity,strArea);
			}
		} else if (v == btnCancel) {

		} else if (v == lyChangeAddressChild) {
			return;
		} else {
//			dismiss();
		}
		dismiss();
	}

	/**
	 * 回调接口
	 * 
	 * @author Administrator
	 *
	 */
	public interface OnAddressCListener {
		public void onClick(String province, String city, String area);
	}

	/**
	 * 从文件中读取地址数据
	 */
	private void initJsonData() {
		try {
			StringBuffer sb = new StringBuffer();
			InputStream is = context.getClass().getClassLoader().getResourceAsStream("assets/" + "city.json");
			int len = -1;
			byte[] buf = new byte[1024];
			while ((len = is.read(buf)) != -1) {
				sb.append(new String(buf, 0, len, "gbk"));
			}
			is.close();
			mJsonObj = new JSONObject(sb.toString());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 解析整个Json对象,完成后释放Json对象的内存
	 */
	private void initDatas()
	{
		try
		{
			JSONArray jsonArray = mJsonObj.getJSONArray("citylist");
			mProvinceDatas = new String[jsonArray.length()];
			for (int i = 0; i < jsonArray.length(); i++)
			{
				JSONObject jsonP = jsonArray.getJSONObject(i);// 每个省的json对象
				String province = jsonP.getString("p");// 省名字

				mProvinceDatas[i] = province;

				JSONArray jsonCs = null;
				try
				{
					/**
					 * Throws JSONException if the mapping doesn't exist or is
					 * not a JSONArray.
					 */
					jsonCs = jsonP.getJSONArray("c");
				} catch (Exception e1)
				{
					continue;
				}
				String[] mCitiesDatas = new String[jsonCs.length()];
				for (int j = 0; j < jsonCs.length(); j++)
				{
					JSONObject jsonCity = jsonCs.getJSONObject(j);
					String city = jsonCity.getString("n");// 市名字
					mCitiesDatas[j] = city;
					JSONArray jsonAreas = null;
					try
					{
						/**
						 * Throws JSONException if the mapping doesn't exist or
						 * is not a JSONArray.
						 */
						jsonAreas = jsonCity.getJSONArray("a");
					} catch (Exception e)
					{
						continue;
					}

					String[] mAreasDatas = new String[jsonAreas.length()];// 当前市的所有区
					for (int k = 0; k < jsonAreas.length(); k++)
					{
						String area = jsonAreas.getJSONObject(k).getString("s");// 区域的名称
						mAreasDatas[k] = area;
					}
					mAreaDatasMap.put(city, mAreasDatas);
				}

				mCitisDatasMap.put(province, mCitiesDatas);
			}

		} catch (JSONException e)
		{
			e.printStackTrace();
		}
		mJsonObj = null;
	}

	/**
	 * 初始化省会
	 */
	public void initProvinces() {
		int length = mProvinceDatas.length;
		for (int i = 0; i < length; i++) {
			arrProvinces.add(mProvinceDatas[i]);
		}
	}

	/**
	 * 根据省会,生成该省会的所有城市
	 * 
	 * @param citys
	 */
	public void initCitys(String[] citys) {
		if (citys != null) {
			arrCitys.clear();
			int length = citys.length;
			for (int i = 0; i < length; i++) {
				arrCitys.add(citys[i]);
			}
		} else {
			String[] city = mCitisDatasMap.get("广东");
			arrCitys.clear();
			int length = city.length;
			for (int i = 0; i < length; i++) {
				arrCitys.add(city[i]);
			}
		}
		if (arrCitys != null && arrCitys.size() > 0
				&& !arrCitys.contains(strCity)) {
			strCity = arrCitys.get(0);
		}
	}

	/**
	 * 根据城市,生成该城市的所有地区
	 *
	 * @param areas
	 */
	public void initAreas(String[] areas) {
		if (areas != null) {
			arrAreas.clear();
			int length = areas.length;
			for (int i = 0; i < length; i++) {
				arrAreas.add(areas[i]);
			}
		} else {
			String[] area = mAreaDatasMap.get("深圳");
			arrAreas.clear();
			int length = area.length;
			for (int i = 0; i < length; i++) {
				arrAreas.add(area[i]);
			}
		}
		if (arrAreas != null && arrAreas.size() > 0
				&& !arrAreas.contains(strArea)) {
			strArea = arrAreas.get(0);
		}
	}

	/**
	 * 初始化地点
	 * 
	 * @param province
	 * @param city
	 */
	public void setAddress(String province, String city, String area) {
		if (province != null && province.length() > 0) {
			this.strProvince = province;
		}
		if (city != null && city.length() > 0) {
			this.strCity = city;
		}

		if (area != null && area.length() > 0) {
			this.strArea = area;
		}
	}

	/**
	 * 返回省会索引,没有就返回默认“广东”
	 * 
	 * @param province
	 * @return
	 */
	public int getProvinceItem(String province) {
		int size = arrProvinces.size();
		int provinceIndex = 0;
		boolean noprovince = true;
		for (int i = 0; i < size; i++) {
			if (province.equals(arrProvinces.get(i))) {
				noprovince = false;
				return provinceIndex;
			} else {
				provinceIndex++;
			}
		}
		if (noprovince) {
			strProvince = "广东";
			return 18;
		}
		return provinceIndex;
	}

	/**
	 * 得到城市索引,没有返回默认“深圳”
	 * 
	 * @param city
	 * @return
	 */
	public int getCityItem(String city) {
		int size = arrCitys.size();
		int cityIndex = 0;
		boolean nocity = true;
		for (int i = 0; i < size; i++) {
			System.out.println(arrCitys.get(i));
			if (city.equals(arrCitys.get(i))) {
				nocity = false;
				return cityIndex;
			} else {
				cityIndex++;
			}
		}
		if (nocity) {
			strCity = "深圳";
			return 2;
		}
		return cityIndex;
	}

	/**
	 * 得到地区索引,没有返回默认“福田区”
	 *
	 * @param area
	 * @return
	 */
	public int getAreaItem(String area) {
		int size = arrAreas.size();
		int areaIndex = 0;
		boolean noarea = true;
		for (int i = 0; i < size; i++) {
			System.out.println(arrAreas.get(i));
			if (area.equals(arrAreas.get(i))) {
				noarea = false;
				return areaIndex;
			} else {
				areaIndex++;
			}
		}
		if (noarea) {
			strArea = "福田区";
			return 1;
		}
		return areaIndex;
	}


}
弹出框布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ly_myinfo_changeaddress"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00000000"
    android:gravity="bottom"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/ly_myinfo_changeaddress_child"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
		android:layout_alignParentBottom="true"
        android:background="#ffffff"
        android:orientation="vertical" >


        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="44dp"
             >

            <TextView
                android:id="@+id/btn_myinfo_cancel"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
				android:paddingLeft="12dp"
                android:text="取消"
                android:gravity="center"
                android:layout_alignParentLeft="true"
                android:layout_marginRight="15dip"
				android:textColor="#e84515"
                android:textSize="13sp" />


            <TextView
                android:id="@+id/btn_myinfo_sure"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:gravity="center"
                android:text="完成"
				android:textColor="#e84515"
				android:paddingRight="12dp"
                android:textSize="12sp" />

        </RelativeLayout>

        <View android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#d8d8d8"/>

		<LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="160dip"
	        android:orientation="horizontal"
	        android:gravity="center_vertical">
	        <com.example.user.myapplication.wheelview.WheelView
	            android:id="@+id/wv_address_province"
	            android:layout_width="0dip"
	            android:layout_weight="1"
	            android:layout_height="match_parent"
	            android:layout_gravity="center_vertical"
	            />
	        <com.example.user.myapplication.wheelview.WheelView
	            android:id="@+id/wv_address_city"
	            android:layout_width="0dip"
	            android:layout_weight="1"
	            android:layout_height="match_parent"
	            android:layout_gravity="center_vertical"
	            />

            <com.example.user.myapplication.wheelview.WheelView
                android:id="@+id/wv_address_area"
                android:layout_width="0dip"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:layout_gravity="center_vertical"
                />
	    </LinearLayout>

    </LinearLayout>

</LinearLayout>
运行效果图:

源代码下载