控件很简单,上方tab是使用LinearLayout动态添加View,下方就是一个RecyclerView;
目前的数据就三级(省市区\县),选择完成或点击确定就回调结果(Json字符串);
点击上方的tab可以回选;
....
很简单,主要是代码和思路吧;看一下代码;
public class AddressSelectView extends RelativeLayout {
private LinearLayout tab;
private RecyclerView rv;
private Context mC;
private AddressBean addressBean;//数据源
private List<AddressBean.AddressItemBean> addressDatas; //当前正在选择的数据
private List<AddressBean.AddressItemBean> alreadySelectDatas; //已经选择的数据
public AddressSelectView(Context context) {
super(context);
init(context);
}
public AddressSelectView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public AddressSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private View rootView;
private void init(Context context) {
mC = context;
rootView = View.inflate(context, R.layout.activity_address_select, this);
tab = rootView.findViewById(R.id.tab);
rv = rootView.findViewById(R.id.rv);
initList();
initData();
initView();
}
private String clickText; //回退时点击的文字
private void initList() {
rootView.findViewById(R.id.tvQ).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (onSelectConfirmListEner != null) onSelectConfirmListEner.onConfirm(new Gson().toJson(alreadySelectDatas));
}
});
setOnTabClickListEner(new OnTabClickListEner() {
@Override
public void onTabClick(View view, int position) {
if (alreadySelectDatas == null || position == tab.getChildCount() - 1) return;
if (alreadySelectDatas.size() > position)
clickText = alreadySelectDatas.get(position).getName();
if (position == 0) {
//如果点击第一个,就重新开始选择
if (alreadySelectDatas != null) alreadySelectDatas.clear();
tab.removeAllViews();
addRadioButton("选择省");
if (addressBean != null) {
addressAdapter.setDatas(addressBean.getProvince());
}
} else {
//如果点击的不是第一个,则刷新数据
List<AddressBean.AddressItemBean> alreadySelectDatas2 = new ArrayList<>();
if (alreadySelectDatas.size() >= position) {
for (int i = 0; i < position; i++) {
//只保留点击的这个之前的数据;
alreadySelectDatas2.add(alreadySelectDatas.get(i));
}
}
alreadySelectDatas.clear();
alreadySelectDatas.addAll(alreadySelectDatas2);
//使用新的数据重新规划数据源和UI
tab.removeAllViews();
for (int j = 0; j < alreadySelectDatas.size(); j++) {
addRadioButton(alreadySelectDatas.get(j).getName());
}
selectPostion(alreadySelectDatas.get(alreadySelectDatas.size() - 1), false);
}
}
});
}
private AddressAdapter addressAdapter;
private void initView() {
addRadioButton("选择省");
rv.setLayoutManager(new LinearLayoutManager(mC));
addressAdapter = new AddressAdapter(mC, null);
rv.setAdapter(addressAdapter);
if (addressBean != null) {
addressAdapter.setDatas(addressBean.getProvince());
}
}
/**
* 初始化数据
* 拿assets下的json文件
*/
private void initData() {
StringBuilder jsonSB = new StringBuilder();
try {
BufferedReader addressJsonStream = new BufferedReader(new InputStreamReader(mC.getAssets().open("address.json")));
String line;
while ((line = addressJsonStream.readLine()) != null) {
jsonSB.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// 将数据转换为对象
addressBean = new Gson().fromJson(jsonSB.toString(), AddressBean.class);
}
/**
* 添加一个Tab
*
* @param text
* @return
*/
private void addRadioButton(String text) {
for (int i = 0; i < tab.getChildCount(); i++) {
((TextView) tab.getChildAt(i)).setTextColor(getResources().getColor(R.color.textmain));
}
final TextView textView = new TextView(mC);
textView.setTag(tab.getChildCount());
textView.setText(text);
textView.setTextSize(16);
textView.setPadding(20, 0, 0, 0);
textView.setTextColor(getResources().getColor(R.color.textselect));
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (onTabClickListEner != null)
onTabClickListEner.onTabClick(textView, (int) textView.getTag());
}
});
tab.addView(textView);
}
/**
* 选择一个位置后
*
* @param data
*/
private void selectPostion(AddressBean.AddressItemBean data, boolean isAddData) {
rv.scrollToPosition(0);
if (alreadySelectDatas == null) {
alreadySelectDatas = new ArrayList<>();
}
if (isAddData) alreadySelectDatas.add(data);
if (addressDatas == null) {
addressDatas = new ArrayList<>();
} else {
addressDatas.clear();
}
//修改当前选择的名称
((TextView) tab.getChildAt(tab.getChildCount() - 1)).setText(data.getName());
if (tab.getChildCount() == 1) {
addRadioButton("选择市");
for (int i = 0; i < addressBean.getCity().size(); i++) {
if (TextUtils.equals(data.getId(), addressBean.getCity().get(i).getAboveId())) {
addressDatas.add(addressBean.getCity().get(i));
}
}
} else if (tab.getChildCount() == 2) {
addRadioButton("选择区");
for (int i = 0; i < addressBean.getDistrict().size(); i++) {
if (TextUtils.equals(data.getId(), addressBean.getDistrict().get(i).getAboveId())) {
addressDatas.add(addressBean.getDistrict().get(i));
}
}
}else {
if (onSelectConfirmListEner != null) onSelectConfirmListEner.onConfirm(new Gson().toJson(alreadySelectDatas));
}
addressAdapter.setDatas(addressDatas);
}
private class AddressAdapter extends RecyclerView.Adapter<AddressAdapter.Vh> {
private Context context;
private List<AddressBean.AddressItemBean> datas;
public AddressAdapter(Context context, List<AddressBean.AddressItemBean> datas) {
this.context = context;
if (datas == null) {
this.datas = new ArrayList<>();
} else {
this.datas = datas;
}
}
public void setDatas(List<AddressBean.AddressItemBean> datas) {
if (datas == null) {
this.datas = new ArrayList<>();
} else {
this.datas = datas;
}
notifyDataSetChanged();
}
@NonNull
@Override
public Vh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new Vh(LayoutInflater.from(context).inflate(R.layout.item_address, parent, false));
}
@Override
public void onBindViewHolder(@NonNull Vh holder, final int position) {
holder.tv.setText(datas.get(position).getName());
holder.tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectPostion(datas.get(position), true);
}
});
//如果用户点击导航条重新选择的话,就标记当前选择过的颜色加深
if (TextUtils.equals(datas.get(position).getName(), clickText)) {
holder.tv.setTextColor(context.getResources().getColor(R.color.textselect));
} else {
holder.tv.setTextColor(context.getResources().getColor(R.color.textmain));
}
}
@Override
public int getItemCount() {
return datas.size();
}
class Vh extends RecyclerView.ViewHolder {
public TextView tv;
public Vh(@NonNull View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.tv);
}
}
}
interface OnTabClickListEner {
void onTabClick(View view, int position);
}
private OnTabClickListEner onTabClickListEner;
private void setOnTabClickListEner(OnTabClickListEner onTabClickListEner) {
this.onTabClickListEner = onTabClickListEner;
}
public interface OnSelectConfirmListEner {
void onConfirm(String s);
}
public OnSelectConfirmListEner onSelectConfirmListEner;
public void setOnSelectConfirmListEner(OnSelectConfirmListEner onSelectConfirmListEner) {
this.onSelectConfirmListEner = onSelectConfirmListEner;
}
}
项目在这里:https://github.com/CuiChenbo/AddressSelectView
若是想实现类似的效果,推荐把源代码copy下来,按照自己的UI风格和数据源格式改一下就OK啦;
当然什么代码都不动也可以,就是上面的效果;
把控件放在一个PopupWindow或Dialog中弹出来,选择完成后在隐藏掉;