效果和淘宝地址选择如出一辙,放个GIF。 android
先扯一下地址数据源问题,必须是层层关联,递进关系,例如省级用 01,02,03,到了市级01001,县区01001001,网上的数据大多数也是这个关系。github上有个数据源:中国省市区镇村三级四级五级联动地址数据git
最开始,想用tablayout + viewpager 作,可是写了一半发现用viewpager代码量太多,太复杂了(viewpager中放fragment,里面再放recycleview),而后改用tablayout + recycleview ,好在recycleview部分代码不变,因此最开始也没白写。github
因此这个效果是用tablayout + recycleview写出来的,稍微提一下原生tablayout的用法(平时都用自定义的,原生都快忘了)bash
XML:网络
app:tabMode="scrollable" 从头显示,不会居中
android:scrollbars="none" 去掉滑动到头的阴影效果
复制代码
添加,删除Tab:app
tablayout .addTab(tablayout .newTab().setText("请选择"), true); 添加tab,true表示当即选中添加的tab
tablayout .getTabAt(position).setText(name); 给指定tab从新settext
tablayout .removeTabAtposition); 删除指定tab
int tabCount = tablayout .getTabCount(); 获取tab总数,注意这里不能.getChildCount
复制代码
其实这玩意儿就那么点东西,tablayout的增长删除,recycleview的从新绑定,还有的都是小细节。 ide
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="配送至"
android:textColor="#000000"
android:textSize="16sp" />
<ImageView
android:id="@+id/close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:foreground="?android:attr/selectableItemBackground"
android:padding="10dp"
android:src="@mipmap/sic_close" />
</RelativeLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
app:tabBackground="@drawable/item_bg"
app:tabMode="scrollable"
app:tabSelectedTextColor="#000000"
app:tabTextAppearance="@style/ChooseView"
app:tabTextColor="#000000" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="vertical">
<utils.LoadingUtil.NewLoadingView
android:id="@+id/loading"
android:layout_width="match_parent"
android:layout_height="300dp"
android:visibility="gone" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="300dp"
android:overScrollMode="never" />
</LinearLayout>
</LinearLayout>
复制代码
NewLoadingView是站位view,加载中,网络错误,其余异经常使用到的。布局
弹窗我用的popupwindow,先建立一个:ui
private PopupWindow popupWindow;
private Context mContext;
private Activity mActivity;
private ImageView mIv_close;
private TabLayout mTabLayout;
private RecyclerView mRecyclerView;
private NewLoadingView mLoadingView;
//地址数据集合 数据源
private List<AraeData> mAraeDatas;
//地址数据集合 结果集
private List<AraeDataResult> mResultList = new ArrayList<>();
//标示 用来判断是否为最后一级数据
private boolean isLast = false;
//标示 用来区分是列表item点击 仍是tab点击
private boolean itemClick = false;
//当前选中的tab
private int mTabCurrent = 0;
//地址选择完成的监听
private OnSelectOkListener mlistener;
//初始化
private void init() {
View pop_view = LayoutInflater.from(mContext).inflate(R.layout.address_choose_pop, null);
popupWindow = new PopupWindow(pop_view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
// 点击其余区域关闭
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
popupWindow.setAnimationStyle(android.R.style.Animation_Toast);
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
Window window = mActivity.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.alpha = 1.0F;
window.setAttributes(params);
if (isLast) {
mlistener.Select(mResultList);
}
}
});
mIv_close = pop_view.findViewById(R.id.close);
mTabLayout = pop_view.findViewById(R.id.tablayout);
mLoadingView = pop_view.findViewById(R.id.loading);
mRecyclerView = pop_view.findViewById(R.id.recyclerview);
mIv_close.setOnClickListener(this);
mTabLayout.addOnTabSelectedListener(this);
}
复制代码
注意popup的dismiss监听,在每次dismiss时都会给外部发选择完成的地址(isLast决定是否发送)。this
最主要的,仍是2个监听:
recycleview的item点击监听
tablayout切换监听(只用到3个方法中的onTabSelected)
//recycleivew的item点击监听,也就是用户选择地址了
RvAdapter.OnSelectorListener mListener = new RvAdapter.OnSelectorListener() {
@Override
public void setSelect(String name, String id, int sPosition) {
int tabCount = mTabLayout.getTabCount();
//从新点击新地址后 循环删除 旧tab
if (mTabCurrent < tabCount - 1) {
for (int i = 0; i < tabCount - 1 - mTabCurrent; i++) {
mTabLayout.removeTabAt(tabCount - 1 - i);
mResultList.remove(tabCount - 1 - i);
}
}
mTabLayout.getTabAt(mTabCurrent).setText(name);
mResultList.add(new AraeDataResult(id, name, sPosition));
itemClick = true;
getdata(id, "0", 0, false);
}
};
//tablayout中某个tab选中的监听
@Override
public void onTabSelected(TabLayout.Tab tab) {
mTabCurrent = tab.getPosition();
if (itemClick) {
} else {
String nowID = "0";
int sPosition = 0;
int tabCount = mTabLayout.getTabCount();
//若是是最后一个tab 则不须要默认选中 而且移动recycle位置
if (mTabCurrent >= tabCount - 1) {
nowID = "0";
sPosition = 0;
} else {
nowID = mResultList.get(mTabCurrent + 1).getAreaId();
sPosition = mResultList.get(mTabCurrent + 1).getPosition();
}
getdata(mResultList.get(mTabCurrent).getAreaId(), nowID, sPosition, true);
}
}
//添加Tab
private void addTab() {
mTabLayout.addTab(mTabLayout.newTab().setText("请选择"), true);
}
/**
* 网络获取数据
*
* @param pId 每级地址ID
* @param nowId 当前选中的地址id 在recycleview的选中效果中使用
* @param sposition 当前选中的item的position 用来把选中的item移动到第一位置
* @param onlyShow 用来判断点击的为item 仍是tab 若是是item 则要添加tab
*/
private void getdata(final String pId, final String nowId, final int sposition, final boolean onlyShow) {
isLast = false;
HttpManager manager = new HttpManager.Builder();
manager.setListener(new HttpManagerListen() {
@Override
public void onSucceed(String request) {
mAraeDatas = GsonManager.getInstance().getGson().fromJson(request, new TypeToken<List<AraeData>>() {
}.getType());
if (mAraeDatas == null || mAraeDatas.size() == 0) {
//没有数据了 改变标示
isLast = true;
itemClick = false;
}
//无数据标示成立,说明是最后一级
if (isLast) {
popupWindow.dismiss();
return;
}
//若是是点击item,则添加tab
if (!onlyShow) {
addTab();
}
RvAdapter adapter = new RvAdapter(mContext, nowId, mAraeDatas, mListener);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
mRecyclerView.setAdapter(adapter);
//显示item为视图第一个
if (onlyShow) {
mRecyclerView.scrollToPosition(sposition);
}
itemClick = false;
}
复制代码
全场的难点就在这2个监听里面,getdata()中是网络获取数据onSucceed请求成功这部分代码。
整体实现不难,须要注意的地方有: