taomenggo init

This commit is contained in:
guozhen
2024-08-06 10:30:15 +08:00
committed by xuhuixiang
parent 3e7fd07f4f
commit c929efd05e
3007 changed files with 229844 additions and 77 deletions

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lljjcoder.style.citypickerview">
<application
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="com.lljjcoder.style.citylist.CityListSelectActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustNothing|stateUnchanged">
</activity>
<activity
android:name="com.lljjcoder.style.citythreelist.ProvinceActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustNothing|stateUnchanged">
</activity>
<activity
android:name="com.lljjcoder.style.citythreelist.CityActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustNothing|stateUnchanged">
</activity>
<activity
android:name="com.lljjcoder.style.citythreelist.AreaActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustNothing|stateUnchanged">
</activity>
</application>
</manifest>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
package com.lljjcoder;
/**
* 作者liji on 2018/1/22 09:46
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class Constant {
public static final String CITY_DATA = "china_city_data.json";
public static final String CITY_DATA_TW = "china_city_data_tw.json";
}

View File

@@ -0,0 +1,31 @@
package com.lljjcoder.Interface;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
/**
* 作者liji on 2017/11/16 10:06
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public abstract class OnCityItemClickListener {
/**
* 当选择省市区三级选择器时,需要覆盖此方法
* @param province
* @param city
* @param district
*/
public void onSelected(ProvinceBean province, CityBean city, DistrictBean district) {
}
/**
* 取消
*/
public void onCancel() {
}
}

View File

@@ -0,0 +1,33 @@
package com.lljjcoder.Interface;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.CustomCityData;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
/**
* 作者liji on 2017/11/16 10:06
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public abstract class OnCustomCityPickerItemClickListener {
/**
* 当选择省市区三级选择器时,需要覆盖此方法
*
* @param province
* @param city
* @param district
*/
public void onSelected(CustomCityData province, CustomCityData city, CustomCityData district) {
}
/**
* 取消
*/
public void onCancel() {
}
}

View File

@@ -0,0 +1,85 @@
package com.lljjcoder.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
/**
* @2Do:
* @Author M2
* @Version v ${VERSION}
* @Date 2017/7/7 0007.
*/
public class CityBean implements Parcelable {
private String id; /*110101*/
private String name; /*东城区*/
private ArrayList<DistrictBean> cityList;
@Override
public String toString() {
return name;
}
public String getId() {
return id == null ? "" : id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name == null ? "" : name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<DistrictBean> getCityList() {
return cityList;
}
public void setCityList(ArrayList<DistrictBean> cityList) {
this.cityList = cityList;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
dest.writeTypedList(this.cityList);
}
public CityBean() {
}
protected CityBean(Parcel in) {
this.id = in.readString();
this.name = in.readString();
this.cityList = in.createTypedArrayList(DistrictBean.CREATOR);
}
public static final Creator<CityBean> CREATOR = new Creator<CityBean>() {
@Override
public CityBean createFromParcel(Parcel source) {
return new CityBean(source);
}
@Override
public CityBean[] newArray(int size) {
return new CityBean[size];
}
};
}

View File

@@ -0,0 +1,4 @@
package com.lljjcoder.bean;
public class CityJson {
}

View File

@@ -0,0 +1,58 @@
package com.lljjcoder.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义数据源需要的数据model,自定义的话需要继承该数据model
*/
public class CustomCityData {
private String id; /*110101*/
private String name; /*东城区*/
private List<CustomCityData> list = new ArrayList<>();
public CustomCityData() {
}
@Override
public String toString() {
return name;
}
public CustomCityData(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CustomCityData> getList() {
return list;
}
public void setList(List<CustomCityData> list) {
this.list = list;
}
}

View File

@@ -0,0 +1,69 @@
package com.lljjcoder.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @2Do:
* @Author M2
* @Version v ${VERSION}
* @Date 2017/7/7 0007.
*/
public class DistrictBean implements Parcelable {
private String id; /*110101*/
private String name; /*东城区*/
@Override
public String toString() {
return name;
}
public String getId() {
return id == null ? "" : id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name == null ? "" : name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
}
public DistrictBean() {
}
protected DistrictBean(Parcel in) {
this.id = in.readString();
this.name = in.readString();
}
public static final Creator<DistrictBean> CREATOR = new Creator<DistrictBean>() {
@Override
public DistrictBean createFromParcel(Parcel source) {
return new DistrictBean(source);
}
@Override
public DistrictBean[] newArray(int size) {
return new DistrictBean[size];
}
};
}

View File

@@ -0,0 +1,86 @@
package com.lljjcoder.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
/**
* @2Do:
* @Author M2
* @Version v ${VERSION}
* @Date 2017/7/7 0007.
*/
public class ProvinceBean implements Parcelable {
private String id; /*110101*/
private String name; /*东城区*/
private ArrayList<CityBean> cityList;
@Override
public String toString() {
return name ;
}
public String getId() {
return id == null ? "" : id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name == null ? "" : name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<CityBean> getCityList() {
return cityList;
}
public void setCityList(ArrayList<CityBean> cityList) {
this.cityList = cityList;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
dest.writeTypedList(this.cityList);
}
public ProvinceBean() {
}
protected ProvinceBean(Parcel in) {
this.id = in.readString();
this.name = in.readString();
this.cityList = in.createTypedArrayList(CityBean.CREATOR);
}
public static final Creator<ProvinceBean> CREATOR = new Creator<ProvinceBean>() {
@Override
public ProvinceBean createFromParcel(Parcel source) {
return new ProvinceBean(source);
}
@Override
public ProvinceBean[] newArray(int size) {
return new ProvinceBean[size];
}
};
}

View File

@@ -0,0 +1,848 @@
package com.lljjcoder.citywheel;
/**
* 城市选择器样式配置
* 作者liji on 2017/11/4 10:31
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityConfig {
public static final Integer NONE = -1111;
// private Context mContext;
/**
* 滚轮显示的item个数
*/
private int visibleItems = 5;
/**
* 省滚轮是否循环滚动
*/
private boolean isProvinceCyclic = true;
/**
* 市滚轮是否循环滚动
*/
private boolean isCityCyclic = true;
/**
* 区滚轮是否循环滚动
*/
private boolean isDistrictCyclic = true;
/**
* Color.BLACK
*/
private String cancelTextColorStr = "#000000";
/**
* Color.BLACK
*/
private String cancelText = "取消";
private int cancelTextSize = 16;
/**
* Color.BLUE
*/
private String confirmTextColorStr = "#0000FF";
/**
* Color.BLUE
*/
private String confirmText = "确定";
/**
* Color.BLUE
*/
private int confirmTextSize = 16;
/**
* 标题
*/
private String mTitle = "选择地区";
/**
* 标题背景颜色
*/
private String titleBackgroundColorStr = "#E9E9E9";
/**
* 标题颜色
*/
private String titleTextColorStr = "#585858";
/**
* 标题字体大小
*/
private int titleTextSize = 18;
/**
* 第一次默认的显示省份,一般配合定位,使用
*/
private String defaultProvinceName = "浙江";
/**
* 第一次默认得显示城市,一般配合定位,使用
*/
private String defaultCityName = "杭州";
/**
* 第一次默认得显示,一般配合定位,使用
*/
private String defaultDistrict = "滨江区";
/**
* 自定义的item布局
*/
private Integer customItemLayout;
/**
* 自定义的item txt id
*/
private Integer customItemTextViewId;
/**
* 是否显示滚轮上面的模糊阴影效果
*/
private boolean drawShadows = true;
/**
* 是否显示港澳台城市数据
*/
private boolean showGAT = false;
/**
* 中间线的颜色
*/
private String lineColor = "#C7C7C7";
/**
* 中间线的宽度
*/
private int lineHeigh = 3;
private int loclanguage = 0;
/**
* 默认显示的城市数据,只包含省市区名称
*/
/**
* 定义显示省市区三种滚轮的显示状态
* PRO:只显示省份的一级选择器
* PRO_CITY:显示省份和城市二级联动的选择器
* PRO_CITY_DIS:显示省份和城市和县区三级联动的选择器
*/
public enum WheelType {
PRO, PRO_CITY, PRO_CITY_DIS
}
/**
* 是否显示半透明的背景
*/
private boolean isShowBackground = true;
/**
* 定义默认显示省市区三级联动的滚轮选择器
*/
public WheelType mWheelType = WheelType.PRO_CITY_DIS;
public CityConfig.WheelType getWheelType() {
return mWheelType;
}
public boolean isShowBackground() {
return isShowBackground;
}
public boolean isShowGAT() {
return showGAT;
}
public void setShowGAT(boolean showGAT) {
this.showGAT = showGAT;
}
public String getLineColor() {
return lineColor == null ? "" : lineColor;
}
public void setLineColor(String lineColor) {
this.lineColor = lineColor;
}
public int getLineHeigh() {
return lineHeigh;
}
public void setLineHeigh(int lineHeigh) {
this.lineHeigh = lineHeigh;
}
public boolean isDrawShadows() {
return drawShadows;
}
public void setDrawShadows(boolean drawShadows) {
this.drawShadows = drawShadows;
}
public int getVisibleItems() {
return visibleItems;
}
public void setVisibleItems(int visibleItems) {
this.visibleItems = visibleItems;
}
public boolean isProvinceCyclic() {
return isProvinceCyclic;
}
public void setProvinceCyclic(boolean provinceCyclic) {
isProvinceCyclic = provinceCyclic;
}
public boolean isCityCyclic() {
return isCityCyclic;
}
public void setCityCyclic(boolean cityCyclic) {
isCityCyclic = cityCyclic;
}
public boolean isDistrictCyclic() {
return isDistrictCyclic;
}
public void setDistrictCyclic(boolean districtCyclic) {
isDistrictCyclic = districtCyclic;
}
public String getCancelTextColorStr() {
return cancelTextColorStr == null ? "" : cancelTextColorStr;
}
public void setCancelTextColorStr(String cancelTextColorStr) {
this.cancelTextColorStr = cancelTextColorStr;
}
public String getCancelText() {
return cancelText == null ? "" : cancelText;
}
public void setCancelText(String cancelText) {
this.cancelText = cancelText;
}
public int getCancelTextSize() {
return cancelTextSize;
}
public void setCancelTextSize(int cancelTextSize) {
this.cancelTextSize = cancelTextSize;
}
public String getConfirmTextColorStr() {
return confirmTextColorStr == null ? "" : confirmTextColorStr;
}
public void setConfirmTextColorStr(String confirmTextColorStr) {
this.confirmTextColorStr = confirmTextColorStr;
}
public String getConfirmText() {
return confirmText == null ? "" : confirmText;
}
public void setConfirmText(String confirmText) {
this.confirmText = confirmText;
}
public int getConfirmTextSize() {
return confirmTextSize;
}
public void setConfirmTextSize(int confirmTextSize) {
this.confirmTextSize = confirmTextSize;
}
public String getTitle() {
return mTitle == null ? "" : mTitle;
}
public void setTitle(String title) {
mTitle = title;
}
public String getTitleBackgroundColorStr() {
return titleBackgroundColorStr == null ? "" : titleBackgroundColorStr;
}
public void setTitleBackgroundColorStr(String titleBackgroundColorStr) {
this.titleBackgroundColorStr = titleBackgroundColorStr;
}
public String getTitleTextColorStr() {
return titleTextColorStr == null ? "" : titleTextColorStr;
}
public void setTitleTextColorStr(String titleTextColorStr) {
this.titleTextColorStr = titleTextColorStr;
}
public int getTitleTextSize() {
return titleTextSize;
}
public void setTitleTextSize(int titleTextSize) {
this.titleTextSize = titleTextSize;
}
public String getDefaultProvinceName() {
return defaultProvinceName == null ? "" : defaultProvinceName;
}
public void setDefaultProvinceName(String defaultProvinceName) {
this.defaultProvinceName = defaultProvinceName;
}
public String getDefaultCityName() {
return defaultCityName == null ? "" : defaultCityName;
}
public void setDefaultCityName(String defaultCityName) {
this.defaultCityName = defaultCityName;
}
public String getDefaultDistrict() {
return defaultDistrict == null ? "" : defaultDistrict;
}
public void setDefaultDistrict(String defaultDistrict) {
this.defaultDistrict = defaultDistrict;
}
public int setLanguage() {
return loclanguage;
}
public void getLanguage(int loclanguage) {
this.loclanguage = loclanguage;
}
public Integer getCustomItemLayout() {
return customItemLayout == null ? NONE : customItemLayout;
}
public void setCustomItemLayout(int customItemLayout) {
this.customItemLayout = customItemLayout;
}
public Integer getCustomItemTextViewId() {
return customItemTextViewId == null ? NONE : customItemTextViewId;
}
public void setCustomItemTextViewId(Integer customItemTextViewId) {
this.customItemTextViewId = customItemTextViewId;
}
public void setShowBackground(boolean showBackground) {
isShowBackground = showBackground;
}
public CityConfig(Builder builder) {
// this.mContext = builder.mContext;
/**
* 标题栏相关的属性:
* 0、标题栏背景颜色
* 1、标题文字、大小、颜色
*
* 2、取消字体的颜色、大小、内容
* 3、确认字体的颜色、大小、内容
*/
this.titleBackgroundColorStr = builder.titleBackgroundColorStr;
this.mTitle = builder.mTitle;
this.titleTextColorStr = builder.titleTextColorStr;
this.titleTextSize = builder.titleTextSize;
this.cancelTextColorStr = builder.cancelTextColorStr;
this.cancelText = builder.cancelText;
this.cancelTextSize = builder.cancelTextSize;
this.confirmTextColorStr = builder.confirmTextColorStr;
this.confirmText = builder.confirmText;
this.confirmTextSize = builder.confirmTextSize;
/**
* 滚轮相关的属性:
* 1、item显示的个数
* 2、省份是否可以循环
* 3、城市是否可以循环
* 4、地区是否可以循环
*/
this.visibleItems = builder.visibleItems;
this.isProvinceCyclic = builder.isProvinceCyclic;
this.isDistrictCyclic = builder.isDistrictCyclic;
this.isCityCyclic = builder.isCityCyclic;
this.loclanguage = builder.lauguage;
/**
* 默认的省市区地址
*/
this.defaultDistrict = builder.defaultDistrict;
this.defaultCityName = builder.defaultCityName;
this.defaultProvinceName = builder.defaultProvinceName;
/**
* 是否显示城市和地区
*/
this.mWheelType = builder.mWheelType;
/**
* 是否显示半透明
*/
this.isShowBackground = builder.isShowBackground;
/**
* 自定义item的布局必须制定Layout和id
*/
this.customItemLayout = builder.customItemLayout;
this.customItemTextViewId = builder.customItemTextViewId;
/**
* 是否显示滚轮上面的模糊阴影效果
*/
this.drawShadows = builder.drawShadows;
this.lineColor = builder.lineColor;
this.lineHeigh = builder.lineHeigh;
this.showGAT = builder.showGAT;
}
public static class Builder {
/**
* 滚轮显示的item个数
*/
private int visibleItems = 5;
/**
* 省滚轮是否循环滚动
*/
private boolean isProvinceCyclic = true;
/**
* 市滚轮是否循环滚动
*/
private boolean isCityCyclic = true;
/**
* 区滚轮是否循环滚动
*/
private boolean isDistrictCyclic = true;
/**
* Color.BLACK
*/
private String cancelTextColorStr = "#000000";
/**
* Color.BLACK
*/
private String cancelText = "取消";
private int cancelTextSize = 16;
/**
* Color.BLUE
*/
private String confirmTextColorStr = "#0000FF";
/**
* Color.BLUE
*/
private String confirmText = "确定";
/**
* Color.BLUE
*/
private int confirmTextSize = 16;
/**
* 标题
*/
private String mTitle = "选择地区";
/**
* 标题背景颜色
*/
private String titleBackgroundColorStr = "#E9E9E9";
/**
* 标题颜色
*/
private String titleTextColorStr = "#585858";
/**
* 标题字体大小
*/
private int titleTextSize = 18;
/**
* 第一次默认的显示省份,一般配合定位,使用
*/
private String defaultProvinceName = "浙江";
/**
* 第一次默认得显示城市,一般配合定位,使用
*/
private String defaultCityName = "杭州";
/**
* 第一次默认得显示,一般配合定位,使用
*/
private String defaultDistrict = "滨江区";
private int lauguage = 0;
/**
* 定义默认显示省市区三级联动的滚轮选择器
*/
private CityConfig.WheelType mWheelType = CityConfig.WheelType.PRO_CITY_DIS;
/**
* 是否显示半透明的背景
*/
private boolean isShowBackground = true;
/**
* 自定义的item布局
*/
private Integer customItemLayout;
/**
* 自定义的item txt id
*/
private Integer customItemTextViewId;
/**
* 是否显示滚轮上面的模糊阴影效果
*/
private boolean drawShadows = true;
/**
* 中间线的颜色
*/
private String lineColor = "#C7C7C7";
/**
* 是否显示港澳台城市数据
*/
private boolean showGAT = false;
/**
* 中间线的宽度
*/
private int lineHeigh = 3;
public Builder() {
}
/**
* 是否显示港澳台城市数据,默认不显示
* @param showGAT
* @return
*/
public Builder setShowGAT(boolean showGAT) {
this.showGAT = showGAT;
return this;
}
/**
* 中间线的宽度
* @param lineHeigh
* @return
*/
public Builder setLineHeigh(int lineHeigh) {
this.lineHeigh = lineHeigh;
return this;
}
/**
* 中间线的颜色
* @param lineColor
* @return
*/
public Builder setLineColor(String lineColor) {
this.lineColor = lineColor;
return this;
}
/**
* 是否显示滚轮上面的模糊阴影效果
*
* @param drawShadows
* @return
*/
public Builder drawShadows(boolean drawShadows) {
this.drawShadows = drawShadows;
return this;
}
/**
* 设置标题背景颜色
*
* @param colorBg
* @return
*/
public Builder titleBackgroundColor(String colorBg) {
this.titleBackgroundColorStr = colorBg;
return this;
}
/**
* 设置标题字体颜色
*
* @param titleTextColorStr
* @return
*/
public Builder titleTextColor(String titleTextColorStr) {
this.titleTextColorStr = titleTextColorStr;
return this;
}
/**
* 设置标题字体大小
*
* @param titleTextSize
* @return
*/
public Builder titleTextSize(int titleTextSize) {
this.titleTextSize = titleTextSize;
return this;
}
/**
* 设置标题
*
* @param mtitle
* @return
*/
public Builder title(String mtitle) {
this.mTitle = mtitle;
return this;
}
/**
* 确认按钮文字
*
* @param confirmTextSize
* @return
*/
public Builder confirmTextSize(int confirmTextSize) {
this.confirmTextSize = confirmTextSize;
return this;
}
/**
* 确认按钮文字
*
* @param confirmText
* @return
*/
public Builder confirmText(String confirmText) {
this.confirmText = confirmText;
return this;
}
/**
* 确认按钮文字颜色
*
* @param color
* @return
*/
public Builder confirTextColor(String color) {
this.confirmTextColorStr = color;
return this;
}
/**
* 取消按钮文字颜色
*
* @param color
* @return
*/
public Builder cancelTextColor(String color) {
this.cancelTextColorStr = color;
return this;
}
/**
* 取消按钮文字大小
*
* @param cancelTextSize
* @return
*/
public Builder cancelTextSize(int cancelTextSize) {
this.cancelTextSize = cancelTextSize;
return this;
}
/**
* 取消按钮文字
*
* @param cancelText
* @return
*/
public Builder cancelText(String cancelText) {
this.cancelText = cancelText;
return this;
}
/**
* 滚轮显示的item个数
*
* @param visibleItems
* @return
*/
public Builder visibleItemsCount(int visibleItems) {
this.visibleItems = visibleItems;
return this;
}
/**
* 省滚轮是否循环滚动
*
* @param isProvinceCyclic
* @return
*/
public Builder provinceCyclic(boolean isProvinceCyclic) {
this.isProvinceCyclic = isProvinceCyclic;
return this;
}
/**
* 市滚轮是否循环滚动
*
* @param isCityCyclic
* @return
*/
public Builder cityCyclic(boolean isCityCyclic) {
this.isCityCyclic = isCityCyclic;
return this;
}
/**
* 区滚轮是否循环滚动
*
* @param isDistrictCyclic
* @return
*/
public Builder districtCyclic(boolean isDistrictCyclic) {
this.isDistrictCyclic = isDistrictCyclic;
return this;
}
/**
* 显示省市区三级联动的显示状态
* PRO:只显示省份的一级选择器
* PRO_CITY:显示省份和城市二级联动的选择器
* PRO_CITY_DIS:显示省份和城市和县区三级联动的选择器
* @param wheelType
* @return
*/
public Builder setCityWheelType(CityConfig.WheelType wheelType) {
this.mWheelType = wheelType;
return this;
}
/**
* 第一次默认的显示省份,一般配合定位,使用
*
* @param defaultProvinceName
* @return
*/
public Builder province(String defaultProvinceName) {
this.defaultProvinceName = defaultProvinceName;
return this;
}
/**
* 第一次默认得显示城市,一般配合定位,使用
*
* @param defaultCityName
* @return
*/
public Builder city(String defaultCityName) {
this.defaultCityName = defaultCityName;
return this;
}
/**
* 第一次默认地区显示,一般配合定位,使用
*
* @param defaultDistrict
* @return
*/
public Builder district(String defaultDistrict) {
this.defaultDistrict = defaultDistrict;
return this;
}
/**
* 第一次默认地区显示,一般配合定位,使用
*
* @param defaultDistrict
* @return
*/
public Builder setLanguage(int language) {
this.lauguage = language;
return this;
}
/**
* 是否显示半透明的背景
* @param isShowBackground
* @return
*/
public Builder showBackground(boolean isShowBackground) {
this.isShowBackground = isShowBackground;
return this;
}
/**
* 自定义item布局
* @param itemLayout
* @return
*/
public Builder setCustomItemLayout(Integer itemLayout) {
this.customItemLayout = itemLayout;
return this;
}
/**
* 自定义item布局中的id
* @param setCustomItemTextViewId
* @return
*/
public Builder setCustomItemTextViewId(Integer setCustomItemTextViewId) {
this.customItemTextViewId = setCustomItemTextViewId;
return this;
}
public CityConfig build() {
CityConfig config = new CityConfig(this);
return config;
}
}
}

View File

@@ -0,0 +1,347 @@
package com.lljjcoder.citywheel;
import android.content.Context;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lljjcoder.Constant;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
import com.lljjcoder.utils.utils;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 省市区解析辅助类
* 作者liji on 2017/11/4 10:09
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityParseHelper {
/**
* 省份数据
*/
private ArrayList<ProvinceBean> mProvinceBeanArrayList = new ArrayList<>();
/**
* 城市数据
*/
private ArrayList<ArrayList<CityBean>> mCityBeanArrayList;
/**
* 地区数据
*/
private ArrayList<ArrayList<ArrayList<DistrictBean>>> mDistrictBeanArrayList;
private List<ProvinceBean> mProvinceBeenArray;
private ProvinceBean mProvinceBean;
private CityBean mCityBean;
private DistrictBean mDistrictBean;
// private CityConfig config;
/**
* key - 省 value - 市
*/
private Map<String, List<CityBean>> mPro_CityMap = new HashMap<String, List<CityBean>>();
/**
* key - 市 values - 区
*/
private Map<String, List<DistrictBean>> mCity_DisMap = new HashMap<String, List<DistrictBean>>();
/**
* key - 区 values - 邮编
*/
private Map<String, DistrictBean> mDisMap = new HashMap<String, DistrictBean>();
public ArrayList<ProvinceBean> getProvinceBeanArrayList() {
return mProvinceBeanArrayList;
}
public void setProvinceBeanArrayList(ArrayList<ProvinceBean> provinceBeanArrayList) {
mProvinceBeanArrayList = provinceBeanArrayList;
}
public ArrayList<ArrayList<CityBean>> getCityBeanArrayList() {
return mCityBeanArrayList;
}
public void setCityBeanArrayList(ArrayList<ArrayList<CityBean>> cityBeanArrayList) {
mCityBeanArrayList = cityBeanArrayList;
}
public ArrayList<ArrayList<ArrayList<DistrictBean>>> getDistrictBeanArrayList() {
return mDistrictBeanArrayList;
}
public void setDistrictBeanArrayList(ArrayList<ArrayList<ArrayList<DistrictBean>>> districtBeanArrayList) {
mDistrictBeanArrayList = districtBeanArrayList;
}
public List<ProvinceBean> getProvinceBeenArray() {
return mProvinceBeenArray;
}
public void setProvinceBeenArray(List<ProvinceBean> provinceBeenArray) {
mProvinceBeenArray = provinceBeenArray;
}
public ProvinceBean getProvinceBean() {
return mProvinceBean;
}
public void setProvinceBean(ProvinceBean provinceBean) {
mProvinceBean = provinceBean;
}
public CityBean getCityBean() {
return mCityBean;
}
public void setCityBean(CityBean cityBean) {
mCityBean = cityBean;
}
public DistrictBean getDistrictBean() {
return mDistrictBean;
}
public void setDistrictBean(DistrictBean districtBean) {
mDistrictBean = districtBean;
}
public Map<String, List<CityBean>> getPro_CityMap() {
return mPro_CityMap;
}
public void setPro_CityMap(Map<String, List<CityBean>> pro_CityMap) {
mPro_CityMap = pro_CityMap;
}
public Map<String, List<DistrictBean>> getCity_DisMap() {
return mCity_DisMap;
}
public void setCity_DisMap(Map<String, List<DistrictBean>> city_DisMap) {
mCity_DisMap = city_DisMap;
}
public Map<String, DistrictBean> getDisMap() {
return mDisMap;
}
public void setDisMap(Map<String, DistrictBean> disMap) {
mDisMap = disMap;
}
public CityParseHelper() {
}
/**
* 初始化数据解析json数据
*/
public void initData(Context context) {
String cityJson = utils.getJson(context, Constant.CITY_DATA);
Type type = new TypeToken<ArrayList<ProvinceBean>>() {
}.getType();
mProvinceBeanArrayList = new Gson().fromJson(cityJson, type);
if (mProvinceBeanArrayList == null || mProvinceBeanArrayList.isEmpty()) {
return;
}
mCityBeanArrayList = new ArrayList<>(mProvinceBeanArrayList.size());
mDistrictBeanArrayList = new ArrayList<>(mProvinceBeanArrayList.size());
//*/ 初始化默认选中的省、市、区,默认选中第一个省份的第一个市区中的第一个区县
if (mProvinceBeanArrayList != null && !mProvinceBeanArrayList.isEmpty()) {
mProvinceBean = mProvinceBeanArrayList.get(0);
List<CityBean> cityList = mProvinceBean.getCityList();
if (cityList != null && !cityList.isEmpty() && cityList.size() > 0) {
mCityBean = cityList.get(0);
List<DistrictBean> districtList = mCityBean.getCityList();
if (districtList != null && !districtList.isEmpty() && districtList.size() > 0) {
mDistrictBean = districtList.get(0);
}
}
}
//省份数据
mProvinceBeenArray = new ArrayList<ProvinceBean>();
for (int p = 0; p < mProvinceBeanArrayList.size(); p++) {
//遍历每个省份
ProvinceBean itemProvince = mProvinceBeanArrayList.get(p);
//每个省份对应下面的市
ArrayList<CityBean> cityList = itemProvince.getCityList();
//当前省份下面的所有城市
// List<CityBean> cityNames = new ArrayList<>();
//遍历当前省份下面城市的所有数据
for (int j = 0; j < cityList.size(); j++) {
// cityNames[j] = cityList.get(j);
//当前省份下面每个城市下面再次对应的区或者县
List<DistrictBean> districtList = cityList.get(j).getCityList();
if (districtList == null) {
break;
}
// DistrictBean[] distrinctArray = new DistrictBean[districtList.size()];
for (int k = 0; k < districtList.size(); k++) {
// 遍历市下面所有区/县的数据
DistrictBean districtModel = districtList.get(k);
//存放 省市区-区 数据
mDisMap.put(itemProvince.getName() + cityList.get(j).getName() + districtList.get(k).getName(),
districtModel);
// districtList.add(districtModel);
}
// 市-区/县的数据保存到mDistrictDatasMap
mCity_DisMap.put(itemProvince.getName() + cityList.get(j).getName(), districtList);
}
// 省-市的数据保存到mCitisDatasMap
mPro_CityMap.put(itemProvince.getName(), cityList);
mCityBeanArrayList.add(cityList);
//只有显示三级联动,才会执行
ArrayList<ArrayList<DistrictBean>> array2DistrictLists = new ArrayList<>(cityList.size());
for (int c = 0; c < cityList.size(); c++) {
CityBean cityBean = cityList.get(c);
array2DistrictLists.add(cityBean.getCityList());
}
mDistrictBeanArrayList.add(array2DistrictLists);
// }
mProvinceBeenArray.add(p, itemProvince);
//赋值所有省份的名称
// mProvinceBeenArray[p] = ;
}
}
/**
* 初始化数据解析json数据
*/
public void initDataTw(Context context) {
String cityJson = utils.getJson(context, Constant.CITY_DATA_TW);
Type type = new TypeToken<ArrayList<ProvinceBean>>() {
}.getType();
mProvinceBeanArrayList = new Gson().fromJson(cityJson, type);
if (mProvinceBeanArrayList == null || mProvinceBeanArrayList.isEmpty()) {
return;
}
mCityBeanArrayList = new ArrayList<>(mProvinceBeanArrayList.size());
mDistrictBeanArrayList = new ArrayList<>(mProvinceBeanArrayList.size());
//*/ 初始化默认选中的省、市、区,默认选中第一个省份的第一个市区中的第一个区县
if (mProvinceBeanArrayList != null && !mProvinceBeanArrayList.isEmpty()) {
mProvinceBean = mProvinceBeanArrayList.get(0);
List<CityBean> cityList = mProvinceBean.getCityList();
if (cityList != null && !cityList.isEmpty() && cityList.size() > 0) {
mCityBean = cityList.get(0);
List<DistrictBean> districtList = mCityBean.getCityList();
if (districtList != null && !districtList.isEmpty() && districtList.size() > 0) {
mDistrictBean = districtList.get(0);
}
}
}
//省份数据
mProvinceBeenArray = new ArrayList<ProvinceBean>();
for (int p = 0; p < mProvinceBeanArrayList.size(); p++) {
//遍历每个省份
ProvinceBean itemProvince = mProvinceBeanArrayList.get(p);
//每个省份对应下面的市
ArrayList<CityBean> cityList = itemProvince.getCityList();
//当前省份下面的所有城市
// List<CityBean> cityNames = new ArrayList<>();
//遍历当前省份下面城市的所有数据
for (int j = 0; j < cityList.size(); j++) {
// cityNames[j] = cityList.get(j);
//当前省份下面每个城市下面再次对应的区或者县
List<DistrictBean> districtList = cityList.get(j).getCityList();
if (districtList == null) {
break;
}
// DistrictBean[] distrinctArray = new DistrictBean[districtList.size()];
for (int k = 0; k < districtList.size(); k++) {
// 遍历市下面所有区/县的数据
DistrictBean districtModel = districtList.get(k);
//存放 省市区-区 数据
mDisMap.put(itemProvince.getName() + cityList.get(j).getName() + districtList.get(k).getName(),
districtModel);
// districtList.add(districtModel);
}
// 市-区/县的数据保存到mDistrictDatasMap
mCity_DisMap.put(itemProvince.getName() + cityList.get(j).getName(), districtList);
}
// 省-市的数据保存到mCitisDatasMap
mPro_CityMap.put(itemProvince.getName(), cityList);
mCityBeanArrayList.add(cityList);
//只有显示三级联动,才会执行
ArrayList<ArrayList<DistrictBean>> array2DistrictLists = new ArrayList<>(cityList.size());
for (int c = 0; c < cityList.size(); c++) {
CityBean cityBean = cityList.get(c);
array2DistrictLists.add(cityBean.getCityList());
}
mDistrictBeanArrayList.add(array2DistrictLists);
// }
mProvinceBeenArray.add(p, itemProvince);
//赋值所有省份的名称
// mProvinceBeenArray[p] = ;
}
}
}

View File

@@ -0,0 +1,827 @@
package com.lljjcoder.citywheel;
import android.content.Context;
import com.lljjcoder.bean.CustomCityData;
import java.util.ArrayList;
import java.util.List;
/**
* 城市选择器样式配置
* 作者liji on 2017/11/4 10:31
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CustomConfig {
public static final Integer NONE = -1111;
/**
* 滚轮显示的item个数
*/
private int visibleItems = 5;
/**
* 省滚轮是否循环滚动
*/
private boolean isProvinceCyclic = true;
/**
* 市滚轮是否循环滚动
*/
private boolean isCityCyclic = true;
/**
* 区滚轮是否循环滚动
*/
private boolean isDistrictCyclic = true;
/**
* Color.BLACK
*/
private String cancelTextColorStr = "#000000";
/**
* Color.BLACK
*/
private String cancelText = "取消";
private int cancelTextSize = 16;
/**
* Color.BLUE
*/
private String confirmTextColorStr = "#0000FF";
/**
* Color.BLUE
*/
private String confirmText = "确定";
/**
* Color.BLUE
*/
private int confirmTextSize = 16;
/**
* 标题
*/
private String mTitle = "选择地区";
/**
* 标题背景颜色
*/
private String titleBackgroundColorStr = "#E9E9E9";
/**
* 标题颜色
*/
private String titleTextColorStr = "#585858";
/**
* 标题字体大小
*/
private int titleTextSize = 18;
/**
* 自定义的item布局
*/
private Integer customItemLayout;
/**
* 自定义的item txt id
*/
private Integer customItemTextViewId;
/**
* 是否显示滚轮上面的模糊阴影效果
*/
private boolean drawShadows = true;
/**
* 第一次默认的显示省份,一般配合定位,使用
*/
private String defaultProvinceName = "";
/**
* 第一次默认得显示城市,一般配合定位,使用
*/
private String defaultCityName = "";
/**
* 第一次默认得显示,一般配合定位,使用
*/
private String defaultDistrict = "";
/**
* 中间线的颜色
*/
private String lineColor = "#C7C7C7";
/**
* 中间线的宽度
*/
private int lineHeigh = 3;
/**
* 默认显示的城市数据,只包含省市区名称
*/
/**
* 定义显示省市区三种滚轮的显示状态
* PRO:只显示省份的一级选择器
* PRO_CITY:显示省份和城市二级联动的选择器
* PRO_CITY_DIS:显示省份和城市和县区三级联动的选择器
*/
public enum WheelType {
PRO, PRO_CITY, PRO_CITY_DIS
}
/**
* 定义默认显示省市区三级联动的滚轮选择器
*/
public CustomConfig.WheelType mWheelType = CustomConfig.WheelType.PRO_CITY_DIS;
public CustomConfig.WheelType getWheelType() {
return mWheelType;
}
/**
* 是否显示半透明的背景
*/
private boolean isShowBackground = true;
private List<CustomCityData> cityDataList = new ArrayList<>();
public boolean isShowBackground() {
return isShowBackground;
}
public String getLineColor() {
return lineColor == null ? "" : lineColor;
}
public void setLineColor(String lineColor) {
this.lineColor = lineColor;
}
public int getLineHeigh() {
return lineHeigh;
}
public void setLineHeigh(int lineHeigh) {
this.lineHeigh = lineHeigh;
}
public boolean isDrawShadows() {
return drawShadows;
}
public void setDrawShadows(boolean drawShadows) {
this.drawShadows = drawShadows;
}
public int getVisibleItems() {
return visibleItems;
}
public void setVisibleItems(int visibleItems) {
this.visibleItems = visibleItems;
}
public boolean isProvinceCyclic() {
return isProvinceCyclic;
}
public void setProvinceCyclic(boolean provinceCyclic) {
isProvinceCyclic = provinceCyclic;
}
public boolean isCityCyclic() {
return isCityCyclic;
}
public void setCityCyclic(boolean cityCyclic) {
isCityCyclic = cityCyclic;
}
public boolean isDistrictCyclic() {
return isDistrictCyclic;
}
public void setDistrictCyclic(boolean districtCyclic) {
isDistrictCyclic = districtCyclic;
}
public String getDefaultProvinceName() {
return defaultProvinceName == null ? "" : defaultProvinceName;
}
public void setDefaultProvinceName(String defaultProvinceName) {
this.defaultProvinceName = defaultProvinceName;
}
public String getDefaultCityName() {
return defaultCityName == null ? "" : defaultCityName;
}
public void setDefaultCityName(String defaultCityName) {
this.defaultCityName = defaultCityName;
}
public String getDefaultDistrict() {
return defaultDistrict == null ? "" : defaultDistrict;
}
public void setDefaultDistrict(String defaultDistrict) {
this.defaultDistrict = defaultDistrict;
}
public String getCancelTextColorStr() {
return cancelTextColorStr == null ? "" : cancelTextColorStr;
}
public void setCancelTextColorStr(String cancelTextColorStr) {
this.cancelTextColorStr = cancelTextColorStr;
}
public String getCancelText() {
return cancelText == null ? "" : cancelText;
}
public void setCancelText(String cancelText) {
this.cancelText = cancelText;
}
public int getCancelTextSize() {
return cancelTextSize;
}
public void setCancelTextSize(int cancelTextSize) {
this.cancelTextSize = cancelTextSize;
}
public String getConfirmTextColorStr() {
return confirmTextColorStr == null ? "" : confirmTextColorStr;
}
public void setConfirmTextColorStr(String confirmTextColorStr) {
this.confirmTextColorStr = confirmTextColorStr;
}
public String getConfirmText() {
return confirmText == null ? "" : confirmText;
}
public void setConfirmText(String confirmText) {
this.confirmText = confirmText;
}
public int getConfirmTextSize() {
return confirmTextSize;
}
public void setConfirmTextSize(int confirmTextSize) {
this.confirmTextSize = confirmTextSize;
}
public String getTitle() {
return mTitle == null ? "" : mTitle;
}
public void setTitle(String title) {
mTitle = title;
}
public String getTitleBackgroundColorStr() {
return titleBackgroundColorStr == null ? "" : titleBackgroundColorStr;
}
public void setTitleBackgroundColorStr(String titleBackgroundColorStr) {
this.titleBackgroundColorStr = titleBackgroundColorStr;
}
public String getTitleTextColorStr() {
return titleTextColorStr == null ? "" : titleTextColorStr;
}
public void setTitleTextColorStr(String titleTextColorStr) {
this.titleTextColorStr = titleTextColorStr;
}
public int getTitleTextSize() {
return titleTextSize;
}
public void setTitleTextSize(int titleTextSize) {
this.titleTextSize = titleTextSize;
}
//
public Integer getCustomItemLayout() {
return customItemLayout == null ? NONE : customItemLayout;
}
public void setCustomItemLayout(int customItemLayout) {
this.customItemLayout = customItemLayout;
}
public Integer getCustomItemTextViewId() {
return customItemTextViewId == null ? NONE : customItemTextViewId;
}
public void setCustomItemTextViewId(Integer customItemTextViewId) {
this.customItemTextViewId = customItemTextViewId;
}
public List<CustomCityData> getCityDataList() {
return cityDataList;
}
public void setCityDataList(List<CustomCityData> cityDataList) {
this.cityDataList = cityDataList;
}
public void setShowBackground(boolean showBackground) {
isShowBackground = showBackground;
}
public CustomConfig(Builder builder) {
/**
* 标题栏相关的属性:
* 0、标题栏背景颜色
* 1、标题文字、大小、颜色
*
* 2、取消字体的颜色、大小、内容
* 3、确认字体的颜色、大小、内容
*/
this.titleBackgroundColorStr = builder.titleBackgroundColorStr;
this.mTitle = builder.mTitle;
this.titleTextColorStr = builder.titleTextColorStr;
this.titleTextSize = builder.titleTextSize;
this.cancelTextColorStr = builder.cancelTextColorStr;
this.cancelText = builder.cancelText;
this.cancelTextSize = builder.cancelTextSize;
this.confirmTextColorStr = builder.confirmTextColorStr;
this.confirmText = builder.confirmText;
this.confirmTextSize = builder.confirmTextSize;
/**
* 滚轮相关的属性:
* 1、item显示的个数
* 2、省份是否可以循环
* 3、城市是否可以循环
* 4、地区是否可以循环
*/
this.visibleItems = builder.visibleItems;
this.isProvinceCyclic = builder.isProvinceCyclic;
this.isDistrictCyclic = builder.isDistrictCyclic;
this.isCityCyclic = builder.isCityCyclic;
/**
* 默认的省市区地址
*/
this.defaultDistrict = builder.defaultDistrict;
this.defaultCityName = builder.defaultCityName;
this.defaultProvinceName = builder.defaultProvinceName;
/**
* 是否显示城市和地区
*/
this.mWheelType = builder.mWheelType;
/**
* 是否显示半透明
*/
this.isShowBackground = builder.isShowBackground;
//
/**
* 自定义item的布局必须制定Layout和id
*/
this.customItemLayout = builder.customItemLayout;
this.customItemTextViewId = builder.customItemTextViewId;
/**
* 是否显示滚轮上面的模糊阴影效果
*/
this.drawShadows = builder.drawShadows;
this.lineColor = builder.lineColor;
this.lineHeigh = builder.lineHeigh;
this.cityDataList = builder.cityDataList;
}
public static class Builder {
/**
* 滚轮显示的item个数
*/
private int visibleItems = 5;
/**
* 省滚轮是否循环滚动
*/
private boolean isProvinceCyclic = true;
/**
* 市滚轮是否循环滚动
*/
private boolean isCityCyclic = true;
/**
* 区滚轮是否循环滚动
*/
private boolean isDistrictCyclic = true;
/**
* Color.BLACK
*/
private String cancelTextColorStr = "#000000";
/**
* Color.BLACK
*/
private String cancelText = "取消";
private int cancelTextSize = 16;
/**
* Color.BLUE
*/
private String confirmTextColorStr = "#0000FF";
/**
* Color.BLUE
*/
private String confirmText = "确定";
/**
* Color.BLUE
*/
private int confirmTextSize = 16;
/**
* 标题
*/
private String mTitle = "选择地区";
/**
* 标题背景颜色
*/
private String titleBackgroundColorStr = "#E9E9E9";
/**
* 标题颜色
*/
private String titleTextColorStr = "#585858";
/**
* 标题字体大小
*/
private int titleTextSize = 18;
/**
* 是否显示半透明的背景
*/
private boolean isShowBackground = true;
/**
* 自定义的item布局
*/
private Integer customItemLayout;
/**
* 自定义的item txt id
*/
private Integer customItemTextViewId;
/**
* 是否显示滚轮上面的模糊阴影效果
*/
private boolean drawShadows = true;
/**
* 中间线的颜色
*/
private String lineColor = "#C7C7C7";
/**
* 定义默认显示省市区三级联动的滚轮选择器
*/
private CustomConfig.WheelType mWheelType = CustomConfig.WheelType.PRO_CITY_DIS;
/**
* 中间线的宽度
*/
private int lineHeigh = 3;
private List<CustomCityData> cityDataList = new ArrayList<>();
/**
* 第一次默认的显示省份,一般配合定位,使用
*/
private String defaultProvinceName = "";
/**
* 第一次默认得显示城市,一般配合定位,使用
*/
private String defaultCityName = "";
/**
* 第一次默认得显示,一般配合定位,使用
*/
private String defaultDistrict = "";
public Builder() {
}
/**
* 显示省市区三级联动的显示状态
* PRO:只显示省份的一级选择器
* PRO_CITY:显示省份和城市二级联动的选择器
* PRO_CITY_DIS:显示省份和城市和县区三级联动的选择器
*
* @param wheelType
* @return
*/
public CustomConfig.Builder setCityWheelType(CustomConfig.WheelType wheelType) {
this.mWheelType = wheelType;
return this;
}
public Builder setCityData(List<CustomCityData> data) {
this.cityDataList = data;
return this;
}
/**
* 第一次默认的显示省份,一般配合定位,使用
*
* @param defaultProvinceName
* @return
*/
public Builder province(String defaultProvinceName) {
this.defaultProvinceName = defaultProvinceName;
return this;
}
/**
* 第一次默认得显示城市,一般配合定位,使用
*
* @param defaultCityName
* @return
*/
public Builder city(String defaultCityName) {
this.defaultCityName = defaultCityName;
return this;
}
/**
* 第一次默认地区显示,一般配合定位,使用
*
* @param defaultDistrict
* @return
*/
public Builder district(String defaultDistrict) {
this.defaultDistrict = defaultDistrict;
return this;
}
/**
* 中间线的宽度
*
* @param lineHeigh
* @return
*/
public Builder setLineHeigh(int lineHeigh) {
this.lineHeigh = lineHeigh;
return this;
}
/**
* 中间线的颜色
*
* @param lineColor
* @return
*/
public Builder setLineColor(String lineColor) {
this.lineColor = lineColor;
return this;
}
/**
* 是否显示滚轮上面的模糊阴影效果
*
* @param drawShadows
* @return
*/
public Builder drawShadows(boolean drawShadows) {
this.drawShadows = drawShadows;
return this;
}
/**
* 设置标题背景颜色
*
* @param colorBg
* @return
*/
public Builder titleBackgroundColor(String colorBg) {
this.titleBackgroundColorStr = colorBg;
return this;
}
/**
* 设置标题字体颜色
*
* @param titleTextColorStr
* @return
*/
public Builder titleTextColor(String titleTextColorStr) {
this.titleTextColorStr = titleTextColorStr;
return this;
}
/**
* 设置标题字体大小
*
* @param titleTextSize
* @return
*/
public Builder titleTextSize(int titleTextSize) {
this.titleTextSize = titleTextSize;
return this;
}
/**
* 设置标题
*
* @param mtitle
* @return
*/
public Builder title(String mtitle) {
this.mTitle = mtitle;
return this;
}
/**
* 确认按钮文字
*
* @param confirmTextSize
* @return
*/
public Builder confirmTextSize(int confirmTextSize) {
this.confirmTextSize = confirmTextSize;
return this;
}
/**
* 确认按钮文字
*
* @param confirmText
* @return
*/
public Builder confirmText(String confirmText) {
this.confirmText = confirmText;
return this;
}
/**
* 确认按钮文字颜色
*
* @param color
* @return
*/
public Builder confirTextColor(String color) {
this.confirmTextColorStr = color;
return this;
}
/**
* 取消按钮文字颜色
*
* @param color
* @return
*/
public Builder cancelTextColor(String color) {
this.cancelTextColorStr = color;
return this;
}
/**
* 取消按钮文字大小
*
* @param cancelTextSize
* @return
*/
public Builder cancelTextSize(int cancelTextSize) {
this.cancelTextSize = cancelTextSize;
return this;
}
/**
* 取消按钮文字
*
* @param cancelText
* @return
*/
public Builder cancelText(String cancelText) {
this.cancelText = cancelText;
return this;
}
/**
* 滚轮显示的item个数
*
* @param visibleItems
* @return
*/
public Builder visibleItemsCount(int visibleItems) {
this.visibleItems = visibleItems;
return this;
}
/**
* 省滚轮是否循环滚动
*
* @param isProvinceCyclic
* @return
*/
public Builder provinceCyclic(boolean isProvinceCyclic) {
this.isProvinceCyclic = isProvinceCyclic;
return this;
}
/**
* 市滚轮是否循环滚动
*
* @param isCityCyclic
* @return
*/
public Builder cityCyclic(boolean isCityCyclic) {
this.isCityCyclic = isCityCyclic;
return this;
}
/**
* 区滚轮是否循环滚动
*
* @param isDistrictCyclic
* @return
*/
public Builder districtCyclic(boolean isDistrictCyclic) {
this.isDistrictCyclic = isDistrictCyclic;
return this;
}
/**
* 是否显示半透明的背景
*
* @param isShowBackground
* @return
*/
public Builder showBackground(boolean isShowBackground) {
this.isShowBackground = isShowBackground;
return this;
}
//
/**
* 自定义item布局
*
* @param itemLayout
* @return
*/
public Builder setCustomItemLayout(Integer itemLayout) {
this.customItemLayout = itemLayout;
return this;
}
/**
* 自定义item布局中的id
*
* @param setCustomItemTextViewId
* @return
*/
public Builder setCustomItemTextViewId(Integer setCustomItemTextViewId) {
this.customItemTextViewId = setCustomItemTextViewId;
return this;
}
public CustomConfig build() {
CustomConfig config = new CustomConfig(this);
return config;
}
}
}

View File

@@ -0,0 +1,464 @@
package com.lljjcoder.style.citycustome;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.lljjcoder.Interface.OnCustomCityPickerItemClickListener;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.CustomCityData;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
import com.lljjcoder.citywheel.CityConfig;
import com.lljjcoder.citywheel.CustomConfig;
import com.lljjcoder.style.citylist.Toast.ToastUtils;
import com.lljjcoder.style.citypickerview.R;
import com.lljjcoder.style.citypickerview.widget.CanShow;
import com.lljjcoder.style.citypickerview.widget.wheel.OnWheelChangedListener;
import com.lljjcoder.style.citypickerview.widget.wheel.WheelView;
import com.lljjcoder.style.citypickerview.widget.wheel.adapters.ArrayWheelAdapter;
import com.lljjcoder.utils.utils;
import java.util.List;
public class CustomCityPicker implements CanShow, OnWheelChangedListener {
private PopupWindow popwindow;
private View popview;
private WheelView mViewProvince;
private WheelView mViewCity;
private WheelView mViewDistrict;
private Context mContext;
private RelativeLayout mRelativeTitleBg;
private TextView mTvOK;
private TextView mTvTitle;
private TextView mTvCancel;
private CustomConfig config;
private OnCustomCityPickerItemClickListener listener = null;
private CustomConfig.WheelType type = CustomConfig.WheelType.PRO_CITY_DIS;
public void setOnCustomCityPickerItemClickListener(OnCustomCityPickerItemClickListener listener) {
this.listener = listener;
}
public CustomCityPicker(Context context) {
this.mContext = context;
}
public void setCustomConfig(CustomConfig config) {
this.config = config;
}
private void initView() {
if (config == null) {
ToastUtils.showLongToast(mContext, "请设置相关的config");
return;
}
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
popview = layoutInflater.inflate(R.layout.pop_citypicker, null);
mViewProvince = (WheelView) popview.findViewById(R.id.id_province);
mViewCity = (WheelView) popview.findViewById(R.id.id_city);
mViewDistrict = (WheelView) popview.findViewById(R.id.id_district);
mRelativeTitleBg = (RelativeLayout) popview.findViewById(R.id.rl_title);
mTvOK = (TextView) popview.findViewById(R.id.tv_confirm);
mTvTitle = (TextView) popview.findViewById(R.id.tv_title);
mTvCancel = (TextView) popview.findViewById(R.id.tv_cancel);
popwindow = new PopupWindow(popview, LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popwindow.setAnimationStyle(R.style.AnimBottom);
popwindow.setBackgroundDrawable(new ColorDrawable());
popwindow.setTouchable(true);
popwindow.setOutsideTouchable(false);
popwindow.setFocusable(true);
popwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if (config.isShowBackground()) {
utils.setBackgroundAlpha(mContext, 1.0f);
}
}
});
//设置显示层级
type = config.getWheelType();
setWheelShowLevel(type);
/**
* 设置标题背景颜色
*/
if (!TextUtils.isEmpty(config.getTitleBackgroundColorStr())) {
if (config.getTitleBackgroundColorStr().startsWith("#")) {
mRelativeTitleBg.setBackgroundColor(Color.parseColor(config.getTitleBackgroundColorStr()));
} else {
mRelativeTitleBg.setBackgroundColor(Color.parseColor("#" + config.getTitleBackgroundColorStr()));
}
}
//标题
if (!TextUtils.isEmpty(config.getTitle())) {
mTvTitle.setText(config.getTitle());
}
//标题文字大小
if (config.getTitleTextSize() > 0) {
mTvTitle.setTextSize(config.getTitleTextSize());
}
//标题文字颜色
if (!TextUtils.isEmpty(config.getTitleTextColorStr())) {
if (config.getTitleTextColorStr().startsWith("#")) {
mTvTitle.setTextColor(Color.parseColor(config.getTitleTextColorStr()));
} else {
mTvTitle.setTextColor(Color.parseColor("#" + config.getTitleTextColorStr()));
}
}
//设置确认按钮文字大小颜色
if (!TextUtils.isEmpty(config.getConfirmTextColorStr())) {
if (config.getConfirmTextColorStr().startsWith("#")) {
mTvOK.setTextColor(Color.parseColor(config.getConfirmTextColorStr()));
} else {
mTvOK.setTextColor(Color.parseColor("#" + config.getConfirmTextColorStr()));
}
}
if (!TextUtils.isEmpty(config.getConfirmText())) {
mTvOK.setText(config.getConfirmText());
}
if ((config.getConfirmTextSize() > 0)) {
mTvOK.setTextSize(config.getConfirmTextSize());
}
//设置取消按钮文字颜色
if (!TextUtils.isEmpty(config.getCancelTextColorStr())) {
if (config.getCancelTextColorStr().startsWith("#")) {
mTvCancel.setTextColor(Color.parseColor(config.getCancelTextColorStr()));
} else {
mTvCancel.setTextColor(Color.parseColor("#" + config.getCancelTextColorStr()));
}
}
if (!TextUtils.isEmpty(config.getCancelText())) {
mTvCancel.setText(config.getCancelText());
}
if ((config.getCancelTextSize() > 0)) {
mTvCancel.setTextSize(config.getCancelTextSize());
}
// 添加change事件
mViewProvince.addChangingListener(this);
// 添加change事件
mViewCity.addChangingListener(this);
// 添加change事件
mViewDistrict.addChangingListener(this);
// 添加onclick事件
mTvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onCancel();
hide();
}
});
//确认选择
mTvOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (type == CustomConfig.WheelType.PRO) {
int pCurrent = mViewProvince.getCurrentItem();
List<CustomCityData> provinceList = config.getCityDataList();
CustomCityData province = provinceList.get(pCurrent);
listener.onSelected(province, new CustomCityData(), new CustomCityData());
} else if (type == CustomConfig.WheelType.PRO_CITY) {
int pCurrent = mViewProvince.getCurrentItem();
List<CustomCityData> provinceList = config.getCityDataList();
CustomCityData province = provinceList.get(pCurrent);
int cCurrent = mViewCity.getCurrentItem();
List<CustomCityData> cityDataList = province.getList();
if (cityDataList == null) return;
CustomCityData city = cityDataList.get(cCurrent);
listener.onSelected(province, city, new CustomCityData());
} else if (type == CustomConfig.WheelType.PRO_CITY_DIS) {
int pCurrent = mViewProvince.getCurrentItem();
List<CustomCityData> provinceList = config.getCityDataList();
CustomCityData province = provinceList.get(pCurrent);
int cCurrent = mViewCity.getCurrentItem();
List<CustomCityData> cityDataList = province.getList();
if (cityDataList == null) return;
CustomCityData city = cityDataList.get(cCurrent);
int dCurrent = mViewDistrict.getCurrentItem();
List<CustomCityData> areaList = city.getList();
if (areaList == null) return;
CustomCityData area = areaList.get(dCurrent);
listener.onSelected(province, city, area);
}
hide();
}
});
//背景半透明
if (config != null && config.isShowBackground()) {
utils.setBackgroundAlpha(mContext, 0.5f);
}
//显示省市区数据
setUpData();
}
/**
* 显示省市区等级
*
* @param type
*/
private void setWheelShowLevel(CustomConfig.WheelType type) {
if (type == CustomConfig.WheelType.PRO) {
mViewProvince.setVisibility(View.VISIBLE);
mViewCity.setVisibility(View.GONE);
mViewDistrict.setVisibility(View.GONE);
} else if (type == CustomConfig.WheelType.PRO_CITY) {
mViewProvince.setVisibility(View.VISIBLE);
mViewCity.setVisibility(View.VISIBLE);
mViewDistrict.setVisibility(View.GONE);
} else {
mViewProvince.setVisibility(View.VISIBLE);
mViewCity.setVisibility(View.VISIBLE);
mViewDistrict.setVisibility(View.VISIBLE);
}
}
private void setUpData() {
List<CustomCityData> proArra = config.getCityDataList();
if (proArra == null) return;
int provinceDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultProvinceName()) && proArra.size() > 0) {
for (int i = 0; i < proArra.size(); i++) {
if (proArra.get(i).getName().startsWith(config.getDefaultProvinceName())) {
provinceDefault = i;
break;
}
}
}
ArrayWheelAdapter arrayWheelAdapter = new ArrayWheelAdapter<CustomCityData>(mContext, proArra);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE && config.getCustomItemTextViewId() != CityConfig.NONE) {
arrayWheelAdapter.setItemResource(config.getCustomItemLayout());
arrayWheelAdapter.setItemTextResource(config.getCustomItemTextViewId());
} else {
arrayWheelAdapter.setItemResource(R.layout.default_item_city);
arrayWheelAdapter.setItemTextResource(R.id.default_item_city_name_tv);
}
mViewProvince.setViewAdapter(arrayWheelAdapter);
//获取所设置的省的位置,直接定位到该位置
if (-1 != provinceDefault) {
mViewProvince.setCurrentItem(provinceDefault);
}
// 设置可见条目数量
mViewProvince.setVisibleItems(config.getVisibleItems());
mViewCity.setVisibleItems(config.getVisibleItems());
mViewDistrict.setVisibleItems(config.getVisibleItems());
mViewProvince.setCyclic(config.isProvinceCyclic());
mViewCity.setCyclic(config.isCityCyclic());
mViewDistrict.setCyclic(config.isDistrictCyclic());
//显示滚轮模糊效果
mViewProvince.setDrawShadows(config.isDrawShadows());
mViewCity.setDrawShadows(config.isDrawShadows());
mViewDistrict.setDrawShadows(config.isDrawShadows());
//中间线的颜色及高度
mViewProvince.setLineColorStr(config.getLineColor());
mViewProvince.setLineWidth(config.getLineHeigh());
mViewCity.setLineColorStr(config.getLineColor());
mViewCity.setLineWidth(config.getLineHeigh());
mViewDistrict.setLineColorStr(config.getLineColor());
mViewDistrict.setLineWidth(config.getLineHeigh());
if (type == CustomConfig.WheelType.PRO_CITY || type == CustomConfig.WheelType.PRO_CITY_DIS) {
updateCities();
}
}
/**
* 根据当前的省更新市WheelView的信息
*/
private void updateCities() {
//省份滚轮滑动的当前位置
int pCurrent = mViewProvince.getCurrentItem();
//省份选中的名称
List<CustomCityData> proArra = config.getCityDataList();
CustomCityData mProvinceBean = proArra.get(pCurrent);
List<CustomCityData> pCityList = mProvinceBean.getList();
if (pCityList == null) return;
//设置最初的默认城市
int cityDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultCityName()) && pCityList.size() > 0) {
for (int i = 0; i < pCityList.size(); i++) {
if (pCityList.get(i).getName().startsWith(config.getDefaultCityName())) {
cityDefault = i;
break;
}
}
}
ArrayWheelAdapter cityWheel = new ArrayWheelAdapter<CustomCityData>(mContext, pCityList);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE && config.getCustomItemTextViewId() != CityConfig.NONE) {
cityWheel.setItemResource(config.getCustomItemLayout());
cityWheel.setItemTextResource(config.getCustomItemTextViewId());
} else {
cityWheel.setItemResource(R.layout.default_item_city);
cityWheel.setItemTextResource(R.id.default_item_city_name_tv);
}
mViewCity.setViewAdapter(cityWheel);
if (-1 != cityDefault) {
mViewCity.setCurrentItem(cityDefault);
} else {
mViewCity.setCurrentItem(0);
}
mViewCity.setViewAdapter(cityWheel);
if (type == CustomConfig.WheelType.PRO_CITY_DIS) {
updateAreas();
}
}
/**
* 根据当前的市更新区WheelView的信息
*/
private void updateAreas() {
int pCurrent = mViewProvince.getCurrentItem();
int cCurrent = mViewCity.getCurrentItem();
List<CustomCityData> provinceList = config.getCityDataList();
CustomCityData province = provinceList.get(pCurrent);
List<CustomCityData> cityDataList = province.getList();
if (cityDataList == null || cityDataList.size() <= cCurrent) return;
CustomCityData city = cityDataList.get(cCurrent);
List<CustomCityData> areaList = city.getList();
if (areaList == null) return;
int districtDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultDistrict()) && areaList.size() > 0) {
for (int i = 0; i < areaList.size(); i++) {
if (areaList.get(i).getName().startsWith(config.getDefaultDistrict())) {
districtDefault = i;
break;
}
}
}
ArrayWheelAdapter districtWheel = new ArrayWheelAdapter<CustomCityData>(mContext, areaList);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE
&& config.getCustomItemTextViewId() != CityConfig.NONE) {
districtWheel.setItemResource(config.getCustomItemLayout());
districtWheel.setItemTextResource(config.getCustomItemTextViewId());
} else {
districtWheel.setItemResource(R.layout.default_item_city);
districtWheel.setItemTextResource(R.id.default_item_city_name_tv);
}
//设置默认城市
if (-1 != districtDefault) {
mViewDistrict.setCurrentItem(districtDefault);
} else {
mViewDistrict.setCurrentItem(0);
}
mViewDistrict.setViewAdapter(districtWheel);
}
public void showCityPicker() {
initView();
if (!isShow()) {
popwindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);
}
}
@Override
public void hide() {
if (isShow()) {
popwindow.dismiss();
}
}
@Override
public boolean isShow() {
return popwindow.isShowing();
}
@Override
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (wheel == mViewProvince) {
updateCities();
} else if (wheel == mViewCity) {
updateAreas();
} else if (wheel == mViewDistrict) {
}
}
}

View File

@@ -0,0 +1,94 @@
package com.lljjcoder.style.cityjd;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.style.citypickerview.R;
import java.util.List;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_INVALID;
/**
* 作者liji on 2018/1/29 17:01
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class AreaAdapter extends BaseAdapter {
Context context;
List<DistrictBean> mDistrictList;
private int districtIndex = INDEX_INVALID;
public AreaAdapter(Context context, List<DistrictBean> mDistrictList) {
this.context = context;
this.mDistrictList = mDistrictList;
}
public int getSelectedPosition() {
return this.districtIndex;
}
public void updateSelectedPosition(int index) {
this.districtIndex = index;
}
@Override
public int getCount() {
return mDistrictList.size();
}
@Override
public DistrictBean getItem(int position) {
return mDistrictList.get(position);
}
@Override
public long getItemId(int position) {
return Long.parseLong(mDistrictList.get(position).getId());
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.pop_jdcitypicker_item, parent, false);
holder = new Holder();
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.selectImg = (ImageView) convertView.findViewById(R.id.selectImg);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
DistrictBean item = getItem(position);
holder.name.setText(item.getName());
boolean checked = districtIndex != INDEX_INVALID && mDistrictList.get(districtIndex).getName().equals(item.getName());
holder.name.setEnabled(!checked);
holder.selectImg.setVisibility(checked ? View.VISIBLE : View.GONE);
return convertView;
}
class Holder {
TextView name;
ImageView selectImg;
}
}

View File

@@ -0,0 +1,93 @@
package com.lljjcoder.style.cityjd;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.style.citypickerview.R;
import java.util.List;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_INVALID;
/**
* 作者liji on 2018/1/29 17:01
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityAdapter extends BaseAdapter {
Context context;
List<CityBean> mCityList;
private int cityIndex = INDEX_INVALID;
public CityAdapter(Context context, List<CityBean> mCityList) {
this.context = context;
this.mCityList = mCityList;
}
public int getSelectedPosition() {
return this.cityIndex;
}
public void updateSelectedPosition(int index) {
this.cityIndex = index;
}
@Override
public int getCount() {
return mCityList.size();
}
@Override
public CityBean getItem(int position) {
return mCityList.get(position);
}
@Override
public long getItemId(int position) {
return Long.parseLong(mCityList.get(position).getId());
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.pop_jdcitypicker_item, parent, false);
holder = new Holder();
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.selectImg = (ImageView) convertView.findViewById(R.id.selectImg);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
CityBean item = getItem(position);
holder.name.setText(item.getName());
boolean checked = cityIndex != INDEX_INVALID && mCityList.get(cityIndex).getName().equals(item.getName());
holder.name.setEnabled(!checked);
holder.selectImg.setVisibility(checked ? View.VISIBLE : View.GONE);
return convertView;
}
class Holder {
TextView name;
ImageView selectImg;
}
}

View File

@@ -0,0 +1,60 @@
package com.lljjcoder.style.cityjd;
import com.lljjcoder.citywheel.CityConfig;
public class JDCityConfig {
/**
* 默认显示的城市数据,只包含省市区名称
* 定义显示省市区三种显示状态
* PRO:只显示省份的一级选择器
* PRO_CITY:显示省份和城市二级联动的选择器
* PRO_CITY_DIS:显示省份和城市和县区三级联动的选择器
*/
public enum ShowType {
PRO_CITY, PRO_CITY_DIS
}
private ShowType showType = ShowType.PRO_CITY_DIS;
public ShowType getShowType() {
return showType;
}
public void setShowType(ShowType showType) {
this.showType = showType;
}
public JDCityConfig(Builder builder) {
this.showType = builder.showType;
}
public static class Builder {
public Builder() {
}
public ShowType showType = ShowType.PRO_CITY_DIS;
/**
* 显示省市区三级联动的显示状态
* PRO_CITY:显示省份和城市二级联动的选择器
* PRO_CITY_DIS:显示省份和城市和县区三级联动的选择器
*
* @param showType
* @return
*/
public Builder setJDCityShowType(ShowType showType) {
this.showType = showType;
return this;
}
public JDCityConfig build() {
JDCityConfig config = new JDCityConfig(this);
return config;
}
}
}

View File

@@ -0,0 +1,461 @@
package com.lljjcoder.style.cityjd;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import com.lljjcoder.Interface.OnCityItemClickListener;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
import com.lljjcoder.citywheel.CityParseHelper;
import com.lljjcoder.style.citylist.Toast.ToastUtils;
import com.lljjcoder.style.citypickerview.R;
import com.lljjcoder.style.citypickerview.widget.CanShow;
import com.lljjcoder.utils.utils;
import java.util.List;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_INVALID;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_TAB_AREA;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_TAB_CITY;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_TAB_PROVINCE;
/**
* 仿京东城市选择器
* 作者liji on 2018/1/26 16:08
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class JDCityPicker {
private ListView mCityListView;
private TextView mProTv;
private TextView mCityTv;
private TextView mAreaTv;
private ImageView mCloseImg;
private PopupWindow popwindow;
private View mSelectedLine;
private View popview;
private CityParseHelper parseHelper;
private ProvinceAdapter mProvinceAdapter;
private CityAdapter mCityAdapter;
private AreaAdapter mAreaAdapter;
private List<ProvinceBean> provinceList = null;
private List<CityBean> cityList = null;
private List<DistrictBean> areaList = null;
private int tabIndex = INDEX_TAB_PROVINCE;
private Context context;
private String colorSelected = "#ff181c20";
private String colorAlert = "#ffff4444";
private OnCityItemClickListener mBaseListener;
private JDCityConfig cityConfig = null;
public void setOnCityItemClickListener(OnCityItemClickListener listener) {
mBaseListener = listener;
}
public void setConfig(JDCityConfig cityConfig) {
this.cityConfig = cityConfig;
}
private void initJDCityPickerPop() {
if (this.cityConfig == null) {
this.cityConfig = new JDCityConfig.Builder().setJDCityShowType(JDCityConfig.ShowType.PRO_CITY_DIS).build();
}
tabIndex = INDEX_TAB_PROVINCE;
//解析初始数据
if (parseHelper == null) {
parseHelper = new CityParseHelper();
}
if (parseHelper.getProvinceBeanArrayList().isEmpty()) {
ToastUtils.showLongToast(context, "请调用init方法进行初始化相关操作");
return;
}
LayoutInflater layoutInflater = LayoutInflater.from(context);
popview = layoutInflater.inflate(R.layout.pop_jdcitypicker, null);
mCityListView = (ListView) popview.findViewById(R.id.city_listview);
mProTv = (TextView) popview.findViewById(R.id.province_tv);
mCityTv = (TextView) popview.findViewById(R.id.city_tv);
mAreaTv = (TextView) popview.findViewById(R.id.area_tv);
mCloseImg = (ImageView) popview.findViewById(R.id.close_img);
mSelectedLine = (View) popview.findViewById(R.id.selected_line);
popwindow = new PopupWindow(popview, LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popwindow.setAnimationStyle(R.style.AnimBottom);
popwindow.setBackgroundDrawable(new ColorDrawable());
popwindow.setTouchable(true);
popwindow.setOutsideTouchable(false);
popwindow.setFocusable(true);
popwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
utils.setBackgroundAlpha(context, 1.0f);
}
});
mCloseImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hidePop();
utils.setBackgroundAlpha(context, 1.0f);
if (mBaseListener != null) {
mBaseListener.onCancel();
}
}
});
mProTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tabIndex = INDEX_TAB_PROVINCE;
if (mProvinceAdapter != null) {
mCityListView.setAdapter(mProvinceAdapter);
if (mProvinceAdapter.getSelectedPosition() != INDEX_INVALID) {
mCityListView.setSelection(mProvinceAdapter.getSelectedPosition());
}
}
updateTabVisible();
updateIndicator();
}
});
mCityTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tabIndex = INDEX_TAB_CITY;
if (mCityAdapter != null) {
mCityListView.setAdapter(mCityAdapter);
if (mCityAdapter.getSelectedPosition() != INDEX_INVALID) {
mCityListView.setSelection(mCityAdapter.getSelectedPosition());
}
}
updateTabVisible();
updateIndicator();
}
});
mAreaTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tabIndex = INDEX_TAB_AREA;
if (mAreaAdapter != null) {
mCityListView.setAdapter(mAreaAdapter);
if (mAreaAdapter.getSelectedPosition() != INDEX_INVALID) {
mCityListView.setSelection(mAreaAdapter.getSelectedPosition());
}
}
updateTabVisible();
updateIndicator();
}
});
mCityListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedList(position);
}
});
utils.setBackgroundAlpha(context, 0.5f);
updateIndicator();
updateTabsStyle(INDEX_INVALID);
setProvinceListData();
}
private void selectedList(int position) {
switch (tabIndex) {
case INDEX_TAB_PROVINCE:
ProvinceBean provinceBean = mProvinceAdapter.getItem(position);
if (provinceBean != null) {
mProTv.setText("" + provinceBean.getName());
mCityTv.setText("请选择");
mProvinceAdapter.updateSelectedPosition(position);
mProvinceAdapter.notifyDataSetChanged();
mCityAdapter = new CityAdapter(context, provinceBean.getCityList());
//选中省份数据后更新市数据
mHandler.sendMessage(Message.obtain(mHandler, INDEX_TAB_CITY, provinceBean.getCityList()));
}
break;
case INDEX_TAB_CITY:
CityBean cityBean = mCityAdapter.getItem(position);
if (cityBean != null) {
mCityTv.setText("" + cityBean.getName());
mAreaTv.setText("请选择");
mCityAdapter.updateSelectedPosition(position);
mCityAdapter.notifyDataSetChanged();
if (this.cityConfig != null && this.cityConfig.getShowType() == JDCityConfig.ShowType.PRO_CITY) {
callback(new DistrictBean());
} else {
mAreaAdapter = new AreaAdapter(context, cityBean.getCityList());
//选中省份数据后更新市数据
mHandler.sendMessage(Message.obtain(mHandler, INDEX_TAB_AREA, cityBean.getCityList()));
}
}
break;
case INDEX_TAB_AREA:
//返回选中的省市区数据
DistrictBean districtBean = mAreaAdapter.getItem(position);
if (districtBean != null) {
callback(districtBean);
}
break;
}
}
/**
* 设置默认的省份数据
*/
private void setProvinceListData() {
provinceList = parseHelper.getProvinceBeanArrayList();
if (provinceList != null && !provinceList.isEmpty()) {
mProvinceAdapter = new ProvinceAdapter(context, provinceList);
mCityListView.setAdapter(mProvinceAdapter);
} else {
ToastUtils.showLongToast(context, "解析本地城市数据失败!");
return;
}
}
/**
* 初始化,默认解析城市数据,提交加载速度
*/
public void init(Context context) {
this.context = context;
parseHelper = new CityParseHelper();
//解析初始数据
if (parseHelper.getProvinceBeanArrayList().isEmpty()) {
parseHelper.initData(context);
}
}
/**
* 更新选中城市下面的红色横线指示器
*/
private void updateIndicator() {
popview.post(new Runnable() {
@Override
public void run() {
switch (tabIndex) {
case INDEX_TAB_PROVINCE:
tabSelectedIndicatorAnimation(mProTv).start();
break;
case INDEX_TAB_CITY:
tabSelectedIndicatorAnimation(mCityTv).start();
break;
case INDEX_TAB_AREA:
tabSelectedIndicatorAnimation(mAreaTv).start();
break;
}
}
});
}
/**
* tab 选中的红色下划线动画
*
* @param tab
* @return
*/
private AnimatorSet tabSelectedIndicatorAnimation(TextView tab) {
ObjectAnimator xAnimator = ObjectAnimator.ofFloat(mSelectedLine, "X", mSelectedLine.getX(), tab.getX());
final ViewGroup.LayoutParams params = mSelectedLine.getLayoutParams();
ValueAnimator widthAnimator = ValueAnimator.ofInt(params.width, tab.getMeasuredWidth());
widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
params.width = (int) animation.getAnimatedValue();
mSelectedLine.setLayoutParams(params);
}
});
AnimatorSet set = new AnimatorSet();
set.setInterpolator(new FastOutSlowInInterpolator());
set.playTogether(xAnimator, widthAnimator);
return set;
}
public void showCityPicker() {
initJDCityPickerPop();
if (!isShow()) {
popwindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);
}
}
private void hidePop() {
if (isShow()) {
popwindow.dismiss();
}
}
private boolean isShow() {
return popwindow.isShowing();
}
private void updateTabVisible() {
mProTv.setVisibility(provinceList == null || provinceList.isEmpty() ? View.GONE : View.VISIBLE);
mCityTv.setVisibility(cityList == null || cityList.isEmpty() ? View.GONE : View.VISIBLE);
mAreaTv.setVisibility(areaList == null || areaList.isEmpty() ? View.GONE : View.VISIBLE);
}
/**
* 选择回调
*
* @param districtBean
*/
private void callback(DistrictBean districtBean) {
ProvinceBean provinceBean = provinceList != null &&
!provinceList.isEmpty() &&
mProvinceAdapter != null &&
mProvinceAdapter.getSelectedPosition() != INDEX_INVALID ?
provinceList.get(mProvinceAdapter.getSelectedPosition()) : null;
CityBean cityBean = cityList != null &&
!cityList.isEmpty() &&
mCityAdapter != null &&
mCityAdapter.getSelectedPosition() != INDEX_INVALID ?
cityList.get(mCityAdapter.getSelectedPosition()) : null;
mBaseListener.onSelected(provinceBean, cityBean, districtBean);
hidePop();
}
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case INDEX_INVALID:
provinceList = (List<ProvinceBean>) msg.obj;
mProvinceAdapter.notifyDataSetChanged();
mCityListView.setAdapter(mProvinceAdapter);
break;
case INDEX_TAB_PROVINCE:
provinceList = (List<ProvinceBean>) msg.obj;
mProvinceAdapter.notifyDataSetChanged();
mCityListView.setAdapter(mProvinceAdapter);
break;
case INDEX_TAB_CITY:
cityList = (List<CityBean>) msg.obj;
mCityAdapter.notifyDataSetChanged();
if (cityList != null && !cityList.isEmpty()) {
mCityListView.setAdapter(mCityAdapter);
tabIndex = INDEX_TAB_CITY;
}
break;
case INDEX_TAB_AREA:
areaList = (List<DistrictBean>) msg.obj;
mAreaAdapter.notifyDataSetChanged();
if (areaList != null && !areaList.isEmpty()) {
mCityListView.setAdapter(mAreaAdapter);
tabIndex = INDEX_TAB_AREA;
}
break;
}
updateTabsStyle(tabIndex);
updateIndicator();
return true;
}
});
/**
* 设置选中的城市tab是否可见
*/
private void updateTabsStyle(int tabIndex) {
switch (tabIndex) {
case INDEX_INVALID:
mProTv.setTextColor(Color.parseColor(colorAlert));
mProTv.setVisibility(View.VISIBLE);
mCityTv.setVisibility(View.GONE);
mAreaTv.setVisibility(View.GONE);
break;
case INDEX_TAB_PROVINCE:
mProTv.setTextColor(Color.parseColor(colorAlert));
mProTv.setVisibility(View.VISIBLE);
mCityTv.setVisibility(View.GONE);
mAreaTv.setVisibility(View.GONE);
break;
case INDEX_TAB_CITY:
mProTv.setTextColor(Color.parseColor(colorSelected));
mCityTv.setTextColor(Color.parseColor(colorAlert));
mProTv.setVisibility(View.VISIBLE);
mCityTv.setVisibility(View.VISIBLE);
mAreaTv.setVisibility(View.GONE);
break;
case INDEX_TAB_AREA:
mProTv.setTextColor(Color.parseColor(colorSelected));
mCityTv.setTextColor(Color.parseColor(colorSelected));
mAreaTv.setTextColor(Color.parseColor(colorAlert));
mProTv.setVisibility(View.VISIBLE);
mCityTv.setVisibility(View.VISIBLE);
mAreaTv.setVisibility(View.VISIBLE);
break;
}
}
}

View File

@@ -0,0 +1,11 @@
package com.lljjcoder.style.cityjd;
public class JDConst {
public static final int INDEX_TAB_PROVINCE = 0;
public static final int INDEX_TAB_CITY = 1;
public static final int INDEX_TAB_AREA = 2;
public static final int INDEX_INVALID = -1;
}

View File

@@ -0,0 +1,26 @@
package com.lljjcoder.style.cityjd;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;
public class MyListView extends ListView {
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(ev);
}
}

View File

@@ -0,0 +1,93 @@
package com.lljjcoder.style.cityjd;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.lljjcoder.bean.ProvinceBean;
import com.lljjcoder.style.citypickerview.R;
import java.util.List;
import static com.lljjcoder.style.cityjd.JDConst.INDEX_INVALID;
/**
* 作者liji on 2018/1/29 17:01
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class ProvinceAdapter extends BaseAdapter {
Context context;
List<ProvinceBean> mProList;
private int provinceIndex = INDEX_INVALID;
public ProvinceAdapter(Context context, List<ProvinceBean> mProList) {
this.context = context;
this.mProList = mProList;
}
public void updateSelectedPosition(int index) {
this.provinceIndex = index;
}
public int getSelectedPosition() {
return this.provinceIndex;
}
@Override
public int getCount() {
return mProList.size();
}
@Override
public ProvinceBean getItem(int position) {
return mProList.get(position);
}
@Override
public long getItemId(int position) {
return Long.parseLong(mProList.get(position).getId());
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.pop_jdcitypicker_item, parent, false);
holder = new Holder();
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.selectImg = (ImageView) convertView.findViewById(R.id.selectImg);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
ProvinceBean item = getItem(position);
holder.name.setText(item.getName());
boolean checked = provinceIndex != INDEX_INVALID && mProList.get(provinceIndex).getName().equals(item.getName());
holder.name.setEnabled(!checked);
holder.selectImg.setVisibility(checked ? View.VISIBLE : View.GONE);
return convertView;
}
class Holder {
TextView name;
ImageView selectImg;
}
}

View File

@@ -0,0 +1,23 @@
package com.lljjcoder.style.citylist;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
/**
* 作者liji on 2017/5/21 16:23
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CConfig {
private static CityInfoBean sCityInfoBean;
public static void setCity(CityInfoBean city) {
sCityInfoBean = city;
}
public static CityInfoBean getCitySelected() {
return sCityInfoBean;
}
}

View File

@@ -0,0 +1,262 @@
package com.lljjcoder.style.citylist;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.github.promeg.pinyinhelper.Pinyin;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
import com.lljjcoder.style.citylist.sortlistview.CharacterParser;
import com.lljjcoder.style.citylist.sortlistview.PinyinComparator;
import com.lljjcoder.style.citylist.sortlistview.SideBar;
import com.lljjcoder.style.citylist.sortlistview.SortAdapter;
import com.lljjcoder.style.citylist.sortlistview.SortModel;
import com.lljjcoder.style.citylist.utils.CityListLoader;
import com.lljjcoder.style.citylist.widget.CleanableEditView;
import com.lljjcoder.style.citypickerview.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CityListSelectActivity extends Activity {
CleanableEditView mCityTextSearch;
TextView mCurrentCityTag;
TextView mCurrentCity;
TextView mLocalCityTag;
TextView mLocalCity;
ListView sortListView;
TextView mDialog;
SideBar mSidrbar;
ImageView imgBack;
public SortAdapter adapter;
/**
* 汉字转换成拼音的类
*/
private CharacterParser characterParser;
private List<SortModel> sourceDateList;
/**
* 根据拼音来排列ListView里面的数据类
*/
private PinyinComparator pinyinComparator;
private List<CityInfoBean> cityListInfo = new ArrayList<>();
private CityInfoBean cityInfoBean = new CityInfoBean();
//startActivityForResult flag
public static final int CITY_SELECT_RESULT_FRAG = 0x0000032;
public static List<CityInfoBean> sCityInfoBeanList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_city_list_select);
initView();
initList();
setCityData(CityListLoader.getInstance().getCityListData());
}
private void initView() {
mCityTextSearch = (CleanableEditView) findViewById(R.id.cityInputText);
mCurrentCityTag = (TextView) findViewById(R.id.currentCityTag);
mCurrentCity = (TextView) findViewById(R.id.currentCity);
mLocalCityTag = (TextView) findViewById(R.id.localCityTag);
mLocalCity = (TextView) findViewById(R.id.localCity);
sortListView = (ListView) findViewById(R.id.country_lvcountry);
mDialog = (TextView) findViewById(R.id.dialog);
mSidrbar = (SideBar) findViewById(R.id.sidrbar);
imgBack = (ImageView) findViewById(R.id.imgBack);
imgBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
private void setCityData(List<CityInfoBean> cityList) {
cityListInfo = cityList;
if (cityListInfo == null) {
return;
}
int count = cityList.size();
String[] list = new String[count];
for (int i = 0; i < count; i++)
list[i] = cityList.get(i).getName();
sourceDateList.addAll(filledData(cityList));
// 根据a-z进行排序源数据
Collections.sort(sourceDateList, pinyinComparator);
adapter.notifyDataSetChanged();
}
/**
* 为ListView填充数据
*
* @return
*/
private List<SortModel> filledData(List<CityInfoBean> cityList) {
List<SortModel> mSortList = new ArrayList<SortModel>();
for (int i = 0; i < cityList.size(); i++) {
CityInfoBean result = cityList.get(i);
if (result != null) {
SortModel sortModel = new SortModel();
String cityName = result.getName();
//汉字转换成拼音
if (!TextUtils.isEmpty(cityName) && cityName.length() > 0) {
// String pinyin = "";
// if (cityName.equals("重庆市")) {
// pinyin = "chong";
// }
// else if (cityName.equals("长沙市")) {
// pinyin = "chang";
// }
// else if (cityName.equals("长春市")) {
// pinyin = "chang";
// }
// else {
// pinyin = mPinYinUtils.getStringPinYin(cityName.substring(0, 1));
// }
//
String pinyin = Pinyin.toPinyin(cityName.substring(0, 1), "").toLowerCase();
if (!TextUtils.isEmpty(pinyin)) {
sortModel.setName(cityName);
String sortString = pinyin.substring(0, 1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if (sortString.matches("[A-Z]")) {
sortModel.setSortLetters(sortString.toUpperCase());
} else {
sortModel.setSortLetters("#");
}
mSortList.add(sortModel);
} else {
Log.d("citypicker_log", "null,cityName:-> " + cityName + " pinyin:-> " + pinyin);
}
}
}
}
return mSortList;
}
private void initList() {
sourceDateList = new ArrayList<SortModel>();
adapter = new SortAdapter(CityListSelectActivity.this, sourceDateList);
sortListView.setAdapter(adapter);
//实例化汉字转拼音类
characterParser = CharacterParser.getInstance();
pinyinComparator = new PinyinComparator();
mSidrbar.setTextView(mDialog);
//设置右侧触摸监听
mSidrbar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() {
@Override
public void onTouchingLetterChanged(String s) {
//该字母首次出现的位置
int position = adapter.getPositionForSection(s.charAt(0));
if (position != -1) {
sortListView.setSelection(position);
}
}
});
sortListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String cityName = ((SortModel) adapter.getItem(position)).getName();
cityInfoBean = CityInfoBean.findCity(cityListInfo, cityName);
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putParcelable("cityinfo", cityInfoBean);
intent.putExtras(bundle);
setResult(RESULT_OK, intent);
finish();
}
});
//根据输入框输入值的改变来过滤搜索
mCityTextSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表
filterData(s.toString());
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
/**
* 根据输入框中的值来过滤数据并更新ListView
*
* @param filterStr
*/
private void filterData(String filterStr) {
List<SortModel> filterDateList = new ArrayList<SortModel>();
if (TextUtils.isEmpty(filterStr)) {
filterDateList = sourceDateList;
} else {
filterDateList.clear();
for (SortModel sortModel : sourceDateList) {
String name = sortModel.getName();
if (name.contains(filterStr) || characterParser.getSelling(name).startsWith(filterStr)) {
filterDateList.add(sortModel);
}
}
}
// 根据a-z进行排序
Collections.sort(filterDateList, pinyinComparator);
adapter.updateListView(filterDateList);
}
}

View File

@@ -0,0 +1,47 @@
package com.lljjcoder.style.citylist.Toast;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.lljjcoder.style.citypickerview.R;
/**
* authoradmin on 2016/5/4 10:50
* emailfangkaijin@gmail.com
*/
public class AlarmDailog extends Toast
{
private Toast toast;
private Context context;
private TextView noticeText;
public AlarmDailog(Context context)
{
super(context);
this.context = context;
LayoutInflater inflater = LayoutInflater.from(context);
View layout = inflater.inflate( R.layout.dialog_alarm_ui, null);
noticeText = (TextView) layout.findViewById( R.id.noticeText);
toast = new Toast(context);
toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_SHORT);
//让Toast显示为我们自定义的样子
toast.setView(layout);
}
public void setShowText(String dialogNotice)
{
noticeText.setText(dialogNotice);
}
public void show()
{
toast.show();
}
}

View File

@@ -0,0 +1,67 @@
package com.lljjcoder.style.citylist.Toast;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.widget.Toast;
/**
* authoradmin on 2016/5/4 10:49
* emailfangkaijin@gmail.com
*/
public class ToastUtils {
private static AlarmDailog alarmDialog;
public static
void showShortToast (Context context, String showMsg ) {
if ( null != alarmDialog ) {
alarmDialog = null;
}
alarmDialog = new AlarmDailog(context);
alarmDialog.setShowText(showMsg);
alarmDialog.setDuration(Toast.LENGTH_SHORT);
alarmDialog.show();
}
public static void showLongToast(Context context, String showMsg)
{
if (null != alarmDialog)
{
alarmDialog = null;
}
alarmDialog = new AlarmDailog(context);
alarmDialog.setShowText(showMsg);
alarmDialog.show();
}
public static void showMomentToast(final Activity activity, final Context context, final String showMsg)
{
activity.runOnUiThread(new Runnable() {
public void run() {
if (null == alarmDialog)
{
alarmDialog = new AlarmDailog(context);
alarmDialog.setShowText(showMsg);
alarmDialog.setDuration(Toast.LENGTH_SHORT);
alarmDialog.show();
}
else
{
alarmDialog.setShowText(showMsg);
alarmDialog.show();
}
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
if(null != alarmDialog)
{
alarmDialog.cancel();
}
}
}, 2000);
}
});
}
}

View File

@@ -0,0 +1,98 @@
package com.lljjcoder.style.citylist.bean;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
/**
* 作者liji on 2017/5/19 17:07
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityInfoBean implements Parcelable {
private String id; /*110101*/
private String name; /*东城区*/
private ArrayList<CityInfoBean> cityList;
public ArrayList<CityInfoBean> getCityList() {
return cityList;
}
public void setCityList(ArrayList<CityInfoBean> cityList) {
this.cityList = cityList;
}
public CityInfoBean() {
}
public static CityInfoBean findCity(List<CityInfoBean> list, String cityName) {
try {
for (int i = 0; i < list.size(); i++) {
CityInfoBean city = list.get(i);
if (cityName.equals(city.getName()) /*|| cityName.contains(city.getName())
|| city.getName().contains(cityName)*/) {
return city;
}
}
}
catch (Exception e) {
return null;
}
return null;
}
public String getId() {
return id == null ? "" : id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name == null ? "" : name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
dest.writeTypedList(this.cityList);
}
protected CityInfoBean(Parcel in) {
this.id = in.readString();
this.name = in.readString();
this.cityList = in.createTypedArrayList(CityInfoBean.CREATOR);
}
public static final Creator<CityInfoBean> CREATOR = new Creator<CityInfoBean>() {
@Override
public CityInfoBean createFromParcel(Parcel source) {
return new CityInfoBean(source);
}
@Override
public CityInfoBean[] newArray(int size) {
return new CityInfoBean[size];
}
};
}

View File

@@ -0,0 +1,134 @@
package com.lljjcoder.style.citylist.sortlistview;
/**
* Java汉字转换为拼音
*
*/
public class CharacterParser {
private static int[] pyvalue = new int[] {-20319, -20317, -20304, -20295, -20292, -20283, -20265, -20257, -20242, -20230, -20051, -20036, -20032,
-20026, -20002, -19990, -19986, -19982, -19976, -19805, -19784, -19775, -19774, -19763, -19756, -19751, -19746, -19741, -19739, -19728,
-19725, -19715, -19540, -19531, -19525, -19515, -19500, -19484, -19479, -19467, -19289, -19288, -19281, -19275, -19270, -19263, -19261,
-19249, -19243, -19242, -19238, -19235, -19227, -19224, -19218, -19212, -19038, -19023, -19018, -19006, -19003, -18996, -18977, -18961,
-18952, -18783, -18774, -18773, -18763, -18756, -18741, -18735, -18731, -18722, -18710, -18697, -18696, -18526, -18518, -18501, -18490,
-18478, -18463, -18448, -18447, -18446, -18239, -18237, -18231, -18220, -18211, -18201, -18184, -18183, -18181, -18012, -17997, -17988,
-17970, -17964, -17961, -17950, -17947, -17931, -17928, -17922, -17759, -17752, -17733, -17730, -17721, -17703, -17701, -17697, -17692,
-17683, -17676, -17496, -17487, -17482, -17468, -17454, -17433, -17427, -17417, -17202, -17185, -16983, -16970, -16942, -16915, -16733,
-16708, -16706, -16689, -16664, -16657, -16647, -16474, -16470, -16465, -16459, -16452, -16448, -16433, -16429, -16427, -16423, -16419,
-16412, -16407, -16403, -16401, -16393, -16220, -16216, -16212, -16205, -16202, -16187, -16180, -16171, -16169, -16158, -16155, -15959,
-15958, -15944, -15933, -15920, -15915, -15903, -15889, -15878, -15707, -15701, -15681, -15667, -15661, -15659, -15652, -15640, -15631,
-15625, -15454, -15448, -15436, -15435, -15419, -15416, -15408, -15394, -15385, -15377, -15375, -15369, -15363, -15362, -15183, -15180,
-15165, -15158, -15153, -15150, -15149, -15144, -15143, -15141, -15140, -15139, -15128, -15121, -15119, -15117, -15110, -15109, -14941,
-14937, -14933, -14930, -14929, -14928, -14926, -14922, -14921, -14914, -14908, -14902, -14894, -14889, -14882, -14873, -14871, -14857,
-14678, -14674, -14670, -14668, -14663, -14654, -14645, -14630, -14594, -14429, -14407, -14399, -14384, -14379, -14368, -14355, -14353,
-14345, -14170, -14159, -14151, -14149, -14145, -14140, -14137, -14135, -14125, -14123, -14122, -14112, -14109, -14099, -14097, -14094,
-14092, -14090, -14087, -14083, -13917, -13914, -13910, -13907, -13906, -13905, -13896, -13894, -13878, -13870, -13859, -13847, -13831,
-13658, -13611, -13601, -13406, -13404, -13400, -13398, -13395, -13391, -13387, -13383, -13367, -13359, -13356, -13343, -13340, -13329,
-13326, -13318, -13147, -13138, -13120, -13107, -13096, -13095, -13091, -13076, -13068, -13063, -13060, -12888, -12875, -12871, -12860,
-12858, -12852, -12849, -12838, -12831, -12829, -12812, -12802, -12607, -12597, -12594, -12585, -12556, -12359, -12346, -12320, -12300,
-12120, -12099, -12089, -12074, -12067, -12058, -12039, -11867, -11861, -11847, -11831, -11798, -11781, -11604, -11589, -11536, -11358,
-11340, -11339, -11324, -11303, -11097, -11077, -11067, -11055, -11052, -11045, -11041, -11038, -11024, -11020, -11019, -11018, -11014,
-10838, -10832, -10815, -10800, -10790, -10780, -10764, -10587, -10544, -10533, -10519, -10331, -10329, -10328, -10322, -10315, -10309,
-10307, -10296, -10281, -10274, -10270, -10262, -10260, -10256, -10254};
public static String[] pystr = new String[] {"a", "ai", "an", "ang", "ao", "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian",
"biao", "bie", "bin", "bing", "bo", "bu", "ca", "cai", "can", "cang", "cao", "ce", "ceng", "cha", "chai", "chan", "chang", "chao", "che",
"chen", "cheng", "chi", "chong", "chou", "chu", "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong", "cou", "cu", "cuan",
"cui", "cun", "cuo", "da", "dai", "dan", "dang", "dao", "de", "deng", "di", "dian", "diao", "die", "ding", "diu", "dong", "dou", "du",
"duan", "dui", "dun", "duo", "e", "en", "er", "fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu", "ga", "gai", "gan", "gang",
"gao", "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", "guo", "ha", "hai", "han", "hang",
"hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun", "huo", "ji", "jia", "jian",
"jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun", "ka", "kai", "kan", "kang", "kao", "ke", "ken",
"keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo", "la", "lai", "lan", "lang", "lao", "le", "lei", "leng",
"li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", "lv", "luan", "lue", "lun", "luo", "ma", "mai",
"man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min", "ming", "miu", "mo", "mou", "mu", "na", "nai",
"nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", "niao", "nie", "nin", "ning", "niu", "nong", "nu", "nv", "nuan",
"nue", "nuo", "o", "ou", "pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po", "pu",
"qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", "qiong", "qiu", "qu", "quan", "que", "qun", "ran", "rang", "rao", "re",
"ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo", "sa", "sai", "san", "sang", "sao", "se", "sen", "seng", "sha",
"shai", "shan", "shang", "shao", "she", "shen", "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang", "shui", "shun",
"shuo", "si", "song", "sou", "su", "suan", "sui", "sun", "suo", "ta", "tai", "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao",
"tie", "ting", "tong", "tou", "tu", "tuan", "tui", "tun", "tuo", "wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu", "xi",
"xia", "xian", "xiang", "xiao", "xie", "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun", "ya", "yan", "yang", "yao", "ye", "yi",
"yin", "ying", "yo", "yong", "you", "yu", "yuan", "yue", "yun", "za", "zai", "zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha",
"zhai", "zhan", "zhang", "zhao", "zhe", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai", "zhuan", "zhuang", "zhui",
"zhun", "zhuo", "zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"};
private StringBuilder buffer;
private String resource;
private static CharacterParser characterParser = new CharacterParser();
public static CharacterParser getInstance() {
return characterParser;
}
public String getResource() {
return resource;
}
public void setResource(String resource) {
this.resource = resource;
}
/** * 汉字转成ASCII码 * * @param chs * @return */
private int getChsAscii(String chs) {
int asc = 0;
try {
byte[] bytes = chs.getBytes("gb2312");
if (bytes == null || bytes.length > 2 || bytes.length <= 0) {
throw new RuntimeException("illegal resource string");
}
if (bytes.length == 1) {
asc = bytes[0];
}
if (bytes.length == 2) {
int hightByte = 256 + bytes[0];
int lowByte = 256 + bytes[1];
asc = (256 * hightByte + lowByte) - 256 * 256;
}
} catch (Exception e) {
System.out.println("ERROR:ChineseSpelling.class-getChsAscii(String chs)" + e);
}
return asc;
}
/** * 单字解析 * * @param str * @return */
public String convert(String str) {
String result = null;
int ascii = getChsAscii(str);
if (ascii > 0 && ascii < 160) {
result = String.valueOf((char) ascii);
} else {
for (int i = (pyvalue.length - 1); i >= 0; i--) {
if (pyvalue[i] <= ascii) {
result = pystr[i];
break;
}
}
}
return result;
}
/** * 词组解析 * * @param chs * @return */
public String getSelling(String chs) {
String key, value;
buffer = new StringBuilder();
for (int i = 0; i < chs.length(); i++) {
key = chs.substring(i, i + 1);
if (key.getBytes().length >= 2) {
value = (String) convert(key);
if (value == null) {
value = "unknown";
}
} else {
value = key;
}
buffer.append(value);
}
return buffer.toString();
}
public String getSpelling() {
return this.getSelling(this.getResource());
}
}

View File

@@ -0,0 +1,24 @@
package com.lljjcoder.style.citylist.sortlistview;
import java.util.Comparator;
/**
*
* @author xiaanming
*
*/
public class PinyinComparator implements Comparator<SortModel> {
public int compare(SortModel o1, SortModel o2) {
if (o1.getSortLetters().equals("@")
|| o2.getSortLetters().equals("#")) {
return -1;
} else if (o1.getSortLetters().equals("#")
|| o2.getSortLetters().equals("@")) {
return 1;
} else {
return o1.getSortLetters().compareTo(o2.getSortLetters());
}
}
}

View File

@@ -0,0 +1,135 @@
package com.lljjcoder.style.citylist.sortlistview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import com.lljjcoder.style.citypickerview.R;
public class SideBar extends View {
// 触摸事件
private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
// 26个字母
public static String[] b = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z", "#" };
private int choose = -1;// 选中
private Paint paint = new Paint();
private TextView mTextDialog;
public void setTextView(TextView mTextDialog) {
this.mTextDialog = mTextDialog;
}
public SideBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SideBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SideBar(Context context) {
super(context);
}
/**
* 重写这个方法
*/
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取焦点改变背景颜色.
int height = getHeight();// 获取对应高度
int width = getWidth(); // 获取对应宽度
int singleHeight = height / b.length;// 获取每一个字母的高度
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.rgb(33, 65, 98));
// paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
paint.setTextSize(20);
// 选中的状态
if (i == choose) {
paint.setColor(Color.parseColor("#000000"));
paint.setFakeBoldText(true);
}
// x坐标等于中间-字符串宽度的一半.
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(b[i], xPos, yPos, paint);
paint.reset();// 重置画笔
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();// 点击y坐标
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
switch (action) {
case MotionEvent.ACTION_UP:
setBackgroundDrawable(new ColorDrawable(0x00000000));
choose = -1;//
invalidate();
if (mTextDialog != null) {
mTextDialog.setVisibility(View.INVISIBLE);
}
break;
default:
setBackgroundResource(R.drawable.sidebar_background);
if (oldChoose != c) {
if (c >= 0 && c < b.length) {
if (listener != null) {
listener.onTouchingLetterChanged(b[c]);
}
if (mTextDialog != null) {
mTextDialog.setText(b[c]);
mTextDialog.setVisibility(View.VISIBLE);
}
choose = c;
invalidate();
}
}
break;
}
return true;
}
/**
* 向外公开的方法
*
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}
/**
* 接口
*
* @author coder
*
*/
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
}

View File

@@ -0,0 +1,127 @@
package com.lljjcoder.style.citylist.sortlistview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.SectionIndexer;
import android.widget.TextView;
import com.lljjcoder.style.citypickerview.R;
import java.util.List;
public class SortAdapter extends BaseAdapter implements SectionIndexer {
private List<SortModel> list = null;
private Context mContext;
public SortAdapter(Context mContext, List<SortModel> list) {
this.mContext = mContext;
this.list = list;
}
/**
* 当ListView数据发生变化时,调用此方法来更新ListView
* @param list
*/
public void updateListView(List<SortModel> list){
this.list = list;
notifyDataSetChanged();
}
public int getCount() {
return this.list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup arg2) {
ViewHolder viewHolder = null;
if (view == null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.sortlistview_item, null);
viewHolder.tvTitle = (TextView) view.findViewById(R.id.title);
viewHolder.tvLetter = (TextView) view.findViewById(R.id.catalog);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
if(null!=list&&!list.isEmpty())
{
SortModel mContent = list.get(position);
//根据position获取分类的首字母的Char ascii值
int section = getSectionForPosition(position);
//如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
if(position == getPositionForSection(section)){
viewHolder.tvLetter.setVisibility(View.VISIBLE);
viewHolder.tvLetter.setText(mContent.getSortLetters());
}else{
viewHolder.tvLetter.setVisibility(View.GONE);
}
viewHolder.tvTitle.setText(this.list.get(position).getName());
}
return view;
}
final static class ViewHolder {
TextView tvLetter;
TextView tvTitle;
}
/**
* 根据ListView的当前位置获取分类的首字母的Char ascii值
*/
public int getSectionForPosition(int position) {
return list.get(position).getSortLetters().charAt(0);
}
/**
* 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
*/
public int getPositionForSection(int section) {
for (int i = 0; i < getCount(); i++) {
String sortStr = list.get(i).getSortLetters();
char firstChar = sortStr.toUpperCase().charAt(0);
if (firstChar == section) {
return i;
}
}
return -1;
}
/**
* 提取英文的首字母,非英文字母用#代替。
*
* @param str
* @return
*/
private String getAlpha(String str) {
String sortStr = str.trim().substring(0, 1).toUpperCase();
// 正则表达式,判断首字母是否是英文字母
if (sortStr.matches("[A-Z]")) {
return sortStr;
} else {
return "#";
}
}
@Override
public Object[] getSections() {
return null;
}
}

View File

@@ -0,0 +1,20 @@
package com.lljjcoder.style.citylist.sortlistview;
public class SortModel {
private String name; //显示的数据
private String sortLetters; //显示数据拼音的首字母
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSortLetters() {
return sortLetters;
}
public void setSortLetters(String sortLetters) {
this.sortLetters = sortLetters;
}
}

View File

@@ -0,0 +1,109 @@
package com.lljjcoder.style.citylist.utils;
import android.content.Context;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lljjcoder.Constant;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
import com.lljjcoder.utils.utils;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* 作者liji on 2017/5/21 15:35
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityListLoader {
public static final String BUNDATA = "bundata";
private static List<CityInfoBean> mCityListData = new ArrayList<>();
private static List<CityInfoBean> mProListData = new ArrayList<>();
/**
* 解析所有的城市数据 357个数据
*/
public List<CityInfoBean> getCityListData() {
return mCityListData;
}
/**
* 只解析省份34个数据
*/
public List<CityInfoBean> getProListData() {
return mProListData;
}
private volatile static CityListLoader instance;
private CityListLoader() {
}
/**
* 单例模式
* @return
*/
public static CityListLoader getInstance() {
if (instance == null) {
synchronized (CityListLoader.class) {
if (instance == null) {
instance = new CityListLoader();
}
}
}
return instance;
}
/**
* 解析357个城市数据
* @param context
*/
public void loadCityData(Context context) {
String cityJson = utils.getJson(context, Constant.CITY_DATA);
Type type = new TypeToken<ArrayList<CityInfoBean>>() {
}.getType();
//解析省份
ArrayList<CityInfoBean> mProvinceBeanArrayList = new Gson().fromJson(cityJson, type);
if (mProvinceBeanArrayList == null || mProvinceBeanArrayList.isEmpty()) {
return;
}
for (int p = 0; p < mProvinceBeanArrayList.size(); p++) {
//遍历每个省份
CityInfoBean itemProvince = mProvinceBeanArrayList.get(p);
//每个省份对应下面的市
ArrayList<CityInfoBean> cityList = itemProvince.getCityList();
//遍历当前省份下面城市的所有数据
for (int j = 0; j < cityList.size(); j++) {
mCityListData.add(cityList.get(j));
}
}
}
/**
* 解析34个省市直辖区数据
* @param context
*/
public void loadProData(Context context) {
String cityJson = utils.getJson(context, Constant.CITY_DATA);
Type type = new TypeToken<ArrayList<CityInfoBean>>() {
}.getType();
//解析省份
mProListData = new Gson().fromJson(cityJson, type);
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.lljjcoder.style.citylist.widget;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
/**
* 说明:
* 作者: fangkaijin on 2017/4/10.13:27
* 邮箱:fangkaijin@gmail.com
*/
public class CleanableEditView extends EditText implements TextWatcher, View.OnFocusChangeListener {
/**
* 左右两侧图片资源
*/
private Drawable left, right;
/**
* 是否获取焦点,默认没有焦点
*/
private boolean hasFocus = false;
/**
* 手指抬起时的X坐标
*/
private int xUp = 0;
public CleanableEditView(Context context) {
this(context, null);
}
public CleanableEditView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
}
public CleanableEditView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWedgits(attrs);
}
/**
* 初始化各组件
* @param attrs
* 属性集
*/
private void initWedgits(AttributeSet attrs) {
try {
left = getCompoundDrawables()[0];
right = getCompoundDrawables()[2];
initDatas();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化数据
*/
private void initDatas() {
try {
// 第一次显示,隐藏删除图标
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
addListeners();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 添加事件监听
*/
private void addListeners() {
try {
setOnFocusChangeListener(this);
addTextChangedListener(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int after) {
if (hasFocus) {
if (TextUtils.isEmpty(s)) {
// 如果为空,则不显示删除图标
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
} else {
// 如果非空,则要显示删除图标
if (null == right) {
right = getCompoundDrawables()[2];
}
setCompoundDrawablesWithIntrinsicBounds(left, null, right, null);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
try {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 获取点击时手指抬起的X坐标
xUp = (int) event.getX();
// 当点击的坐标到当前输入框右侧的距离小于等于getCompoundPaddingRight()的距离时,则认为是点击了删除图标
// getCompoundPaddingRight()的说明Returns the right padding of the view, plus space for the right Drawable if any.
if ((getWidth() - xUp) <= getCompoundPaddingRight()) {
if (!TextUtils.isEmpty(getText().toString())) {
setText("");
}
}
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return super.onTouchEvent(event);
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
try {
this.hasFocus = hasFocus;
String msg=getText().toString();
if(hasFocus){
if(msg.equalsIgnoreCase("")){
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
}else{
setCompoundDrawablesWithIntrinsicBounds(left, null, right, null);
}
}
if(hasFocus==false){
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//获取输入内容
public String text_String (){
return getText().toString();
}
}

View File

@@ -0,0 +1,529 @@
package com.lljjcoder.style.citypickerview;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.lljjcoder.Interface.OnCityItemClickListener;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
import com.lljjcoder.citywheel.CityConfig;
import com.lljjcoder.citywheel.CityParseHelper;
import com.lljjcoder.style.citylist.Toast.ToastUtils;
import com.lljjcoder.style.citypickerview.widget.CanShow;
import com.lljjcoder.style.citypickerview.widget.wheel.OnWheelChangedListener;
import com.lljjcoder.style.citypickerview.widget.wheel.WheelView;
import com.lljjcoder.style.citypickerview.widget.wheel.adapters.ArrayWheelAdapter;
import com.lljjcoder.utils.utils;
import java.util.ArrayList;
import java.util.List;
/**
* 省市区三级选择
* 作者liji on 2015/12/17 10:40
* 邮箱lijiwork@sina.com
*/
public class CityPickerView implements CanShow, OnWheelChangedListener {
private String TAG = "citypicker_log";
private PopupWindow popwindow;
private View popview;
private WheelView mViewProvince;
private WheelView mViewCity;
private WheelView mViewDistrict;
private RelativeLayout mRelativeTitleBg;
private TextView mTvOK;
private TextView mTvTitle;
private TextView mTvCancel;
private OnCityItemClickListener mBaseListener;
private CityParseHelper parseHelper;
private CityConfig config;
private Context context;
private List<ProvinceBean> proArra;
public void setOnCityItemClickListener(OnCityItemClickListener listener) {
mBaseListener = listener;
}
public CityPickerView() {
}
/**
* 设置属性
*
* @param config
*/
public void setConfig(final CityConfig config) {
this.config = config;
}
/**
* 初始化,默认解析城市数据,提交加载速度
*/
public void init(Context context) {
this.context = context;
parseHelper = new CityParseHelper();
//解析初始数据
if (parseHelper.getProvinceBeanArrayList().isEmpty()) {
parseHelper.initData(context);
}
}
/**
* 初始化popWindow
*/
private void initCityPickerPopwindow() {
if (config == null) {
throw new IllegalArgumentException("please set config first...");
}
//解析初始数据
if (parseHelper == null) {
parseHelper = new CityParseHelper();
}
if (parseHelper.getProvinceBeanArrayList().isEmpty()) {
ToastUtils.showLongToast(context, "请在Activity中增加init操作");
return;
}
LayoutInflater layoutInflater = LayoutInflater.from(context);
popview = layoutInflater.inflate(R.layout.pop_citypicker, null);
mViewProvince = (WheelView) popview.findViewById(R.id.id_province);
mViewCity = (WheelView) popview.findViewById(R.id.id_city);
mViewDistrict = (WheelView) popview.findViewById(R.id.id_district);
mRelativeTitleBg = (RelativeLayout) popview.findViewById(R.id.rl_title);
mTvOK = (TextView) popview.findViewById(R.id.tv_confirm);
mTvTitle = (TextView) popview.findViewById(R.id.tv_title);
mTvCancel = (TextView) popview.findViewById(R.id.tv_cancel);
popwindow = new PopupWindow(popview, LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popwindow.setAnimationStyle(R.style.AnimBottom);
popwindow.setBackgroundDrawable(new ColorDrawable());
popwindow.setTouchable(true);
popwindow.setOutsideTouchable(false);
popwindow.setFocusable(true);
popwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if (config.isShowBackground()) {
utils.setBackgroundAlpha(context, 1.0f);
}
}
});
/**
* 设置标题背景颜色
*/
if (!TextUtils.isEmpty(config.getTitleBackgroundColorStr())) {
if (config.getTitleBackgroundColorStr().startsWith("#")) {
mRelativeTitleBg.setBackgroundColor(Color.parseColor(config.getTitleBackgroundColorStr()));
} else {
mRelativeTitleBg.setBackgroundColor(Color.parseColor("#" + config.getTitleBackgroundColorStr()));
}
}
//标题
if (!TextUtils.isEmpty(config.getTitle())) {
mTvTitle.setText(config.getTitle());
}
//标题文字大小
if (config.getTitleTextSize() > 0) {
mTvTitle.setTextSize(config.getTitleTextSize());
}
//标题文字颜色
if (!TextUtils.isEmpty(config.getTitleTextColorStr())) {
if (config.getTitleTextColorStr().startsWith("#")) {
mTvTitle.setTextColor(Color.parseColor(config.getTitleTextColorStr()));
} else {
mTvTitle.setTextColor(Color.parseColor("#" + config.getTitleTextColorStr()));
}
}
//设置确认按钮文字大小颜色
if (!TextUtils.isEmpty(config.getConfirmTextColorStr())) {
if (config.getConfirmTextColorStr().startsWith("#")) {
mTvOK.setTextColor(Color.parseColor(config.getConfirmTextColorStr()));
} else {
mTvOK.setTextColor(Color.parseColor("#" + config.getConfirmTextColorStr()));
}
}
if (!TextUtils.isEmpty(config.getConfirmText())) {
mTvOK.setText(config.getConfirmText());
}
if ((config.getConfirmTextSize() > 0)) {
mTvOK.setTextSize(config.getConfirmTextSize());
}
//设置取消按钮文字颜色
if (!TextUtils.isEmpty(config.getCancelTextColorStr())) {
if (config.getCancelTextColorStr().startsWith("#")) {
mTvCancel.setTextColor(Color.parseColor(config.getCancelTextColorStr()));
} else {
mTvCancel.setTextColor(Color.parseColor("#" + config.getCancelTextColorStr()));
}
}
if (!TextUtils.isEmpty(config.getCancelText())) {
mTvCancel.setText(config.getCancelText());
}
if ((config.getCancelTextSize() > 0)) {
mTvCancel.setTextSize(config.getCancelTextSize());
}
//只显示省市两级联动
if (config.getWheelType() == CityConfig.WheelType.PRO) {
mViewCity.setVisibility(View.GONE);
mViewDistrict.setVisibility(View.GONE);
} else if (config.getWheelType() == CityConfig.WheelType.PRO_CITY) {
mViewDistrict.setVisibility(View.GONE);
} else {
mViewProvince.setVisibility(View.VISIBLE);
mViewCity.setVisibility(View.VISIBLE);
mViewDistrict.setVisibility(View.VISIBLE);
}
// 添加change事件
mViewProvince.addChangingListener(this);
// 添加change事件
mViewCity.addChangingListener(this);
// 添加change事件
mViewDistrict.addChangingListener(this);
// 添加onclick事件
mTvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mBaseListener.onCancel();
hide();
}
});
//确认选择
mTvOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (parseHelper != null) {
if (config.getWheelType() == CityConfig.WheelType.PRO) {
mBaseListener.onSelected(parseHelper.getProvinceBean(), new CityBean(), new DistrictBean());
} else if (config.getWheelType() == CityConfig.WheelType.PRO_CITY) {
mBaseListener.onSelected(parseHelper.getProvinceBean(),
parseHelper.getCityBean(),
new DistrictBean());
} else {
mBaseListener.onSelected(parseHelper.getProvinceBean(),
parseHelper.getCityBean(),
parseHelper.getDistrictBean());
}
} else {
mBaseListener.onSelected(new ProvinceBean(), new CityBean(), new DistrictBean());
}
hide();
}
});
//显示省市区数据
setUpData();
//背景半透明
if (config != null && config.isShowBackground()) {
utils.setBackgroundAlpha(context, 0.5f);
}
}
/**
* 根据是否显示港澳台数据来初始化最新的数据
*
* @param array
* @return
*/
private List<ProvinceBean> getProArrData(List<ProvinceBean> array) {
List<ProvinceBean> provinceBeanList = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
provinceBeanList.add(array.get(i));
}
//不需要港澳台数据
if (!config.isShowGAT()) {
provinceBeanList.remove(provinceBeanList.size() - 1);
provinceBeanList.remove(provinceBeanList.size() - 1);
provinceBeanList.remove(provinceBeanList.size() - 1);
}
proArra = new ArrayList<ProvinceBean>();
for (int i = 0; i < provinceBeanList.size(); i++) {
proArra.add(provinceBeanList.get(i));
}
return proArra;
}
/**
* 加载数据
*/
private void setUpData() {
if (parseHelper == null || config == null) {
return;
}
//根据是否显示港澳台数据来初始化最新的数据
getProArrData(parseHelper.getProvinceBeenArray());
int provinceDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultProvinceName()) && proArra.size() > 0) {
for (int i = 0; i < proArra.size(); i++) {
if (proArra.get(i).getName().equals(config.getDefaultProvinceName())) {
provinceDefault = i;
break;
}
}
}
ArrayWheelAdapter arrayWheelAdapter = new ArrayWheelAdapter<ProvinceBean>(context, proArra);
mViewProvince.setViewAdapter(arrayWheelAdapter);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE && config.getCustomItemTextViewId() != CityConfig.NONE) {
arrayWheelAdapter.setItemResource(config.getCustomItemLayout());
arrayWheelAdapter.setItemTextResource(config.getCustomItemTextViewId());
} else {
arrayWheelAdapter.setItemResource(R.layout.default_item_city);
arrayWheelAdapter.setItemTextResource(R.id.default_item_city_name_tv);
}
//获取所设置的省的位置,直接定位到该位置
if (-1 != provinceDefault) {
mViewProvince.setCurrentItem(provinceDefault);
}
// 设置可见条目数量
mViewProvince.setVisibleItems(config.getVisibleItems());
mViewCity.setVisibleItems(config.getVisibleItems());
mViewDistrict.setVisibleItems(config.getVisibleItems());
mViewProvince.setCyclic(config.isProvinceCyclic());
mViewCity.setCyclic(config.isCityCyclic());
mViewDistrict.setCyclic(config.isDistrictCyclic());
//显示滚轮模糊效果
mViewProvince.setDrawShadows(config.isDrawShadows());
mViewCity.setDrawShadows(config.isDrawShadows());
mViewDistrict.setDrawShadows(config.isDrawShadows());
//中间线的颜色及高度
mViewProvince.setLineColorStr(config.getLineColor());
mViewProvince.setLineWidth(config.getLineHeigh());
mViewCity.setLineColorStr(config.getLineColor());
mViewCity.setLineWidth(config.getLineHeigh());
mViewDistrict.setLineColorStr(config.getLineColor());
mViewDistrict.setLineWidth(config.getLineHeigh());
updateCities();
updateAreas();
}
/**
* 根据当前的省更新市WheelView的信息
*/
private void updateCities() {
if (parseHelper == null || config == null) {
return;
}
//省份滚轮滑动的当前位置
int pCurrent = mViewProvince.getCurrentItem();
//省份选中的名称
ProvinceBean mProvinceBean = proArra.get(pCurrent);
parseHelper.setProvinceBean(mProvinceBean);
if (parseHelper.getPro_CityMap() == null) {
return;
}
List<CityBean> cities = parseHelper.getPro_CityMap().get(mProvinceBean.getName());
if (cities == null) {
return;
}
//设置最初的默认城市
int cityDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultCityName()) && cities.size() > 0) {
for (int i = 0; i < cities.size(); i++) {
if (config.getDefaultCityName().equals(cities.get(i).getName())) {
cityDefault = i;
break;
}
}
}
ArrayWheelAdapter cityWheel = new ArrayWheelAdapter<CityBean>(context, cities);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE && config.getCustomItemTextViewId() != CityConfig.NONE) {
cityWheel.setItemResource(config.getCustomItemLayout());
cityWheel.setItemTextResource(config.getCustomItemTextViewId());
} else {
cityWheel.setItemResource(R.layout.default_item_city);
cityWheel.setItemTextResource(R.id.default_item_city_name_tv);
}
mViewCity.setViewAdapter(cityWheel);
if (-1 != cityDefault) {
mViewCity.setCurrentItem(cityDefault);
} else {
mViewCity.setCurrentItem(0);
}
updateAreas();
}
/**
* 根据当前的市更新区WheelView的信息
*/
private void updateAreas() {
int pCurrent = mViewCity.getCurrentItem();
if (parseHelper.getPro_CityMap() == null || parseHelper.getCity_DisMap() == null) {
return;
}
if (config.getWheelType() == CityConfig.WheelType.PRO_CITY
|| config.getWheelType() == CityConfig.WheelType.PRO_CITY_DIS) {
CityBean mCityBean = parseHelper.getPro_CityMap().get(parseHelper.getProvinceBean().getName()).get(pCurrent);
parseHelper.setCityBean(mCityBean);
if (config.getWheelType() == CityConfig.WheelType.PRO_CITY_DIS) {
List<DistrictBean> areas = parseHelper.getCity_DisMap()
.get(parseHelper.getProvinceBean().getName() + mCityBean.getName());
if (areas == null) {
return;
}
int districtDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultDistrict()) && areas.size() > 0) {
for (int i = 0; i < areas.size(); i++) {
if (config.getDefaultDistrict().equals(areas.get(i).getName())) {
districtDefault = i;
break;
}
}
}
ArrayWheelAdapter districtWheel = new ArrayWheelAdapter<DistrictBean>(context, areas);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE
&& config.getCustomItemTextViewId() != CityConfig.NONE) {
districtWheel.setItemResource(config.getCustomItemLayout());
districtWheel.setItemTextResource(config.getCustomItemTextViewId());
} else {
districtWheel.setItemResource(R.layout.default_item_city);
districtWheel.setItemTextResource(R.id.default_item_city_name_tv);
}
mViewDistrict.setViewAdapter(districtWheel);
DistrictBean mDistrictBean = null;
if (parseHelper.getDisMap() == null) {
return;
}
if (-1 != districtDefault) {
mViewDistrict.setCurrentItem(districtDefault);
//获取第一个区名称
mDistrictBean = parseHelper.getDisMap().get(parseHelper.getProvinceBean().getName()
+ mCityBean.getName() + config.getDefaultDistrict());
} else {
mViewDistrict.setCurrentItem(0);
if (areas.size() > 0) {
mDistrictBean = areas.get(0);
}
}
parseHelper.setDistrictBean(mDistrictBean);
}
}
}
public void showCityPicker() {
initCityPickerPopwindow();
if (!isShow()) {
popwindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);
}
}
@Override
public void hide() {
if (isShow()) {
popwindow.dismiss();
}
}
@Override
public boolean isShow() {
return popwindow.isShowing();
}
@Override
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (wheel == mViewProvince) {
updateCities();
} else if (wheel == mViewCity) {
updateAreas();
} else if (wheel == mViewDistrict) {
if (parseHelper != null && parseHelper.getCity_DisMap() != null) {
DistrictBean mDistrictBean = parseHelper.getCity_DisMap()
.get(parseHelper.getProvinceBean().getName() + parseHelper.getCityBean().getName()).get(newValue);
parseHelper.setDistrictBean(mDistrictBean);
}
}
}
}

View File

@@ -0,0 +1,528 @@
package com.lljjcoder.style.citypickerview;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.lljjcoder.Interface.OnCityItemClickListener;
import com.lljjcoder.bean.CityBean;
import com.lljjcoder.bean.DistrictBean;
import com.lljjcoder.bean.ProvinceBean;
import com.lljjcoder.citywheel.CityConfig;
import com.lljjcoder.citywheel.CityParseHelper;
import com.lljjcoder.style.citylist.Toast.ToastUtils;
import com.lljjcoder.style.citypickerview.widget.CanShow;
import com.lljjcoder.style.citypickerview.widget.wheel.OnWheelChangedListener;
import com.lljjcoder.style.citypickerview.widget.wheel.WheelView;
import com.lljjcoder.style.citypickerview.widget.wheel.adapters.ArrayWheelAdapter;
import com.lljjcoder.utils.utils;
import java.util.ArrayList;
import java.util.List;
/**
* 省市区三级选择
* 作者liji on 2015/12/17 10:40
* 邮箱lijiwork@sina.com
*/
public class CityPickerViewTw implements CanShow, OnWheelChangedListener {
private String TAG = "citypicker_log";
private PopupWindow popwindow;
private View popview;
private WheelView mViewProvince;
private WheelView mViewCity;
private WheelView mViewDistrict;
private RelativeLayout mRelativeTitleBg;
private TextView mTvOK;
private TextView mTvTitle;
private TextView mTvCancel;
private OnCityItemClickListener mBaseListener;
private CityParseHelper parseHelper;
private CityConfig config;
private Context context;
private List<ProvinceBean> proArra;
public void setOnCityItemClickListener(OnCityItemClickListener listener) {
mBaseListener = listener;
}
public CityPickerViewTw() {
}
/**
* 设置属性
*
* @param config
*/
public void setConfig(final CityConfig config) {
this.config = config;
}
/**
* 初始化,默认解析城市数据,提交加载速度
*/
public void init(Context context) {
this.context = context;
parseHelper = new CityParseHelper();
//解析初始数据
if (parseHelper.getProvinceBeanArrayList().isEmpty()) {
parseHelper.initDataTw(context);
}
}
/**
* 初始化popWindow
*/
private void initCityPickerPopwindow() {
if (config == null) {
throw new IllegalArgumentException("please set config first...");
}
//解析初始数据
if (parseHelper == null) {
parseHelper = new CityParseHelper();
}
if (parseHelper.getProvinceBeanArrayList().isEmpty()) {
ToastUtils.showLongToast(context, "请在Activity中增加init操作");
return;
}
LayoutInflater layoutInflater = LayoutInflater.from(context);
popview = layoutInflater.inflate(R.layout.pop_citypicker, null);
mViewProvince = (WheelView) popview.findViewById(R.id.id_province);
mViewCity = (WheelView) popview.findViewById(R.id.id_city);
mViewDistrict = (WheelView) popview.findViewById(R.id.id_district);
mRelativeTitleBg = (RelativeLayout) popview.findViewById(R.id.rl_title);
mTvOK = (TextView) popview.findViewById(R.id.tv_confirm);
mTvTitle = (TextView) popview.findViewById(R.id.tv_title);
mTvCancel = (TextView) popview.findViewById(R.id.tv_cancel);
popwindow = new PopupWindow(popview, LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popwindow.setAnimationStyle(R.style.AnimBottom);
popwindow.setBackgroundDrawable(new ColorDrawable());
popwindow.setTouchable(true);
popwindow.setOutsideTouchable(false);
popwindow.setFocusable(true);
popwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if (config.isShowBackground()) {
utils.setBackgroundAlpha(context, 1.0f);
}
}
});
/**
* 设置标题背景颜色
*/
if (!TextUtils.isEmpty(config.getTitleBackgroundColorStr())) {
if (config.getTitleBackgroundColorStr().startsWith("#")) {
mRelativeTitleBg.setBackgroundColor(Color.parseColor(config.getTitleBackgroundColorStr()));
} else {
mRelativeTitleBg.setBackgroundColor(Color.parseColor("#" + config.getTitleBackgroundColorStr()));
}
}
//标题
if (!TextUtils.isEmpty(config.getTitle())) {
mTvTitle.setText(config.getTitle());
}
//标题文字大小
if (config.getTitleTextSize() > 0) {
mTvTitle.setTextSize(config.getTitleTextSize());
}
//标题文字颜色
if (!TextUtils.isEmpty(config.getTitleTextColorStr())) {
if (config.getTitleTextColorStr().startsWith("#")) {
mTvTitle.setTextColor(Color.parseColor(config.getTitleTextColorStr()));
} else {
mTvTitle.setTextColor(Color.parseColor("#" + config.getTitleTextColorStr()));
}
}
//设置确认按钮文字大小颜色
if (!TextUtils.isEmpty(config.getConfirmTextColorStr())) {
if (config.getConfirmTextColorStr().startsWith("#")) {
mTvOK.setTextColor(Color.parseColor(config.getConfirmTextColorStr()));
} else {
mTvOK.setTextColor(Color.parseColor("#" + config.getConfirmTextColorStr()));
}
}
if (!TextUtils.isEmpty(config.getConfirmText())) {
mTvOK.setText(config.getConfirmText());
}
if ((config.getConfirmTextSize() > 0)) {
mTvOK.setTextSize(config.getConfirmTextSize());
}
//设置取消按钮文字颜色
if (!TextUtils.isEmpty(config.getCancelTextColorStr())) {
if (config.getCancelTextColorStr().startsWith("#")) {
mTvCancel.setTextColor(Color.parseColor(config.getCancelTextColorStr()));
} else {
mTvCancel.setTextColor(Color.parseColor("#" + config.getCancelTextColorStr()));
}
}
if (!TextUtils.isEmpty(config.getCancelText())) {
mTvCancel.setText(config.getCancelText());
}
if ((config.getCancelTextSize() > 0)) {
mTvCancel.setTextSize(config.getCancelTextSize());
}
//只显示省市两级联动
if (config.getWheelType() == CityConfig.WheelType.PRO) {
mViewCity.setVisibility(View.GONE);
mViewDistrict.setVisibility(View.GONE);
} else if (config.getWheelType() == CityConfig.WheelType.PRO_CITY) {
mViewDistrict.setVisibility(View.GONE);
} else {
mViewProvince.setVisibility(View.VISIBLE);
mViewCity.setVisibility(View.VISIBLE);
mViewDistrict.setVisibility(View.VISIBLE);
}
// 添加change事件
mViewProvince.addChangingListener(this);
// 添加change事件
mViewCity.addChangingListener(this);
// 添加change事件
mViewDistrict.addChangingListener(this);
// 添加onclick事件
mTvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mBaseListener.onCancel();
hide();
}
});
//确认选择
mTvOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (parseHelper != null) {
if (config.getWheelType() == CityConfig.WheelType.PRO) {
mBaseListener.onSelected(parseHelper.getProvinceBean(), new CityBean(), new DistrictBean());
} else if (config.getWheelType() == CityConfig.WheelType.PRO_CITY) {
mBaseListener.onSelected(parseHelper.getProvinceBean(),
parseHelper.getCityBean(),
new DistrictBean());
} else {
mBaseListener.onSelected(parseHelper.getProvinceBean(),
parseHelper.getCityBean(),
parseHelper.getDistrictBean());
}
} else {
mBaseListener.onSelected(new ProvinceBean(), new CityBean(), new DistrictBean());
}
hide();
}
});
//显示省市区数据
setUpData();
//背景半透明
if (config != null && config.isShowBackground()) {
utils.setBackgroundAlpha(context, 0.5f);
}
}
/**
* 根据是否显示港澳台数据来初始化最新的数据
*
* @param array
* @return
*/
private List<ProvinceBean> getProArrData(List<ProvinceBean> array) {
List<ProvinceBean> provinceBeanList = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
provinceBeanList.add(array.get(i));
}
//不需要港澳台数据
if (!config.isShowGAT()) {
provinceBeanList.remove(provinceBeanList.size() - 1);
provinceBeanList.remove(provinceBeanList.size() - 1);
provinceBeanList.remove(provinceBeanList.size() - 1);
}
proArra = new ArrayList<ProvinceBean>();
for (int i = 0; i < provinceBeanList.size(); i++) {
proArra.add(provinceBeanList.get(i));
}
return proArra;
}
/**
* 加载数据
*/
private void setUpData() {
if (parseHelper == null || config == null) {
return;
}
//根据是否显示港澳台数据来初始化最新的数据
getProArrData(parseHelper.getProvinceBeenArray());
int provinceDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultProvinceName()) && proArra.size() > 0) {
for (int i = 0; i < proArra.size(); i++) {
if (proArra.get(i).getName().equals(config.getDefaultProvinceName())) {
provinceDefault = i;
break;
}
}
}
ArrayWheelAdapter arrayWheelAdapter = new ArrayWheelAdapter<ProvinceBean>(context, proArra);
mViewProvince.setViewAdapter(arrayWheelAdapter);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE && config.getCustomItemTextViewId() != CityConfig.NONE) {
arrayWheelAdapter.setItemResource(config.getCustomItemLayout());
arrayWheelAdapter.setItemTextResource(config.getCustomItemTextViewId());
} else {
arrayWheelAdapter.setItemResource(R.layout.default_item_city);
arrayWheelAdapter.setItemTextResource(R.id.default_item_city_name_tv);
}
//获取所设置的省的位置,直接定位到该位置
if (-1 != provinceDefault) {
mViewProvince.setCurrentItem(provinceDefault);
}
// 设置可见条目数量
mViewProvince.setVisibleItems(config.getVisibleItems());
mViewCity.setVisibleItems(config.getVisibleItems());
mViewDistrict.setVisibleItems(config.getVisibleItems());
mViewProvince.setCyclic(config.isProvinceCyclic());
mViewCity.setCyclic(config.isCityCyclic());
mViewDistrict.setCyclic(config.isDistrictCyclic());
//显示滚轮模糊效果
mViewProvince.setDrawShadows(config.isDrawShadows());
mViewCity.setDrawShadows(config.isDrawShadows());
mViewDistrict.setDrawShadows(config.isDrawShadows());
//中间线的颜色及高度
mViewProvince.setLineColorStr(config.getLineColor());
mViewProvince.setLineWidth(config.getLineHeigh());
mViewCity.setLineColorStr(config.getLineColor());
mViewCity.setLineWidth(config.getLineHeigh());
mViewDistrict.setLineColorStr(config.getLineColor());
mViewDistrict.setLineWidth(config.getLineHeigh());
updateCities();
updateAreas();
}
/**
* 根据当前的省更新市WheelView的信息
*/
private void updateCities() {
if (parseHelper == null || config == null) {
return;
}
//省份滚轮滑动的当前位置
int pCurrent = mViewProvince.getCurrentItem();
//省份选中的名称
ProvinceBean mProvinceBean = proArra.get(pCurrent);
parseHelper.setProvinceBean(mProvinceBean);
if (parseHelper.getPro_CityMap() == null) {
return;
}
List<CityBean> cities = parseHelper.getPro_CityMap().get(mProvinceBean.getName());
if (cities == null) {
return;
}
//设置最初的默认城市
int cityDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultCityName()) && cities.size() > 0) {
for (int i = 0; i < cities.size(); i++) {
if (config.getDefaultCityName().equals(cities.get(i).getName())) {
cityDefault = i;
break;
}
}
}
ArrayWheelAdapter cityWheel = new ArrayWheelAdapter<CityBean>(context, cities);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE && config.getCustomItemTextViewId() != CityConfig.NONE) {
cityWheel.setItemResource(config.getCustomItemLayout());
cityWheel.setItemTextResource(config.getCustomItemTextViewId());
} else {
cityWheel.setItemResource(R.layout.default_item_city);
cityWheel.setItemTextResource(R.id.default_item_city_name_tv);
}
mViewCity.setViewAdapter(cityWheel);
if (-1 != cityDefault) {
mViewCity.setCurrentItem(cityDefault);
} else {
mViewCity.setCurrentItem(0);
}
updateAreas();
}
/**
* 根据当前的市更新区WheelView的信息
*/
private void updateAreas() {
int pCurrent = mViewCity.getCurrentItem();
if (parseHelper.getPro_CityMap() == null || parseHelper.getCity_DisMap() == null) {
return;
}
if (config.getWheelType() == CityConfig.WheelType.PRO_CITY
|| config.getWheelType() == CityConfig.WheelType.PRO_CITY_DIS) {
CityBean mCityBean = parseHelper.getPro_CityMap().get(parseHelper.getProvinceBean().getName()).get(pCurrent);
parseHelper.setCityBean(mCityBean);
if (config.getWheelType() == CityConfig.WheelType.PRO_CITY_DIS) {
List<DistrictBean> areas = parseHelper.getCity_DisMap()
.get(parseHelper.getProvinceBean().getName() + mCityBean.getName());
if (areas == null) {
return;
}
int districtDefault = -1;
if (!TextUtils.isEmpty(config.getDefaultDistrict()) && areas.size() > 0) {
for (int i = 0; i < areas.size(); i++) {
if (config.getDefaultDistrict().equals(areas.get(i).getName())) {
districtDefault = i;
break;
}
}
}
ArrayWheelAdapter districtWheel = new ArrayWheelAdapter<DistrictBean>(context, areas);
//自定义item
if (config.getCustomItemLayout() != CityConfig.NONE
&& config.getCustomItemTextViewId() != CityConfig.NONE) {
districtWheel.setItemResource(config.getCustomItemLayout());
districtWheel.setItemTextResource(config.getCustomItemTextViewId());
} else {
districtWheel.setItemResource(R.layout.default_item_city);
districtWheel.setItemTextResource(R.id.default_item_city_name_tv);
}
mViewDistrict.setViewAdapter(districtWheel);
DistrictBean mDistrictBean = null;
if (parseHelper.getDisMap() == null) {
return;
}
if (-1 != districtDefault) {
mViewDistrict.setCurrentItem(districtDefault);
//获取第一个区名称
mDistrictBean = parseHelper.getDisMap().get(parseHelper.getProvinceBean().getName()
+ mCityBean.getName() + config.getDefaultDistrict());
} else {
mViewDistrict.setCurrentItem(0);
if (areas.size() > 0) {
mDistrictBean = areas.get(0);
}
}
parseHelper.setDistrictBean(mDistrictBean);
}
}
}
public void showCityPicker() {
initCityPickerPopwindow();
if (!isShow()) {
popwindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);
}
}
@Override
public void hide() {
if (isShow()) {
popwindow.dismiss();
}
}
@Override
public boolean isShow() {
return popwindow.isShowing();
}
@Override
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (wheel == mViewProvince) {
updateCities();
} else if (wheel == mViewCity) {
updateAreas();
} else if (wheel == mViewDistrict) {
if (parseHelper != null && parseHelper.getCity_DisMap() != null) {
DistrictBean mDistrictBean = parseHelper.getCity_DisMap()
.get(parseHelper.getProvinceBean().getName() + parseHelper.getCityBean().getName()).get(newValue);
parseHelper.setDistrictBean(mDistrictBean);
}
}
}
}

View File

@@ -0,0 +1,41 @@
package com.lljjcoder.style.citypickerview.model;
import java.util.List;
public class CityModel {
private String name;
private List<DistrictModel> districtList;
public CityModel() {
super();
}
public CityModel(String name, List<DistrictModel> districtList) {
super();
this.name = name;
this.districtList = districtList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<DistrictModel> getDistrictList() {
return districtList;
}
public void setDistrictList(List<DistrictModel> districtList) {
this.districtList = districtList;
}
@Override
public String toString() {
return "CityModel [name=" + name + ", districtList=" + districtList
+ "]";
}
}

View File

@@ -0,0 +1,38 @@
package com.lljjcoder.style.citypickerview.model;
public class DistrictModel {
private String name;
private String zipcode;
public DistrictModel() {
super();
}
public DistrictModel(String name, String zipcode) {
super();
this.name = name;
this.zipcode = zipcode;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
@Override
public String toString() {
return "DistrictModel [name=" + name + ", zipcode=" + zipcode + "]";
}
}

View File

@@ -0,0 +1,40 @@
package com.lljjcoder.style.citypickerview.model;
import java.util.List;
public class ProvinceModel {
private String name;
private List<CityModel> cityList;
public ProvinceModel() {
super();
}
public ProvinceModel(String name, List<CityModel> cityList) {
super();
this.name = name;
this.cityList = cityList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CityModel> getCityList() {
return cityList;
}
public void setCityList(List<CityModel> cityList) {
this.cityList = cityList;
}
@Override
public String toString() {
return "ProvinceModel [name=" + name + ", cityList=" + cityList + "]";
}
}

View File

@@ -0,0 +1,11 @@
package com.lljjcoder.style.citypickerview.widget;
/**
* 作者liji on 2016/6/30 14:58
* 邮箱lijiwork@sina.com
*/
public interface CanShow {
void hide();
boolean isShow();
}

View File

@@ -0,0 +1,12 @@
package com.lljjcoder.style.citypickerview.widget;
public abstract class XCallbackListener {
protected abstract void callback(Object... obj);
public void call(Object... obj) {
callback(obj);
}
}

View File

@@ -0,0 +1,81 @@
/*
* Android Wheel Control.
* https://code.google.com/p/android-wheel/
*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
/**
* Range for visible items.
*/
public class ItemsRange {
// First item number
private int first;
// Items count
private int count;
/**
* Default constructor. Creates an empty range
*/
public ItemsRange() {
this(0, 0);
}
/**
* Constructor
* @param first the number of first item
* @param count the count of items
*/
public ItemsRange(int first, int count) {
this.first = first;
this.count = count;
}
/**
* Gets number of first item
* @return the number of the first item
*/
public int getFirst() {
return first;
}
/**
* Gets number of last item
* @return the number of last item
*/
public int getLast() {
return getFirst() + getCount() - 1;
}
/**
* Get items count
* @return the count of items
*/
public int getCount() {
return count;
}
/**
* Tests whether item is contained by range
* @param index the item number
* @return true if item is contained
*/
public boolean contains(int index) {
return index >= getFirst() && index <= getLast();
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
/**
* Wheel changed listener interface.
* <p>The onChanged() method is called whenever current wheel positions is changed:
* <li> New Wheel position is set
* <li> Wheel view is scrolled
*/
public interface OnWheelChangedListener {
/**
* Callback method to be invoked when current item changed
* @param wheel the wheel view whose state has changed
* @param oldValue the old value of current item
* @param newValue the new value of current item
*/
void onChanged(WheelView wheel, int oldValue, int newValue);
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
/**
* Wheel clicked listener interface.
* <p>The onItemClicked() method is called whenever a wheel item is clicked
* <li> New Wheel position is set
* <li> Wheel view is scrolled
*/
public interface OnWheelClickedListener {
/**
* Callback method to be invoked when current item clicked
* @param wheel the wheel view
* @param itemIndex the index of clicked item
*/
void onItemClicked(WheelView wheel, int itemIndex);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2010 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
/**
* Wheel scrolled listener interface.
*/
public interface OnWheelScrollListener {
/**
* Callback method to be invoked when scrolling started.
* @param wheel the wheel view whose state has changed.
*/
void onScrollingStarted(WheelView wheel);
/**
* Callback method to be invoked when scrolling ended.
* @param wheel the wheel view whose state has changed.
*/
void onScrollingFinished(WheelView wheel);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2010 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
/**
* Wheel adapter interface
*
* @deprecated Use WheelViewAdapter
*/
public interface WheelAdapter {
/**
* Gets items count
* @return the count of wheel items
*/
public int getItemsCount();
/**
* Gets a wheel item by index.
*
* @param index the item index
* @return the wheel item text or null
*/
public String getItem(int index);
/**
* Gets maximum item length. It is used to determine the wheel width.
* If -1 is returned there will be used the default wheel width.
*
* @return the maximum item length or -1
*/
public int getMaximumLength();
}

View File

@@ -0,0 +1,153 @@
/*
* Android Wheel Control.
* https://code.google.com/p/android-wheel/
*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
import java.util.LinkedList;
import java.util.List;
import android.view.View;
import android.widget.LinearLayout;
/**
* Recycle stores wheel items to reuse.
*/
public class WheelRecycle {
// Cached items
private List<View> items;
// Cached empty items
private List<View> emptyItems;
// Wheel view
private WheelView wheel;
/**
* Constructor
* @param wheel the wheel view
*/
public WheelRecycle(WheelView wheel) {
this.wheel = wheel;
}
/**
* Recycles items from specified layout.
* There are saved only items not included to specified range.
* All the cached items are removed from original layout.
*
* @param layout the layout containing items to be cached
* @param firstItem the number of first item in layout
* @param range the range of current wheel items
* @return the new value of first item number
*/
public int recycleItems(LinearLayout layout, int firstItem, ItemsRange range) {
int index = firstItem;
for (int i = 0; i < layout.getChildCount();) {
if (!range.contains(index)) {
recycleView(layout.getChildAt(i), index);
layout.removeViewAt(i);
if (i == 0) { // first item
firstItem++;
}
} else {
i++; // go to next item
}
index++;
}
return firstItem;
}
/**
* Gets item view
* @return the cached view
*/
public View getItem() {
return getCachedView(items);
}
/**
* Gets empty item view
* @return the cached empty view
*/
public View getEmptyItem() {
return getCachedView(emptyItems);
}
/**
* Clears all views
*/
public void clearAll() {
if (items != null) {
items.clear();
}
if (emptyItems != null) {
emptyItems.clear();
}
}
/**
* Adds view to specified cache. Creates a cache list if it is null.
* @param view the view to be cached
* @param cache the cache list
* @return the cache list
*/
private List<View> addView(View view, List<View> cache) {
if (cache == null) {
cache = new LinkedList<View>();
}
cache.add(view);
return cache;
}
/**
* Adds view to cache. Determines view type (item view or empty one) by index.
* @param view the view to be cached
* @param index the index of view
*/
private void recycleView(View view, int index) {
int count = wheel.getViewAdapter().getItemsCount();
if ((index < 0 || index >= count) && !wheel.isCyclic()) {
// empty view
emptyItems = addView(view, emptyItems);
} else {
while (index < 0) {
index = count + index;
}
index %= count;
items = addView(view, items);
}
}
/**
* Gets view from specified cache.
* @param cache the cache
* @return the first view from cache.
*/
private View getCachedView(List<View> cache) {
if (cache != null && cache.size() > 0) {
View view = cache.get(0);
cache.remove(0);
return view;
}
return null;
}
}

View File

@@ -0,0 +1,252 @@
/*
* Android Wheel Control.
* https://code.google.com/p/android-wheel/
*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import android.widget.Scroller;
/**
* Scroller class handles scrolling events and updates the
*/
public class WheelScroller {
/**
* Scrolling listener interface
*/
public interface ScrollingListener {
/**
* Scrolling callback called when scrolling is performed.
* @param distance the distance to scroll
*/
void onScroll(int distance);
/**
* Starting callback called when scrolling is started
*/
void onStarted();
/**
* Finishing callback called after justifying
*/
void onFinished();
/**
* Justifying callback called to justify a view when scrolling is ended
*/
void onJustify();
}
/** Scrolling duration */
private static final int SCROLLING_DURATION = 400;
/** Minimum delta for scrolling */
public static final int MIN_DELTA_FOR_SCROLLING = 1;
// Listener
private ScrollingListener listener;
// Context
private Context context;
// Scrolling
private GestureDetector gestureDetector;
private Scroller scroller;
private int lastScrollY;
private float lastTouchedY;
private boolean isScrollingPerformed;
/**
* Constructor
* @param context the current context
* @param listener the scrolling listener
*/
public WheelScroller(Context context, ScrollingListener listener) {
gestureDetector = new GestureDetector(context, gestureListener);
gestureDetector.setIsLongpressEnabled(false);
scroller = new Scroller(context);
this.listener = listener;
this.context = context;
}
/**
* Set the the specified scrolling interpolator
* @param interpolator the interpolator
*/
public void setInterpolator(Interpolator interpolator) {
scroller.forceFinished(true);
scroller = new Scroller(context, interpolator);
}
/**
* Scroll the wheel
* @param distance the scrolling distance
* @param time the scrolling duration
*/
public void scroll(int distance, int time) {
scroller.forceFinished(true);
lastScrollY = 0;
scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION);
setNextMessage(MESSAGE_SCROLL);
startScrolling();
}
/**
* Stops scrolling
*/
public void stopScrolling() {
scroller.forceFinished(true);
}
/**
* Handles Touch event
* @param event the motion event
* @return
*/
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastTouchedY = event.getY();
scroller.forceFinished(true);
clearMessages();
break;
case MotionEvent.ACTION_MOVE:
// perform scrolling
int distanceY = (int)(event.getY() - lastTouchedY);
if (distanceY != 0) {
startScrolling();
listener.onScroll(distanceY);
lastTouchedY = event.getY();
}
break;
}
if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {
justify();
}
return true;
}
// gesture listener
private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// Do scrolling in onTouchEvent() since onScroll() are not call immediately
// when user touch and move the wheel
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
lastScrollY = 0;
final int maxY = 0x7FFFFFFF;
final int minY = -maxY;
scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY);
setNextMessage(MESSAGE_SCROLL);
return true;
}
};
// Messages
private final int MESSAGE_SCROLL = 0;
private final int MESSAGE_JUSTIFY = 1;
/**
* Set next message to queue. Clears queue before.
*
* @param message the message to set
*/
private void setNextMessage(int message) {
clearMessages();
animationHandler.sendEmptyMessage(message);
}
/**
* Clears messages from queue
*/
private void clearMessages() {
animationHandler.removeMessages(MESSAGE_SCROLL);
animationHandler.removeMessages(MESSAGE_JUSTIFY);
}
// animation handler
private Handler animationHandler = new Handler() {
public void handleMessage(Message msg) {
scroller.computeScrollOffset();
int currY = scroller.getCurrY();
int delta = lastScrollY - currY;
lastScrollY = currY;
if (delta != 0) {
listener.onScroll(delta);
}
// scrolling is not finished when it comes to final Y
// so, finish it manually
if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
currY = scroller.getFinalY();
scroller.forceFinished(true);
}
if (!scroller.isFinished()) {
animationHandler.sendEmptyMessage(msg.what);
} else if (msg.what == MESSAGE_SCROLL) {
justify();
} else {
finishScrolling();
}
}
};
/**
* Justifies wheel
*/
private void justify() {
listener.onJustify();
setNextMessage(MESSAGE_JUSTIFY);
}
/**
* Starts scrolling
*/
private void startScrolling() {
if (!isScrollingPerformed) {
isScrollingPerformed = true;
listener.onStarted();
}
}
/**
* Finishes scrolling
*/
void finishScrolling() {
if (isScrollingPerformed) {
listener.onFinished();
isScrollingPerformed = false;
}
}
}

View File

@@ -0,0 +1,1058 @@
/*
* Android Wheel Control.
* https://code.google.com/p/android-wheel/
*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import com.lljjcoder.style.citypickerview.R;
import com.lljjcoder.style.citypickerview.widget.wheel.adapters.WheelViewAdapter;
import java.util.LinkedList;
import java.util.List;
/**
* Numeric wheel view.
*
* @author Yuri Kanivets
*/
public class WheelView extends View {
/**
* 滚轮从上到下背景逐渐变淡,到中间,逆反改变
*/
private int[] SHADOWS_COLORS = new int[] { 0xefF9F9F9, 0xcfF9F9F9, 0x3fF9F9F9 };
/**
* Top and bottom items offset (to hide that)
*/
private static final int ITEM_OFFSET_PERCENT = 0;
/**
* 滚轮左右间隔距离
*/
private static final int PADDING = 5;
/**
* 滚轮显示的item个数
*/
private static final int DEF_VISIBLE_ITEMS = 5;
// Wheel Values
private int currentItem = 0;
// Count of visible items
private int visibleItems = DEF_VISIBLE_ITEMS;
// Item height
private int itemHeight = 0;
// Center Line
private Drawable centerDrawable;
// Wheel drawables
private int wheelBackground = R.drawable.wheel_bg;
private int wheelForeground = R.drawable.wheel_val;
// Shadows drawables
private GradientDrawable topShadow;
private GradientDrawable bottomShadow;
// Draw Shadows
private boolean drawShadows = true;
// Scrolling
private WheelScroller scroller;
private boolean isScrollingPerformed;
private int scrollingOffset;
/**
* 滚轮是否循环滚动
*/
boolean isCyclic = false;
// Items layout
private LinearLayout itemsLayout;
// The number of first item in layout
private int firstItem;
// View adapter
private WheelViewAdapter viewAdapter;
// Recycle
private WheelRecycle recycle = new WheelRecycle(this);
// Listeners
private List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();
private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();
private List<OnWheelClickedListener> clickingListeners = new LinkedList<OnWheelClickedListener>();
/**
* 中间线的颜色
*/
private String lineColorStr = "#C7C7C7";
/**
* 中间线的宽度
*/
private int lineWidth = 3;
/**
* Constructor
*/
public WheelView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initData(context);
}
/**
* Constructor
*/
public WheelView(Context context, AttributeSet attrs) {
super(context, attrs);
initData(context);
}
/**
* Constructor
*/
public WheelView(Context context) {
super(context);
initData(context);
}
/**
* Initializes class data
*
* @param context the context
*/
private void initData(Context context) {
scroller = new WheelScroller(getContext(), scrollingListener);
}
// Scrolling listener
WheelScroller.ScrollingListener scrollingListener = new WheelScroller.ScrollingListener() {
@Override
public void onStarted() {
isScrollingPerformed = true;
notifyScrollingListenersAboutStart();
}
@Override
public void onScroll(int distance) {
doScroll(distance);
int height = getHeight();
if (scrollingOffset > height) {
scrollingOffset = height;
scroller.stopScrolling();
}
else if (scrollingOffset < -height) {
scrollingOffset = -height;
scroller.stopScrolling();
}
}
@Override
public void onFinished() {
if (isScrollingPerformed) {
notifyScrollingListenersAboutEnd();
isScrollingPerformed = false;
}
scrollingOffset = 0;
invalidate();
}
@Override
public void onJustify() {
if (Math.abs(scrollingOffset) > WheelScroller.MIN_DELTA_FOR_SCROLLING) {
scroller.scroll(scrollingOffset, 0);
}
}
};
public String getLineColorStr() {
return lineColorStr == null ? "" : lineColorStr;
}
public void setLineColorStr(String lineColorStr) {
this.lineColorStr = lineColorStr;
}
public int getLineWidth() {
return lineWidth;
}
public void setLineWidth(int lineWidth) {
this.lineWidth = lineWidth;
}
/**
* Set the the specified scrolling interpolator
*
* @param interpolator the interpolator
*/
public void setInterpolator(Interpolator interpolator) {
scroller.setInterpolator(interpolator);
}
/**
* Gets count of visible items
*
* @return the count of visible items
*/
public int getVisibleItems() {
return visibleItems;
}
/**
* Sets the desired count of visible items.
* Actual amount of visible items depends on wheel layout parameters.
* To apply changes and rebuild view call measure().
*
* @param count the desired count for visible items
*/
public void setVisibleItems(int count) {
visibleItems = count;
}
/**
* Gets view adapter
*
* @return the view adapter
*/
public WheelViewAdapter getViewAdapter() {
return viewAdapter;
}
// Adapter listener
private DataSetObserver dataObserver = new DataSetObserver() {
@Override
public void onChanged() {
invalidateWheel(false);
}
@Override
public void onInvalidated() {
invalidateWheel(true);
}
};
/**
* Sets view adapter. Usually new adapters contain different views, so
* it needs to rebuild view by calling measure().
*
* @param viewAdapter the view adapter
*/
public void setViewAdapter(WheelViewAdapter viewAdapter) {
if (this.viewAdapter != null) {
this.viewAdapter.unregisterDataSetObserver(dataObserver);
}
this.viewAdapter = viewAdapter;
if (this.viewAdapter != null) {
this.viewAdapter.registerDataSetObserver(dataObserver);
}
invalidateWheel(true);
}
/**
* Adds wheel changing listener
*
* @param listener the listener
*/
public void addChangingListener(OnWheelChangedListener listener) {
changingListeners.add(listener);
}
/**
* Removes wheel changing listener
*
* @param listener the listener
*/
public void removeChangingListener(OnWheelChangedListener listener) {
changingListeners.remove(listener);
}
/**
* Notifies changing listeners
*
* @param oldValue the old wheel value
* @param newValue the new wheel value
*/
protected void notifyChangingListeners(int oldValue, int newValue) {
for (OnWheelChangedListener listener : changingListeners) {
listener.onChanged(this, oldValue, newValue);
}
}
/**
* Adds wheel scrolling listener
*
* @param listener the listener
*/
public void addScrollingListener(OnWheelScrollListener listener) {
scrollingListeners.add(listener);
}
/**
* Removes wheel scrolling listener
*
* @param listener the listener
*/
public void removeScrollingListener(OnWheelScrollListener listener) {
scrollingListeners.remove(listener);
}
/**
* Notifies listeners about starting scrolling
*/
protected void notifyScrollingListenersAboutStart() {
for (OnWheelScrollListener listener : scrollingListeners) {
listener.onScrollingStarted(this);
}
}
/**
* Notifies listeners about ending scrolling
*/
protected void notifyScrollingListenersAboutEnd() {
for (OnWheelScrollListener listener : scrollingListeners) {
listener.onScrollingFinished(this);
}
}
/**
* Adds wheel clicking listener
*
* @param listener the listener
*/
public void addClickingListener(OnWheelClickedListener listener) {
clickingListeners.add(listener);
}
/**
* Removes wheel clicking listener
*
* @param listener the listener
*/
public void removeClickingListener(OnWheelClickedListener listener) {
clickingListeners.remove(listener);
}
/**
* Notifies listeners about clicking
*/
protected void notifyClickListenersAboutClick(int item) {
for (OnWheelClickedListener listener : clickingListeners) {
listener.onItemClicked(this, item);
}
}
/**
* Gets current value
*
* @return the current value
*/
public int getCurrentItem() {
return currentItem;
}
/**
* Sets the current item. Does nothing when index is wrong.
*
* @param index the item index
* @param animated the animation flag
*/
public void setCurrentItem(int index, boolean animated) {
if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
return; // throw?
}
int itemCount = viewAdapter.getItemsCount();
if (index < 0 || index >= itemCount) {
if (isCyclic) {
while (index < 0) {
index += itemCount;
}
index %= itemCount;
}
else {
return; // throw?
}
}
if (index != currentItem) {
if (animated) {
int itemsToScroll = index - currentItem;
if (isCyclic) {
int scroll = itemCount + Math.min(index, currentItem) - Math.max(index, currentItem);
if (scroll < Math.abs(itemsToScroll)) {
itemsToScroll = itemsToScroll < 0 ? scroll : -scroll;
}
}
scroll(itemsToScroll, 0);
}
else {
scrollingOffset = 0;
int old = currentItem;
currentItem = index;
notifyChangingListeners(old, currentItem);
invalidate();
}
}
}
/**
* Sets the current item w/o animation. Does nothing when index is wrong.
*
* @param index the item index
*/
public void setCurrentItem(int index) {
setCurrentItem(index, false);
}
/**
* Tests if wheel is cyclic. That means before the 1st item there is shown the last one
*
* @return true if wheel is cyclic
*/
public boolean isCyclic() {
return isCyclic;
}
/**
* Set wheel cyclic flag
*
* @param isCyclic the flag to set
*/
public void setCyclic(boolean isCyclic) {
this.isCyclic = isCyclic;
invalidateWheel(false);
}
/**
* Determine whether shadows are drawn
*
* @return true is shadows are drawn
*/
public boolean drawShadows() {
return drawShadows;
}
/**
* Set whether shadows should be drawn
*
* @param drawShadows flag as true or false
*/
public void setDrawShadows(boolean drawShadows) {
this.drawShadows = drawShadows;
}
/**
* Set the shadow gradient color
*
* @param start
* @param middle
* @param end
*/
public void setShadowColor(int start, int middle, int end) {
SHADOWS_COLORS = new int[] { start, middle, end };
}
/**
* Sets the drawable for the wheel background
*
* @param resource
*/
public void setWheelBackground(int resource) {
wheelBackground = resource;
setBackgroundResource(wheelBackground);
}
/**
* Sets the drawable for the wheel foreground
*
* @param resource
*/
public void setWheelForeground(int resource) {
wheelForeground = resource;
centerDrawable = getContext().getResources().getDrawable(wheelForeground);
}
/**
* Invalidates wheel
*
* @param clearCaches if true then cached views will be clear
*/
public void invalidateWheel(boolean clearCaches) {
if (clearCaches) {
recycle.clearAll();
if (itemsLayout != null) {
itemsLayout.removeAllViews();
}
scrollingOffset = 0;
}
else if (itemsLayout != null) {
// cache all items
recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
}
invalidate();
}
/**
* Initializes resources
*/
private void initResourcesIfNecessary() {
if (centerDrawable == null) {
centerDrawable = getContext().getResources().getDrawable(wheelForeground);
}
if (topShadow == null) {
topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);
}
if (bottomShadow == null) {
bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);
}
setBackgroundResource(wheelBackground);
}
/**
* Calculates desired height for layout
*
* @param layout the source layout
* @return the desired layout height
*/
private int getDesiredHeight(LinearLayout layout) {
if (layout != null && layout.getChildAt(0) != null) {
itemHeight = layout.getChildAt(0).getMeasuredHeight();
}
int desired = itemHeight * visibleItems - itemHeight * ITEM_OFFSET_PERCENT / 50;
return Math.max(desired, getSuggestedMinimumHeight());
}
/**
* Returns height of wheel item
*
* @return the item height
*/
private int getItemHeight() {
if (itemHeight != 0) {
return itemHeight;
}
if (itemsLayout != null && itemsLayout.getChildAt(0) != null) {
itemHeight = itemsLayout.getChildAt(0).getHeight();
return itemHeight;
}
return getHeight() / visibleItems;
}
/**
* Calculates control width and creates text layouts
*
* @param widthSize the input layout width
* @param mode the layout mode
* @return the calculated control width
*/
private int calculateLayoutWidth(int widthSize, int mode) {
initResourcesIfNecessary();
// TODO: make it static
itemsLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
itemsLayout.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int width = itemsLayout.getMeasuredWidth();
if (mode == MeasureSpec.EXACTLY) {
width = widthSize;
}
else {
width += 2 * PADDING;
// Check against our minimum width
width = Math.max(width, getSuggestedMinimumWidth());
if (mode == MeasureSpec.AT_MOST && widthSize < width) {
width = widthSize;
}
}
itemsLayout.measure(MeasureSpec.makeMeasureSpec(width - 2 * PADDING, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
return width;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
buildViewForMeasuring();
int width = calculateLayoutWidth(widthSize, widthMode);
int height;
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
}
else {
height = getDesiredHeight(itemsLayout);
if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, heightSize);
}
}
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
layout(r - l, b - t);
}
/**
* Sets layouts width and height
*
* @param width the layout width
* @param height the layout height
*/
private void layout(int width, int height) {
int itemsWidth = width - 2 * PADDING;
itemsLayout.layout(0, 0, itemsWidth, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (viewAdapter != null && viewAdapter.getItemsCount() > 0) {
updateView();
drawItems(canvas);
drawCenterRect(canvas);
}
if (drawShadows)
drawShadows(canvas);
}
/**
* Draws shadows on top and bottom of control
*
* @param canvas the canvas for drawing
*/
private void drawShadows(Canvas canvas) {
/*/ Modified by wulianghuan 2014-11-25
int height = (int)(1.5 * getItemHeight());
//*/
//从中间到顶部渐变处理
int count = getVisibleItems() == 2 ? 1 : getVisibleItems() / 2;
int height = (int) (count * getItemHeight());
topShadow.setBounds(0, 0, getWidth(), height);
topShadow.draw(canvas);
bottomShadow.setBounds(0, getHeight() - height, getWidth(), getHeight());
bottomShadow.draw(canvas);
}
/**
* Draws items
*
* @param canvas the canvas for drawing
*/
private void drawItems(Canvas canvas) {
canvas.save();
int top = (currentItem - firstItem) * getItemHeight() + (getItemHeight() - getHeight()) / 2;
canvas.translate(PADDING, -top + scrollingOffset);
itemsLayout.draw(canvas);
canvas.restore();
}
/**
* Draws rect for current value
*
* @param canvas the canvas for drawing
*/
private void drawCenterRect(Canvas canvas) {
int center = getHeight() / 2;
int offset = (int) (getItemHeight() / 2 * 1.2);
/*/ Remarked by wulianghuan 2014-11-27 使用自己的画线,而不是描边
Rect rect = new Rect(left, top, right, bottom)
centerDrawable.setBounds(bounds)
centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);
centerDrawable.draw(canvas);
//*/
Paint paint = new Paint();
if (getLineColorStr().startsWith("#")) {
paint.setColor(Color.parseColor(getLineColorStr()));
}
else {
paint.setColor(Color.parseColor("#" + getLineColorStr()));
}
// 设置线宽
if (getLineWidth() > 3) {
paint.setStrokeWidth((float) getLineWidth());
}
else {
paint.setStrokeWidth((float) 3);
}
// 绘制上边直线
canvas.drawLine(0, center - offset, getWidth(), center - offset, paint);
// 绘制下边直线
canvas.drawLine(0, center + offset, getWidth(), center + offset, paint);
//*/
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled() || getViewAdapter() == null) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
if (!isScrollingPerformed) {
int distance = (int) event.getY() - getHeight() / 2;
if (distance > 0) {
distance += getItemHeight() / 2;
}
else {
distance -= getItemHeight() / 2;
}
int items = distance / getItemHeight();
if (items != 0 && isValidItemIndex(currentItem + items)) {
notifyClickListenersAboutClick(currentItem + items);
}
}
break;
}
return scroller.onTouchEvent(event);
}
/**
* Scrolls the wheel
*
* @param delta the scrolling value
*/
private void doScroll(int delta) {
scrollingOffset += delta;
int itemHeight = getItemHeight();
int count = scrollingOffset / itemHeight;
int pos = currentItem - count;
int itemCount = viewAdapter.getItemsCount();
int fixPos = scrollingOffset % itemHeight;
if (Math.abs(fixPos) <= itemHeight / 2) {
fixPos = 0;
}
if (isCyclic && itemCount > 0) {
if (fixPos > 0) {
pos--;
count++;
}
else if (fixPos < 0) {
pos++;
count--;
}
// fix position by rotating
while (pos < 0) {
pos += itemCount;
}
pos %= itemCount;
}
else {
//
if (pos < 0) {
count = currentItem;
pos = 0;
}
else if (pos >= itemCount) {
count = currentItem - itemCount + 1;
pos = itemCount - 1;
}
else if (pos > 0 && fixPos > 0) {
pos--;
count++;
}
else if (pos < itemCount - 1 && fixPos < 0) {
pos++;
count--;
}
}
int offset = scrollingOffset;
if (pos != currentItem) {
setCurrentItem(pos, false);
}
else {
invalidate();
}
// update offset
scrollingOffset = offset - count * itemHeight;
if (scrollingOffset > getHeight()) {
scrollingOffset = scrollingOffset % getHeight() + getHeight();
}
}
/**
* Scroll the wheel
*
* @param time scrolling duration
*/
public void scroll(int itemsToScroll, int time) {
int distance = itemsToScroll * getItemHeight() - scrollingOffset;
scroller.scroll(distance, time);
}
/**
* Calculates range for wheel items
*
* @return the items range
*/
private ItemsRange getItemsRange() {
if (getItemHeight() == 0) {
return null;
}
int first = currentItem;
int count = 1;
while (count * getItemHeight() < getHeight()) {
first--;
count += 2; // top + bottom items
}
if (scrollingOffset != 0) {
if (scrollingOffset > 0) {
first--;
}
count++;
// process empty items above the first or below the second
int emptyItems = scrollingOffset / getItemHeight();
first -= emptyItems;
count += Math.asin(emptyItems);
}
return new ItemsRange(first, count);
}
/**
* Rebuilds wheel items if necessary. Caches all unused items.
*
* @return true if items are rebuilt
*/
private boolean rebuildItems() {
boolean updated = false;
ItemsRange range = getItemsRange();
if (itemsLayout != null) {
int first = recycle.recycleItems(itemsLayout, firstItem, range);
updated = firstItem != first;
firstItem = first;
}
else {
createItemsLayout();
updated = true;
}
if (!updated) {
updated = firstItem != range.getFirst() || itemsLayout.getChildCount() != range.getCount();
}
if (firstItem > range.getFirst() && firstItem <= range.getLast()) {
for (int i = firstItem - 1; i >= range.getFirst(); i--) {
if (!addViewItem(i, true)) {
break;
}
firstItem = i;
}
}
else {
firstItem = range.getFirst();
}
int first = firstItem;
for (int i = itemsLayout.getChildCount(); i < range.getCount(); i++) {
if (!addViewItem(firstItem + i, false) && itemsLayout.getChildCount() == 0) {
first++;
}
}
firstItem = first;
return updated;
}
/**
* Updates view. Rebuilds items and label if necessary, recalculate items sizes.
*/
private void updateView() {
if (rebuildItems()) {
calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);
layout(getWidth(), getHeight());
}
}
/**
* Creates item layouts if necessary
*/
private void createItemsLayout() {
if (itemsLayout == null) {
itemsLayout = new LinearLayout(getContext());
itemsLayout.setOrientation(LinearLayout.VERTICAL);
}
}
/**
* Builds view for measuring
*/
private void buildViewForMeasuring() {
// clear all items
if (itemsLayout != null) {
recycle.recycleItems(itemsLayout, firstItem, new ItemsRange());
}
else {
createItemsLayout();
}
// add views
int addItems = visibleItems / 2;
for (int i = currentItem + addItems; i >= currentItem - addItems; i--) {
if (addViewItem(i, true)) {
firstItem = i;
}
}
}
/**
* Adds view for item to items layout
*
* @param index the item index
* @param first the flag indicates if view should be first
* @return true if corresponding item exists and is added
*/
private boolean addViewItem(int index, boolean first) {
View view = getItemView(index);
if (view != null) {
if (first) {
itemsLayout.addView(view, 0);
}
else {
itemsLayout.addView(view);
}
return true;
}
return false;
}
/**
* Checks whether intem index is valid
*
* @param index the item index
* @return true if item index is not out of bounds or the wheel is cyclic
*/
private boolean isValidItemIndex(int index) {
return viewAdapter != null && viewAdapter.getItemsCount() > 0
&& (isCyclic || index >= 0 && index < viewAdapter.getItemsCount());
}
/**
* Returns view for specified item
*
* @param index the item index
* @return item view or empty view if index is out of bounds
*/
private View getItemView(int index) {
if (viewAdapter == null || viewAdapter.getItemsCount() == 0) {
return null;
}
int count = viewAdapter.getItemsCount();
if (!isValidItemIndex(index)) {
return viewAdapter.getEmptyItem(recycle.getEmptyItem(), itemsLayout);
}
else {
while (index < 0) {
index = count + index;
}
}
index %= count;
return viewAdapter.getItem(index, recycle.getItem(), itemsLayout);
}
/**
* Stops scrolling
*/
public void stopScrolling() {
scroller.stopScrolling();
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel.adapters;
import java.util.LinkedList;
import java.util.List;
import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
/**
* Abstract Wheel adapter.
*/
public abstract class AbstractWheelAdapter implements WheelViewAdapter {
// Observers
private List<DataSetObserver> datasetObservers;
@Override
public View getEmptyItem(View convertView, ViewGroup parent) {
return null;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
if (datasetObservers == null) {
datasetObservers = new LinkedList<DataSetObserver>();
}
datasetObservers.add(observer);
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
if (datasetObservers != null) {
datasetObservers.remove(observer);
}
}
/**
* Notifies observers about data changing
*/
protected void notifyDataChangedEvent() {
if (datasetObservers != null) {
for (DataSetObserver observer : datasetObservers) {
observer.onChanged();
}
}
}
/**
* Notifies observers about invalidating data
*/
protected void notifyDataInvalidatedEvent() {
if (datasetObservers != null) {
for (DataSetObserver observer : datasetObservers) {
observer.onInvalidated();
}
}
}
}

View File

@@ -0,0 +1,286 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel.adapters;
import android.content.Context;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Abstract wheel adapter provides common functionality for adapters.
*/
public abstract class AbstractWheelTextAdapter extends AbstractWheelAdapter {
/** Text view resource. Used as a default view for adapter. */
public static final int TEXT_VIEW_ITEM_RESOURCE = -1;
/** No resource constant. */
protected static final int NO_RESOURCE = 0;
/** Default text color */
public static final int DEFAULT_TEXT_COLOR = 0xFF585858;
/** Default text color */
public static final int LABEL_COLOR = 0xFF700070;
/** Default text size */
public static final int DEFAULT_TEXT_SIZE = 18;
// Text settings
private int textColor = DEFAULT_TEXT_COLOR;
private int textSize = DEFAULT_TEXT_SIZE;
private int padding = 5;
// Current context
protected Context context;
// Layout inflater
protected LayoutInflater inflater;
// Items resources
protected int itemResourceId;
protected int itemTextResourceId;
// Empty items resources
protected int emptyItemResourceId;
/**
* Constructor
* @param context the current context
*/
protected AbstractWheelTextAdapter(Context context) {
this(context, TEXT_VIEW_ITEM_RESOURCE);
}
/**
* Constructor
* @param context the current context
* @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views
*/
protected AbstractWheelTextAdapter(Context context, int itemResource) {
this(context, itemResource, NO_RESOURCE);
}
/**
* Constructor
* @param context the current context
* @param itemResource the resource ID for a layout file containing a TextView to use when instantiating items views
* @param itemTextResource the resource ID for a text view in the item layout
*/
protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource) {
this.context = context;
itemResourceId = itemResource;
itemTextResourceId = itemTextResource;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* Gets text color
* @return the text color
*/
public int getTextColor() {
return textColor;
}
/**
* Sets text color
* @param textColor the text color to set
*/
public void setTextColor(int textColor) {
this.textColor = textColor;
}
/**
* item间距
* @return
*/
public int getPadding() {
return padding;
}
public void setPadding(int padding) {
this.padding = padding;
}
/**
* Gets text size
* @return the text size
*/
public int getTextSize() {
return textSize;
}
/**
* Sets text size
* @param textSize the text size to set
*/
public void setTextSize(int textSize) {
this.textSize = textSize;
}
/**
* Gets resource Id for items views
* @return the item resource Id
*/
public int getItemResource() {
return itemResourceId;
}
/**
* Sets resource Id for items views
* @param itemResourceId the resource Id to set
*/
public void setItemResource(int itemResourceId) {
this.itemResourceId = itemResourceId;
}
/**
* Gets resource Id for text view in item layout
* @return the item text resource Id
*/
public int getItemTextResource() {
return itemTextResourceId;
}
/**
* Sets resource Id for text view in item layout
* @param itemTextResourceId the item text resource Id to set
*/
public void setItemTextResource(int itemTextResourceId) {
this.itemTextResourceId = itemTextResourceId;
}
/**
* Gets resource Id for empty items views
* @return the empty item resource Id
*/
public int getEmptyItemResource() {
return emptyItemResourceId;
}
/**
* Sets resource Id for empty items views
* @param emptyItemResourceId the empty item resource Id to set
*/
public void setEmptyItemResource(int emptyItemResourceId) {
this.emptyItemResourceId = emptyItemResourceId;
}
/**
* Returns text for specified item
* @param index the item index
* @return the text of specified items
*/
protected abstract CharSequence getItemText(int index);
@Override
public View getItem(int index, View convertView, ViewGroup parent) {
if (index >= 0 && index < getItemsCount()) {
if (convertView == null) {
convertView = getView(itemResourceId, parent);
}
TextView textView = getTextView(convertView, itemTextResourceId);
if (textView != null) {
CharSequence text = getItemText(index);
if (text == null) {
text = "";
}
textView.setText(text);
if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) {
configureTextView(textView);
}
}
return convertView;
}
return null;
}
@Override
public View getEmptyItem(View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getView(emptyItemResourceId, parent);
}
if (emptyItemResourceId == TEXT_VIEW_ITEM_RESOURCE && convertView instanceof TextView) {
configureTextView((TextView) convertView);
}
return convertView;
}
/**
* Configures text view. Is called for the TEXT_VIEW_ITEM_RESOURCE views.
* @param view the text view to be configured
*/
protected void configureTextView(TextView view) {
view.setTextColor(textColor);
view.setGravity(Gravity.CENTER);
view.setPadding(0, padding, 0, padding);
view.setTextSize(textSize);
// view.setEllipsize(TextUtils.TruncateAt.END);
// view.setLines(1);
// view.setCompoundDrawablePadding(20);
// view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
}
/**
* Loads a text view from view
* @param view the text view or layout containing it
* @param textResource the text resource Id in layout
* @return the loaded text view
*/
private TextView getTextView(View view, int textResource) {
TextView text = null;
try {
if (textResource == NO_RESOURCE && view instanceof TextView) {
text = (TextView) view;
}
else if (textResource != NO_RESOURCE) {
text = (TextView) view.findViewById(textResource);
}
}
catch (ClassCastException e) {
Log.e("AbstractWheelAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException("AbstractWheelAdapter requires the resource ID to be a TextView", e);
}
return text;
}
/**
* Loads view from resources
* @param resource the resource Id
* @return the loaded view or null if resource is not set
*/
private View getView(int resource, ViewGroup parent) {
switch (resource) {
case NO_RESOURCE:
return null;
case TEXT_VIEW_ITEM_RESOURCE:
return new TextView(context);
default:
return inflater.inflate(resource, parent, false);
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel.adapters;
import android.content.Context;
import com.lljjcoder.style.citypickerview.widget.wheel.WheelAdapter;
/**
* Adapter class for old wheel adapter (deprecated WheelAdapter class).
*
* @deprecated Will be removed soon
*/
public class AdapterWheel extends AbstractWheelTextAdapter {
// Source adapter
private WheelAdapter adapter;
/**
* Constructor
* @param context the current context
* @param adapter the source adapter
*/
public AdapterWheel(Context context, WheelAdapter adapter) {
super(context);
this.adapter = adapter;
}
/**
* Gets original adapter
* @return the original adapter
*/
public WheelAdapter getAdapter() {
return adapter;
}
@Override
public int getItemsCount() {
return adapter.getItemsCount();
}
@Override
protected CharSequence getItemText(int index) {
return adapter.getItem(index);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel.adapters;
import android.content.Context;
import java.util.List;
/**
* The simple Array wheel adapter
*
* @param <T> the element type
*/
public class ArrayWheelAdapter<T> extends AbstractWheelTextAdapter {
// items
private List<T> items;
/**
* Constructor
*
* @param context the current context
* @param items the items
*/
public ArrayWheelAdapter(Context context, List<T> items) {
super(context);
//setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE);
this.items = items;
}
@Override
public CharSequence getItemText(int index) {
if (index >= 0 && index < items.size()) {
T item = items.get(index);
if (item instanceof CharSequence) {
return (CharSequence) item;
}
return item.toString();
}
return null;
}
@Override
public int getItemsCount() {
return items.size();
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel.adapters;
import android.content.Context;
/**
* Numeric Wheel adapter.
*/
public class NumericWheelAdapter extends AbstractWheelTextAdapter {
/** The default min value */
public static final int DEFAULT_MAX_VALUE = 9;
/** The default max value */
private static final int DEFAULT_MIN_VALUE = 0;
// Values
private int minValue;
private int maxValue;
// format
private String format;
/**
* Constructor
* @param context the current context
*/
public NumericWheelAdapter(Context context) {
this(context, DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE);
}
/**
* Constructor
* @param context the current context
* @param minValue the wheel min value
* @param maxValue the wheel max value
*/
public NumericWheelAdapter(Context context, int minValue, int maxValue) {
this(context, minValue, maxValue, null);
}
/**
* Constructor
* @param context the current context
* @param minValue the wheel min value
* @param maxValue the wheel max value
* @param format the format string
*/
public NumericWheelAdapter(Context context, int minValue, int maxValue, String format) {
super(context);
this.minValue = minValue;
this.maxValue = maxValue;
this.format = format;
}
@Override
public CharSequence getItemText(int index) {
if (index >= 0 && index < getItemsCount()) {
int value = minValue + index;
return format != null ? String.format(format, value) : Integer.toString(value);
}
return null;
}
@Override
public int getItemsCount() {
return maxValue - minValue + 1;
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2011 Yuri Kanivets
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lljjcoder.style.citypickerview.widget.wheel.adapters;
import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
/**
* Wheel items adapter interface
*/
public interface WheelViewAdapter {
/**
* Gets items count
* @return the count of wheel items
*/
public int getItemsCount();
/**
* Get a View that displays the data at the specified position in the data set
*
* @param index the item index
* @param convertView the old view to reuse if possible
* @param parent the parent that this view will eventually be attached to
* @return the wheel item View
*/
public View getItem(int index, View convertView, ViewGroup parent);
/**
* Get a View that displays an empty wheel item placed before the first or after
* the last wheel item.
*
* @param convertView the old view to reuse if possible
* @param parent the parent that this view will eventually be attached to
* @return the empty item View
*/
public View getEmptyItem(View convertView, ViewGroup parent);
/**
* Register an observer that is called when changes happen to the data used by this adapter.
* @param observer the observer to be registered
*/
public void registerDataSetObserver(DataSetObserver observer);
/**
* Unregister an observer that has previously been registered
* @param observer the observer to be unregistered
*/
void unregisterDataSetObserver(DataSetObserver observer);
}

View File

@@ -0,0 +1,93 @@
package com.lljjcoder.style.citythreelist;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
import com.lljjcoder.style.citypickerview.R;
import com.lljjcoder.widget.RecycleViewDividerForList;
import java.util.List;
import static com.lljjcoder.style.citylist.utils.CityListLoader.BUNDATA;
import static com.lljjcoder.style.citythreelist.ProvinceActivity.RESULT_DATA;
public class AreaActivity extends Activity {
private TextView mCityNameTv;
private ImageView mImgBack;
private RecyclerView mCityRecyclerView;
private CityInfoBean mProCityInfo = null;
private CityBean areaBean = new CityBean();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_citylist);
mProCityInfo = this.getIntent().getParcelableExtra(BUNDATA);
initView();
setData();
}
private void setData() {
if (mProCityInfo != null && mProCityInfo.getCityList().size() > 0) {
mCityNameTv.setText("" + mProCityInfo.getName());
final List<CityInfoBean> cityList = mProCityInfo.getCityList();
if (cityList == null) {
return;
}
CityAdapter cityAdapter = new CityAdapter(AreaActivity.this, cityList);
mCityRecyclerView.setAdapter(cityAdapter);
cityAdapter.setOnItemClickListener(new CityAdapter.OnItemSelectedListener() {
@Override
public void onItemSelected(View view, int position) {
areaBean.setName(cityList.get(position).getName());
areaBean.setId(cityList.get(position).getId());
//将计算的结果回传给第一个Activity
Intent reReturnIntent = new Intent();
reReturnIntent.putExtra("area", areaBean);
setResult(RESULT_DATA, reReturnIntent);
//退出第二个Activity
AreaActivity.this.finish();
}
});
}
}
private void initView() {
mImgBack = (ImageView) findViewById(R.id.img_left);
mCityNameTv = (TextView) findViewById(R.id.cityname_tv);
mImgBack.setVisibility(View.VISIBLE);
mImgBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mCityRecyclerView = (RecyclerView) findViewById(R.id.city_recyclerview);
mCityRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mCityRecyclerView.addItemDecoration(new RecycleViewDividerForList(this, LinearLayoutManager.HORIZONTAL, true));
}
}

View File

@@ -0,0 +1,111 @@
package com.lljjcoder.style.citythreelist;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
import com.lljjcoder.style.citypickerview.R;
import com.lljjcoder.widget.RecycleViewDividerForList;
import java.util.List;
import static com.lljjcoder.style.citylist.utils.CityListLoader.BUNDATA;
import static com.lljjcoder.style.citythreelist.ProvinceActivity.RESULT_DATA;
public class CityActivity extends Activity {
private TextView mCityNameTv;
private ImageView mImgBack;
private RecyclerView mCityRecyclerView;
private CityInfoBean mProInfo = null;
private String cityName = "";
private CityBean cityBean = new CityBean();
private CityBean area = new CityBean();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_citylist);
mProInfo = this.getIntent().getParcelableExtra(BUNDATA);
initView();
setData(mProInfo);
}
private void setData(CityInfoBean mProInfo) {
if (mProInfo != null && mProInfo.getCityList().size() > 0) {
mCityNameTv.setText("" + mProInfo.getName());
final List<CityInfoBean> cityList = mProInfo.getCityList();
if (cityList == null) {
return;
}
CityAdapter cityAdapter = new CityAdapter(CityActivity.this, cityList);
mCityRecyclerView.setAdapter(cityAdapter);
cityAdapter.setOnItemClickListener(new CityAdapter.OnItemSelectedListener() {
@Override
public void onItemSelected(View view, int position) {
cityBean.setId(cityList.get(position).getId());
cityBean.setName(cityList.get(position).getName());
Intent intent = new Intent(CityActivity.this, AreaActivity.class);
intent.putExtra(BUNDATA, cityList.get(position));
startActivityForResult(intent, RESULT_DATA);
}
});
}
}
private void initView() {
mImgBack = (ImageView) findViewById(R.id.img_left);
mCityNameTv = (TextView) findViewById(R.id.cityname_tv);
mImgBack.setVisibility(View.VISIBLE);
mImgBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mCityNameTv = (TextView) findViewById(R.id.cityname_tv);
mCityRecyclerView = (RecyclerView) findViewById(R.id.city_recyclerview);
mCityRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mCityRecyclerView.addItemDecoration(new RecycleViewDividerForList(this, LinearLayoutManager.HORIZONTAL, true));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_DATA && data != null) {
area = data.getParcelableExtra("area");
Intent intent = new Intent();
intent.putExtra("city", cityBean);
intent.putExtra("area", area);
setResult(RESULT_OK, intent);
finish();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}

View File

@@ -0,0 +1,83 @@
package com.lljjcoder.style.citythreelist;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
import com.lljjcoder.style.citypickerview.R;
import java.util.ArrayList;
import java.util.List;
/**
* 作者liji on 2017/12/16 15:13
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityAdapter extends RecyclerView.Adapter<CityAdapter.MyViewHolder> {
List<CityInfoBean> cityList = new ArrayList<>();
Context context;
private OnItemSelectedListener mOnItemClickListener;
public void setOnItemClickListener(OnItemSelectedListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public interface OnItemSelectedListener {
/**
* item点击事件
*
* @param view
* @param position
*/
void onItemSelected(View view, int position);
}
public CityAdapter(Context context, List<CityInfoBean> cityList) {
this.cityList = cityList;
this.context = context;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(
LayoutInflater.from(context).inflate(R.layout.item_citylist, parent, false));
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tv.setText(cityList.get(position).getName());
holder.tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickListener != null && position < cityList.size()) {
mOnItemClickListener.onItemSelected(v, position);
}
}
});
}
@Override
public int getItemCount() {
return cityList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public MyViewHolder(View view) {
super(view);
tv = (TextView) view.findViewById(R.id.default_item_city_name_tv);
}
}
}

View File

@@ -0,0 +1,63 @@
package com.lljjcoder.style.citythreelist;
import android.os.Parcel;
import android.os.Parcelable;
/**
* 作者liji on 2018/3/20 10:57
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class CityBean implements Parcelable {
private String id; /*110101*/
private String name; /*东城区*/
public String getId() {
return id == null ? "" : id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name == null ? "" : name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.name);
}
public CityBean() {
}
protected CityBean(Parcel in) {
this.id = in.readString();
this.name = in.readString();
}
public static final Parcelable.Creator<CityBean> CREATOR = new Parcelable.Creator<CityBean>() {
@Override
public CityBean createFromParcel(Parcel source) {
return new CityBean(source);
}
@Override
public CityBean[] newArray(int size) {
return new CityBean[size];
}
};
}

View File

@@ -0,0 +1,88 @@
package com.lljjcoder.style.citythreelist;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.lljjcoder.style.citylist.bean.CityInfoBean;
import com.lljjcoder.style.citylist.utils.CityListLoader;
import com.lljjcoder.style.citypickerview.R;
import com.lljjcoder.widget.RecycleViewDividerForList;
import java.util.List;
import static com.lljjcoder.style.citylist.utils.CityListLoader.BUNDATA;
public class ProvinceActivity extends Activity {
private TextView mCityNameTv;
private RecyclerView mCityRecyclerView;
public static final int RESULT_DATA = 1001;
private CityBean provinceBean = new CityBean();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_citylist);
initView();
setData();
}
private void setData() {
final List<CityInfoBean> cityList = CityListLoader.getInstance().getProListData();
if (cityList == null) {
return;
}
CityAdapter cityAdapter = new CityAdapter(ProvinceActivity.this, cityList);
mCityRecyclerView.setAdapter(cityAdapter);
cityAdapter.setOnItemClickListener(new CityAdapter.OnItemSelectedListener() {
@Override
public void onItemSelected(View view, int position) {
provinceBean.setId(cityList.get(position).getId());
provinceBean.setName(cityList.get(position).getName());
Intent intent = new Intent(ProvinceActivity.this, CityActivity.class);
intent.putExtra(BUNDATA, cityList.get(position));
startActivityForResult(intent, RESULT_DATA);
}
});
}
private void initView() {
mCityNameTv = (TextView) findViewById(R.id.cityname_tv);
mCityNameTv.setText("选择省份");
mCityRecyclerView = (RecyclerView) findViewById(R.id.city_recyclerview);
mCityRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mCityRecyclerView.addItemDecoration(new RecycleViewDividerForList(this, LinearLayoutManager.HORIZONTAL, true));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_DATA && data != null) {
CityBean area = data.getParcelableExtra("area");
CityBean city = data.getParcelableExtra("city");
Intent intent = new Intent();
intent.putExtra("province", provinceBean);
intent.putExtra("city", city);
intent.putExtra("area", area);
setResult(RESULT_OK, intent);
finish();
}
}
}

View File

@@ -0,0 +1,77 @@
package com.lljjcoder.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.ViewGroup;
import android.view.ViewGroupOverlay;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 作者liji on 2017/7/24 06:42
* 邮箱lijiwork@sina.com
* QQ 275137657
*/
public class utils {
String cityJsonStr = "";
//读取方法
public static String getJson(Context context, String fileName) {
StringBuilder stringBuilder = new StringBuilder();
try {
AssetManager assetManager = context.getAssets();
BufferedReader bf = new BufferedReader(new InputStreamReader(assetManager.open(fileName)));
String line;
while ((line = bf.readLine()) != null) {
stringBuilder.append(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
public static void setBackgroundAlpha(Context mContext, float bgAlpha) {
// WindowManager.LayoutParams lp = ((Activity) mContext).getWindow().getAttributes();
// lp.alpha = bgAlpha;
// ((Activity) mContext).getWindow().setAttributes(lp);
if (bgAlpha == 1f) {
clearDim((Activity) mContext);
}else{
applyDim((Activity) mContext, bgAlpha);
}
}
private static void applyDim(Activity activity, float bgAlpha) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
ViewGroup parent = (ViewGroup) activity.getWindow().getDecorView().getRootView();
//activity跟布局
// ViewGroup parent = (ViewGroup) parent1.getChildAt(0);
Drawable dim = new ColorDrawable(Color.BLACK);
dim.setBounds(0, 0, parent.getWidth(), parent.getHeight());
dim.setAlpha((int) (255 * bgAlpha));
ViewGroupOverlay overlay = parent.getOverlay();
overlay.add(dim);
}
}
private static void clearDim(Activity activity) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
ViewGroup parent = (ViewGroup) activity.getWindow().getDecorView().getRootView();
//activity跟布局
// ViewGroup parent = (ViewGroup) parent1.getChildAt(0);
ViewGroupOverlay overlay = parent.getOverlay();
overlay.clear();
}
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.lljjcoder.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* 说明:
* 作者: fangkaijin on 2017/4/11.10:37
* 邮箱:fangkaijin@gmail.com
*/
public class RecycleViewDividerForList extends RecyclerView.ItemDecoration {
private Paint mPaint;
private Drawable mDivider;
private int mDividerHeight = 2;//分割线高度默认为1px
private int mOrientation;//列表的方向LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
private boolean mLastLineShow = true;
/**
* 默认分割线高度为2px颜色为灰色
*
* @param context
* @param orientation 列表方向
*/
public RecycleViewDividerForList(Context context, int orientation) {
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("请输入正确的参数!");
}
mOrientation = orientation;
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
public RecycleViewDividerForList(Context context, int orientation, boolean mLastLineShow) {
if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
throw new IllegalArgumentException("请输入正确的参数!");
}
mOrientation = orientation;
this.mLastLineShow = mLastLineShow;
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param drawableId 分割线图片
*/
public RecycleViewDividerForList(Context context, int orientation, int drawableId) {
this(context, orientation);
mDivider = ContextCompat.getDrawable(context, drawableId);
mDividerHeight = mDivider.getIntrinsicHeight();
}
/**
* 自定义分割线
*
* @param context
* @param orientation 列表方向
* @param dividerHeight 分割线高度
* @param dividerColor 分割线颜色
*/
public RecycleViewDividerForList(Context context, int orientation, int dividerHeight, int dividerColor) {
this(context, orientation);
mDividerHeight = dividerHeight;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(dividerColor);
mPaint.setStyle(Paint.Style.FILL);
}
//获取分割线尺寸
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(0, 0, 0, mDividerHeight);
}
//绘制分割线
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
if (mOrientation == LinearLayoutManager.VERTICAL) {
drawVertical(c, parent);
}
else {
drawHorizontal(c, parent);
}
}
//绘制横向 item 分割线
private void drawHorizontal(Canvas canvas, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize - (mLastLineShow ? 0 : 1); i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int top = child.getBottom() + layoutParams.bottomMargin;
final int bottom = top + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
//绘制纵向 item 分割线
private void drawVertical(Canvas canvas, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
final int childSize = parent.getChildCount();
for (int i = 0; i < childSize; i++) {
final View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + layoutParams.rightMargin;
final int right = left + mDividerHeight;
if (mDivider != null) {
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(canvas);
}
if (mPaint != null) {
canvas.drawRect(left, top, right, bottom, mPaint);
}
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0"
/>
</set>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑出式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="0"
android:toYDelta="50%p" />
</set>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/holo_red_light" android:state_enabled="false" />
<item android:color="@android:color/black" android:state_enabled="true" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape>
<solid android:color="@color/split_line_color" />
</shape>
</item>
<!-- 主体背景颜色值 -->
<item android:bottom="1px">
<shape>
<solid android:color="#ffffff" />
</shape>
</item>
</layer-list>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@color/white" />
<stroke android:color="@color/split_line_color" android:width="1px"></stroke>
<corners android:radius="2dp"></corners>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@color/white" />
<stroke android:color="@color/split_line_color" android:width="1px"></stroke>
<corners android:radius="3dp"></corners>
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="20dp">
</corners>
<solid android:color="#ff40c2fc"></solid>
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:useLevel="false" >
<solid android:color="#ff000000" />
<corners android:radius="6dp" ></corners>
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/split_line_bootom_color" android:state_pressed="true"></item>
<item android:drawable="@color/white" android:state_pressed="false"></item>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/sort_catagory" android:state_pressed="true"/>
<item android:drawable="@color/white" android:state_pressed="false"/>
</selector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:drawable="@drawable/edittext_normal" />
<item android:state_focused="true" android:drawable="@drawable/edittext_focused" />
</selector>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
~ Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
~ Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
~ Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
~ Vestibulum commodo. Ut rhoncus gravida arcu.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<corners android:radius="2dp"/>
<stroke
android:width="2px"
android:color="@color/colorPrimary" />
</shape>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
~ Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
~ Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
~ Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
~ Vestibulum commodo. Ut rhoncus gravida arcu.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<corners android:radius="2dp"/>
<stroke
android:width="1px"
android:color="@color/input_stock" />
</shape>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#00000000" android:endColor="#00000000" android:angle="90.0" />
<corners
android:topLeftRadius="8dip"
android:bottomLeftRadius="8dip"/>
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/liji_c_blue"></solid>
</shape>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Android Wheel Control.
http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
Copyright 2010 Yuri Kanivets
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
</layer-list>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Android Wheel Control.
http://android-devblog.blogspot.com/2010/05/wheel-ui-contol.html
Copyright 2010 Yuri Kanivets
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--
<gradient
android:startColor="#70222222"
android:centerColor="#70222222"
android:endColor="#70EEEEEE"
android:angle="90" />
-->
<stroke android:width="1dp" android:color="#C7C7C7" />
</shape>

View File

@@ -0,0 +1,171 @@
<?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:background="#ffffff"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="#ff40c2fc"
android:visibility="visible">
<ImageView
android:id="@+id/imgBack"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:background="@drawable/bar_back"
android:visibility="gone"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="城市选择"
android:textColor="@color/white"
android:textSize="16sp"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:padding="5dp">
<com.lljjcoder.style.citylist.widget.CleanableEditView
android:id="@+id/cityInputText"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/edittext_bg"
android:drawableLeft="@drawable/search_bar_icon_normal"
android:drawablePadding="5dp"
android:drawableRight="@drawable/input_close"
android:gravity="left|center_vertical"
android:hint="请输入城市"
android:padding="10dp"
android:textColor="@color/color_text_02"
android:textColorHint="@color/color_text_01"
android:textSize="14sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="@drawable/bg_draw1"
android:orientation="vertical"
android:padding="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/currentCityTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="当前城市"
android:textColor="@color/text_color_02"
android:textSize="12sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/currentCity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/currentCityTag"
android:ellipsize="none"
android:singleLine="true"
android:textColor="@color/text_color_02"
android:textSize="12sp"
android:textStyle="bold"/>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/sort_catagory"
android:orientation="vertical"
android:paddingBottom="15dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:visibility="gone">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/localCityTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="定位城市"
android:textColor="@color/text_color_02"
android:textSize="12sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/localCity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/localCityTag"
android:background="@drawable/bg_draw13"
android:ellipsize="middle"
android:gravity="center"
android:maxLength="4"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp"
android:textColor="@color/text_color_02"
android:textSize="12sp"/>
</RelativeLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/country_lvcountry"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:divider="@color/split_line_color"
android:dividerHeight="1px"/>
<TextView
android:id="@+id/dialog"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:background="@drawable/bg_draw15"
android:gravity="center"
android:textColor="@color/text_color_02"
android:textSize="20sp"
android:visibility="gone"/>
<com.lljjcoder.style.citylist.sortlistview.SideBar
android:id="@+id/sidrbar"
android:layout_width="30.0dip"
android:layout_height="fill_parent"
android:layout_gravity="right|center"/>
</FrameLayout>
</LinearLayout>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="#ff40c2fc">
<ImageView
android:id="@+id/img_left"
android:layout_width="9dp"
android:layout_height="15dp"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:background="@drawable/ic_citypicker_bar_back"
android:visibility="gone"/>
<TextView
android:id="@+id/cityname_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="选择省份"
android:textColor="@color/white"
android:textStyle="bold"/>
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/city_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:dividerHeight="10dp"/>
</LinearLayout>

View File

@@ -0,0 +1,16 @@
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/default_item_city_name_tv"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="30dp"
android:gravity="center"
android:textSize="14sp"
/>
</LinearLayout>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:theme="@android:style/Theme.Translucent">
<TextView
android:id="@+id/noticeText"
android:layout_width="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="TextView"
android:gravity="center"
android:textColor="@color/white"
android:textSize="14sp"
android:background="@drawable/circle_text"
android:focusable="true"
android:focusableInTouchMode="true"
android:singleLine="true"/>
</RelativeLayout>

View File

@@ -0,0 +1,16 @@
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/default_item_city_name_tv"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/white"
android:gravity="center"
android:textSize="14sp"
/>
</LinearLayout>

View File

@@ -0,0 +1,83 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_title_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#E9E9E9"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/province_line_border">
<TextView
android:id="@+id/tv_confirm"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:gravity="center_vertical"
android:text="确定"
android:textColor="@color/colorPrimary"
android:textSize="16sp"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:gravity="center_vertical"
android:text="选择地区"
android:textColor="#000000"
android:textSize="16sp"/>
<TextView
android:id="@+id/tv_cancel"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_marginLeft="15dp"
android:gravity="center_vertical"
android:text="取消"
android:textColor="@color/colorPrimary"
android:textSize="16sp"/>
</RelativeLayout>
<LinearLayout
android:id="@+id/ll_title"
android:layout_width="fill_parent"
android:background="@color/white"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.lljjcoder.style.citypickerview.widget.wheel.WheelView
android:id="@+id/id_province"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
</com.lljjcoder.style.citypickerview.widget.wheel.WheelView>
<com.lljjcoder.style.citypickerview.widget.wheel.WheelView
android:id="@+id/id_city"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
</com.lljjcoder.style.citypickerview.widget.wheel.WheelView>
<com.lljjcoder.style.citypickerview.widget.wheel.WheelView
android:id="@+id/id_district"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
</com.lljjcoder.style.citypickerview.widget.wheel.WheelView>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,98 @@
<?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="400dp"
android:background="#E9E9E9"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="400dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/white">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="请选择"
android:textColor="@color/color_text_03"
android:textSize="14sp" />
<ImageView
android:id="@+id/close_img"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:background="@drawable/ic_close" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="#e8e8e8" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="41dp"
android:background="@color/white">
<LinearLayout
android:id="@+id/choose_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/province_tv"
style="@style/tab"
android:text="请选择" />
<TextView
android:id="@+id/city_tv"
style="@style/tab" />
<TextView
android:id="@+id/area_tv"
style="@style/tab" />
</LinearLayout>
<View
android:id="@+id/selected_line"
android:layout_width="0dp"
android:layout_height="2dp"
android:layout_below="@+id/choose_tab"
android:background="@android:color/holo_red_light" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e8e8e8" />
<com.lljjcoder.style.cityjd.MyListView
android:id="@+id/city_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:divider="@null" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,29 @@
<?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:padding="10dp">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/selector_text_color_tab"
android:textSize="14sp" />
<ImageView
android:id="@+id/selectImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_toEndOf="@+id/name"
android:layout_toRightOf="@+id/name"
android:src="@drawable/ic_check"
android:visibility="gone" />
</RelativeLayout>

View File

@@ -0,0 +1,31 @@
<?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="wrap_content"
android:background="@drawable/cityitem_click"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/catalog"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#ff40c2fc"
android:padding="10dp"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="10dp"
android:textColor="@color/text_color_02"
android:textSize="16sp"
/>
</LinearLayout>

View File

@@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CityPickerView">
<attr name="citypicker_title_background" format="color"></attr><!--标题背景颜色-->
<attr name="citypicker_text_confirm_color" format="color"></attr><!--确认文字的颜色-->
<attr name="citypicker_text_cancel_color" format="color"></attr><!--取消文字的颜色-->
<attr name="citypicker_wheel_color" format="color"></attr><!--滚轮的颜色-->
<attr name="citypicker_wheel_text_color" format="color"></attr><!--滚轮里面内容的文字颜色-->
<attr name="citypicker_wheel_text_size" format="dimension"></attr><!--滚轮里面内容的文字大小-->
<attr name="citypicker_title_text_size" format="dimension"></attr><!--标题的文字大小-->
<attr name="citypicker_title_action_size" format="dimension"></attr><!--确认和取消的文字大小-->
</declare-styleable>
</resources>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#ff40c2fc</color>
<color name="colorPrimaryDark">#ff08a7ee</color>
<color name="colorAccent">#ff75d1fa</color>
<color name="activity_bg">#ffe7e7e7</color>
<color name="color_text_01">#ffc5c9ce</color>
<color name="color_text_03">#ffb1b7be</color>
<color name="split_line_color">#ffc9d1d9</color>
<color name="split_line_bootom_color">#ffa8adb3</color>
<color name="input_stock">#ffbdc7d8</color>
<color name="color_text_02">#ff181c20</color>
<color name="location_circle_bg">#320483b9</color>
<color name="indicator_color">#fffff18f</color>
<color name="tabs_click">#ff8a153e</color>
<color name="bank_bg01">#ff002142</color>
<color name="bank_bg02">#ffe2607b</color>
<color name="bank_FF6C6C6C">#FF6C6C6C</color>
<color name="text_color_02">#FF6C6C6C</color>
<color name="sort_catagory">#FFE0E0E0</color>
<color name="white">#FFFFFF</color>
<color name="province_line_border">#C7C7C7</color>
<color name="liji_c_blue">#26A5FF</color>
<color name="liji_material_blue_500">#03a9f4</color>
<color name="liji_material_blue_700">#0288d1</color>
<color name="liji_material_red_500">#e51c23</color>
<color name="liji_material_red_700">#d01716</color>
</resources>

View File

@@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">CityPicker</string>
</resources>

View File

@@ -0,0 +1,28 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AnimBottom" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
<item name="android:windowExitAnimation">@anim/push_bottom_out</item>
</style>
<style name="tab">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:padding">10dp</item>
<item name="android:textColor">@color/color_text_02</item>
<item name="android:textSize">14sp</item>
<item name="android:visibility">visible</item>
</style>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- /storage/emulated/0/Download/com.bugly.upgrade.demo/.beta/apk-->
<external-path name="beta_external_path" path="Download/"/>
<!--/storage/emulated/0/Android/data/com.bugly.upgrade.demo/files/apk/-->
<external-path name="beta_external_files_path" path="Android/data/"/>
</paths>

View File

@@ -0,0 +1,15 @@
package com.lljjcoder.style.citypickerview;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}